From 958b25be5098ede9d1e273c4de35d116ac61f472 Mon Sep 17 00:00:00 2001 From: Thomas Veerman Date: Sun, 20 Dec 2009 20:27:14 +0000 Subject: [PATCH] - Introduce support for sticky bit. - Revise VFS-FS protocol and update VFS/MFS/ISOFS accordingly. - Clean up MFS by removing old, dead code (backwards compatibility is broken by the new VFS-FS protocol, anyway) and rewrite other parts. Also, make sure all functions have proper banners and prototypes. - VFS should always provide a (syntactically) valid path to the FS; no need for the FS to do sanity checks when leaving/entering mount points. - Fix several bugs in MFS: - Several path lookup bugs in MFS. - A link can be too big for the path buffer. - A mountpoint can become inaccessible when the creation of a new inode fails, because the inode already exists and is a mountpoint. - Introduce support for supplemental groups. - Add test 46 to test supplemental group functionality (and removed obsolete suppl. tests from test 2). - Clean up VFS (not everything is done yet). - ISOFS now opens device read-only. This makes the -r flag in the mount command unnecessary (but will still report to be mounted read-write). - Introduce PipeFS. PipeFS is a new FS that handles all anonymous and named pipes. However, named pipes still reside on the (M)FS, as they are part of the file system on disk. To make this work VFS now has a concept of 'mapped' inodes, which causes read, write, truncate and stat requests to be redirected to the mapped FS, and all other requests to the original FS. --- commands/simple/login.c | 2 - commands/simple/su.c | 6 - include/limits.h | 6 +- include/minix/callnr.h | 2 + include/minix/com.h | 10 +- include/minix/const.h | 5 +- include/minix/ipc.h | 7 +- include/minix/vfsif.h | 304 ++++----- include/sys/param.h | 1 + include/sys/stat.h | 3 +- include/unistd.h | 1 + kernel/table.c | 1 + lib/other/Makefile.in | 1 + lib/other/setgroups.c | 45 +- lib/posix/_fchmod.c | 4 +- lib/posix/_getgroups.c | 21 +- lib/syscall/Makefile.in | 1 + servers/Makefile | 2 + servers/iso9660fs/Makefile | 3 +- servers/iso9660fs/cache.c | 3 +- servers/iso9660fs/const.h | 9 +- servers/iso9660fs/device.c | 45 +- servers/iso9660fs/inode.c | 302 ++++----- servers/iso9660fs/main.c | 53 +- servers/iso9660fs/misc.c | 8 +- servers/iso9660fs/mount.c | 113 ++-- servers/iso9660fs/path.c | 394 ++---------- servers/iso9660fs/protect.c | 2 +- servers/iso9660fs/proto.h | 107 ++- servers/iso9660fs/read.c | 442 +++++-------- servers/iso9660fs/stadir.c | 30 +- servers/iso9660fs/table.c | 37 +- servers/mfs/Makefile | 6 +- servers/mfs/cache.c | 8 - servers/mfs/const.h | 5 +- servers/mfs/device.c | 188 +++--- servers/mfs/glo.h | 3 + servers/mfs/inode.c | 124 ++-- servers/mfs/inode.h | 3 - servers/mfs/link.c | 1044 +++++++----------------------- servers/mfs/main.c | 164 +++-- servers/mfs/misc.c | 27 +- servers/mfs/mount.c | 266 ++------ servers/mfs/open.c | 693 ++++---------------- servers/mfs/path.c | 1201 ++++++---------------------------- servers/mfs/pipe.c | 54 -- servers/mfs/protect.c | 102 +-- servers/mfs/proto.h | 130 ++-- servers/mfs/read.c | 772 ++++++---------------- servers/mfs/stadir.c | 40 +- servers/mfs/super.c | 72 +-- servers/mfs/table.c | 83 +-- servers/mfs/time.c | 27 +- servers/mfs/utility.c | 38 +- servers/mfs/write.c | 33 +- servers/pm/getset.c | 55 +- servers/pm/main.c | 2 + servers/pm/mproc.h | 5 + servers/pm/param.h | 2 + servers/pm/table.c | 4 +- servers/rs/table.c | 2 + servers/vfs/device.c | 615 ++++++++---------- servers/vfs/exec.c | 438 +++++-------- servers/vfs/filedes.c | 43 +- servers/vfs/fproc.h | 2 + servers/vfs/link.c | 364 +++++------ servers/vfs/lock.c | 21 +- servers/vfs/lock.h | 3 + servers/vfs/main.c | 27 +- servers/vfs/misc.c | 150 +++-- servers/vfs/mmap.c | 3 +- servers/vfs/mount.c | 471 +++++--------- servers/vfs/open.c | 720 ++++++++------------- servers/vfs/param.h | 4 + servers/vfs/path.c | 337 ++++------ servers/vfs/pipe.c | 200 +++--- servers/vfs/protect.c | 179 +++--- servers/vfs/proto.h | 45 +- servers/vfs/read.c | 253 +++----- servers/vfs/request.c | 1213 +++++++++++++++++------------------ servers/vfs/select.c | 855 ++++++++++++------------ servers/vfs/stadir.c | 137 ++-- servers/vfs/table.c | 15 +- servers/vfs/time.c | 59 +- servers/vfs/timers.c | 1 - servers/vfs/utility.c | 69 +- servers/vfs/vmnt.c | 16 +- servers/vfs/vnode.c | 113 ++-- servers/vfs/vnode.h | 16 +- test/Makefile | 3 +- test/run | 4 +- test/t40b.c | 2 +- test/test2.c | 15 - tools/Makefile | 1 + 94 files changed, 4717 insertions(+), 8800 deletions(-) diff --git a/commands/simple/login.c b/commands/simple/login.c index 1eed3ae37..b720faa49 100644 --- a/commands/simple/login.c +++ b/commands/simple/login.c @@ -434,9 +434,7 @@ char *argv[]; chmod(tty_name, 0620); /* Change id. */ -#if __minix_vmd initgroups(pwd->pw_name, pwd->pw_gid); -#endif setgid(pwd->pw_gid); setuid(pwd->pw_uid); diff --git a/commands/simple/su.c b/commands/simple/su.c index 53c92c241..91d620b26 100644 --- a/commands/simple/su.c +++ b/commands/simple/su.c @@ -31,11 +31,9 @@ char *argv[]; char *p; int super; int loginshell; -#if __minix_vmd gid_t groups[NGROUPS_MAX]; int ngroups; int g; -#endif smallenv = 0; loginshell = 0; @@ -76,10 +74,8 @@ char *argv[]; } super = 0; if (getgid() == 0) super = 1; -#if __minix_vmd ngroups = getgroups(NGROUPS_MAX, groups); for (g = 0; g < ngroups; g++) if (groups[g] == 0) super = 1; -#endif if (!super && strcmp(pwd->pw_passwd, crypt("", pwd->pw_passwd)) != 0) { #if __minix_vmd @@ -103,9 +99,7 @@ char *argv[]; #endif } -#if __minix_vmd initgroups(pwd->pw_name, pwd->pw_gid); -#endif setgid(pwd->pw_gid); setuid(pwd->pw_uid); if (loginshell) { diff --git a/include/limits.h b/include/limits.h index 37ae59ccc..3fdc11d66 100644 --- a/include/limits.h +++ b/include/limits.h @@ -61,7 +61,7 @@ #define _POSIX_MAX_CANON 255 /* size of the canonical input queue */ #define _POSIX_MAX_INPUT 255 /* you can type 255 chars ahead */ #define _POSIX_NAME_MAX DIRSIZ /* max. file name length */ -#define _POSIX_NGROUPS_MAX 0 /* supplementary group IDs are optional */ +#define _POSIX_NGROUPS_MAX 8 /* max. number of supplemental groups */ #define _POSIX_OPEN_MAX 16 /* a process may have 16 files open */ #define _POSIX_PATH_MAX 255 /* a pathname may contain 255 chars */ #define _POSIX_PIPE_BUF 512 /* pipes writes of 512 bytes must be atomic */ @@ -72,12 +72,13 @@ * traversed in the resolution of a pathname * in the absence of a loop. */ +#define _POSIX_SYMLINK_MAX 255 /* The number of bytes in a symbolic link */ /* Values actually implemented by MINIX (Tables 2-4, 2-5, 2-6, and 2-7). */ /* Some of these old names had better be defined when not POSIX. */ #define _NO_LIMIT 100 /* arbitrary number; limit not enforced */ -#define NGROUPS_MAX 0 /* supplemental group IDs not available */ +#define NGROUPS_MAX 8 /* max. number of supplemental groups */ #if _EM_WSIZE > 2 #define ARG_MAX 262144 /* # bytes of args + environ for exec() */ #else @@ -98,6 +99,7 @@ #define STREAM_MAX 20 /* must be the same as FOPEN_MAX in stdio.h */ #define TZNAME_MAX 3 /* maximum bytes in a time zone name is 3 */ #define SSIZE_MAX 32767 /* max defined byte count for read() */ +#define SYMLINK_MAX 1024 /* # bytes in a symbolic link */ #define SYMLOOP_MAX 16 /* maximum number of symbolic links that can * be reliably traversed in the resolution of * a pathname in the absence of a loop. diff --git a/include/minix/callnr.h b/include/minix/callnr.h index 75b4b78bb..6d64c0b4f 100644 --- a/include/minix/callnr.h +++ b/include/minix/callnr.h @@ -54,6 +54,8 @@ #define SETSID 62 #define GETPGRP 63 #define ITIMER 64 +#define GETGROUPS 65 +#define SETGROUPS 66 /* Posix signal handling. */ #define SIGACTION 71 diff --git a/include/minix/com.h b/include/minix/com.h index 8afdba0d5..2825d14f9 100644 --- a/include/minix/com.h +++ b/include/minix/com.h @@ -71,7 +71,8 @@ #define DS_PROC_NR 6 /* data store server */ #define MFS_PROC_NR 7 /* minix root filesystem */ #define VM_PROC_NR 8 /* memory server */ -#define INIT_PROC_NR 9 /* init -- goes multiuser */ +#define PFS_PROC_NR 9 /* pipe filesystem */ +#define INIT_PROC_NR 10 /* init -- goes multiuser */ /* Root system process and root user process. */ #define ROOT_SYS_PROC_NR RS_PROC_NR @@ -752,6 +753,7 @@ #define PM_FORK_NB (PM_RQ_BASE + 8) /* Non-blocking fork */ #define PM_UNPAUSE (PM_RQ_BASE + 9) /* Interrupt process call */ #define PM_REBOOT (PM_RQ_BASE + 10) /* System reboot */ +#define PM_SETGROUPS (PM_RQ_BASE + 11) /* Tell VFS about setgroups */ /* Replies from VFS to PM */ #define PM_SETUID_REPLY (PM_RS_BASE + 21) @@ -764,6 +766,7 @@ #define PM_FORK_NB_REPLY (PM_RS_BASE + 28) #define PM_UNPAUSE_REPLY (PM_RS_BASE + 29) #define PM_REBOOT_REPLY (PM_RS_BASE + 30) +#define PM_SETGROUPS_REPLY (PM_RS_BASE + 31) /* Standard parameters for all requests and replies, except PM_REBOOT */ # define PM_PROC m1_i1 /* process */ @@ -772,6 +775,11 @@ # define PM_EID m1_i2 /* effective user/group id */ # define PM_RID m1_i3 /* real user/group id */ +/* Additional parameter for PM_SETGROUPS */ +#define PM_GROUP_NO m1_i2 /* number of groups */ +#define PM_GROUP_ADDR m1_p1 /* struct holding group data */ + + /* Additional parameters for PM_EXEC */ # define PM_PATH m1_p1 /* executable */ # define PM_PATH_LEN m1_i2 /* length of path including diff --git a/include/minix/const.h b/include/minix/const.h index 010ad7df7..9c591965a 100644 --- a/include/minix/const.h +++ b/include/minix/const.h @@ -108,10 +108,11 @@ #define I_BLOCK_SPECIAL 0060000 /* block special file */ #define I_DIRECTORY 0040000 /* file is a directory */ #define I_CHAR_SPECIAL 0020000 /* character special file */ -#define I_NAMED_PIPE 0010000 /* named pipe (FIFO) */ +#define I_NAMED_PIPE 0010000 /* named pipe (FIFO) */ #define I_SET_UID_BIT 0004000 /* set effective uid_t on exec */ #define I_SET_GID_BIT 0002000 /* set effective gid_t on exec */ -#define ALL_MODES 0006777 /* all bits for user, group and others */ +#define I_SET_STCKY_BIT 0001000 /* sticky bit */ +#define ALL_MODES 0007777 /* all bits for user, group and others */ #define RWX_MODES 0000777 /* mode bits for RWX only */ #define R_BIT 0000004 /* Rwx protection bit */ #define W_BIT 0000002 /* rWx protection bit */ diff --git a/include/minix/ipc.h b/include/minix/ipc.h index 811dad192..dd3c08414 100644 --- a/include/minix/ipc.h +++ b/include/minix/ipc.h @@ -22,8 +22,8 @@ typedef struct {long m6l1, m6l2, m6l3; short m6s1, m6s2, m6s3; char m6c1, m6c2; char *m6p1, *m6p2;} mess_6; typedef struct {int m7i1, m7i2, m7i3, m7i4; char *m7p1, *m7p2;} mess_7; typedef struct {int m8i1, m8i2; char *m8p1, *m8p2, *m8p3, *m8p4;} mess_8; -typedef struct {long m9l1, m9l2, m9l3, m9l4, m9l5; short m9s1, m9s2, m9s3; - char m9c1, m9c2; } mess_9; +typedef struct {long m9l1, m9l2, m9l3, m9l4, m9l5; + short m9s1, m9s2, m9s3, m9s4; } mess_9; typedef struct { endpoint_t m_source; /* who sent the message */ @@ -110,8 +110,7 @@ typedef struct { #define m9_s1 m_u.m_m9.m9s1 #define m9_s2 m_u.m_m9.m9s2 #define m9_s3 m_u.m_m9.m9s3 -#define m9_c1 m_u.m_m9.m9c1 -#define m9_c2 m_u.m_m9.m9c2 +#define m9_s4 m_u.m_m9.m9s4 /*==========================================================================* * Minix run-time system (IPC). * diff --git a/include/minix/vfsif.h b/include/minix/vfsif.h index 8096a62d1..022a16f5a 100644 --- a/include/minix/vfsif.h +++ b/include/minix/vfsif.h @@ -1,200 +1,120 @@ +#ifndef __MINIX_VFSIF_H +#define __MINIX_VFSIF_H + +#include +#include + +/* VFS/FS request fields */ +#define REQ_ACTIME m9_l2 +#define REQ_COUNT m9_l2 +#define REQ_DEV m9_l5 +#define REQ_DEV2 m9_l1 +#define REQ_DIR_INO m9_l3 +#define REQ_DRIVER_E m9_l2 +#define REQ_FLAGS m9_s3 +#define REQ_GID m9_s1 +#define REQ_GRANT m9_l2 +#define REQ_GRANT2 m9_l1 +#define REQ_GRANT3 m9_l3 +#define REQ_INODE_NR m9_l1 +#define REQ_MEM_SIZE m9_l5 +#define REQ_MODE m9_s3 +#define REQ_MODTIME m9_l3 +#define REQ_NBYTES m9_l5 +#define REQ_PATH_LEN m9_s2 +#define REQ_PATH_SIZE m9_l5 +#define REQ_REN_GRANT_NEW m9_l1 +#define REQ_REN_GRANT_OLD m9_l2 +#define REQ_REN_LEN_NEW m9_s2 +#define REQ_REN_LEN_OLD m9_s1 +#define REQ_REN_NEW_DIR m9_l4 +#define REQ_REN_OLD_DIR m9_l3 +#define REQ_ROOT_INO m9_l4 +#define REQ_SEEK_POS_HI m9_l3 +#define REQ_SEEK_POS_LO m9_l4 +#define REQ_TRC_END_HI m9_l4 +#define REQ_TRC_END_LO m9_l5 +#define REQ_TRC_START_HI m9_l2 +#define REQ_TRC_START_LO m9_l3 +#define REQ_UCRED_SIZE m9_s4 +#define REQ_UID m9_s4 + + +/* VFS/FS reply fields */ +#define RES_DEV m9_l4 +#define RES_GID m9_s1 +#define RES_INODE_NR m9_l1 +#define RES_FILE_SIZE_HI m9_l2 +#define RES_FILE_SIZE_LO m9_l3 +#define RES_MODE m9_s2 +#define RES_NBYTES m9_l5 +#define RES_OFFSET m9_s2 +#define RES_SEEK_POS_HI m9_l3 +#define RES_SEEK_POS_LO m9_l4 +#define RES_SYMLOOP m9_s3 +#define RES_UID m9_s4 + +/* VFS/FS flags */ +#define REQ_RDONLY 001 +#define REQ_ISROOT 002 +#define PATH_NOFLAGS 000 +#define PATH_RET_SYMLINK 001 /* Return a symlink object (i.e. + * do not continue with the contents + * of the symlink if it is the last + * component in a path). */ +#define PATH_GET_UCRED 002 /* Request provides a grant ID in m9_l1 + * and struct ucred size in m9_s4 (as + * opposed to a REQ_UID). */ -/* Fields of VFS/FS request messages */ -#define REQ_INODE_NR m6_l1 -#define REQ_CHROOT_NR m6_l2 -#define REQ_DEVx m6_l2 -#define REQ_GRANT2 m6_l2 -#define REQ_UID m6_s1 -#define REQ_GID m6_c1 -#define REQ_MODE m6_s3 -#define REQ_PATH m6_p1 -#define REQ_PATH_LEN m6_s2 -#define REQ_FLAGS m6_l3 -#define REQ_DEV m6_l3 -#define REQ_WHO_E m6_l3 -#define REQ_GRANT m6_l3 -#define REQ_USER_ADDR m6_p2 -#define REQ_LENGTH m6_l3 -#define REQ_SYMLOOP m6_c2 -#define REQ_COUNT m6_l2 - -#define REQ_NEW_UID m6_s3 -#define REQ_NEW_GID m6_c2 - -#define REQ_INODE_INDEX m6_l3 - -#define REQ_ACTIME m6_l2 -#define REQ_MODTIME m6_l3 - -#define REQ_VMNT_IND m6_c2 -#define REQ_SLINK_STORAGE m6_p1 -#define REQ_BOOTTIME m6_l1 -#define REQ_DRIVER_E m6_l2 -#define REQ_READONLY m6_c1 -#define REQ_ISROOT m6_c2 - -#define REQ_REMOUNT m6_c2 - -#define REQ_LINKED_FILE m6_l1 -#define REQ_LINK_PARENT m6_l2 - -#define REQ_OLD_DIR m6_l2 -#define REQ_NEW_DIR m6_l3 -#define REQ_SLENGTH m6_s3 - -#define REQ_PIPE_POS m6_l1 - -#define REQ_FD_INODE_NR m2_i1 -#define REQ_FD_WHO_E m2_i2 -#define REQ_FD_GID m2_i2 -#define REQ_FD_POS m2_i3 -#define REQ_FD_NBYTES m2_l1 -#define REQ_FD_SEG m2_l2 -#define REQ_FD_INODE_INDEX m2_s1 - -#define REQ_FD_USER_ADDR m2_p1 -#define REQ_FD_LENGTH m2_i2 -#define REQ_FD_START m2_i2 -#define REQ_FD_END m2_i3 - -#define REQ_FD_BDRIVER_E m2_i1 - -#define REQ_XFD_BDEV m2_i1 -#define REQ_XFD_WHO_E m2_i2 -#define REQ_XFD_GID m2_i2 -#define REQ_XFD_NBYTES m2_i3 -#define REQ_XFD_POS_LO m2_l1 -#define REQ_XFD_POS_HI m2_l2 -#define REQ_XFD_USER_ADDR m2_p1 -/* #define REQ_XFD_BLOCK_SIZE m2_s1 */ - -#define REQ_L_GRANT m9_l1 -#define REQ_L_PATH_LEN m9_s1 -#define REQ_L_PATH_SIZE m9_s2 -#define REQ_L_PATH_OFF m9_l2 -#define REQ_L_DIR_INO m9_l3 -#define REQ_L_ROOT_INO m9_l4 -#define REQ_L_FLAGS m9_c1 -#define REQ_L_UID m9_s3 -#define REQ_L_GID m9_c2 - -/* For REQ_GETDENTS */ -#define REQ_GDE_INODE m2_i1 -#define REQ_GDE_GRANT m2_i2 -#define REQ_GDE_SIZE m2_i3 -#define REQ_GDE_POS m2_l1 - -/* For REQ_RENAME_S */ -#define REQ_REN_OLD_DIR m2_l1 -#define REQ_REN_NEW_DIR m2_l2 -#define REQ_REN_GRANT_OLD m2_i1 -#define REQ_REN_LEN_OLD m2_i2 -#define REQ_REN_GRANT_NEW m2_i3 -#define REQ_REN_LEN_NEW m2_s1 - -/* Fields of VFS/FS respons messages */ -#define RES_MOUNTED m6_s1 -#define RES_OFFSET m6_s2 -#define RES_INODE_NR m6_l1 -#define RES_MODE m6_s1 -#define RES_FILE_SIZE m6_l2 -#define RES_DEV m6_l3 -#define RES_INODE_INDEX m6_s2 -#define RES_NLINKS m6_s3 -#define RES_SYMLOOP m6_c1 -#define RES_SYMLOOP2 m6_c2 - -#define RES_UID m6_s3 -#define RES_GID m6_c1 -#define RES_CTIME m6_l3 /* Should be removed */ - -#define RES_FD_POS m2_i1 -#define RES_FD_CUM_IO m2_i2 -#define RES_FD_SIZE m2_i3 - -#define RES_XFD_POS_LO m2_l1 -#define RES_XFD_POS_HI m2_l2 -#define RES_XFD_CUM_IO m2_i1 - -#define RES_DIR m6_l1 -#define RES_FILE m6_l2 - -#define RES_MAXSIZE m6_l3 /* Should be removed */ -#define RES_BLOCKSIZE m6_s2 /* Should be removed */ +/* VFS/FS error messages */ +#define EENTERMOUNT (-301) +#define ELEAVEMOUNT (-302) +#define ESYMLINK (-303) -/* For REQ_GETDENTS */ -#define RES_GDE_POS_CHANGE m2_l1 -#define RES_GDE_CUM_IO m2_i1 +/* VFS/FS types */ -/* For REQ_RDLINK */ -#define RES_RDL_LENGTH m6_l1 +/* User credential structure */ +typedef struct { + uid_t vu_uid; + gid_t vu_gid; + int vu_ngroups; + gid_t vu_sgroups[NGROUPS_MAX]; +} vfs_ucred_t; /* Request numbers */ #define REQ_GETNODE (VFS_BASE + 1) /* Should be removed */ #define REQ_PUTNODE (VFS_BASE + 2) -#define REQ_SLINK_S (VFS_BASE + 3) -#define REQ_PIPE (VFS_BASE + 4) /* Replaced with REQ_NEWNODE */ -#define REQ_READ_O (VFS_BASE + 5) /* Replaced with REQ_READ_S */ -#define REQ_WRITE_O (VFS_BASE + 6) /* Replaced with REQ_WRITE_S */ -#define REQ_CLONE_OPCL (VFS_BASE + 7) /* Replaced with REQ_NEWNODE */ -#define REQ_FTRUNC (VFS_BASE + 8) -#define REQ_CHOWN (VFS_BASE + 9) -#define REQ_CHMOD (VFS_BASE + 10) -#define REQ_ACCESS_O (VFS_BASE + 11) /* Removed */ -#define REQ_MKNOD_O (VFS_BASE + 12) /* Replaced with REQ_MKNOD_S */ -#define REQ_MKDIR_O (VFS_BASE + 13) /* Replaced with REQ_MKDIR_S */ -#define REQ_INHIBREAD (VFS_BASE + 14) -#define REQ_STAT (VFS_BASE + 15) -#define REQ_CREATE_O (VFS_BASE + 16) /* Replaced with REQ_CREATE_S */ -#define REQ_UNLINK_O (VFS_BASE + 17) /* Replaced with REQ_UNLINK_S */ -#define REQ_RMDIR_O (VFS_BASE + 18) /* Replaced with REQ_RMDIR_S */ -#define REQ_UTIME (VFS_BASE + 19) -#define REQ_RDLINK_SO (VFS_BASE + 20) /* Replaced with REQ_RDLINK_S */ -#define REQ_FSTATFS (VFS_BASE + 21) -#define REQ_BREAD_S (VFS_BASE + 22) -#define REQ_BWRITE_S (VFS_BASE + 23) -#define REQ_UNLINK_S (VFS_BASE + 24) -#define REQ_LINK_O (VFS_BASE + 25) /* Replaced with REQ_LINK_S */ -#define REQ_SLINK_O (VFS_BASE + 26) /* Replaced with REQ_SLINK_S */ -#define REQ_RDLINK_O (VFS_BASE + 27) /* Replaced with REQ_RDLINK_S */ -#define REQ_RENAME_O (VFS_BASE + 28) /* Replaced with REQ_RENAME_S */ -#define REQ_RMDIR_S (VFS_BASE + 29) -#define REQ_MOUNTPOINT_O (VFS_BASE + 30) /* Replaced with REQ_MOUNTPOINT_S */ -#define REQ_READSUPER_O (VFS_BASE + 31) /* Replaced with REQ_READSUPER_S */ -#define REQ_UNMOUNT (VFS_BASE + 32) -#define REQ_TRUNC (VFS_BASE + 33) /* Should be removed */ -#define REQ_SYNC (VFS_BASE + 34) -#define REQ_LOOKUP_O (VFS_BASE + 35) /* Replaced with REQ_LOOKUP_S */ -#define REQ_STIME (VFS_BASE + 36) /* To be removed */ -#define REQ_NEW_DRIVER (VFS_BASE + 37) -#define REQ_BREAD_O (VFS_BASE + 38) /* Replaced with REQ_BREAD_S */ -#define REQ_BWRITE_O (VFS_BASE + 39) /* Replaced with REQ_BWRITE_S */ -#define REQ_GETDENTS_O (VFS_BASE + 40) /* Replaced with REQ_GETDENTS */ -#define REQ_FLUSH (VFS_BASE + 41) -#define REQ_READ_S (VFS_BASE + 42) -#define REQ_WRITE_S (VFS_BASE + 43) -#define REQ_MKNOD_S (VFS_BASE + 44) -#define REQ_MKDIR_S (VFS_BASE + 45) -#define REQ_CREATE_S (VFS_BASE + 46) -#define REQ_LINK_S (VFS_BASE + 47) -#define REQ_RENAME_S (VFS_BASE + 48) -#define REQ_LOOKUP_S (VFS_BASE + 49) -#define REQ_MOUNTPOINT_S (VFS_BASE + 50) -#define REQ_READSUPER_S (VFS_BASE + 51) -#define REQ_NEWNODE (VFS_BASE + 52) -#define REQ_RDLINK_S (VFS_BASE + 53) -#define REQ_GETDENTS (VFS_BASE + 54) +#define REQ_SLINK (VFS_BASE + 3) +#define REQ_FTRUNC (VFS_BASE + 4) +#define REQ_CHOWN (VFS_BASE + 5) +#define REQ_CHMOD (VFS_BASE + 6) +#define REQ_INHIBREAD (VFS_BASE + 7) +#define REQ_STAT (VFS_BASE + 8) +#define REQ_UTIME (VFS_BASE + 9) +#define REQ_FSTATFS (VFS_BASE + 10) +#define REQ_BREAD (VFS_BASE + 11) +#define REQ_BWRITE (VFS_BASE + 12) +#define REQ_UNLINK (VFS_BASE + 13) +#define REQ_RMDIR (VFS_BASE + 14) +#define REQ_UNMOUNT (VFS_BASE + 15) +#define REQ_SYNC (VFS_BASE + 16) +#define REQ_NEW_DRIVER (VFS_BASE + 17) +#define REQ_FLUSH (VFS_BASE + 18) +#define REQ_READ (VFS_BASE + 19) +#define REQ_WRITE (VFS_BASE + 20) +#define REQ_MKNOD (VFS_BASE + 21) +#define REQ_MKDIR (VFS_BASE + 22) +#define REQ_CREATE (VFS_BASE + 23) +#define REQ_LINK (VFS_BASE + 24) +#define REQ_RENAME (VFS_BASE + 25) +#define REQ_LOOKUP (VFS_BASE + 26) +#define REQ_MOUNTPOINT (VFS_BASE + 27) +#define REQ_READSUPER (VFS_BASE + 28) +#define REQ_NEWNODE (VFS_BASE + 29) +#define REQ_RDLINK (VFS_BASE + 30) +#define REQ_GETDENTS (VFS_BASE + 31) + +#define NREQS 32 + +#endif -#define NREQS 55 - - -#define EENTERMOUNT (-301) -#define ELEAVEMOUNT (-302) -#define ESYMLINK (-303) - -/* REQ_L_FLAGS */ -#define PATH_RET_SYMLINK 1 /* Return a symlink object (i.e. - * do not continue with the contents - * of the symlink if it is the last - * component in a path). - */ diff --git a/include/sys/param.h b/include/sys/param.h index a6a11e702..f8a794260 100644 --- a/include/sys/param.h +++ b/include/sys/param.h @@ -5,5 +5,6 @@ sys/param.h */ #define MAXHOSTNAMELEN 256 /* max hostname size */ +#define NGROUPS 8 /* max number of supplementary groups */ #endif /* __SYS_PARAM_H__ */ diff --git a/include/sys/stat.h b/include/sys/stat.h index dddb6968e..736d24275 100644 --- a/include/sys/stat.h +++ b/include/sys/stat.h @@ -34,8 +34,7 @@ struct stat { #define S_IFIFO 0010000 /* this is a FIFO */ #define S_ISUID 0004000 /* set user id on execution */ #define S_ISGID 0002000 /* set group id on execution */ - /* next is reserved for future use */ -#define S_ISVTX 01000 /* save swapped text even after use */ +#define S_ISVTX 0001000 /* save swapped text even after use */ /* POSIX masks for st_mode. */ #define S_IRWXU 00700 /* owner: rwx------ */ diff --git a/include/unistd.h b/include/unistd.h index 3d129bfeb..5c84d2e9c 100644 --- a/include/unistd.h +++ b/include/unistd.h @@ -118,6 +118,7 @@ _PROTOTYPE( gid_t getegid, (void) ); _PROTOTYPE( uid_t geteuid, (void) ); _PROTOTYPE( gid_t getgid, (void) ); _PROTOTYPE( int getgroups, (int _gidsetsize, gid_t _grouplist[]) ); +_PROTOTYPE( int setgroups, (int _ngroups, gid_t const *grps) ); _PROTOTYPE( char *getlogin, (void) ); _PROTOTYPE( pid_t getpgrp, (void) ); _PROTOTYPE( pid_t getpid, (void) ); diff --git a/kernel/table.c b/kernel/table.c index d4d830e41..7ce3a240b 100644 --- a/kernel/table.c +++ b/kernel/table.c @@ -74,6 +74,7 @@ PUBLIC struct boot_image image[] = { {DS_PROC_NR, 0, BVM_F, 4, 4, 0, "ds" }, {MFS_PROC_NR, 0, BVM_F, 32, 5, 0, "mfs" }, {VM_PROC_NR, 0, 0, 32, 2, 0, "vm" }, +{PFS_PROC_NR, 0, BVM_F, 32, 5, 0, "pfs" }, {INIT_PROC_NR, 0, BVM_F, 8, USER_Q, 0, "init" }, }; diff --git a/lib/other/Makefile.in b/lib/other/Makefile.in index bc7bc570e..ae32bc330 100644 --- a/lib/other/Makefile.in +++ b/lib/other/Makefile.in @@ -59,6 +59,7 @@ libc_FILES=" \ getw.c \ hypot.c \ index.c \ + initgroups.c \ itoa.c \ loadname.c \ lock.c \ diff --git a/lib/other/setgroups.c b/lib/other/setgroups.c index 25107ffe4..62e356623 100644 --- a/lib/other/setgroups.c +++ b/lib/other/setgroups.c @@ -2,52 +2,17 @@ setgroups.c */ -#include +#include #include -#include -#include int setgroups(int ngroups, const gid_t *gidset) { - if(ngroups > 1) { - /* Supplementary groups not implemented */ - errno= EINVAL; - return -1; - } + message m; - if(ngroups == 1) - return setgid(gidset[0]); + m.m1_p1 = gidset; + m.m1_i1 = ngroups; - return 0; + return(_syscall(MM, SETGROUPS, &m)); } -int initgroups(const char *name, gid_t basegid) -{ - struct group *gr; - int r, found = 0; - if((r = setgid(basegid)) < 0) - return r; - - setgrent(); - while (!found && (gr = getgrent()) != NULL) { - char **mem; - for(mem = gr->gr_mem; mem && *mem; mem++) { - if(!strcmp(name, *mem)) { - found = 1; - break; - } - } - } - endgrent(); - - /* Because supplemental groups aren't implemented, this call - * should fail if the user is in any supplemental groups. - */ - if(found) { - errno = EINVAL; - return -1; - } - - return 0; -} diff --git a/lib/posix/_fchmod.c b/lib/posix/_fchmod.c index 54fdd19eb..e10f2f707 100644 --- a/lib/posix/_fchmod.c +++ b/lib/posix/_fchmod.c @@ -8,7 +8,7 @@ _mnx_Mode_t mode; { message m; - m.m3_i1 = fd; - m.m3_i2 = mode; + m.m1_i1 = fd; + m.m1_i2 = mode; return(_syscall(FS, FCHMOD, &m)); } diff --git a/lib/posix/_getgroups.c b/lib/posix/_getgroups.c index 80bfb4560..7f8a6c330 100644 --- a/lib/posix/_getgroups.c +++ b/lib/posix/_getgroups.c @@ -1,18 +1,17 @@ -/* getgroups.c POSIX 4.2.3 - * int getgroups(gidsetsize, grouplist); - * - * This call relates to suplementary group ids, which are not - * supported in MINIX. - */ +/* +getgroups.c +*/ #include #define getgroups _getgroups #include -#include -PUBLIC int getgroups(gidsetsize, grouplist) -int gidsetsize; -gid_t grouplist[]; +PUBLIC int getgroups(int ngroups, gid_t *arr) { - return(0); + message m; + m.m1_i1 = ngroups; + m.m1_p1 = arr; + + return(_syscall(MM, GETGROUPS, &m)); } + diff --git a/lib/syscall/Makefile.in b/lib/syscall/Makefile.in index 8dee5e90a..434adecd9 100644 --- a/lib/syscall/Makefile.in +++ b/lib/syscall/Makefile.in @@ -96,6 +96,7 @@ libc_FILES=" \ select.s \ seekdir.s \ setgid.s \ + setgroups.s \ setitimer.s \ setsid.s \ setuid.s \ diff --git a/servers/Makefile b/servers/Makefile index 0a232e78e..2b5a979b8 100644 --- a/servers/Makefile +++ b/servers/Makefile @@ -18,6 +18,7 @@ all install depend clean: cd ./pm && $(MAKE) $@ cd ./vfs && $(MAKE) $@ cd ./mfs && $(MAKE) $@ + cd ./pfs && $(MAKE) $@ cd ./iso9660fs && $(MAKE) $@ cd ./rs && $(MAKE) $@ cd ./ds && $(MAKE) $@ @@ -30,6 +31,7 @@ all install depend clean: image: cd ./pm && $(MAKE) EXTRA_OPTS=$(EXTRA_OPTS) build cd ./vfs && $(MAKE) EXTRA_OPTS=$(EXTRA_OPTS) build + cd ./pfs && $(MAKE) EXTRA_OPTS=$(EXTRA_OPTS) build cd ./mfs && $(MAKE) EXTRA_OPTS=$(EXTRA_OPTS) build cd ./rs && $(MAKE) EXTRA_OPTS=$(EXTRA_OPTS) build cd ./ds && $(MAKE) EXTRA_OPTS=$(EXTRA_OPTS) build diff --git a/servers/iso9660fs/Makefile b/servers/iso9660fs/Makefile index 072a978a1..35aff9ddc 100644 --- a/servers/iso9660fs/Makefile +++ b/servers/iso9660fs/Makefile @@ -15,8 +15,7 @@ LDFLAGS = -i LIBS = -lsys -ltimers OBJ = main.o table.o mount.o super.o inode.o device.o \ - utility.o misc.o path.o read.o stadir.o cache.o \ - protect.o + utility.o misc.o path.o read.o stadir.o cache.o # build local binary all build: $(SERVER) diff --git a/servers/iso9660fs/cache.c b/servers/iso9660fs/cache.c index b393f7e68..990aa190d 100644 --- a/servers/iso9660fs/cache.c +++ b/servers/iso9660fs/cache.c @@ -21,6 +21,7 @@ FORWARD _PROTOTYPE(int read_block, (struct buf *)); PUBLIC struct buf *bp_to_pickup = buf; /* This is a pointer to the next node in the * buffer cache to pick up*/ + /*===========================================================================* * get_block * *===========================================================================*/ @@ -103,7 +104,7 @@ register struct buf *bp; /* buffer pointer */ if (r != block_size) { if (r >= 0) r = END_OF_FILE; if (r != END_OF_FILE) - printf("ISO9660FS(%d) I/O error on device %d/%d, block %ld\n", + printf("ISOFS(%d) I/O error on device %d/%d, block %ld\n", SELF_E, (fs_dev>>MAJOR)&BYTE, (fs_dev>>MINOR)&BYTE, bp->b_blocknr); diff --git a/servers/iso9660fs/const.h b/servers/iso9660fs/const.h index 43e2a69a5..e3808a4c0 100644 --- a/servers/iso9660fs/const.h +++ b/servers/iso9660fs/const.h @@ -1,6 +1,5 @@ -/* In this file are declared all the constant used by the server. */ -#define WRITE_LOG(TEXT) printf("iso9660fs: " TEXT "\n"); +#define GETDENTS_BUFSIZ 257 #define ISO9660_STANDARD_ID "CD001" /* Standard code for ISO9660 filesystems */ @@ -11,7 +10,7 @@ /* #define NR_ID_INODES 1024 */ /* The ISO9660 doesn't save the inode numbers. * There is a table that assign to every inode * a particular id. This number defines the - * maximum number of ids the finesystem can + * maximum number of ids the filesystem can * handle */ #define NO_ADDRESS -1 /* Error constants */ @@ -64,3 +63,7 @@ #define END_OF_FILE (-104) /* eof detected */ #define offsetof(type, field) ((size_t)(&((type *)0)->field)) + +/* Miscellaneous constants */ +#define SYS_UID ((uid_t) 0) /* uid_t for processes MM and INIT */ +#define SYS_GID ((gid_t) 0) /* gid_t for processes MM and INIT */ diff --git a/servers/iso9660fs/device.c b/servers/iso9660fs/device.c index 1ffa70e8b..0b8cf25cd 100644 --- a/servers/iso9660fs/device.c +++ b/servers/iso9660fs/device.c @@ -1,5 +1,3 @@ - -/* This file handles the direct communication to the device */ #include "inc.h" #include @@ -9,13 +7,13 @@ FORWARD _PROTOTYPE( int safe_io_conversion, (endpoint_t, cp_grant_id_t *, int *, cp_grant_id_t *, int, endpoint_t *, void **, int *, vir_bytes)); - FORWARD _PROTOTYPE( void safe_io_cleanup, (cp_grant_id_t, cp_grant_id_t *, int)); FORWARD _PROTOTYPE( int gen_opcl, (endpoint_t driver_e, int op, Dev_t dev, int proc_e, int flags)); FORWARD _PROTOTYPE( int gen_io, (int task_nr, message *mess_ptr)); + /*===========================================================================* * fs_new_driver * *===========================================================================*/ @@ -24,7 +22,7 @@ PUBLIC int fs_new_driver(void) /* New driver endpoint for this device */ driver_endpoints[(fs_m_in.REQ_DEV >> MAJOR) & BYTE].driver_e = fs_m_in.REQ_DRIVER_E; - return OK; + return(OK); } @@ -118,6 +116,7 @@ vir_bytes bytes; return 0; } + /*===========================================================================* * safe_io_cleanup * *===========================================================================*/ @@ -127,16 +126,17 @@ cp_grant_id_t *gids; int gids_size; { /* Free resources (specifically, grants) allocated by safe_io_conversion(). */ - int j; + int j; - cpf_revoke(gid); + cpf_revoke(gid); - for(j = 0; j < gids_size; j++) - cpf_revoke(gids[j]); + for(j = 0; j < gids_size; j++) + cpf_revoke(gids[j]); - return; + return; } + /*===========================================================================* * dev_open * *===========================================================================*/ @@ -159,6 +159,7 @@ int flags; /* mode bits and flags */ return(r); } + /*===========================================================================* * block_dev_io * *===========================================================================*/ @@ -187,14 +188,11 @@ int flags; /* special flags, like O_NONBLOCK */ driver_e = driver_endpoints[(dev >> MAJOR) & BYTE].driver_e; /* See if driver is roughly valid. */ - if (driver_e == NONE) { - printf("ISO9660FS(%d) block_dev_io: no driver for dev %x\n", SELF_E, dev); - return EDSTDIED; - } + if (driver_e == NONE) return(EDSTDIED); /* The io vector copying relies on this I/O being for FS itself. */ if(proc_e != SELF_E) { - printf("ISO9660FS(%d) doing block_dev_io for non-self %d\n", SELF_E, proc_e); + printf("ISOFS(%d) doing block_dev_io for non-self %d\n", SELF_E, proc_e); panic(__FILE__, "doing block_dev_io for non-self", proc_e); } @@ -232,28 +230,26 @@ int flags; /* special flags, like O_NONBLOCK */ */ if (r != OK) { if (r == EDEADSRCDST || r == EDSTDIED || r == ESRCDIED) { - printf("ISO9660FS(%d) dead driver %d\n", SELF_E, driver_e); + printf("ISOFS(%d) dead driver %d\n", SELF_E, driver_e); driver_endpoints[(dev >> MAJOR) & BYTE].driver_e = NONE; - return r; - /*dmap_unmap_by_endpt(task_nr); <- in the VFS proc... */ + return(r); } else if (r == ELOCKED) { - printf("ISO9660FS(%d) ELOCKED talking to %d\n", SELF_E, driver_e); - return r; + return(r); } else panic(__FILE__,"call_task: can't send/receive", r); } else { /* Did the process we did the sendrec() for get a result? */ if (m.REP_ENDPT != proc_e) { - printf("I9660FS(%d) strange device reply from %d, type = %d, proc = %d (not %d) (2) ignored\n", SELF_E, m.m_source, m.m_type, proc_e, m.REP_ENDPT); + printf("ISOFS (%d) strange device reply from %d, type = %d, proc = %d (not %d) (2) ignored\n", SELF_E, m.m_source, m.m_type, proc_e, m.REP_ENDPT); r = EIO; } } /* Task has completed. See if call completed. */ if (m.REP_STATUS == SUSPEND) { - panic(__FILE__, "ISO9660FS block_dev_io: driver returned SUSPEND", NO_NUM); + panic(__FILE__, "ISOFS block_dev_io: driver returned SUSPEND", NO_NUM); } if(buf != buf_used && r == OK) { @@ -263,6 +259,7 @@ int flags; /* special flags, like O_NONBLOCK */ return(m.REP_STATUS); } + /*===========================================================================* * gen_opcl * *===========================================================================*/ @@ -327,12 +324,13 @@ message *mess_ptr; /* pointer to message for task */ mess_ptr->m_type, proc_e, mess_ptr->REP_ENDPT); - return EIO; + return(EIO); } - return OK; + return(OK); } + /*===========================================================================* * dev_close * *===========================================================================*/ @@ -342,3 +340,4 @@ dev_t dev; /* device to close */ { (void) gen_opcl(driver_e, DEV_CLOSE, dev, 0, 0); } + diff --git a/servers/iso9660fs/inode.c b/servers/iso9660fs/inode.c index 2289aad49..381e8344c 100644 --- a/servers/iso9660fs/inode.c +++ b/servers/iso9660fs/inode.c @@ -6,125 +6,87 @@ #include "buf.h" #include -/*===========================================================================* - * fs_getnode * - *===========================================================================*/ -PUBLIC int fs_getnode() -{ -/* Increase the inode's counter specified in the request message - */ - struct dir_record *dir; - - /* Get the dir record by the id */ - dir = get_dir_record(fs_m_in.REQ_INODE_NR); - if (dir == NULL) - return EINVAL; - - /* Transfer back the inode's details */ - fs_m_out.m_source = fs_dev; - fs_m_out.RES_INODE_NR = fs_m_in.REQ_INODE_NR; - fs_m_out.RES_MODE = dir->d_mode; - fs_m_out.RES_FILE_SIZE = dir->d_file_size; - fs_m_out.RES_DEV = (Dev_t)fs_dev; - fs_m_out.RES_UID = 0; - fs_m_out.RES_GID = 0; - - return OK; -} /*===========================================================================* * fs_putnode * *===========================================================================*/ PUBLIC int fs_putnode() { -/* Find the inode specified by the request message and decrease its counter. - */ +/* Find the inode specified by the request message and decrease its counter. */ int count; - struct dir_record *dir = (void *)0; - -/* if (fs_m_in.REQ_INODE_INDEX >= 0 && */ -/* fs_m_in.REQ_INODE_INDEX <= NR_DIR_RECORDS && */ -/* ID_DIR_RECORD((dir_records + fs_m_in.REQ_INODE_INDEX)) == fs_m_in.REQ_INODE_NR) { */ -/* dir = &dir_records[fs_m_in.REQ_INODE_INDEX]; */ -/* /\* In this case the dir record by the dir record table *\/ */ -/* } else { */ + struct dir_record *dir = NULL; + dir = get_dir_record(fs_m_in.REQ_INODE_NR); - /* Get dir record increased the counter. We must decrease it releasing - * it */ release_dir_record(dir); - if (dir == (void *)0) { - panic(__FILE__, "fs_putnode failed", NO_NUM); - } - - count= fs_m_in.REQ_COUNT; /* I will check that the values of the count - * are the same */ + count = fs_m_in.REQ_COUNT; - if (count <= 0) { - printf("put_inode: bad value for count: %d\n", count); - panic(__FILE__, "fs_putnode failed", NO_NUM); - return EINVAL; - } + if (count <= 0) return(EINVAL); + if (count > dir->d_count) { - printf("put_inode: count too high: %d > %d\n", count, dir->d_count); - panic(__FILE__, "fs_putnode failed", NO_NUM); - return EINVAL; + printf("put_inode: count too high: %d > %d\n", count, dir->d_count); + return(EINVAL); } if (dir->d_count > 1) - dir->d_count = dir->d_count - count + 1; /* If the dir record should be released this - operation will bring the counter to 1. - The next function will further decreases it - releasing it completely. */ + dir->d_count = dir->d_count - count + 1;/*Keep at least one reference*/ - release_dir_record(dir); /* I finally release it */ + release_dir_record(dir); /* Actual inode release, might be last reference */ - return OK; + return(OK); } -/* Release a dir record (decrement the counter) */ + +/*===========================================================================* + * release_dir_record * + *===========================================================================*/ PUBLIC int release_dir_record(dir) - register struct dir_record *dir; +struct dir_record *dir; { +/* Release a dir record (decrement the counter) */ if (dir == NULL) - return EINVAL; + return(EINVAL); if (--dir->d_count == 0) { - if (dir->ext_attr != NULL) - dir->ext_attr->count = 0; - dir->ext_attr = NULL; - dir->d_mountpoint = FALSE; - /* This if checks we remove the good dir record and not another one - * associated to the same id.*/ -/* if (dir->id != NULL && dir->id->h_dir_record == dir) */ -/* dir->id->h_dir_record = NULL; */ - - dir->d_prior = NULL; - if (dir->d_next != NULL) - release_dir_record(dir); - dir->d_next = NULL; + if (dir->ext_attr != NULL) + dir->ext_attr->count = 0; + dir->ext_attr = NULL; + dir->d_mountpoint = FALSE; + + dir->d_prior = NULL; + if (dir->d_next != NULL) + release_dir_record(dir); + dir->d_next = NULL; } -return OK; + return(OK); } -/* Get a free dir record */ + +/*===========================================================================* + * get_free_dir_record * + *===========================================================================*/ PUBLIC struct dir_record *get_free_dir_record(void) { +/* Get a free dir record */ struct dir_record *dir; - for(dir = dir_records;dir<&dir_records[NR_ATTR_RECS]; dir++) { - if (dir->d_count == 0) { /* The record is free */ - dir->d_count = 1; /* Set count to 1 */ - dir->ext_attr = NULL; - return dir; - } + for(dir = dir_records; dir < &dir_records[NR_ATTR_RECS]; dir++) { + if (dir->d_count == 0) { /* The record is free */ + dir->d_count = 1; /* Set count to 1 */ + dir->ext_attr = NULL; + return(dir); + } } - return NULL; + + return(NULL); } -/* This function is a wrapper. It calls dir_record_by_id */ + +/*===========================================================================* + * get_dir_record * + *===========================================================================*/ PUBLIC struct dir_record *get_dir_record(id_dir_record) - ino_t id_dir_record; +ino_t id_dir_record; { struct dir_record *dir = NULL; u32_t address; @@ -132,43 +94,51 @@ PUBLIC struct dir_record *get_dir_record(id_dir_record) /* Search through the cache if the inode is still present */ for(i = 0; i < NR_DIR_RECORDS && dir == NULL; ++i) { - if (dir_records[i].d_ino_nr == id_dir_record && dir_records[i].d_count > 0) { - dir = dir_records + i; - dir->d_count++; - } + if (dir_records[i].d_ino_nr == id_dir_record + && dir_records[i].d_count > 0) { + dir = dir_records + i; + dir->d_count++; + } } if (dir == NULL) { - address = (u32_t)id_dir_record; - dir = load_dir_record_from_disk(address); + address = (u32_t)id_dir_record; + dir = load_dir_record_from_disk(address); } - if (dir == NULL) - return NULL; - else - return dir; + if (dir == NULL) return(NULL); + + return(dir); } -/* Get a free extended attribute structure in a similar way than the dir - * record */ + +/*===========================================================================* + * get_free_ext_attr * + *===========================================================================*/ PUBLIC struct ext_attr_rec *get_free_ext_attr(void) { +/* Get a free extended attribute structure */ struct ext_attr_rec *dir; - for(dir = ext_attr_recs;dir<&ext_attr_recs[NR_ATTR_RECS]; dir++) { - if (dir->count == 0) { /* The record is free */ - dir->count = 1; - return dir; - } + for(dir = ext_attr_recs; dir < &ext_attr_recs[NR_ATTR_RECS]; dir++) { + if (dir->count == 0) { /* The record is free */ + dir->count = 1; + return(dir); + } } - return NULL; + + return(NULL); } -/* Fill an extent structure from the data read on the device */ + +/*===========================================================================* + * create_ext_attr * + *===========================================================================*/ PUBLIC int create_ext_attr(struct ext_attr_rec *ext,char *buffer) { - if (ext == NULL) return EINVAL; +/* Fill an extent structure from the data read on the device */ + if (ext == NULL) return(EINVAL); /* In input we have a stream of bytes that are physically read from the - * device. This stream of data is copied in the data structure. */ + * device. This stream of data is copied to the data structure. */ memcpy(&ext->own_id,buffer,sizeof(u32_t)); memcpy(&ext->group_id,buffer + 4,sizeof(u32_t)); memcpy(&ext->permissions,buffer + 8,sizeof(u16_t)); @@ -184,21 +154,25 @@ PUBLIC int create_ext_attr(struct ext_attr_rec *ext,char *buffer) memcpy(&ext->ext_attr_rec_ver,buffer + 180,sizeof(u8_t)); memcpy(&ext->len_esc_seq,buffer + 181,sizeof(u8_t)); - return OK; + return(OK); } + +/*===========================================================================* + * create_ext_attr * + *===========================================================================*/ +PUBLIC int create_dir_record(dir,buffer,address) +struct dir_record *dir; +char *buffer; +u32_t address; +{ /* Fills a dir record structure from the data read on the device */ /* If the flag assign id is active it will return the id associated; * otherwise it will return OK. */ -PUBLIC int create_dir_record(dir,buffer,address) - struct dir_record *dir; - char *buffer; - u32_t address; -{ short size; size = buffer[0]; - if (dir == NULL) return EINVAL; + if (dir == NULL) return(EINVAL); /* The data structure dir record is filled with the stream of data * that is read. */ @@ -219,11 +193,11 @@ PUBLIC int create_dir_record(dir,buffer,address) /* set memory attrs */ if ((dir->file_flags & D_TYPE) == D_DIRECTORY) - dir->d_mode = I_DIRECTORY; + dir->d_mode = I_DIRECTORY; else - dir->d_mode = I_REGULAR; + dir->d_mode = I_REGULAR; - /* I set the rights to read only ones. Equals for all the users */ + /* Set permission to read only. Equal for all users. */ dir->d_mode |= R_BIT | X_BIT; dir->d_mode |= R_BIT << 3 | X_BIT << 3; dir->d_mode |= R_BIT << 6 | X_BIT << 6; @@ -235,20 +209,21 @@ PUBLIC int create_dir_record(dir,buffer,address) /* Set physical address of the dir record */ dir->d_phy_addr = address; - dir->d_ino_nr = (ino_t)address; /* u32_t e ino_t are the same datatype so + dir->d_ino_nr = (ino_t) address; /* u32_t e ino_t are the same datatype so * the cast is safe */ -/* if (assign_id == ASSIGN_ID) { */ -/* assign_id_to_dir_record(dir); */ -/* return ID_DIR_RECORD(dir->id); */ -/* } else */ - return OK; + return(OK); } -/* This function load a particular dir record from a specific address - * on the device */ + +/*===========================================================================* + * load_dir_record_from_disk * + *===========================================================================*/ PUBLIC struct dir_record *load_dir_record_from_disk(address) - u32_t address; +u32_t address; { +/* This function load a particular dir record from a specific address + * on the device */ + int block_nr, offset, block_size, new_pos; struct buf *bp; struct dir_record *dir, *dir_next, *dir_parent, *dir_tmp; @@ -262,57 +237,60 @@ PUBLIC struct dir_record *load_dir_record_from_disk(address) bp = get_block(block_nr); /* Read the block from the device */ if (bp == NIL_BUF) - return NULL; + return(NULL); dir = get_free_dir_record(); /* Get a free record */ if (dir == NULL) - return NULL; + return(NULL); - /* Fullfill the dir record with the data read from the device */ + /* Fill the dir record with the data read from the device */ create_dir_record(dir,bp->b_data + offset, address); - /* In case the file is composed of more file sections I load also the next in the structure */ + /* In case the file is composed of more file sections, load also the + * next section into the structure */ new_pos = offset + dir->length; dir_parent = dir; new_address = address + dir->length; while (new_pos < block_size) { - dir_next = get_free_dir_record(); - create_dir_record(dir_next, bp->b_data + new_pos, new_address); - if (dir_next->length > 0) { - strncpy(name,dir_next->file_id,dir_next->length_file_id); - name[dir_next->length_file_id] = '\0'; - strncpy(old_name,dir_parent->file_id,dir_parent->length_file_id); - old_name[dir_parent->length_file_id] = '\0'; + dir_next = get_free_dir_record(); + create_dir_record(dir_next, bp->b_data + new_pos, new_address); + + if (dir_next->length > 0) { + strncpy(name,dir_next->file_id,dir_next->length_file_id); + name[dir_next->length_file_id] = '\0'; + strncpy(old_name, dir_parent->file_id, + dir_parent->length_file_id); + old_name[dir_parent->length_file_id] = '\0'; - if (strcmp(name,old_name) == 0) { - dir_parent->d_next = dir_next; - dir_next->d_prior = dir_parent; - - /* Link the dir records */ - dir_tmp = dir_next; - size = dir_tmp->data_length_l; - - /* Update the file size */ - while (dir_tmp->d_prior != NULL) { - dir_tmp = dir_tmp->d_prior; - size += dir_tmp->data_length_l; - dir_tmp->d_file_size = size; + if (strcmp(name, old_name) == 0) { + dir_parent->d_next = dir_next; + dir_next->d_prior = dir_parent; + + /* Link the dir records */ + dir_tmp = dir_next; + size = dir_tmp->data_length_l; + + /* Update the file size */ + while (dir_tmp->d_prior != NULL) { + dir_tmp = dir_tmp->d_prior; + size += dir_tmp->data_length_l; + dir_tmp->d_file_size = size; + } + + new_pos += dir_parent->length; + new_address += dir_next->length; + dir_parent = dir_next; + } else { /* This is another inode. */ + release_dir_record(dir_next); + new_pos = block_size; + } + } else { /* record not valid */ + release_dir_record(dir_next); + new_pos = block_size; /* Exit from the while */ } - - new_pos += dir_parent->length; - new_address += dir_next->length; - dir_parent = dir_next; - } else { /* This is another inode. */ - release_dir_record(dir_next); - new_pos = block_size; - } - } else { /* record not valid */ - release_dir_record(dir_next); - new_pos = block_size; /* Exit from the while */ - } - } put_block(bp); /* Release the block read. */ - return dir; + return(dir); } + diff --git a/servers/iso9660fs/main.c b/servers/iso9660fs/main.c index aaac8f533..38bbd7555 100644 --- a/servers/iso9660fs/main.c +++ b/servers/iso9660fs/main.c @@ -25,44 +25,43 @@ PUBLIC int main(void) { fs_m_in.m_type = FS_READY; if (send(FS_PROC_NR, &fs_m_in) != OK) { - printf("ISO9660FS(%d): Error sending login to VFS\n", SELF_E); + printf("ISOFS (%d): Error sending login to VFS\n", SELF_E); return -1; } for (;;) { - /* Wait for request message. */ - get_work(&fs_m_in); - error = OK; + /* Wait for request message. */ + get_work(&fs_m_in); + error = OK; - caller_uid = -1; /* To trap errors */ - caller_gid = -1; + caller_uid = -1; /* To trap errors */ + caller_gid = -1; - who_e = fs_m_in.m_source; /* source of the request */ + who_e = fs_m_in.m_source; /* source of the request */ - if (who_e != FS_PROC_NR) { /* If the message is not for us just - * continue */ - continue; - } + if (who_e != FS_PROC_NR) { /* If the message is not for us just + * continue */ + continue; + } - req_nr = fs_m_in.m_type; + req_nr = fs_m_in.m_type; - if (req_nr < VFS_BASE) { - fs_m_in.m_type += VFS_BASE; - req_nr = fs_m_in.m_type; - } + if (req_nr < VFS_BASE) { + fs_m_in.m_type += VFS_BASE; + req_nr = fs_m_in.m_type; + } - ind= req_nr-VFS_BASE; + ind = req_nr-VFS_BASE; - if (ind < 0 || ind >= NREQS) { - error = EINVAL; - } - else - error = (*fs_call_vec[ind])(); /* Process the request calling - * the appropriate function. */ + if (ind < 0 || ind >= NREQS) { + error = EINVAL; + } else + error = (*fs_call_vec[ind])(); /* Process the request calling + * the appropriate function. */ - fs_m_out.m_type = error; - reply(who_e, &fs_m_out); /* returns the response to VFS */ + fs_m_out.m_type = error; + reply(who_e, &fs_m_out); /* returns the response to VFS */ } } @@ -90,7 +89,7 @@ message *m_in; /* pointer to message */ { int s; /* receive status */ if (OK != (s = receive(ANY, m_in))) /* wait for message */ - panic("I9660FS","receive failed", s); + panic("ISOFS","receive failed", s); } /*===========================================================================* @@ -101,5 +100,5 @@ int who; message *m_out; /* report result */ { if (OK != send(who, m_out)) /* send the message */ - printf("I9660FS(%d) was unable to send reply\n", SELF_E); + printf("ISOFS(%d) was unable to send reply\n", SELF_E); } diff --git a/servers/iso9660fs/misc.c b/servers/iso9660fs/misc.c index 457bf3f3b..f25dba4a4 100644 --- a/servers/iso9660fs/misc.c +++ b/servers/iso9660fs/misc.c @@ -1,14 +1,14 @@ -/* Some misc functions */ - #include "inc.h" #include #include + /*===========================================================================* * fs_sync * *===========================================================================*/ -PUBLIC int fs_sync() /* Calling of syncing the filesystem. No action - * is taken */ +PUBLIC int fs_sync() { + /* Always mounted read only, so nothing to sync */ return(OK); /* sync() can't fail */ } + diff --git a/servers/iso9660fs/mount.c b/servers/iso9660fs/mount.c index b4706240f..636fe1112 100644 --- a/servers/iso9660fs/mount.c +++ b/servers/iso9660fs/mount.c @@ -3,112 +3,76 @@ #include #include #include - #include "const.h" #include "glo.h" -/* Function of mounting and unmounting for ISO9660 */ -/* Reads the super inode. This function is requested at the mounting of the - * filesystem. */ /*===========================================================================* * fs_readsuper * *===========================================================================*/ PUBLIC int fs_readsuper() { - int r = OK; - - fs_dev = fs_m_in.REQ_DEV; - - driver_endpoints[(fs_dev >> MAJOR) & BYTE].driver_e = fs_m_in.REQ_DRIVER_E; - vfs_slink_storage = fs_m_in.REQ_SLINK_STORAGE; - - r = read_vds(&v_pri, fs_dev); /* This function reads the super block on the - * device and save it in v_pri */ - - if (r != OK) return(r); - - /* Return some root inode properties */ - fs_m_out.RES_INODE_NR = ID_DIR_RECORD(v_pri.dir_rec_root); - fs_m_out.RES_MODE = I_DIRECTORY; - fs_m_out.RES_FILE_SIZE = v_pri.dir_rec_root->d_file_size; - - /* and some partition properties */ - fs_m_out.RES_MAXSIZE = v_pri.volume_space_size_l; /* Volume space */ - fs_m_out.RES_BLOCKSIZE = v_pri.logical_block_size_l; /* block size */ - - return r; -} - -/*===========================================================================* - * fs_readsuper_s * - *===========================================================================*/ -PUBLIC int fs_readsuper_s() { - cp_grant_id_t label_gid; size_t label_len; int r = OK; unsigned long tasknr; endpoint_t driver_e; + int readonly, isroot; - fs_dev = fs_m_in.REQ_DEV; + fs_dev = fs_m_in.REQ_DEV; + label_gid = fs_m_in.REQ_GRANT; + label_len = fs_m_in.REQ_PATH_LEN; + readonly = 1; /* Always mount devices read only. */ + isroot = (fs_m_in.REQ_FLAGS & REQ_ISROOT) ? 1 : 0; - label_gid= fs_m_in.REQ_GRANT2; - label_len= fs_m_in.REQ_PATH_LEN; + if (label_len > sizeof(fs_dev_label)) + return(EINVAL); - if (label_len > sizeof(fs_dev_label)) { - printf("iso9660fs:fs_readsuper: label too long\n"); - return EINVAL; - } - - r= sys_safecopyfrom(fs_m_in.m_source, label_gid, 0, (vir_bytes)fs_dev_label, - label_len, D); + r = sys_safecopyfrom(fs_m_in.m_source, label_gid, 0, (vir_bytes)fs_dev_label, + label_len, D); if (r != OK) { - printf("iso9660fs: fs_readsuper: safecopyfrom failed: %d\n", r); - return EINVAL; + printf("ISOFS %s:%d safecopyfrom failed: %d\n", __FILE__, __LINE__, r); + return(EINVAL); } - r= ds_retrieve_u32(fs_dev_label, &tasknr); + r = ds_retrieve_u32(fs_dev_label, &tasknr); if (r != OK) { - printf("mfs:fs_readsuper: ds_retrieve_u32 failed for '%s': %d\n", - fs_dev_label, r); - return EINVAL; + printf("ISOFS %s:%d ds_retrieve_u32 failed for '%s': %d\n", + __FILE__, __LINE__, fs_dev_label, r); + return(EINVAL); } - driver_e= tasknr; + driver_e = tasknr; /* Map the driver endpoint for this major */ driver_endpoints[(fs_dev >> MAJOR) & BYTE].driver_e = driver_e; + /* Open the device the file system lives on */ if (dev_open(driver_e, fs_dev, driver_e, - fs_m_in.REQ_READONLY ? R_BIT : (R_BIT|W_BIT)) != OK) { + readonly ? R_BIT : (R_BIT|W_BIT)) != OK) { return(EINVAL); } - r = read_vds(&v_pri, fs_dev); /* This function reads the super block on the - * device and save it in v_pri */ - + /* Read the superblock */ + r = read_vds(&v_pri, fs_dev); if (r != OK) - return(r); + return(r); /* Return some root inode properties */ fs_m_out.RES_INODE_NR = ID_DIR_RECORD(v_pri.dir_rec_root); fs_m_out.RES_MODE = v_pri.dir_rec_root->d_mode; - fs_m_out.RES_FILE_SIZE = v_pri.dir_rec_root->d_file_size; - fs_m_out.RES_UID = 0; /* root */ - fs_m_out.RES_GID = 0; /* operator */ - - /* and some partition properties */ - fs_m_out.RES_MAXSIZE = v_pri.volume_space_size_l; /* Volume space */ - fs_m_out.RES_BLOCKSIZE = v_pri.logical_block_size_l; /* block size */ + fs_m_out.RES_FILE_SIZE_LO = v_pri.dir_rec_root->d_file_size; + fs_m_out.RES_UID = SYS_UID; /* Always root */ + fs_m_out.RES_GID = SYS_GID; /* operator */ - return r; + return(r); } + /*===========================================================================* - * fs_mountpoint_s * + * fs_mountpoint * *===========================================================================*/ -PUBLIC int fs_mountpoint_s() { +PUBLIC int fs_mountpoint() { /* This function looks up the mount point, it checks the condition whether * the partition can be mounted on the inode or not. */ @@ -118,34 +82,31 @@ PUBLIC int fs_mountpoint_s() { mode_t bits; /* Temporarily open the file. */ - if ((rip = get_dir_record(fs_m_in.REQ_INODE_NR)) == NULL) { - printf("ISO9660FS(%d) get_inode by fs_mountpoint() failed\n", SELF_E); - return(EINVAL); - } + if ((rip = get_dir_record(fs_m_in.REQ_INODE_NR)) == NULL) + return(EINVAL); if (rip->d_mountpoint) - r= EBUSY; + r = EBUSY; /* If the inode is not a dir returns error */ if ((rip->d_mode & I_TYPE) != I_DIRECTORY) - r = ENOTDIR; + r = ENOTDIR; release_dir_record(rip); if (r == OK) rip->d_mountpoint = TRUE; - return r; + return(r); } -/* Unmount the filesystem */ + /*===========================================================================* * fs_unmount * *===========================================================================*/ PUBLIC int fs_unmount(void) { release_v_pri(&v_pri); /* Release the super block */ - dev_close(driver_endpoints[(fs_dev >> MAJOR) & BYTE].driver_e, fs_dev); - - return OK; + return(OK); } + diff --git a/servers/iso9660fs/path.c b/servers/iso9660fs/path.c index 4c79d60b8..8cbf1d70c 100644 --- a/servers/iso9660fs/path.c +++ b/servers/iso9660fs/path.c @@ -5,159 +5,75 @@ #include "buf.h" -FORWARD _PROTOTYPE(char *get_name, (char *old_name, char string [NAME_MAX])); -FORWARD _PROTOTYPE( char *get_name_s, (char *name, char string[NAME_MAX+1]) ); -FORWARD _PROTOTYPE( int parse_path_s, (ino_t dir_ino, ino_t root_ino, - int flags, struct dir_record **res_inop, - size_t *offsetp)); -FORWARD _PROTOTYPE( int advance_s, (struct dir_record *dirp, - char string[NAME_MAX], struct dir_record **resp)); - -/* Lookup is a function used to ``look up" a particular path. It is called - * very often. */ -/*===========================================================================* - * lookup * - *===========================================================================*/ -PUBLIC int lookup() -{ - char string[PATH_MAX]; - int s_error, flags; - int len; - struct dir_record *dir; - - string[0] = '\0'; - - /* Check length. */ - len = fs_m_in.REQ_PATH_LEN; - if(len > sizeof(user_path)) return E2BIG; /* too big for buffer */ - if(len < 1) return EINVAL; /* too small for \0 */ - - /* Copy the pathname and set up caller's user and group id */ - err_code = sys_datacopy(FS_PROC_NR, (vir_bytes) fs_m_in.REQ_PATH, SELF, - (vir_bytes) user_path, (phys_bytes) len); - if (err_code != OK) { - printf("i9660fs:%s:%d: sys_datacopy failed: %d\n", __FILE__, __LINE__, err_code); - return err_code; - } - - /* Verify this is a null-terminated path. */ - if(user_path[len-1] != '\0') { - printf("i9660fs:lookup: didn't get null-terminated string.\n"); - return EINVAL; - } - - caller_uid = fs_m_in.REQ_UID; - caller_gid = fs_m_in.REQ_GID; - flags = fs_m_in.REQ_FLAGS; - - /* Clear RES_OFFSET for ENOENT */ - fs_m_out.RES_OFFSET= 0; +FORWARD _PROTOTYPE( char *get_name, (char *name, char string[NAME_MAX+1]) ); +FORWARD _PROTOTYPE( int parse_path, (ino_t dir_ino, ino_t root_ino, int flags, + struct dir_record **res_inop, + size_t *offsetp) ); - /* Lookup inode */ - dir = parse_path(user_path, string, flags); - - /* Copy back the last name if it is required */ - if (err_code != OK || (flags & PATH_PENULTIMATE)) { - s_error = sys_datacopy(SELF_E, (vir_bytes) string, FS_PROC_NR, - (vir_bytes) fs_m_in.REQ_USER_ADDR, (phys_bytes) NAME_MAX); - if (s_error != OK) { - printf("i9660fs:%s:%d: sys_datacopy failed: %d\n", - __FILE__, __LINE__, s_error); - return s_error; - } - } - - /* Error or mount point encountered */ - if (dir == NULL) { - if (err_code != EENTERMOUNT) - fs_m_out.RES_INODE_NR = 0; /* signal no inode */ - return err_code; - } - - fs_m_out.RES_INODE_NR = ID_DIR_RECORD(dir); - fs_m_out.RES_MODE = dir->d_mode; - fs_m_out.RES_FILE_SIZE = dir->d_file_size; - - /* Drop inode (path parse increased the counter) */ - release_dir_record(dir); - - return err_code; -} /*===========================================================================* - * fs_lookup_s * + * fs_lookup * *===========================================================================*/ -PUBLIC int fs_lookup_s() { +PUBLIC int fs_lookup() { cp_grant_id_t grant; int r, r1, len, flags; size_t offset, size; ino_t dir_ino, root_ino; struct dir_record *dir; - grant= fs_m_in.REQ_L_GRANT; - size= fs_m_in.REQ_L_PATH_SIZE; /* Size of the buffer */ - len = fs_m_in.REQ_L_PATH_LEN; /* including terminating nul */ - offset= fs_m_in.REQ_L_PATH_OFF; /* offset in buffer */ - dir_ino= fs_m_in.REQ_L_DIR_INO; - root_ino= fs_m_in.REQ_L_ROOT_INO; - flags = fs_m_in.REQ_L_FLAGS; - caller_uid = fs_m_in.REQ_L_UID; - caller_gid = fs_m_in.REQ_L_GID; + grant = fs_m_in.REQ_GRANT; + size = fs_m_in.REQ_PATH_SIZE; /* Size of the buffer */ + len = fs_m_in.REQ_PATH_LEN; /* including terminating nul */ + dir_ino = fs_m_in.REQ_DIR_INO; + root_ino = fs_m_in.REQ_ROOT_INO; + flags = fs_m_in.REQ_FLAGS; + caller_uid = fs_m_in.REQ_UID; + caller_gid = fs_m_in.REQ_GID; /* Check length. */ - if(len > sizeof(user_path)) return E2BIG; /* too big for buffer */ - if(len < 1)return EINVAL; /* too small */ + if(len > sizeof(user_path)) return(E2BIG); /* too big for buffer */ + if(len < 1) return(EINVAL); /* too small */ /* Copy the pathname and set up caller's user and group id */ - r = sys_safecopyfrom(FS_PROC_NR, grant, offset, - (vir_bytes) user_path, (phys_bytes) len, D); - + r = sys_safecopyfrom(FS_PROC_NR, grant, 0, (vir_bytes) user_path, + (phys_bytes) len, D); if (r != OK) { - printf("iso9660fs:fs_lookup_s: sys_safecopyfrom failed: %d\n", r); - return r; + printf("ISOFS %s:%d sys_safecopyfrom failed: %d\n", + __FILE__, __LINE__, r); + return(r); } /* Verify this is a null-terminated path. */ - if(user_path[len-1] != '\0') { - printf("iso9660fs:fs_lookup_s: didn't get null-terminated string.\n"); - return EINVAL; - } + if(user_path[len-1] != '\0') return(EINVAL); /* Lookup inode */ dir = NULL; - r = parse_path_s(dir_ino, root_ino, flags, &dir, &offset); + offset = 0; + r = parse_path(dir_ino, root_ino, flags, &dir, &offset); if (r == ELEAVEMOUNT) { - /* Report offset and the error */ - fs_m_out.RES_OFFSET = offset; - fs_m_out.RES_SYMLOOP = 0; - if (dir) panic(__FILE__, "fs_lookup_s: dir should be clear", - (unsigned)dir); - return r; + /* Report offset and the error */ + fs_m_out.RES_OFFSET = offset; + fs_m_out.RES_SYMLOOP = 0; + return(r); } - if (r != OK && r != EENTERMOUNT) { - if (dir) - panic(__FILE__, "fs_lookup_s: dir should be clear", - (unsigned)dir); - return r; - } + if (r != OK && r != EENTERMOUNT) return(r); - fs_m_out.RES_OFFSET = offset; - fs_m_out.RES_INODE_NR = ID_DIR_RECORD(dir); - fs_m_out.RES_MODE = dir->d_mode; - fs_m_out.RES_FILE_SIZE = dir->d_file_size; - fs_m_out.RES_SYMLOOP2 = 0; - fs_m_out.RES_UID = 0; /* root */ - fs_m_out.RES_GID = 0; /* operator */ + fs_m_out.RES_INODE_NR = ID_DIR_RECORD(dir); + fs_m_out.RES_MODE = dir->d_mode; + fs_m_out.RES_FILE_SIZE_LO = dir->d_file_size; + fs_m_out.RES_SYMLOOP = 0; + fs_m_out.RES_UID = SYS_UID; /* root */ + fs_m_out.RES_GID = SYS_GID; /* operator */ -/* /\* Drop inode (path parse increased the counter) *\/ */ -/* release_dir_record(dir); */ - if (r == EENTERMOUNT) - release_dir_record(dir); + if (r == EENTERMOUNT) { + fs_m_out.RES_OFFSET = offset; + release_dir_record(dir); + } - return r; + return(r); } /* The search dir actually performs the operation of searching for the @@ -266,127 +182,11 @@ PUBLIC int search_dir(ldir_ptr,string,numb) return EINVAL; } -/* Parse path will parse a particular path and return the final dir record. - * The final component of this path will be returned in string. It works in - * two ways: the first is PATH_PENULTIMATE and it returns the last dir of the - * path while the second is PATH_NON_SYMBOLIC where it returns the last - * component of the path. */ -/*===========================================================================* - * parse_path * - *===========================================================================*/ -PUBLIC struct dir_record *parse_path(path, string, action) -char *path; /* the path name to be parsed */ -char string[NAME_MAX]; /* the final component is returned here */ -int action; /* action on last part of path */ -{ -/* This is the actual code for last_dir and eat_path. Return the inode of - * the last directory and the name of object within that directory, or the - * inode of the last object (an empty name will be returned). Names are - * returned in string. If string is null the name is discarded. The action - * code determines how "last" is defined. If an error occurs, NIL_INODE - * will be returned with an error code in err_code. - */ - - char *new_name; - char lstring[NAME_MAX]; - struct dir_record *start_dir, *chroot_dir, *old_dir, *dir; - - /* Find starting inode inode according to the request message */ - if ((start_dir = get_dir_record(fs_m_in.REQ_INODE_NR)) == NULL) { - printf("I9660FS: couldn't find starting inode req_nr: %d %s\n", req_nr, - user_path); - err_code = ENOENT; - printf("%s, %d\n", __FILE__, __LINE__); - return NULL; - } - - /* Set user and group ID */ - caller_uid = fs_m_in.REQ_UID; - caller_gid = fs_m_in.REQ_GID; - - /* No characters were processed yet */ - path_processed = 0; - - /* Current number of symlinks encountered */ - symloop = fs_m_in.REQ_SYMLOOP; - - if (*path == '\0') { - return start_dir; - } - - if (string == (char *) 0) string = lstring; - - /* Scan the path component by component. */ - while (TRUE) { - int slashes = 0; - /* Extract one component. Skip slashes first. */ - while (path[slashes] == '/') { - slashes++; - path_processed++; - } - fs_m_out.RES_OFFSET = path_processed; /* For ENOENT */ - - if ((new_name = get_name(path+slashes, string)) == (char*) 0) { - release_dir_record(start_dir); /* bad path in user space */ - return(NULL); - } - - if (*new_name == '\0' && (action & PATH_PENULTIMATE)) { - if ((start_dir->file_flags & I_TYPE) ==I_DIRECTORY) { - return(start_dir); /* normal exit */ - } else { - /* last file of path prefix is not a directory */ - release_dir_record(start_dir); - err_code = ENOTDIR; - return(NULL); - } - } - - /* There is more path. Keep parsing. */ - old_dir = start_dir; - start_dir = advance(&old_dir, string); - - if (start_dir == NULL) { - if (*new_name == '\0' && (action & PATH_NONSYMBOLIC) != 0) { - return(old_dir); - } - else if (err_code == ENOENT) { - return(old_dir); - } - else { - release_dir_record(old_dir); - return(NULL); - } - } - - if (*new_name != '\0') { - release_dir_record(old_dir); - path = new_name; - continue; - } - - /* Either last name reached or symbolic link is opaque */ - if ((action & PATH_NONSYMBOLIC) != 0) { - release_dir_record(start_dir); - return(old_dir); - } else { - release_dir_record(old_dir); - return(start_dir); - } - } -} -/* Parse the path in user_path, starting at dir_ino. If the path is the empty - * string, just return dir_ino. It is upto the caller to treat an empty - * path in a special way. Otherwise, if the path consists of just one or - * more slash ('/') characters, the path is replaced with ".". Otherwise, - * just look up the first (or only) component in path after skipping any - * leading slashes. - */ /*===========================================================================* - * parse_path_s * + * parse_path * *===========================================================================*/ -PRIVATE int parse_path_s(dir_ino, root_ino, flags, res_inop, offsetp) +PRIVATE int parse_path(dir_ino, root_ino, flags, res_inop, offsetp) ino_t dir_ino; ino_t root_ino; int flags; @@ -400,10 +200,8 @@ size_t *offsetp; /* Find starting inode inode according to the request message */ if ((start_dir = get_dir_record(dir_ino)) == NULL) { - printf("I9660FS: couldn't find starting inode req_nr: %d %s\n", req_nr, - user_path); - printf("%s, %d\n", __FILE__, __LINE__); - return ENOENT; + printf("ISOFS: couldn't find starting inode %d\n", dir_ino); + return(ENOENT); } cp = user_path; @@ -433,10 +231,10 @@ size_t *offsetp; ncp = cp; } else - ncp = get_name_s(cp, string); + ncp = get_name(cp, string); } else /* Just get the first component */ - ncp = get_name_s(cp, string); + ncp = get_name(cp, string); /* Special code for '..'. A process is not allowed to leave a chrooted * environment. A lookup of '..' at the root of a mounted filesystem @@ -471,7 +269,7 @@ size_t *offsetp; /* There is more path. Keep parsing. */ old_dir = start_dir; - r = advance_s(old_dir, string, &start_dir); + r = advance(old_dir, string, &start_dir); if (r != OK) { release_dir_record(old_dir); @@ -483,55 +281,11 @@ size_t *offsetp; } } -/* This function will return the componsent in ``string" looking in the dir - * pdirp... */ -/*===========================================================================* - * advance * - *===========================================================================*/ -PUBLIC struct dir_record *advance(pdirp, string) -struct dir_record **pdirp; /* inode for directory to be searched */ -char string[NAME_MAX]; /* component name to look for */ -{ -/* Given a directory and a component of a path, look up the component in - * the directory, find the inode, open it, and return a pointer to its inode - * slot. If it can't be done, return NULL. - */ - - register struct dir_record *rip, *dirp; - int r, inumb; - dev_t mnt_dev; - ino_t numb; - - dirp = *pdirp; - - /* If 'string' is empty, yield same inode straight away. */ - if (string[0] == '\0') { - return dirp; - } - - /* Check for NULL. */ - if (dirp == NULL) { - return(NULL); - } - - /* If 'string' is not present in the directory, signal error. */ - if ( (r = search_dir(dirp, string, &numb)) != OK) { - err_code = r; - return(NULL); - } - - /* The component has been found in the directory. Get inode. */ - if ( (rip = get_dir_record((int) numb)) == NULL) { - return(NULL); - } - - return(rip); -} /*===========================================================================* - * advance_s * + * advance * *===========================================================================*/ -PRIVATE int advance_s(dirp, string, resp) +PUBLIC int advance(dirp, string, resp) struct dir_record *dirp; /* inode for directory to be searched */ char string[NAME_MAX]; /* component name to look for */ struct dir_record **resp; /* resulting inode */ @@ -570,55 +324,11 @@ struct dir_record **resp; /* resulting inode */ return OK; } -/*===========================================================================* - * get_name * - *===========================================================================*/ -PRIVATE char *get_name(old_name, string) -char *old_name; /* path name to parse */ -char string[NAME_MAX]; /* component extracted from 'old_name' */ -{ -/* Given a pointer to a path name in fs space, 'old_name', copy the next - * component to 'string' and pad with zeros. A pointer to that part of - * the name as yet unparsed is returned. Roughly speaking, - * 'get_name' = 'old_name' - 'string'. - * - * This routine follows the standard convention that /usr/ast, /usr//ast, - * //usr///ast and /usr/ast/ are all equivalent. - */ - - register int c; - register char *np, *rnp; - - np = string; /* 'np' points to current position */ - rnp = old_name; /* 'rnp' points to unparsed string */ - - c = *rnp; - /* Copy the unparsed path, 'old_name', to the array, 'string'. */ - while ( rnp < &old_name[PATH_MAX] && c != '/' && c != '\0') { - if (np < &string[NAME_MAX]) *np++ = c; - c = *++rnp; /* advance to next character */ - path_processed++; /* count characters */ - } - - /* To make /usr/ast/ equivalent to /usr/ast, skip trailing slashes. */ - while (c == '/' && rnp < &old_name[PATH_MAX]) { - c = *++rnp; - path_processed++; /* count characters */ - } - - if (np < &string[NAME_MAX]) *np = '\0'; /* Terminate string */ - - if (rnp >= &old_name[PATH_MAX]) { - err_code = ENAMETOOLONG; - return((char *) 0); - } - return(rnp); -} /*===========================================================================* - * get_name_s * + * get_name * *===========================================================================*/ -PRIVATE char *get_name_s(path_name, string) +PRIVATE char *get_name(path_name, string) char *path_name; /* path name to parse */ char string[NAME_MAX+1]; /* component extracted from 'old_name' */ { @@ -626,7 +336,7 @@ char string[NAME_MAX+1]; /* component extracted from 'old_name' */ * component to 'string' (truncated if necessary, always nul terminated). * A pointer to the string after the first component of the name as yet * unparsed is returned. Roughly speaking, - * 'get_name_s' = 'path_name' - 'string'. + * 'get_name' = 'path_name' - 'string'. * * This routine follows the standard convention that /usr/ast, /usr//ast, * //usr///ast and /usr/ast/ are all equivalent. diff --git a/servers/iso9660fs/protect.c b/servers/iso9660fs/protect.c index c3eb05bf1..1210f102b 100644 --- a/servers/iso9660fs/protect.c +++ b/servers/iso9660fs/protect.c @@ -20,7 +20,7 @@ PUBLIC int fs_access() /* Temporarily open the file. */ if ( (rip = get_dir_record(fs_m_in.REQ_INODE_NR)) == NULL) { - printf("I9660FS(%d) get_dir_record by fs_access() failed\n", SELF_E); + printf("ISOFS(%d) get_dir_record by fs_access() failed\n", SELF_E); return(EINVAL); } diff --git a/servers/iso9660fs/proto.h b/servers/iso9660fs/proto.h index cf4be130c..40cd7b2e4 100644 --- a/servers/iso9660fs/proto.h +++ b/servers/iso9660fs/proto.h @@ -4,80 +4,73 @@ struct dir_record; struct ext_attr_rec; struct iso9660_vd_pri; -int fs_getnode(void); -int fs_putnode(void); -int fs_new_driver(void); -int fs_sync(void); -int lookup(void); -int fs_access(void); -int fs_getdents(void); -int fs_getdents_o(void); /* main.c */ _PROTOTYPE( int main, (void) ); _PROTOTYPE( void reply, (int who, message *m_out) ); +/* cache.c */ +_PROTOTYPE(struct buf *get_block,(block_t block)); +_PROTOTYPE(void put_block,(struct buf *bp)); + /* device.c */ _PROTOTYPE( int block_dev_io, (int op, Dev_t dev, int proc, void *buf, - u64_t pos, int bytes, int flags)); + u64_t pos, int bytes, int flags) ); _PROTOTYPE( int dev_open, (endpoint_t driver_e, Dev_t dev, int proc, - int flags)); -_PROTOTYPE( void dev_close, (endpoint_t driver_e, Dev_t dev)); - -/* super.c */ -_PROTOTYPE(int release_v_pri,(struct iso9660_vd_pri *v_pri)); -_PROTOTYPE(int read_vds,(struct iso9660_vd_pri *v_pri, Dev_t dev)); -_PROTOTYPE(int create_v_pri,(struct iso9660_vd_pri *v_pri, char *buffer,unsigned long address)); + int flags) ); +_PROTOTYPE( void dev_close, (endpoint_t driver_e, Dev_t dev) ); +_PROTOTYPE( int fs_new_driver, (void) ); /* inode.c */ -_PROTOTYPE(int release_dir_record,(struct dir_record *dir)); -_PROTOTYPE(struct dir_record *get_free_dir_record,(void)); -_PROTOTYPE(struct dir_record *get_dir_record,(ino_t id_dir)); -_PROTOTYPE(struct ext_attr_rec *get_free_ext_attr,(void)); -_PROTOTYPE(int create_ext_attr,(struct ext_attr_rec *ext, - char *buffer)); -_PROTOTYPE(int create_dir_record,(struct dir_record *dir, char *buffer, - u32_t address)); -_PROTOTYPE(struct dir_record *load_dir_record_from_disk,(u32_t address)); +_PROTOTYPE( int create_dir_record,(struct dir_record *dir, char *buffer, + u32_t address) ); +_PROTOTYPE( int create_ext_attr,(struct ext_attr_rec *ext, char *buffer)); +_PROTOTYPE( int fs_getnode, (void) ); +_PROTOTYPE( int fs_putnode, (void) ); +_PROTOTYPE( struct dir_record *get_dir_record, (ino_t id_dir) ); +_PROTOTYPE( struct dir_record *get_free_dir_record, (void) ); +_PROTOTYPE( struct ext_attr_rec *get_free_ext_attr, (void) ); +_PROTOTYPE( struct dir_record *load_dir_record_from_disk,(u32_t address)); +_PROTOTYPE( int release_dir_record, (struct dir_record *dir) ); + +/* misc.c */ +_PROTOTYPE( int fs_sync, (void) ); + +/* mount.c */ +_PROTOTYPE( int fs_readsuper, (void) ); +_PROTOTYPE( int fs_mountpoint, (void) ); +_PROTOTYPE( int fs_unmount, (void) ); /* path.c */ -int fs_lookup_s(void); -_PROTOTYPE(struct dir_record *advance,(struct dir_record **dirp, - char string[NAME_MAX])); +_PROTOTYPE( int fs_lookup, (void) ); +_PROTOTYPE( int advance, (struct dir_record *dirp, char string[NAME_MAX], + struct dir_record **resp) ); _PROTOTYPE( int search_dir, (struct dir_record *ldir_ptr, - char string [NAME_MAX], ino_t *numb)); -_PROTOTYPE( struct dir_record *parse_path, (char *path, - char string[NAME_MAX], - int action)); + char string [NAME_MAX], ino_t *numb) ); + +/* protect.c */ +_PROTOTYPE( int fs_access, (void) ); /* read.c */ -int fs_read_s(void); -int fs_read(void); -int fs_bread(void); -int fs_bread_s(void); -_PROTOTYPE(int read_chunk,(struct dir_record *dir, u64_t position, - unsigned off, int chunk, char *buff, int seg, - int usr, int block_size, int *completed)); +_PROTOTYPE( int fs_read, (void) ); +_PROTOTYPE( int fs_bread, (void) ); +_PROTOTYPE( int fs_getdents, (void) ); +_PROTOTYPE( int read_chunk, (struct dir_record *rip, u64_t position, + unsigned off, int chunk, unsigned left, + cp_grant_id_t gid, unsigned buf_off, + int block_size, int *completed) ); + +/* stadir.c */ +_PROTOTYPE( int fs_stat, (void) ); +_PROTOTYPE( int fs_fstatfs, (void) ); + +/* super.c */ +_PROTOTYPE(int release_v_pri, (struct iso9660_vd_pri *v_pri) ); +_PROTOTYPE(int read_vds, (struct iso9660_vd_pri *v_pri, Dev_t dev) ); +_PROTOTYPE(int create_v_pri, (struct iso9660_vd_pri *v_pri, char *buffer, + unsigned long address) ); /* utility.c */ _PROTOTYPE(int no_sys, (void)); _PROTOTYPE(void panic, (char *who, char *mess, int num)); -/* cache.c */ -_PROTOTYPE(struct buf *get_block,(block_t block)); -_PROTOTYPE(void put_block,(struct buf *bp)); - -/* ids.c */ -/* _PROTOTYPE(void hash_init, (void)); */ -/* _PROTOTYPE(int assign_id_to_dir_record, (struct dir_record *dir)); */ -/* _PROTOTYPE(struct dir_record *get_dir_record_by_id,(int id)); */ - -/* mount.c */ -int fs_readsuper(void); -int fs_readsuper_s(void); -int fs_mountpoint_s(void); -int fs_unmount(void); - -/* stadir.c */ -int fs_stat(void); -int fs_fstatfs(void); diff --git a/servers/iso9660fs/read.c b/servers/iso9660fs/read.c index 1df3c3c1e..3d32ce26d 100644 --- a/servers/iso9660fs/read.c +++ b/servers/iso9660fs/read.c @@ -1,21 +1,16 @@ - -/* Functions to reads_file */ - #include "inc.h" #include #include #include #include "buf.h" -FORWARD _PROTOTYPE( int read_chunk_s, (struct dir_record *rip, off_t position, - unsigned off, int chunk, unsigned left,cp_grant_id_t gid, - unsigned buf_off, int block_size, int *completed)); +PRIVATE char getdents_buf[GETDENTS_BUFSIZ]; + /*===========================================================================* - * fs_read_s * + * fs_read * *===========================================================================*/ -PUBLIC int fs_read_s(void) { - +PUBLIC int fs_read(void) { int r, chunk, block_size; int nrbytes; cp_grant_id_t gid; @@ -27,14 +22,13 @@ PUBLIC int fs_read_s(void) { r = OK; /* Try to get inode according to its index */ - dir = get_dir_record(fs_m_in.REQ_FD_INODE_NR); - if (dir == NULL) return EINVAL; /* No inode found */ - + dir = get_dir_record(fs_m_in.REQ_INODE_NR); + if (dir == NULL) return(EINVAL); /* no inode found */ - position = fs_m_in.REQ_FD_POS; /* start reading from this position */ - nrbytes = (unsigned) fs_m_in.REQ_FD_NBYTES; /* number of bytes to read */ + position = fs_m_in.REQ_SEEK_POS_LO; + nrbytes = (unsigned) fs_m_in.REQ_NBYTES; /* number of bytes to read */ block_size = v_pri.logical_block_size_l; - gid = fs_m_in.REQ_FD_GID; + gid = fs_m_in.REQ_GRANT; f_size = dir->d_file_size; rdwt_err = OK; /* set to EIO if disk error occurs */ @@ -42,135 +36,64 @@ PUBLIC int fs_read_s(void) { cum_io = 0; /* Split the transfer into chunks that don't span two blocks. */ while (nrbytes != 0) { - off = (unsigned int) (position % block_size);/* offset in blk*/ + off = (unsigned int) (position % block_size); - chunk = MIN(nrbytes, block_size - off); - if (chunk < 0) chunk = block_size - off; + chunk = MIN(nrbytes, block_size - off); + if (chunk < 0) chunk = block_size - off; - bytes_left = f_size - position; - if (position >= f_size) break; /* we are beyond EOF */ - if (chunk > bytes_left) chunk = (int) bytes_left; + bytes_left = f_size - position; + if (position >= f_size) break; /* we are beyond EOF */ + if (chunk > bytes_left) chunk = (int) bytes_left; - /* Read or write 'chunk' bytes. */ - r = read_chunk_s(dir, position, off, chunk, (unsigned) nrbytes, - gid, cum_io, block_size, &completed); + /* Read or write 'chunk' bytes. */ + r = read_chunk(dir, cvul64(position), off, chunk, (unsigned) nrbytes, + gid, cum_io, block_size, &completed); - if (r != OK) break; /* EOF reached */ - if (rdwt_err < 0) break; + if (r != OK) break; /* EOF reached */ + if (rdwt_err < 0) break; - /* Update counters and pointers. */ - nrbytes -= chunk; /* bytes yet to be read */ - cum_io += chunk; /* bytes read so far */ - position += chunk; /* position within the file */ + /* Update counters and pointers. */ + nrbytes -= chunk; /* bytes yet to be read */ + cum_io += chunk; /* bytes read so far */ + position += chunk; /* position within the file */ } - fs_m_out.RES_FD_POS = position; /* It might change later and the VFS has - to know this value */ + fs_m_out.RES_SEEK_POS_LO = position; if (rdwt_err != OK) r = rdwt_err; /* check for disk error */ if (rdwt_err == END_OF_FILE) r = OK; - -/* rip->i_update |= ATIME; */ - fs_m_out.RES_FD_CUM_IO = cum_io; - fs_m_out.RES_FD_SIZE = dir->d_file_size; + fs_m_out.RES_NBYTES = cum_io; /*dir->d_file_size;*/ release_dir_record(dir); return(r); } -/* Function that is called with the request read. It performs the read and - * returns the answer. */ -/*===========================================================================* - * fs_read * - *===========================================================================*/ -PUBLIC int fs_read(void) { - struct dir_record *dir; - int r,nrbytes,block_size, chunk, completed, seg, usr; - char* user_addr; - off_t bytes_left, position; - unsigned int off, cum_io; - - r = OK; - - dir = get_dir_record(fs_m_in.REQ_FD_INODE_NR); - if (dir == NULL) return EINVAL; /* No inode found */ - - /* Get values for reading */ - position = fs_m_in.REQ_FD_POS; /* start reading from this position */ - nrbytes = (unsigned) fs_m_in.REQ_FD_NBYTES; /* number of bytes to read */ - user_addr = fs_m_in.REQ_FD_USER_ADDR; /* user addr buffer */ - usr = fs_m_in.REQ_FD_WHO_E; - seg = fs_m_in.REQ_FD_SEG; - block_size = v_pri.logical_block_size_l; - - cum_io = 0; - while (nrbytes != 0) { - off = (unsigned int) (position % block_size); /* offset in blk*/ - - chunk = MIN(nrbytes, block_size - off); - if (chunk < 0) chunk = block_size - off; - bytes_left = dir->d_file_size - position; - if (position >= dir->d_file_size) break; /* we are beyond EOF */ - if (chunk > bytes_left) chunk = (int) bytes_left; - - /* Read chunk of block. */ - r = read_chunk(dir, cvul64(position), off, chunk, - user_addr, seg, usr, block_size, &completed); - if (r != OK) - break; /* EOF reached */ - if (rdwt_err < 0) break; - - - user_addr += chunk; /* user buffer address */ - nrbytes -= chunk; /* bytes yet to be read */ - cum_io += chunk; /* bytes read so far */ - position += chunk; /* position within the file */ - } - - fs_m_out.RES_FD_POS = position; /* return the position now within the file */ - fs_m_out.RES_FD_CUM_IO = cum_io; - fs_m_out.RES_FD_SIZE = dir->data_length_l; /* returns the size of the file */ - - release_dir_record(dir); /* release the dir record. */ - return r; -} - -/*===========================================================================* - * fs_bread_s * - *===========================================================================*/ -PUBLIC int fs_bread_s(void) { - return fs_bread(); -} /*===========================================================================* * fs_bread * *===========================================================================*/ PUBLIC int fs_bread(void) { - int r, usr, rw_flag, chunk, block_size, seg; + int r, rw_flag, chunk, block_size; + cp_grant_id_t gid; int nrbytes; u64_t position; unsigned int off, cum_io; mode_t mode_word; int completed, r2 = OK; - char *user_addr; + struct dir_record *dir; - /* This function is called when it is requested a raw reading without any - * conversion. It is similar to fs_read but here the data is returned - * without any preprocessing. */ r = OK; - /* Get the values from the request message */ - rw_flag = (fs_m_in.m_type == REQ_BREAD_S ? READING : WRITING); - usr = fs_m_in.REQ_XFD_WHO_E; - position = make64(fs_m_in.REQ_XFD_POS_LO, fs_m_in.REQ_XFD_POS_HI); - nrbytes = (unsigned) fs_m_in.REQ_XFD_NBYTES; - user_addr = fs_m_in.REQ_XFD_USER_ADDR; - seg = fs_m_in.REQ_FD_SEG; - + rw_flag = (fs_m_in.m_type == REQ_BREAD ? READING : WRITING); + gid = fs_m_in.REQ_GRANT; + position = make64(fs_m_in.REQ_SEEK_POS_LO, fs_m_in.REQ_SEEK_POS_HI); + nrbytes = (unsigned) fs_m_in.REQ_NBYTES; block_size = v_pri.logical_block_size_l; + dir = v_pri.dir_rec_root; + if(rw_flag == WRITING) return (EIO); /* Not supported */ rdwt_err = OK; /* set to EIO if disk error occurs */ cum_io = 0; @@ -180,38 +103,32 @@ PUBLIC int fs_bread(void) chunk = MIN(nrbytes, block_size - off); if (chunk < 0) chunk = block_size - off; - - /* Read or write 'chunk' bytes. */ - r = read_chunk(NULL, position, off, chunk, - user_addr, seg, usr, block_size, &completed); + + /* Read 'chunk' bytes. */ + r = read_chunk(dir, position, off, chunk, (unsigned) nrbytes, + gid, cum_io, block_size, &completed); if (r != OK) break; /* EOF reached */ if (rdwt_err < 0) break; /* Update counters and pointers. */ - user_addr += chunk; /* user buffer address */ nrbytes -= chunk; /* bytes yet to be read */ cum_io += chunk; /* bytes read so far */ position= add64ul(position, chunk); /* position within the file */ } - fs_m_out.RES_XFD_POS_LO = ex64lo(position); - fs_m_out.RES_XFD_POS_HI = ex64hi(position); + fs_m_out.RES_SEEK_POS_LO = ex64lo(position); + fs_m_out.RES_SEEK_POS_HI = ex64hi(position); if (rdwt_err != OK) r = rdwt_err; /* check for disk error */ if (rdwt_err == END_OF_FILE) r = OK; - fs_m_out.RES_XFD_CUM_IO = cum_io; + fs_m_out.RES_NBYTES = cum_io; return(r); } -#define GETDENTS_BUFSIZ 257 - -PRIVATE char getdents_buf[GETDENTS_BUFSIZ]; -/* This function returns the content of a directory using the ``standard" - * data structure (that are non FS dependent). */ /*===========================================================================* * fs_getdents * *===========================================================================*/ @@ -234,10 +151,10 @@ PUBLIC int fs_getdents(void) { memset(name_old,'\0',NAME_MAX); /* Get input parameters */ - ino= fs_m_in.REQ_GDE_INODE; - gid= fs_m_in.REQ_GDE_GRANT; - size_to_read = fs_m_in.REQ_GDE_SIZE; - pos= fs_m_in.REQ_GDE_POS; + ino = fs_m_in.REQ_INODE_NR; + gid = fs_m_in.REQ_GRANT; + size_to_read = fs_m_in.REQ_MEM_SIZE; + pos = fs_m_in.REQ_SEEK_POS_LO; block_size = v_pri.logical_block_size_l; cur_pos = pos; /* The current position */ @@ -245,187 +162,128 @@ PUBLIC int fs_getdents(void) { userbuf_off = 0; memset(getdents_buf, '\0', GETDENTS_BUFSIZ); /* Avoid leaking any data */ - if ((dir = get_dir_record(ino)) == NULL) { - printf("I9660FS(%d) get_dir_record by fs_getdents() failed\n", SELF_E); - return(EINVAL); - } + if ((dir = get_dir_record(ino)) == NULL) return(EINVAL); block = dir->loc_extent_l; /* First block of the directory */ - block += pos / block_size; /* Shift to the block where start to read */ done = FALSE; while (cur_posd_file_size) { - bp = get_block(block); /* Get physical block */ + bp = get_block(block); /* Get physical block */ - if (bp == NIL_BUF) { - release_dir_record(dir); - return EINVAL; - } + if (bp == NIL_BUF) { + release_dir_record(dir); + return(EINVAL); + } - block_pos = cur_pos % block_size; /* Position where to start read */ - - while (block_posb_data + block_pos, - block*block_size + block_pos); - if (dir_tmp->length == 0) { /* EOF. I exit and return 0s */ - block_pos = block_size; - done = TRUE; - release_dir_record(dir_tmp); - } else { /* The dir record is valid. Copy data... */ - if (dir_tmp->file_id[0] == 0) strcpy(name,"."); - else if (dir_tmp->file_id[0] == 1) strcpy(name,".."); - else { - /* These next functions will extract the name from the field - * file_id */ - strncpy(name,dir_tmp->file_id,dir_tmp->length_file_id); - name[dir_tmp->length_file_id] = 0; - cp = memchr(name, ';', NAME_MAX); /* Remove the final part of the - * dir name. */ - if (cp != NULL) - name[cp - name] = 0; + block_pos = cur_pos % block_size; /* Position where to start read */ + + while (block_pos < block_size) { + dir_tmp = get_free_dir_record(); + create_dir_record(dir_tmp,bp->b_data + block_pos, + block*block_size + block_pos); + if (dir_tmp->length == 0) { /* EOF. I exit and return 0s */ + block_pos = block_size; + done = TRUE; + release_dir_record(dir_tmp); + } else { /* The dir record is valid. Copy data... */ + if (dir_tmp->file_id[0] == 0) strcpy(name,"."); + else if (dir_tmp->file_id[0] == 1) strcpy(name,".."); + else { + /* Extract the name from the field file_id */ + strncpy(name, dir_tmp->file_id, + dir_tmp->length_file_id); + name[dir_tmp->length_file_id] = 0; - /* If there is no extension I remove the last '.' */ - if (name[strlen(name) - 1] == '.') - name[strlen(name) - 1] = '\0'; - - } - - if (strcmp(name_old,name) == 0) { - cur_pos += dir_tmp->length; - release_dir_record(dir_tmp); - continue; - } - strcpy(name_old,name); - - /* Compute the length of the name */ - cp= memchr(name, '\0', NAME_MAX); - if (cp == NULL) len= NAME_MAX; - else len= cp - name; - - /* Compute record length */ - reclen= offsetof(struct dirent, d_name) + len + 1; - o= (reclen % sizeof(long)); - if (o != 0) - reclen += sizeof(long)-o; - - /* If the new record does not fit I copy the buffer and I start - * from the beginning. */ - if (tmpbuf_offset + reclen > GETDENTS_BUFSIZ) { - r= sys_safecopyto(FS_PROC_NR, gid, userbuf_off, - (vir_bytes)getdents_buf, tmpbuf_offset, D); - if (r != OK) - panic(__FILE__,"fs_getdents: sys_safecopyto failed\n",r); + /* Tidy up file name */ + cp = memchr(name, ';', NAME_MAX); + if (cp != NULL) name[cp - name] = 0; - userbuf_off += tmpbuf_offset; - tmpbuf_offset= 0; - } - - /* The standard data structure is created using the data in the - * buffer. */ - dirp = (struct dirent *)&getdents_buf[tmpbuf_offset]; - dirp->d_ino = (ino_t)(bp->b_data + block_pos); - dirp->d_off= cur_pos; - dirp->d_reclen= reclen; - memcpy(dirp->d_name, name, len); - dirp->d_name[len]= '\0'; - tmpbuf_offset += reclen; + /*If no file extension, then remove final '.'*/ + if (name[strlen(name) - 1] == '.') + name[strlen(name) - 1] = '\0'; + } + + if (strcmp(name_old, name) == 0) { + cur_pos += dir_tmp->length; + release_dir_record(dir_tmp); + continue; + } + + strcpy(name_old,name); + + /* Compute the length of the name */ + cp = memchr(name, '\0', NAME_MAX); + if (cp == NULL) len = NAME_MAX; + else len= cp - name; + + /* Compute record length */ + reclen = offsetof(struct dirent, d_name) + len + 1; + o = (reclen % sizeof(long)); + if (o != 0) + reclen += sizeof(long) - o; + + /* If the new record does not fit, then copy the buffer + * and start from the beginning. */ + if (tmpbuf_offset + reclen > GETDENTS_BUFSIZ) { + r = sys_safecopyto(FS_PROC_NR, gid, userbuf_off, + (vir_bytes)getdents_buf, tmpbuf_offset, D); + + if (r != OK) + panic(__FILE__, + "fs_getdents: sys_safecopyto failed\n",r); + + userbuf_off += tmpbuf_offset; + tmpbuf_offset= 0; + } + + /* The standard data structure is created using the + * data in the buffer. */ + dirp = (struct dirent *) &getdents_buf[tmpbuf_offset]; + dirp->d_ino = (ino_t)(bp->b_data + block_pos); + dirp->d_off= cur_pos; + dirp->d_reclen= reclen; + memcpy(dirp->d_name, name, len); + dirp->d_name[len]= '\0'; + tmpbuf_offset += reclen; - cur_pos += dir_tmp->length; - release_dir_record(dir_tmp); - } + cur_pos += dir_tmp->length; + release_dir_record(dir_tmp); + } - block_pos += dir_tmp->length; - } + block_pos += dir_tmp->length; + } - put_block(bp); /* release the block */ - if (done == TRUE) break; + put_block(bp); /* release the block */ + if (done == TRUE) break; - cur_pos += block_size - cur_pos; - - block++; /* read the next one */ + cur_pos += block_size - cur_pos; + block++; /* read the next one */ } + if (tmpbuf_offset != 0) { - r= sys_safecopyto(FS_PROC_NR, gid, userbuf_off, - (vir_bytes)getdents_buf, tmpbuf_offset, D); - if (r != OK) - panic(__FILE__, "fs_getdents: sys_safecopyto failed\n", r); + r = sys_safecopyto(FS_PROC_NR, gid, userbuf_off, + (vir_bytes) getdents_buf, tmpbuf_offset, D); + if (r != OK) + panic(__FILE__, "fs_getdents: sys_safecopyto failed\n", r); - userbuf_off += tmpbuf_offset; + userbuf_off += tmpbuf_offset; } - r= ENOSYS; - fs_m_out.RES_GDE_POS_CHANGE= 0; /* No change in case of an error */ - - /* r= userbuf_off;*/ - fs_m_out.RES_GDE_CUM_IO = userbuf_off; - if (cur_pos >= pos) - fs_m_out.RES_GDE_POS_CHANGE= cur_pos-pos; - else - fs_m_out.RES_GDE_POS_CHANGE= 0; + fs_m_out.RES_NBYTES = userbuf_off; + fs_m_out.RES_SEEK_POS_LO = cur_pos; release_dir_record(dir); /* release the inode */ - r= OK; - return(r); + return(OK); } -/*===========================================================================* - * fs_getdents_s * - *===========================================================================*/ -PUBLIC int fs_getdents_o(void) -{ - int r; - r = fs_getdents(); - - if(r == OK) - r = fs_m_out.RES_GDE_CUM_IO; - - return(r); -} -/* Read a chunk of data that does not span in two blocks. */ -PUBLIC int read_chunk(dir, position, off, chunk, buff, seg, usr, block_size, - completed) - struct dir_record *dir; /* file to read */ - u64_t position; /* position within file to read or write */ - unsigned off; /* off within the current block */ - int chunk; /* number of bytes to read or write */ - char *buff; /* virtual address of the user buffer */ - int seg; /* T or D segment in user space */ - int usr; /* which user process */ - int block_size; /* block size of FS operating on */ - int *completed; /* number of bytes copied */ -{ - register struct buf *bp; - register int r = OK; - block_t b; - - b = dir->loc_extent_l + div64u(position, block_size); /* Physical position - * to read. */ - - bp = get_block(b); /* Get physical block */ - if (bp == NIL_BUF) - return EINVAL; - - r = sys_vircopy(SELF_E, D, (phys_bytes) (bp->b_data+off), - usr, seg, (phys_bytes) buff, - (phys_bytes) chunk); - - if (r != OK) - panic(__FILE__,"fs_getdents: sys_vircopy failed\n",r); - - put_block(bp); /* Return the block */ - return OK; -} - -/* Read a chunk of data that does not span in two blocks. */ /*===========================================================================* - * read_chunk_s * + * read_chunk * *===========================================================================*/ -PRIVATE int read_chunk_s(dir, position, off, chunk, left, gid, buf_off, block_size, completed) +PUBLIC int read_chunk(dir, position, off, chunk, left, gid, buf_off, block_size, completed) register struct dir_record *dir;/* pointer to inode for file to be rd/wr */ -off_t position; /* position within file to read or write */ +u64_t position; /* position within file to read or write */ unsigned off; /* off within the current block */ int chunk; /* number of bytes to read or write */ unsigned left; /* max number of bytes wanted after position */ @@ -434,7 +292,6 @@ unsigned buf_off; /* offset in grant */ int block_size; /* block size of FS operating on */ int *completed; /* number of bytes copied */ { -/* Read or write (part of) a block. */ register struct buf *bp; register int r = OK; @@ -445,21 +302,23 @@ int *completed; /* number of bytes copied */ *completed = 0; - if ((position <= dir->d_file_size) && (position > dir->data_length_l)) { - while ((dir->d_next != NULL) && (position > dir->data_length_l)) { - position -= dir->data_length_l; + if ((ex64lo(position) <= dir->d_file_size) && + (ex64lo(position) > dir->data_length_l)) { + while ((dir->d_next != NULL) && (ex64lo(position) > dir->data_length_l)) { + position = sub64ul(position, dir->data_length_l); dir = dir->d_next; } } if (dir->inter_gap_size != 0) { - rel_block = position / block_size; + rel_block = div64u(position, block_size); file_unit = rel_block / dir->data_length_l; offset = rel_block % dir->file_unit_size; - b = dir->loc_extent_l + (dir->file_unit_size + dir->inter_gap_size) * file_unit + offset; + b = dir->loc_extent_l + (dir->file_unit_size + + dir->inter_gap_size) * file_unit + offset; } else { - b = dir->loc_extent_l + position / block_size; /* Physical position - * to read. */ + b = dir->loc_extent_l + div64u(position, block_size); /* Physical position + * to read. */ } bp = get_block(b); @@ -476,3 +335,4 @@ int *completed; /* number of bytes copied */ return(r); } + diff --git a/servers/iso9660fs/stadir.c b/servers/iso9660fs/stadir.c index 5511c67ac..b7c992f89 100644 --- a/servers/iso9660fs/stadir.c +++ b/servers/iso9660fs/stadir.c @@ -9,12 +9,9 @@ FORWARD _PROTOTYPE(int stat_dir_record, (struct dir_record *dir, int pipe_pos, - int who_e, cp_grant_id_t gid)); + int who_e, cp_grant_id_t gid) ); + -/* This function returns all the info about a particular inode. It's missing - * the recording date because of a bug in the standard functions stdtime. - * Once the bug is fixed the function can be called inside this function to - * return the date. */ /*===========================================================================* * stat_dir_record * *===========================================================================*/ @@ -24,6 +21,10 @@ int pipe_pos; /* position in a pipe, supplied by fstat() */ int who_e; /* Caller endpoint */ cp_grant_id_t gid; /* grant for the stat buf */ { +/* This function returns all the info about a particular inode. It's missing + * the recording date because of a bug in the standard functions stdtime. + * Once the bug is fixed the function can be called inside this function to + * return the date. */ /* Common code for stat and fstat system calls. */ struct stat statbuf; @@ -50,7 +51,7 @@ cp_grant_id_t gid; /* grant for the stat buf */ ltime.tm_isdst = 0; if (dir->rec_date[6] != 0) - ltime.tm_hour += dir->rec_date[6] / 4; + ltime.tm_hour += dir->rec_date[6] / 4; time1 = mktime(<ime); @@ -60,13 +61,12 @@ cp_grant_id_t gid; /* grant for the stat buf */ /* Copy the struct to user space. */ r = sys_safecopyto(who_e, gid, 0, (vir_bytes) &statbuf, - (phys_bytes) sizeof(statbuf), D); + (phys_bytes) sizeof(statbuf), D); return(r); } -/* This function is a wrapper to the function above. It is called with the - * request. */ + /*===========================================================================* * fs_stat * *===========================================================================*/ @@ -77,14 +77,14 @@ PUBLIC int fs_stat() r = EINVAL; if ((dir = get_dir_record(fs_m_in.REQ_INODE_NR)) != NULL) { - r = stat_dir_record(dir, 0, fs_m_in.m_source, fs_m_in.REQ_GRANT); - release_dir_record(dir); - } else - printf("I9660FS(%d) fs_stat() failed\n", SELF_E); + r = stat_dir_record(dir, 0, fs_m_in.m_source, fs_m_in.REQ_GRANT); + release_dir_record(dir); + } - return r; + return(r); } + /*===========================================================================* * fs_fstatfs * *===========================================================================*/ @@ -97,7 +97,7 @@ PUBLIC int fs_fstatfs() /* Copy the struct to user space. */ r = sys_safecopyto(fs_m_in.m_source, fs_m_in.REQ_GRANT, 0, - (vir_bytes) &st, (phys_bytes) sizeof(st), D); + (vir_bytes) &st, (phys_bytes) sizeof(st), D); return(r); } diff --git a/servers/iso9660fs/table.c b/servers/iso9660fs/table.c index 690aedb0e..87f0cf125 100644 --- a/servers/iso9660fs/table.c +++ b/servers/iso9660fs/table.c @@ -9,58 +9,35 @@ PUBLIC _PROTOTYPE (int (*fs_call_vec[]), (void) ) = { no_sys, /* 0: not used */ - fs_getnode, /* 1 */ + no_sys, /* 1 */ fs_putnode, /* 2 */ no_sys, /* 3: not used */ - no_sys, /* 4: not used */ - fs_read, /* 5 */ - no_sys, /* 6: not used */ - no_sys, /* 7: not used */ no_sys, /* 8: not used */ no_sys, /* 9: not used */ no_sys, /* 10: not used */ - fs_access, /* 11 */ - no_sys, /* 12: not used */ - no_sys, /* 13: not used */ no_sys, /* 14: not used */ fs_stat, /* 15 */ - no_sys, /* 16: not used */ - no_sys, /* 17: not used */ - no_sys, /* 18: not used */ no_sys, /* 19: not used */ - no_sys, /* 20: not used */ fs_fstatfs, /* 21 */ - fs_bread_s, /* 22 */ + fs_bread, /* 22 */ no_sys, /* 23: not used */ no_sys, /* 24: not used */ - no_sys, /* 25: not used */ - no_sys, /* 26: not used */ - no_sys, /* 27: not used */ - no_sys, /* 28: not used */ no_sys, /* 29: not used */ - no_sys, /* 30: not used */ - fs_readsuper, /* 31 */ fs_unmount, /* 32 */ - no_sys, /* 33: not used */ fs_sync, /* 34 */ - lookup, /* 35 */ - no_sys, /* 36: not used */ fs_new_driver, /* 37 */ - fs_bread, /* 38 */ - no_sys, /* 39 */ - fs_getdents_o, /* 40 */ no_sys, /* 41: not_used */ - fs_read_s, /* 42 */ + fs_read, /* 42 */ no_sys, /* 43: not used */ no_sys, /* 44: not used */ no_sys, /* 45: not used */ no_sys, /* 46: not used */ no_sys, /* 47: not used */ no_sys, /* 48: not used */ - fs_lookup_s, /* 49 */ - fs_mountpoint_s, /* 50 */ - fs_readsuper_s, /* 51 */ + fs_lookup, /* 49 */ + fs_mountpoint, /* 50 */ + fs_readsuper, /* 51 */ no_sys, /* 52: not used */ - no_sys, /* 53 */ + no_sys, /* 53: not used */ fs_getdents, /* 54 */ }; diff --git a/servers/mfs/Makefile b/servers/mfs/Makefile index 84b22cd6b..828664151 100644 --- a/servers/mfs/Makefile +++ b/servers/mfs/Makefile @@ -1,4 +1,4 @@ -# Makefile for File System (FS) +# Makefile for Minix File System (MFS) SERVER = mfs DEST=/sbin/$(SERVER) NR_BUFS=1024 @@ -14,10 +14,10 @@ h = $i/minix CC = exec cc CFLAGS = -I$i $(EXTRA_OPTS) $(CPROFILE) -DNR_BUFS=$(NR_BUFS) LDFLAGS = -i -LIBS = -lsys -ltimers +LIBS = -lsys OBJ = cache.o device.o link.o \ - mount.o misc.o open.o pipe.o protect.o read.o \ + mount.o misc.o open.o protect.o read.o \ stadir.o table.o time.o utility.o \ write.o inode.o main.o path.o super.o diff --git a/servers/mfs/cache.c b/servers/mfs/cache.c index 5ccf9aa34..2b53c0e02 100644 --- a/servers/mfs/cache.c +++ b/servers/mfs/cache.c @@ -303,14 +303,6 @@ int rw_flag; /* READING or WRITING */ /* Report read errors to interested parties. */ if (rw_flag == READING) rdwt_err = r; } - if(op == MFS_DEV_READ) { - int i; -#if 0 - printf("mfsread after contents: 0x%lx, ", bp->b_data); - for(i = 0; i < 10; i++) printf("%02lx ", (unsigned char) bp->b_data[i]); - printf("\n"); -#endif - } } bp->b_dirt = CLEAN; diff --git a/servers/mfs/const.h b/servers/mfs/const.h index e3584908b..00b4fd6e3 100644 --- a/servers/mfs/const.h +++ b/servers/mfs/const.h @@ -5,6 +5,7 @@ #define V2_NR_TZONES 10 /* total # zone numbers in a V2 inode */ #define NR_INODES 256 /* # slots in "in core" inode table */ +#define GETDENTS_BUFSIZ 257 #define INODE_HASH_LOG2 7 /* 2 based logarithm of the inode hash size */ #define INODE_HASH_SIZE ((unsigned long)1< #include @@ -27,31 +26,6 @@ FORWARD _PROTOTYPE( int gen_opcl, (endpoint_t driver_e, int op, Dev_t dev, int proc_e, int flags) ); FORWARD _PROTOTYPE( int gen_io, (int task_nr, message *mess_ptr) ); -/*===========================================================================* - * fs_clone_opcl * - *===========================================================================*/ -PUBLIC int fs_clone_opcl(void) -{ - /* A new minor device number has been returned. - * Create a temporary device file to hold it. - */ - struct inode *ip; - dev_t dev; - - dev = fs_m_in.REQ_DEV; /* Device number */ - - ip = alloc_inode(fs_dev, ALL_MODES | I_CHAR_SPECIAL); - - if (ip == NIL_INODE) return err_code; - - ip->i_zone[0] = dev; - - fs_m_out.m_source = ip->i_dev; - fs_m_out.RES_INODE_NR = ip->i_num; - fs_m_out.RES_MODE = ip->i_mode; - return OK; -} - /*===========================================================================* * fs_new_driver * @@ -60,8 +34,8 @@ PUBLIC int fs_new_driver(void) { /* New driver endpoint for this device */ driver_endpoints[(fs_m_in.REQ_DEV >> MAJOR) & BYTE].driver_e = - fs_m_in.REQ_DRIVER_E; - return OK; + fs_m_in.REQ_DRIVER_E; + return(OK); } @@ -80,81 +54,77 @@ void **buf; int *vec_grants; vir_bytes bytes; { - int access = 0, size; - int j; - iovec_t *v; - static iovec_t *new_iovec; - - STATICINIT(new_iovec, NR_IOREQS); - - /* Number of grants allocated in vector I/O. */ - *vec_grants = 0; - - /* Driver can handle it - change request to a safe one. */ - - *gid = GRANT_INVALID; - - switch(*op) { - case MFS_DEV_READ: - case MFS_DEV_WRITE: - /* Change to safe op. */ - *op = *op == MFS_DEV_READ ? DEV_READ_S : DEV_WRITE_S; - - if((*gid=cpf_grant_direct(driver, (vir_bytes) *buf, - bytes, *op == DEV_READ_S ? CPF_WRITE : - CPF_READ)) < 0) { - panic(__FILE__, - "cpf_grant_magic of buffer failed\n", NO_NUM); - } - - break; - case MFS_DEV_GATHER: - case MFS_DEV_SCATTER: - /* Change to safe op. */ - *op = *op == MFS_DEV_GATHER ? - DEV_GATHER_S : DEV_SCATTER_S; - - /* Grant access to my new i/o vector. */ - if((*gid = cpf_grant_direct(driver, - (vir_bytes) new_iovec, bytes * sizeof(iovec_t), - CPF_READ | CPF_WRITE)) < 0) { - panic(__FILE__, - "cpf_grant_direct of vector failed", NO_NUM); - } - v = (iovec_t *) *buf; - /* Grant access to i/o buffers. */ - for(j = 0; j < bytes; j++) { - if(j >= NR_IOREQS) - panic(__FILE__, "vec too big", bytes); - new_iovec[j].iov_addr = gids[j] = - cpf_grant_direct(driver, (vir_bytes) - v[j].iov_addr, v[j].iov_size, - *op == DEV_GATHER_S ? CPF_WRITE : CPF_READ); - if(!GRANT_VALID(gids[j])) { - panic(__FILE__, "mfs: grant to iovec buf failed", - NO_NUM); - } - new_iovec[j].iov_size = v[j].iov_size; - (*vec_grants)++; - } - - /* Set user's vector to the new one. */ - *buf = new_iovec; - break; - } + int access = 0, size; + int j; + iovec_t *v; + static iovec_t *new_iovec; - /* If we have converted to a safe operation, I/O - * endpoint becomes FS if it wasn't already. - */ - if(GRANT_VALID(*gid)) { - *io_ept = SELF_E; - return 1; - } + STATICINIT(new_iovec, NR_IOREQS); + + /* Number of grants allocated in vector I/O. */ + *vec_grants = 0; + + /* Driver can handle it - change request to a safe one. */ + + *gid = GRANT_INVALID; + + switch(*op) { + case MFS_DEV_READ: + case MFS_DEV_WRITE: + /* Change to safe op. */ + *op = *op == MFS_DEV_READ ? DEV_READ_S : DEV_WRITE_S; + + if((*gid=cpf_grant_direct(driver, (vir_bytes) *buf, bytes, + *op == DEV_READ_S?CPF_WRITE:CPF_READ))<0) { + panic(__FILE__,"cpf_grant_magic of buffer failed\n", NO_NUM); + } + + break; + case MFS_DEV_GATHER: + case MFS_DEV_SCATTER: + /* Change to safe op. */ + *op = *op == MFS_DEV_GATHER ? DEV_GATHER_S : DEV_SCATTER_S; + + /* Grant access to my new i/o vector. */ + if((*gid = cpf_grant_direct(driver, (vir_bytes) new_iovec, + bytes * sizeof(iovec_t), + CPF_READ | CPF_WRITE)) < 0) { + panic(__FILE__, "cpf_grant_direct of vector failed", NO_NUM); + } + v = (iovec_t *) *buf; + /* Grant access to i/o buffers. */ + for(j = 0; j < bytes; j++) { + if(j >= NR_IOREQS) + panic(__FILE__, "vec too big", bytes); + new_iovec[j].iov_addr = gids[j] = + cpf_grant_direct(driver, (vir_bytes) v[j].iov_addr, + v[j].iov_size, + *op == DEV_GATHER_S ? CPF_WRITE : CPF_READ); + if(!GRANT_VALID(gids[j])) { + panic(__FILE__, "mfs: grant to iovec buf failed", + NO_NUM); + } + new_iovec[j].iov_size = v[j].iov_size; + (*vec_grants)++; + } - /* Not converted to a safe operation (because there is no - * copying involved in this operation). - */ - return 0; + /* Set user's vector to the new one. */ + *buf = new_iovec; + break; + } + + /* If we have converted to a safe operation, I/O + * endpoint becomes FS if it wasn't already. + */ + if(GRANT_VALID(*gid)) { + *io_ept = SELF_E; + return 1; + } + + /* Not converted to a safe operation (because there is no + * copying involved in this operation). + */ + return 0; } /*===========================================================================* @@ -166,14 +136,14 @@ cp_grant_id_t *gids; int gids_size; { /* Free resources (specifically, grants) allocated by safe_io_conversion(). */ - int j; + int j; - cpf_revoke(gid); + cpf_revoke(gid); - for(j = 0; j < gids_size; j++) - cpf_revoke(gids[j]); + for(j = 0; j < gids_size; j++) + cpf_revoke(gids[j]); - return; + return; } /*===========================================================================* @@ -208,7 +178,7 @@ int flags; /* special flags, like O_NONBLOCK */ /* See if driver is roughly valid. */ if (driver_e == NONE) { printf("MFS(%d) block_dev_io: no driver for dev %x\n", SELF_E, dev); - return EDSTDIED; + return(EDSTDIED); } /* The io vector copying relies on this I/O being for FS itself. */ @@ -381,9 +351,9 @@ message *mess_ptr; /* pointer to message for task */ mess_ptr->m_type, proc_e, mess_ptr->REP_ENDPT); - return EIO; + return(EIO); } - return OK; + return(OK); } diff --git a/servers/mfs/glo.h b/servers/mfs/glo.h index 10898c0b6..2dfd98fac 100644 --- a/servers/mfs/glo.h +++ b/servers/mfs/glo.h @@ -4,6 +4,8 @@ #define EXTERN #endif +#include + EXTERN off_t rdahedpos; /* position to read ahead */ EXTERN struct inode *rdahed_inode; /* pointer to inode to read ahead */ @@ -21,6 +23,7 @@ extern _PROTOTYPE (int (*fs_call_vec[]), (void) ); /* fs call table */ EXTERN message fs_m_in; EXTERN message fs_m_out; EXTERN int FS_STATE; +EXTERN vfs_ucred_t credentials; EXTERN uid_t caller_uid; EXTERN gid_t caller_gid; diff --git a/servers/mfs/inode.c b/servers/mfs/inode.c index 64bc090e9..4f044dcd2 100644 --- a/servers/mfs/inode.c +++ b/servers/mfs/inode.c @@ -11,25 +11,23 @@ * free_inode: mark an inode as available for a new file * update_times: update atime, ctime, and mtime * rw_inode: read a disk block and extract an inode, or corresp. write - * old_icopy: copy to/from in-core inode struct and disk inode (V1.x) - * new_icopy: copy to/from in-core inode struct and disk inode (V2.x) * dup_inode: indicate that someone else is using an inode table entry + * find_inode: retrieve pointer to inode in inode cache * - * Updates: - * 2007-06-01: jfdsmit@gmail.com added i_zsearch initialization */ #include "fs.h" #include "buf.h" #include "inode.h" #include "super.h" - #include -FORWARD _PROTOTYPE( void old_icopy, (struct inode *rip, d1_inode *dip, - int direction, int norm)); +FORWARD _PROTOTYPE( int addhash_inode, (struct inode *node) ); FORWARD _PROTOTYPE( void new_icopy, (struct inode *rip, d2_inode *dip, int direction, int norm)); +FORWARD _PROTOTYPE( void old_icopy, (struct inode *rip, d1_inode *dip, + int direction, int norm)); +FORWARD _PROTOTYPE( int unhash_inode, (struct inode *node) ); /*===========================================================================* @@ -37,80 +35,36 @@ FORWARD _PROTOTYPE( void new_icopy, (struct inode *rip, d2_inode *dip, *===========================================================================*/ PUBLIC int fs_putnode() { -/* Find the inode specified by the request message and decrease its counter. - */ +/* Find the inode specified by the request message and decrease its counter.*/ + struct inode *rip; int count; - /* Sanity check for the direct index */ - if (fs_m_in.REQ_INODE_INDEX >= 0 && - fs_m_in.REQ_INODE_INDEX < NR_INODES && - inode[fs_m_in.REQ_INODE_INDEX].i_num == fs_m_in.REQ_INODE_NR) { - rip = &inode[fs_m_in.REQ_INODE_INDEX]; - if(!rip) { - panic(__FILE__, "null rip", NO_NUM); - } - } - /* Otherwise find it */ - else { - if(!(rip = find_inode(fs_dev, fs_m_in.REQ_INODE_NR))) { - printf("FSput_inode: inode #%d dev: %d not found, req_nr: %d\n", - fs_m_in.REQ_INODE_NR, fs_dev, req_nr); - } - } + rip = find_inode(fs_dev, fs_m_in.REQ_INODE_NR); - if (!rip) - { - panic(__FILE__, "fs_putnode failed", NO_NUM); + if(!rip) { + printf("%s:%d put_inode: inode #%d dev: %d not found\n", __FILE__, + __LINE__, fs_m_in.REQ_INODE_NR, fs_dev); + panic(__FILE__, "fs_putnode failed", NO_NUM); } - count= fs_m_in.REQ_COUNT; - if (count <= 0) - { - printf("put_inode: bad value for count: %d\n", count); + count = fs_m_in.REQ_COUNT; + if (count <= 0) { + printf("%s:%d put_inode: bad value for count: %d\n", __FILE__, + __LINE__, count); panic(__FILE__, "fs_putnode failed", NO_NUM); - return EINVAL; - } - if (count > rip->i_count) - { - printf("put_inode: count too high: %d > %d\n", count, rip->i_count); + } else if(count > rip->i_count) { + printf("%s:%d put_inode: count too high: %d > %d\n", __FILE__, + __LINE__, count, rip->i_count); panic(__FILE__, "fs_putnode failed", NO_NUM); - return EINVAL; } + /* Decrease reference counter, but keep one reference; it will be consumed by + * put_inode(). */ rip->i_count -= count - 1; put_inode(rip); - return OK; -} - - -/*===========================================================================* - * fs_getnode * - *===========================================================================*/ -PUBLIC int fs_getnode() -{ -/* Increase the inode's counter specified in the request message - */ - struct inode *rip; - /* Get the inode */ - rip = get_inode(fs_dev, fs_m_in.REQ_INODE_NR); - - if (!rip) { - printf("FS: inode #%d couldn't be found\n", fs_m_in.REQ_INODE_NR); - return EINVAL; - } - - /* Transfer back the inode's details */ - fs_m_out.m_source = rip->i_dev; - fs_m_out.RES_INODE_NR = rip->i_num; - fs_m_out.RES_MODE = rip->i_mode; - fs_m_out.RES_FILE_SIZE = rip->i_size; - fs_m_out.RES_DEV = (Dev_t) rip->i_zone[0]; - fs_m_out.RES_UID = rip->i_uid; - fs_m_out.RES_GID = rip->i_gid; - - return OK; + return(OK); } @@ -149,9 +103,10 @@ PRIVATE int addhash_inode(struct inode *node) /* insert into hash table */ LIST_INSERT_HEAD(&hash_inodes[hashi], node, i_hash); - return OK; + return(OK); } + /*===========================================================================* * unhash_inode * *===========================================================================*/ @@ -159,9 +114,10 @@ PRIVATE int unhash_inode(struct inode *node) { /* remove from hash table */ LIST_REMOVE(node, i_hash); - return OK; + return(OK); } + /*===========================================================================* * get_inode * *===========================================================================*/ @@ -186,7 +142,7 @@ int numb; /* inode number (ANSI: may not be unshort) */ TAILQ_REMOVE(&unused_inodes, rip, i_unused); } ++rip->i_count; - return rip; + return(rip); } } @@ -195,7 +151,7 @@ int numb; /* inode number (ANSI: may not be unshort) */ /* Inode is not on the hash, get a free one */ if (TAILQ_EMPTY(&unused_inodes)) { err_code = ENFILE; - return NIL_INODE; + return(NIL_INODE); } rip = TAILQ_FIRST(&unused_inodes); @@ -213,10 +169,6 @@ int numb; /* inode number (ANSI: may not be unshort) */ if (dev != NO_DEV) rw_inode(rip, READING); /* get inode from disk */ rip->i_update = 0; /* all the times are initially up-to-date */ rip->i_zsearch = NO_ZONE; /* no zones searched for yet */ - if ((rip->i_mode & I_TYPE) == I_NAMED_PIPE) - rip->i_pipe = I_PIPE; - else - rip->i_pipe = NO_PIPE; rip->i_mountpoint= FALSE; /* Add to hash */ @@ -225,6 +177,7 @@ int numb; /* inode number (ANSI: may not be unshort) */ return(rip); } + /*===========================================================================* * find_inode * *===========================================================================*/ @@ -242,11 +195,11 @@ int numb; /* inode number (ANSI: may not be unshort) */ /* Search inode in the hash table */ LIST_FOREACH(rip, &hash_inodes[hashi], i_hash) { if (rip->i_count > 0 && rip->i_num == numb && rip->i_dev == dev) { - return rip; + return(rip); } } - return NIL_INODE; + return(NIL_INODE); } @@ -274,9 +227,7 @@ register struct inode *rip; /* pointer to inode to be released */ rip->i_dirt = DIRTY; free_inode(rip->i_dev, rip->i_num); } - else { - if (rip->i_pipe == I_PIPE) truncate_inode(rip, 0); - } + rip->i_mountpoint = FALSE; if (rip->i_dirt == DIRTY) rw_inode(rip, WRITING); @@ -285,8 +236,7 @@ register struct inode *rip; /* pointer to inode to be released */ unhash_inode(rip); rip->i_num = 0; TAILQ_INSERT_HEAD(&unused_inodes, rip, i_unused); - } - else { + } else { /* unused, put at the back of the LRU (cache it) */ TAILQ_INSERT_TAIL(&unused_inodes, rip, i_unused); } @@ -350,6 +300,7 @@ PUBLIC struct inode *alloc_inode(dev_t dev, mode_t bits) return(rip); } + /*===========================================================================* * wipe_inode * *===========================================================================*/ @@ -389,6 +340,7 @@ ino_t inumb; /* number of inode to be freed */ if (b < sp->s_isearch) sp->s_isearch = b; } + /*===========================================================================* * update_times * *===========================================================================*/ @@ -458,6 +410,7 @@ int rw_flag; /* READING or WRITING */ rip->i_dirt = CLEAN; } + /*===========================================================================* * old_icopy * *===========================================================================*/ @@ -466,7 +419,6 @@ register struct inode *rip; /* pointer to the in-core inode struct */ register d1_inode *dip; /* pointer to the d1_inode inode struct */ int direction; /* READING (from disk) or WRITING (to disk) */ int norm; /* TRUE = do not swap bytes; FALSE = swap */ - { /* The V1.x IBM disk, the V1.x 68000 disk, and the V2 disk (same for IBM and * 68000) all have different inode layouts. When an inode is read or written @@ -504,6 +456,7 @@ int norm; /* TRUE = do not swap bytes; FALSE = swap */ } } + /*===========================================================================* * new_icopy * *===========================================================================*/ @@ -512,7 +465,6 @@ register struct inode *rip; /* pointer to the in-core inode struct */ register d2_inode *dip; /* pointer to the d2_inode struct */ int direction; /* READING (from disk) or WRITING (to disk) */ int norm; /* TRUE = do not swap bytes; FALSE = swap */ - { /* Same as old_icopy, but to/from V2 disk layout. */ @@ -547,6 +499,7 @@ int norm; /* TRUE = do not swap bytes; FALSE = swap */ } } + /*===========================================================================* * dup_inode * *===========================================================================*/ @@ -559,3 +512,4 @@ struct inode *ip; /* The inode to be duplicated. */ ip->i_count++; } + diff --git a/servers/mfs/inode.h b/servers/mfs/inode.h index ba055dd77..2a22026e1 100644 --- a/servers/mfs/inode.h +++ b/servers/mfs/inode.h @@ -32,7 +32,6 @@ EXTERN struct inode { int i_nindirs; /* # indirect zones per indirect block */ struct super_block *i_sp; /* pointer to super block for inode's device */ char i_dirt; /* CLEAN or DIRTY */ - char i_pipe; /* set to I_PIPE if pipe */ bit_t i_zsearch; /* where to start search for new zones */ char i_mountpoint; /* true if mounted on */ @@ -57,7 +56,5 @@ EXTERN unsigned int inode_cache_miss; #define NIL_INODE (struct inode *) 0 /* indicates absence of inode slot */ /* Field values. Note that CLEAN and DIRTY are defined in "const.h" */ -#define NO_PIPE 0 /* i_pipe is NO_PIPE if inode is not a pipe */ -#define I_PIPE 1 /* i_pipe is I_PIPE if inode is a pipe */ #define NO_SEEK 0 /* i_seek = NO_SEEK if last op was not SEEK */ #define ISEEK 1 /* i_seek = ISEEK if last op was SEEK */ diff --git a/servers/mfs/link.c b/servers/mfs/link.c index 7f58f8ad6..5645d9426 100644 --- a/servers/mfs/link.c +++ b/servers/mfs/link.c @@ -1,27 +1,19 @@ - - #include "fs.h" #include #include #include #include - #include "buf.h" #include "inode.h" #include "super.h" - #include #define SAME 1000 -FORWARD _PROTOTYPE( int remove_dir_o, (struct inode *rldirp, struct inode *rip, - char dir_name[NAME_MAX]) ); -FORWARD _PROTOTYPE( int remove_dir_nocheck, (struct inode *rldirp, - struct inode *rip, char dir_name[NAME_MAX]) ); -FORWARD _PROTOTYPE( int unlink_file_o, (struct inode *dirp, struct inode *rip, - char file_name[NAME_MAX]) ); -FORWARD _PROTOTYPE( int unlink_file_nocheck, (struct inode *dirp, - struct inode *rip, char file_name[NAME_MAX]) ); +FORWARD _PROTOTYPE( int remove_dir, (struct inode *rldirp, + struct inode *rip, char dir_name[NAME_MAX]) ); +FORWARD _PROTOTYPE( int unlink_file, (struct inode *dirp, + struct inode *rip, char file_name[NAME_MAX]) ); FORWARD _PROTOTYPE( off_t nextblock, (off_t pos, int zonesize) ); FORWARD _PROTOTYPE( void zeroblock_half, (struct inode *i, off_t p, int l)); FORWARD _PROTOTYPE( void zeroblock_range, (struct inode *i, off_t p, off_t h)); @@ -32,9 +24,9 @@ FORWARD _PROTOTYPE( void zeroblock_range, (struct inode *i, off_t p, off_t h)); /*===========================================================================* - * fs_link_o * + * fs_link * *===========================================================================*/ -PUBLIC int fs_link_o() +PUBLIC int fs_link() { /* Perform the link(name1, name2) system call. */ @@ -44,150 +36,60 @@ PUBLIC int fs_link_o() struct inode *new_ip; phys_bytes len; - caller_uid = fs_m_in.REQ_UID; - caller_gid = fs_m_in.REQ_GID; - - len = MFS_MIN(fs_m_in.REQ_PATH_LEN, sizeof(string)); - /* Copy the link name's last component */ - r = sys_datacopy(FS_PROC_NR, (vir_bytes) fs_m_in.REQ_PATH, - SELF, (vir_bytes) string, (phys_bytes) len); - if (r != OK) return r; - MFS_NUL(string, len, sizeof(string)); - - /* Temporarily open the file. */ - if ( (rip = get_inode(fs_dev, fs_m_in.REQ_LINKED_FILE)) == NIL_INODE) { -printf("MFS(%d) get_inode by fs_link() failed\n", SELF_E); - return(EINVAL); - } - - /* Check to see if the file has maximum number of links already. */ - r = OK; - if (rip->i_nlinks >= (rip->i_sp->s_version == V1 ? CHAR_MAX : SHRT_MAX)) - r = EMLINK; - - /* Only super_user may link to directories. */ - if (r == OK) - if ( (rip->i_mode & I_TYPE) == I_DIRECTORY && caller_uid != SU_UID) - r = EPERM; - - /* If error with 'name', return the inode. */ - if (r != OK) { - put_inode(rip); - return(r); - } - - /* Temporarily open the last dir */ - if ( (ip = get_inode(fs_dev, fs_m_in.REQ_LINK_PARENT)) == NIL_INODE) { -printf("MFS(%d) get_inode by fs_link() failed\n", SELF_E); - return(EINVAL); - } - - /* If 'name2' exists in full (even if no space) set 'r' to error. */ - if (r == OK) { - if ( (new_ip = advance_o(&ip, string)) == NIL_INODE) { - r = err_code; - if (r == ENOENT) r = OK; - else if (r == EENTERMOUNT || r == ELEAVEMOUNT) r = EEXIST; - } else { - put_inode(new_ip); - r = EEXIST; - } - } - - /* Try to link. */ - if (r == OK) - r = search_dir(ip, string, &rip->i_num, ENTER); - - /* If success, register the linking. */ - if (r == OK) { - rip->i_nlinks++; - rip->i_update |= CTIME; - rip->i_dirt = DIRTY; - } - - /* Done. Release both inodes. */ - put_inode(rip); - put_inode(ip); - return(r); -} - - -/*===========================================================================* - * fs_link_s * - *===========================================================================*/ -PUBLIC int fs_link_s() -{ -/* Perform the link(name1, name2) system call. */ - - struct inode *ip, *rip; - register int r; - char string[NAME_MAX]; - struct inode *new_ip; - phys_bytes len; - -#if 0 - caller_uid = fs_m_in.REQ_UID; - caller_gid = fs_m_in.REQ_GID; -#endif - len = MFS_MIN(fs_m_in.REQ_PATH_LEN, sizeof(string)); /* Copy the link name's last component */ r = sys_safecopyfrom(FS_PROC_NR, fs_m_in.REQ_GRANT, 0, - (vir_bytes) string, (phys_bytes) len, D); + (vir_bytes) string, (phys_bytes) len, D); if (r != OK) return r; MFS_NUL(string, len, sizeof(string)); /* Temporarily open the file. */ - if ( (rip = get_inode(fs_dev, fs_m_in.REQ_LINKED_FILE)) == NIL_INODE) { -printf("MFS(%d) get_inode by fs_link() failed\n", SELF_E); - return(EINVAL); - } + if( (rip = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) + return(EINVAL); /* Check to see if the file has maximum number of links already. */ r = OK; - if (rip->i_nlinks >= (rip->i_sp->s_version == V1 ? CHAR_MAX : SHRT_MAX)) - r = EMLINK; + if(rip->i_nlinks >= (rip->i_sp->s_version == V1 ? CHAR_MAX : SHRT_MAX)) + r = EMLINK; /* Only super_user may link to directories. */ - if (r == OK) - if ( (rip->i_mode & I_TYPE) == I_DIRECTORY && caller_uid != SU_UID) - r = EPERM; + if(r == OK) + if( (rip->i_mode & I_TYPE) == I_DIRECTORY && caller_uid != SU_UID) + r = EPERM; /* If error with 'name', return the inode. */ if (r != OK) { - put_inode(rip); - return(r); + put_inode(rip); + return(r); } /* Temporarily open the last dir */ - if ( (ip = get_inode(fs_dev, fs_m_in.REQ_LINK_PARENT)) == NIL_INODE) { -printf("MFS(%d) get_inode by fs_link() failed\n", SELF_E); - return(EINVAL); - } + if( (ip = get_inode(fs_dev, fs_m_in.REQ_DIR_INO)) == NIL_INODE) + return(EINVAL); /* If 'name2' exists in full (even if no space) set 'r' to error. */ if (r == OK) { - if ( (new_ip = advance_nocheck(&ip, string)) == NIL_INODE) { - r = err_code; - if (r == ENOENT) r = OK; - else if (r == EENTERMOUNT || r == ELEAVEMOUNT) r = EEXIST; - } else { - put_inode(new_ip); - r = EEXIST; - } + if((new_ip = advance(ip, string, IGN_PERM)) == NIL_INODE) { + r = err_code; + if(r == ENOENT) + r = OK; + } else { + put_inode(new_ip); + r = EEXIST; + } } - + /* Try to link. */ - if (r == OK) - r = search_dir_nocheck(ip, string, &rip->i_num, ENTER); + if(r == OK) + r = search_dir(ip, string, &rip->i_num, ENTER, IGN_PERM); /* If success, register the linking. */ - if (r == OK) { - rip->i_nlinks++; - rip->i_update |= CTIME; - rip->i_dirt = DIRTY; + if(r == OK) { + rip->i_nlinks++; + rip->i_update |= CTIME; + rip->i_dirt = DIRTY; } - + /* Done. Release both inodes. */ put_inode(rip); put_inode(ip); @@ -196,78 +98,9 @@ printf("MFS(%d) get_inode by fs_link() failed\n", SELF_E); /*===========================================================================* - * fs_unlink_o * + * fs_unlink * *===========================================================================*/ -PUBLIC int fs_unlink_o() -{ -/* Perform the unlink(name) or rmdir(name) system call. The code for these two - * is almost the same. They differ only in some condition testing. Unlink() - * may be used by the superuser to do dangerous things; rmdir() may not. - */ - register struct inode *rip; - struct inode *rldirp; - int r; - char string[NAME_MAX]; - phys_bytes len; - - caller_uid = fs_m_in.REQ_UID; - caller_gid = fs_m_in.REQ_GID; - - /* Copy the last component */ - len = MFS_MIN(fs_m_in.REQ_PATH_LEN, sizeof(string)); - r = sys_datacopy(FS_PROC_NR, (vir_bytes) fs_m_in.REQ_PATH, - SELF, (vir_bytes) string, (phys_bytes) len); - if (r != OK) return r; - MFS_NUL(string, len, sizeof(string)); - - /* Temporarily open the dir. */ - if ( (rldirp = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) { - return(EINVAL); - } - - /* The last directory exists. Does the file also exist? */ - r = OK; - if ( (rip = advance_o(&rldirp, string)) == NIL_INODE) r = err_code; - - /* If error, return inode. */ - if (r != OK) { - printf("fs_unlink_o: advance_o failed: %d\n", r); - /* Mount point? */ - if (r == EENTERMOUNT || r == ELEAVEMOUNT) - r = EBUSY; - put_inode(rldirp); - return(r); - } - - /* Now test if the call is allowed, separately for unlink() and rmdir(). */ - if (fs_m_in.m_type == REQ_UNLINK_O) { - /* Only the su may unlink directories, but the su can unlink any dir.*/ - if ( (rip->i_mode & I_TYPE) == I_DIRECTORY - && caller_uid != SU_UID) r = EPERM; - - /* Don't unlink a file if it is the root of a mounted file system. */ - if (rip->i_num == ROOT_INODE) r = EBUSY; - - /* Actually try to unlink the file; fails if parent is mode 0 etc. */ - if (r == OK) r = unlink_file_o(rldirp, rip, string); - - } - else { - r = remove_dir_o(rldirp, rip, string); /* call is RMDIR */ - } - - /* If unlink was possible, it has been done, otherwise it has not. */ - put_inode(rip); - put_inode(rldirp); - if (r != OK) printf("fs_unlink_o: returning %d\n", r); - return(r); -} - - -/*===========================================================================* - * fs_unlink_s * - *===========================================================================*/ -PUBLIC int fs_unlink_s() +PUBLIC int fs_unlink() { /* Perform the unlink(name) or rmdir(name) system call. The code for these two * is almost the same. They differ only in some condition testing. Unlink() @@ -282,38 +115,40 @@ PUBLIC int fs_unlink_s() /* Copy the last component */ len = MFS_MIN(fs_m_in.REQ_PATH_LEN, sizeof(string)); r = sys_safecopyfrom(FS_PROC_NR, fs_m_in.REQ_GRANT, 0, - (vir_bytes) string, (phys_bytes) len, D); + (vir_bytes) string, (phys_bytes) len, D); if (r != OK) return r; MFS_NUL(string, len, sizeof(string)); /* Temporarily open the dir. */ - if ( (rldirp = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) { - return(EINVAL); - } + if( (rldirp = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) + return(EINVAL); /* The last directory exists. Does the file also exist? */ r = OK; - if ( (rip = advance_nocheck(&rldirp, string)) == NIL_INODE) r = err_code; + rip = advance(rldirp, string, IGN_PERM); + r = err_code; /* If error, return inode. */ - if (r != OK) { - /* Mount point? */ - if (r == EENTERMOUNT || r == ELEAVEMOUNT) - r = EBUSY; + if(r != OK) { + /* Mount point? */ + if (r == EENTERMOUNT || r == ELEAVEMOUNT) { + put_inode(rip); + r = EBUSY; + } put_inode(rldirp); return(r); } - + /* Now test if the call is allowed, separately for unlink() and rmdir(). */ - if (fs_m_in.m_type == REQ_UNLINK_S) { - /* Only the su may unlink directories, but the su can unlink any dir.*/ - if ( (rip->i_mode & I_TYPE) == I_DIRECTORY) r = EPERM; + if(fs_m_in.m_type == REQ_UNLINK) { + /* Only the su may unlink directories, but the su can unlink any + * dir.*/ + if( (rip->i_mode & I_TYPE) == I_DIRECTORY) r = EPERM; - /* Actually try to unlink the file; fails if parent is mode 0 etc. */ - if (r == OK) r = unlink_file_nocheck(rldirp, rip, string); - } - else { - r = remove_dir_nocheck(rldirp, rip, string); /* call is RMDIR */ + /* Actually try to unlink the file; fails if parent is mode 0 etc. */ + if (r == OK) r = unlink_file(rldirp, rip, string); + } else { + r = remove_dir(rldirp, rip, string); /* call is RMDIR */ } /* If unlink was possible, it has been done, otherwise it has not. */ @@ -323,11 +158,10 @@ PUBLIC int fs_unlink_s() } - /*===========================================================================* - * fs_rdlink_o * + * fs_rdlink * *===========================================================================*/ -PUBLIC int fs_rdlink_o() +PUBLIC int fs_rdlink() { block_t b; /* block containing link text */ struct buf *bp; /* buffer containing link text */ @@ -335,101 +169,38 @@ PUBLIC int fs_rdlink_o() register int r; /* return value */ int copylen; - copylen = fs_m_in.REQ_SLENGTH; - caller_uid = fs_m_in.REQ_UID; - caller_gid = fs_m_in.REQ_GID; - - /* Temporarily open the file. */ - if ( (rip = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) { - return(EINVAL); - } - - r = EACCES; - if (S_ISLNK(rip->i_mode) && (b = read_map(rip, (off_t) 0)) != NO_BLOCK) { - if (copylen <= 0) r = EINVAL; - else if (copylen < rip->i_size) r = ERANGE; - else { - if(rip->i_size < copylen) copylen = rip->i_size; - bp = get_block(rip->i_dev, b, NORMAL); - r = sys_vircopy(SELF, D, (vir_bytes) bp->b_data, - fs_m_in.REQ_WHO_E, D, (vir_bytes) fs_m_in.REQ_USER_ADDR, - (vir_bytes) copylen); - - if (r == OK) r = copylen; - put_block(bp, DIRECTORY_BLOCK); - } - } - - put_inode(rip); - return(r); -} - - -/*===========================================================================* - * fs_rdlink_s * - *===========================================================================*/ -PUBLIC int fs_rdlink_s() -{ - block_t b; /* block containing link text */ - struct buf *bp; /* buffer containing link text */ - register struct inode *rip; /* target inode */ - register int r; /* return value */ - int copylen; - - copylen = fs_m_in.REQ_SLENGTH; + copylen = fs_m_in.REQ_MEM_SIZE; if (copylen <= 0) return(EINVAL); /* Temporarily open the file. */ - if ( (rip = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) { - return(EINVAL); - } - + if( (rip = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) + return(EINVAL); - if (!S_ISLNK(rip->i_mode)) - r = EACCES; + if(!S_ISLNK(rip->i_mode)) + r = EACCES; else if ((b = read_map(rip, (off_t) 0)) == NO_BLOCK) r = EIO; else { /* Passed all checks */ - if (copylen > rip->i_size) - copylen = rip->i_size; - bp = get_block(rip->i_dev, b, NORMAL); - r = sys_safecopyto(FS_PROC_NR, fs_m_in.REQ_GRANT, 0, - (vir_bytes) bp->b_data, (vir_bytes) copylen, D); - - put_block(bp, DIRECTORY_BLOCK); - if (r == OK) - fs_m_out.RES_RDL_LENGTH = copylen; + if (copylen > rip->i_size) + copylen = rip->i_size; + bp = get_block(rip->i_dev, b, NORMAL); + r = sys_safecopyto(FS_PROC_NR, fs_m_in.REQ_GRANT, 0, + (vir_bytes) bp->b_data, (vir_bytes) copylen, D); + put_block(bp, DIRECTORY_BLOCK); + if (r == OK) + fs_m_out.RES_NBYTES = copylen; } - + put_inode(rip); return(r); } /*===========================================================================* - * fs_rdlink_so * - *===========================================================================*/ -PUBLIC int fs_rdlink_so() -{ -/* Legacy support: wrapper around new rdlink, returning the resulting number of - * bytes in the m_type field of the reply message instead. - */ - int r; - - r = fs_rdlink_s(); - - if (r == OK) - r = fs_m_out.RES_RDL_LENGTH; - - return(r); -} - - -/*===========================================================================* - * remove_dir_o * + * remove_dir * *===========================================================================*/ -PRIVATE int remove_dir_o(rldirp, rip, dir_name) +PRIVATE int remove_dir(rldirp, rip, dir_name) struct inode *rldirp; /* parent directory */ struct inode *rip; /* directory to be removed */ char dir_name[NAME_MAX]; /* name of directory to be removed */ @@ -444,98 +215,28 @@ char dir_name[NAME_MAX]; /* name of directory to be removed */ int r; /* search_dir checks that rip is a directory too. */ - if ((r = search_dir(rip, "", (ino_t *) 0, IS_EMPTY)) != OK) return r; + if ((r = search_dir(rip, "", (ino_t *) 0, IS_EMPTY, IGN_PERM)) != OK) + return r; if (strcmp(dir_name, ".") == 0 || strcmp(dir_name, "..") == 0)return(EINVAL); if (rip->i_num == ROOT_INODE) return(EBUSY); /* can't remove 'root' */ /* Actually try to unlink the file; fails if parent is mode 0 etc. */ - if ((r = unlink_file_o(rldirp, rip, dir_name)) != OK) return r; + if ((r = unlink_file(rldirp, rip, dir_name)) != OK) return r; /* Unlink . and .. from the dir. The super user can link and unlink any dir, * so don't make too many assumptions about them. */ - (void) unlink_file_o(rip, NIL_INODE, dot1); - (void) unlink_file_o(rip, NIL_INODE, dot2); + (void) unlink_file(rip, NIL_INODE, dot1); + (void) unlink_file(rip, NIL_INODE, dot2); return(OK); } /*===========================================================================* - * remove_dir_nocheck * - *===========================================================================*/ -PRIVATE int remove_dir_nocheck(rldirp, rip, dir_name) -struct inode *rldirp; /* parent directory */ -struct inode *rip; /* directory to be removed */ -char dir_name[NAME_MAX]; /* name of directory to be removed */ -{ - /* A directory file has to be removed. Five conditions have to met: - * - The file must be a directory - * - The directory must be empty (except for . and ..) - * - The final component of the path must not be . or .. - * - The directory must not be the root of a mounted file system (VFS) - * - The directory must not be anybody's root/working directory (VFS) - */ - int r; - - /* search_dir checks that rip is a directory too. */ - if ((r = search_dir_nocheck(rip, "", (ino_t *) 0, IS_EMPTY)) != OK) return r; - - if (strcmp(dir_name, ".") == 0 || strcmp(dir_name, "..") == 0)return(EINVAL); - if (rip->i_num == ROOT_INODE) return(EBUSY); /* can't remove 'root' */ - - /* Actually try to unlink the file; fails if parent is mode 0 etc. */ - if ((r = unlink_file_nocheck(rldirp, rip, dir_name)) != OK) return r; - - /* Unlink . and .. from the dir. The super user can link and unlink any dir, - * so don't make too many assumptions about them. - */ - (void) unlink_file_nocheck(rip, NIL_INODE, dot1); - (void) unlink_file_nocheck(rip, NIL_INODE, dot2); - return(OK); -} - - -/*===========================================================================* - * unlink_file_o * - *===========================================================================*/ -PRIVATE int unlink_file_o(dirp, rip, file_name) -struct inode *dirp; /* parent directory of file */ -struct inode *rip; /* inode of file, may be NIL_INODE too. */ -char file_name[NAME_MAX]; /* name of file to be removed */ -{ -/* Unlink 'file_name'; rip must be the inode of 'file_name' or NIL_INODE. */ - - ino_t numb; /* inode number */ - int r; - - /* If rip is not NIL_INODE, it is used to get faster access to the inode. */ - if (rip == NIL_INODE) { - /* Search for file in directory and try to get its inode. */ - err_code = search_dir(dirp, file_name, &numb, LOOK_UP); - if (err_code == OK) rip = get_inode(dirp->i_dev, (int) numb); - if (err_code != OK || rip == NIL_INODE) return(err_code); - } else { - dup_inode(rip); /* inode will be returned with put_inode */ - } - - r = search_dir(dirp, file_name, (ino_t *) 0, DELETE); - - if (r == OK) { - rip->i_nlinks--; /* entry deleted from parent's dir */ - rip->i_update |= CTIME; - rip->i_dirt = DIRTY; - } - - put_inode(rip); - return(r); -} - - -/*===========================================================================* - * unlink_file_nocheck * + * unlink_file * *===========================================================================*/ -PRIVATE int unlink_file_nocheck(dirp, rip, file_name) +PRIVATE int unlink_file(dirp, rip, file_name) struct inode *dirp; /* parent directory of file */ struct inode *rip; /* inode of file, may be NIL_INODE too. */ char file_name[NAME_MAX]; /* name of file to be removed */ @@ -548,14 +249,14 @@ char file_name[NAME_MAX]; /* name of file to be removed */ /* If rip is not NIL_INODE, it is used to get faster access to the inode. */ if (rip == NIL_INODE) { /* Search for file in directory and try to get its inode. */ - err_code = search_dir_nocheck(dirp, file_name, &numb, LOOK_UP); + err_code = search_dir(dirp, file_name, &numb, LOOK_UP, IGN_PERM); if (err_code == OK) rip = get_inode(dirp->i_dev, (int) numb); if (err_code != OK || rip == NIL_INODE) return(err_code); } else { dup_inode(rip); /* inode will be returned with put_inode */ } - r = search_dir_nocheck(dirp, file_name, (ino_t *) 0, DELETE); + r = search_dir(dirp, file_name, (ino_t *) 0, DELETE, IGN_PERM); if (r == OK) { rip->i_nlinks--; /* entry deleted from parent's dir */ @@ -569,216 +270,9 @@ char file_name[NAME_MAX]; /* name of file to be removed */ /*===========================================================================* - * fs_rename_o * + * fs_rename * *===========================================================================*/ -PUBLIC int fs_rename_o() -{ -/* Perform the rename(name1, name2) system call. */ - struct inode *old_dirp, *old_ip; /* ptrs to old dir, file inodes */ - struct inode *new_dirp, *new_ip; /* ptrs to new dir, file inodes */ - struct inode *new_superdirp, *next_new_superdirp; - int r = OK; /* error flag; initially no error */ - int odir, ndir; /* TRUE iff {old|new} file is dir */ - int same_pdir; /* TRUE iff parent dirs are the same */ - char old_name[NAME_MAX], new_name[NAME_MAX]; - ino_t numb; - phys_bytes len; - int r1; - - caller_uid = fs_m_in.REQ_UID; - caller_gid = fs_m_in.REQ_GID; - - /* Copy the last component of the old name */ - len = MFS_MIN(fs_m_in.REQ_PATH_LEN, sizeof(old_name)); - r = sys_datacopy(FS_PROC_NR, (vir_bytes) fs_m_in.REQ_PATH, - SELF, (vir_bytes) old_name, (phys_bytes) len); - if (r != OK) return r; - MFS_NUL(old_name, len, sizeof(old_name)); - - /* Copy the last component of the new name */ - len = MFS_MIN(fs_m_in.REQ_SLENGTH, sizeof(new_name)); - r = sys_datacopy(FS_PROC_NR, (vir_bytes) fs_m_in.REQ_USER_ADDR, - SELF, (vir_bytes) new_name, (phys_bytes) len); - if (r != OK) return r; - MFS_NUL(new_name, len, sizeof(new_name)); - - /* Get old dir inode */ - if ( (old_dirp = get_inode(fs_dev, fs_m_in.REQ_OLD_DIR)) == NIL_INODE) - return(err_code); - - if ( (old_ip = advance_o(&old_dirp, old_name)) == NIL_INODE) { - r = err_code; - if (r == EENTERMOUNT) r = EBUSY; /* should this fail at all? */ - else if (r == ELEAVEMOUNT) r = EINVAL; /* rename on dot-dot */ - } - - /* Get new dir inode */ - if ( (new_dirp = get_inode(fs_dev, fs_m_in.REQ_NEW_DIR)) == NIL_INODE) - r = err_code; - new_ip = advance_o(&new_dirp, new_name); /* not required to exist */ - - /* However, if the check failed because the file does exist, don't continue. - * Note that ELEAVEMOUNT is covered by the dot-dot check later. - */ - if (new_ip == NIL_INODE && err_code == EENTERMOUNT) - r = EBUSY; - - if (old_ip != NIL_INODE) - odir = ((old_ip->i_mode & I_TYPE) == I_DIRECTORY); /* TRUE iff dir */ - - /* If it is ok, check for a variety of possible errors. */ - if (r == OK) { - same_pdir = (old_dirp == new_dirp); - - /* The old inode must not be a superdirectory of the new last dir. */ - if (odir && !same_pdir) { - dup_inode(new_superdirp = new_dirp); - while (TRUE) { /* may hang in a file system loop */ - if (new_superdirp == old_ip) { - put_inode(new_superdirp); - r = EINVAL; - break; - } - next_new_superdirp = advance_o(&new_superdirp, dot2); - put_inode(new_superdirp); - /* - if (next_new_superdirp == new_superdirp) { - put_inode(new_superdirp); - break; - } - */ - if (err_code == ELEAVEMOUNT) { - /* imitate that we are back at the root, - * cross device checked already on VFS */ - /*next_new_superdirp = new_superdirp;*/ - err_code = OK; - break; - } - new_superdirp = next_new_superdirp; - if (new_superdirp == NIL_INODE) { - /* Missing ".." entry. Assume the worst. */ - r = EINVAL; - break; - } - } - /*put_inode(new_superdirp);*/ - } - - /* The old or new name must not be . or .. */ - if (strcmp(old_name, ".")==0 || strcmp(old_name, "..")==0 || - strcmp(new_name, ".")==0 || strcmp(new_name, "..")==0) { - r = EINVAL; - } - /* Both parent directories must be on the same device. - if (old_dirp->i_dev != new_dirp->i_dev) r = EXDEV; */ - - /* Parent dirs must be writable, searchable and on a writable device */ - if ((r1 = forbidden(old_dirp, W_BIT | X_BIT)) != OK || - (r1 = forbidden(new_dirp, W_BIT | X_BIT)) != OK) { - r = r1; - } - - /* Some tests apply only if the new path exists. */ - if (new_ip == NIL_INODE) { - /* don't rename a file with a file system mounted on it. - if (old_ip->i_dev != old_dirp->i_dev) r = EXDEV;*/ - if (odir && new_dirp->i_nlinks >= - (new_dirp->i_sp->s_version == V1 ? CHAR_MAX : SHRT_MAX) && - !same_pdir && r == OK) { - r = EMLINK; - } - } - else { - if (old_ip == new_ip) { - r = SAME; /* old=new */ - } - - /* has the old file or new file a file system mounted on it? - if (old_ip->i_dev != new_ip->i_dev) r = EXDEV; - */ - - ndir = ((new_ip->i_mode & I_TYPE) == I_DIRECTORY); /* dir ? */ - if (odir == TRUE && ndir == FALSE) { - r = ENOTDIR; - } - if (odir == FALSE && ndir == TRUE) { - r = EISDIR; - } - } - } - - /* If a process has another root directory than the system root, we might - * "accidently" be moving it's working directory to a place where it's - * root directory isn't a super directory of it anymore. This can make - * the function chroot useless. If chroot will be used often we should - * probably check for it here. - */ - - /* The rename will probably work. Only two things can go wrong now: - * 1. being unable to remove the new file. (when new file already exists) - * 2. being unable to make the new directory entry. (new file doesn't exists) - * [directory has to grow by one block and cannot because the disk - * is completely full]. - */ - if (r == OK) { - if (new_ip != NIL_INODE) { - /* There is already an entry for 'new'. Try to remove it. */ - if (odir) - r = remove_dir_o(new_dirp, new_ip, new_name); - else - r = unlink_file_o(new_dirp, new_ip, new_name); - } - /* if r is OK, the rename will succeed, while there is now an - * unused entry in the new parent directory. - */ - } - - if (r == OK) { - /* If the new name will be in the same parent directory as the old one, - * first remove the old name to free an entry for the new name, - * otherwise first try to create the new name entry to make sure - * the rename will succeed. - */ - numb = old_ip->i_num; /* inode number of old file */ - - if (same_pdir) { - r = search_dir(old_dirp, old_name, (ino_t *) 0, DELETE); - /* shouldn't go wrong. */ - if (r==OK) (void) search_dir(old_dirp, new_name, &numb, ENTER); - } else { - r = search_dir(new_dirp, new_name, &numb, ENTER); - if (r == OK) - (void) search_dir(old_dirp, old_name, (ino_t *) 0, DELETE); - } - } - /* If r is OK, the ctime and mtime of old_dirp and new_dirp have been marked - * for update in search_dir. - */ - - if (r == OK && odir && !same_pdir) { - /* Update the .. entry in the directory (still points to old_dirp). */ - numb = new_dirp->i_num; - (void) unlink_file_o(old_ip, NIL_INODE, dot2); - if (search_dir(old_ip, dot2, &numb, ENTER) == OK) { - /* New link created. */ - new_dirp->i_nlinks++; - new_dirp->i_dirt = DIRTY; - } - } - - /* Release the inodes. */ - put_inode(old_dirp); - put_inode(old_ip); - put_inode(new_dirp); - put_inode(new_ip); - return(r == SAME ? OK : r); -} - - -/*===========================================================================* - * fs_rename_s * - *===========================================================================*/ -PUBLIC int fs_rename_s() +PUBLIC int fs_rename() { /* Perform the rename(name1, name2) system call. */ struct inode *old_dirp, *old_ip; /* ptrs to old dir, file inodes */ @@ -795,131 +289,113 @@ PUBLIC int fs_rename_s() /* Copy the last component of the old name */ len = MFS_MIN(fs_m_in.REQ_REN_LEN_OLD, sizeof(old_name)); r = sys_safecopyfrom(FS_PROC_NR, fs_m_in.REQ_REN_GRANT_OLD, 0, - (vir_bytes) old_name, (phys_bytes) len, D); + (vir_bytes) old_name, (phys_bytes) len, D); if (r != OK) return r; MFS_NUL(old_name, len, sizeof(old_name)); /* Copy the last component of the new name */ len = MFS_MIN(fs_m_in.REQ_REN_LEN_NEW, sizeof(new_name)); r = sys_safecopyfrom(FS_PROC_NR, fs_m_in.REQ_REN_GRANT_NEW, 0, - (vir_bytes) new_name, (phys_bytes) len, D); + (vir_bytes) new_name, (phys_bytes) len, D); if (r != OK) return r; MFS_NUL(new_name, len, sizeof(new_name)); /* Get old dir inode */ - if ( (old_dirp = get_inode(fs_dev, fs_m_in.REQ_REN_OLD_DIR)) == NIL_INODE) - return(err_code); + if( (old_dirp = get_inode(fs_dev, fs_m_in.REQ_REN_OLD_DIR)) == NIL_INODE) + return(err_code); - if ( (old_ip = advance_nocheck(&old_dirp, old_name)) == NIL_INODE) { - r = err_code; - if (r == EENTERMOUNT) r = EBUSY; /* should this fail at all? */ + old_ip = advance(old_dirp, old_name, IGN_PERM); + r = err_code; + + if (r == EENTERMOUNT || r == ELEAVEMOUNT) { + put_inode(old_ip); + if (r == EENTERMOUNT) r = EXDEV; /* should this fail at all? */ else if (r == ELEAVEMOUNT) r = EINVAL; /* rename on dot-dot */ } /* Get new dir inode */ - if ( (new_dirp = get_inode(fs_dev, fs_m_in.REQ_REN_NEW_DIR)) == NIL_INODE) - r = err_code; - new_ip = advance_nocheck(&new_dirp, new_name); /* not required to exist */ + if( (new_dirp = get_inode(fs_dev, fs_m_in.REQ_REN_NEW_DIR)) == NIL_INODE) + r = err_code; + new_ip = advance(new_dirp, new_name, IGN_PERM); /* not required to exist */ /* However, if the check failed because the file does exist, don't continue. - * Note that ELEAVEMOUNT is covered by the dot-dot check later. - */ - if (new_ip == NIL_INODE && err_code == EENTERMOUNT) - r = EBUSY; - - if (old_ip != NIL_INODE) - odir = ((old_ip->i_mode & I_TYPE) == I_DIRECTORY); /* TRUE iff dir */ + * Note that ELEAVEMOUNT is covered by the dot-dot check later. */ + if(err_code == EENTERMOUNT) { + put_inode(new_ip); + r = EBUSY; + } + + if(old_ip != NIL_INODE) + odir = ((old_ip->i_mode & I_TYPE) == I_DIRECTORY); /* TRUE iff dir */ /* If it is ok, check for a variety of possible errors. */ - if (r == OK) { + if(r == OK) { same_pdir = (old_dirp == new_dirp); /* The old inode must not be a superdirectory of the new last dir. */ if (odir && !same_pdir) { dup_inode(new_superdirp = new_dirp); - while (TRUE) { /* may hang in a file system loop */ + while (TRUE) { /* may hang in a file system loop */ if (new_superdirp == old_ip) { put_inode(new_superdirp); r = EINVAL; break; } -#if 0 -printf("fs_rename_s: new_superdirp: %d on 0x%x\n", - new_superdirp->i_num, new_superdirp->i_dev); -#endif - - next_new_superdirp = advance_nocheck(&new_superdirp, - dot2); - -#if 0 -printf("fs_rename_s: next_new_superdirp: %d on 0x%x\n", - next_new_superdirp->i_num, next_new_superdirp->i_dev); -#endif + next_new_superdirp = advance(new_superdirp, dot2, + IGN_PERM); put_inode(new_superdirp); - if (next_new_superdirp == new_superdirp) { + if(next_new_superdirp == new_superdirp) { put_inode(new_superdirp); break; } - if (err_code == ELEAVEMOUNT) { + if(err_code == ELEAVEMOUNT) { /* imitate that we are back at the root, * cross device checked already on VFS */ - /*next_new_superdirp = new_superdirp;*/ + put_inode(next_new_superdirp); err_code = OK; break; } new_superdirp = next_new_superdirp; - if (new_superdirp == NIL_INODE) { + if(new_superdirp == NIL_INODE) { /* Missing ".." entry. Assume the worst. */ r = EINVAL; break; } } } - + /* The old or new name must not be . or .. */ - if (strcmp(old_name, ".")==0 || strcmp(old_name, "..")==0 || - strcmp(new_name, ".")==0 || strcmp(new_name, "..")==0) { + if(strcmp(old_name, ".") == 0 || strcmp(old_name, "..") == 0 || + strcmp(new_name, ".") == 0 || strcmp(new_name, "..") == 0) { r = EINVAL; } /* Both parent directories must be on the same device. - if (old_dirp->i_dev != new_dirp->i_dev) r = EXDEV; */ + if(old_dirp->i_dev != new_dirp->i_dev) r = EXDEV; */ /* Some tests apply only if the new path exists. */ - if (new_ip == NIL_INODE) { + if(new_ip == NIL_INODE) { /* don't rename a file with a file system mounted on it. if (old_ip->i_dev != old_dirp->i_dev) r = EXDEV;*/ - if (odir && new_dirp->i_nlinks >= - (new_dirp->i_sp->s_version == V1 ? CHAR_MAX : SHRT_MAX) && - !same_pdir && r == OK) { + if(odir && new_dirp->i_nlinks >= + (new_dirp->i_sp->s_version == V1 ? CHAR_MAX : SHRT_MAX) && + !same_pdir && r == OK) { r = EMLINK; } - } - else { - if (old_ip == new_ip) { - r = SAME; /* old=new */ - } + } else { + if(old_ip == new_ip) r = SAME; /* old=new */ - /* has the old file or new file a file system mounted on it? - if (old_ip->i_dev != new_ip->i_dev) r = EXDEV; - */ - - ndir = ((new_ip->i_mode & I_TYPE) == I_DIRECTORY); /* dir ? */ - if (odir == TRUE && ndir == FALSE) { - r = ENOTDIR; - } - if (odir == FALSE && ndir == TRUE) { - r = EISDIR; - } + ndir = ((new_ip->i_mode & I_TYPE) == I_DIRECTORY);/* dir ? */ + if(odir == TRUE && ndir == FALSE) r = ENOTDIR; + if(odir == FALSE && ndir == TRUE) r = EISDIR; } } - + /* If a process has another root directory than the system root, we might * "accidently" be moving it's working directory to a place where it's * root directory isn't a super directory of it anymore. This can make * the function chroot useless. If chroot will be used often we should - * probably check for it here. - */ + * probably check for it here. */ /* The rename will probably work. Only two things can go wrong now: * 1. being unable to remove the new file. (when new file already exists) @@ -927,48 +403,46 @@ printf("fs_rename_s: next_new_superdirp: %d on 0x%x\n", * [directory has to grow by one block and cannot because the disk * is completely full]. */ - if (r == OK) { - if (new_ip != NIL_INODE) { - /* There is already an entry for 'new'. Try to remove it. */ - if (odir) - r = remove_dir_nocheck(new_dirp, new_ip, new_name); + if(r == OK) { + if(new_ip != NIL_INODE) { + /* There is already an entry for 'new'. Try to remove it. */ + if(odir) + r = remove_dir(new_dirp, new_ip, new_name); else - r = unlink_file_nocheck(new_dirp, new_ip, new_name); + r = unlink_file(new_dirp, new_ip, new_name); } /* if r is OK, the rename will succeed, while there is now an - * unused entry in the new parent directory. - */ + * unused entry in the new parent directory. */ } - if (r == OK) { - /* If the new name will be in the same parent directory as the old one, - * first remove the old name to free an entry for the new name, - * otherwise first try to create the new name entry to make sure - * the rename will succeed. - */ + if(r == OK) { + /* If the new name will be in the same parent directory as the old + * one, first remove the old name to free an entry for the new name, + * otherwise first try to create the new name entry to make sure + * the rename will succeed. + */ numb = old_ip->i_num; /* inode number of old file */ - - if (same_pdir) { - r = search_dir_nocheck(old_dirp, old_name, (ino_t *) 0, DELETE); + + if(same_pdir) { + r = search_dir(old_dirp,old_name,(ino_t *) 0,DELETE,IGN_PERM); /* shouldn't go wrong. */ - if (r==OK) (void) search_dir_nocheck(old_dirp, new_name, - &numb, ENTER); + if(r == OK) + search_dir(old_dirp, new_name, &numb, ENTER, IGN_PERM); } else { - r = search_dir_nocheck(new_dirp, new_name, &numb, ENTER); - if (r == OK) - (void) search_dir_nocheck(old_dirp, old_name, - (ino_t *) 0, DELETE); + r = search_dir(new_dirp, new_name, &numb, ENTER, IGN_PERM); + if(r == OK) + search_dir(old_dirp, old_name, (ino_t *) 0, DELETE, + IGN_PERM); } } /* If r is OK, the ctime and mtime of old_dirp and new_dirp have been marked - * for update in search_dir. - */ + * for update in search_dir. */ - if (r == OK && odir && !same_pdir) { - /* Update the .. entry in the directory (still points to old_dirp). */ + if(r == OK && odir && !same_pdir) { + /* Update the .. entry in the directory (still points to old_dirp).*/ numb = new_dirp->i_num; - (void) unlink_file_nocheck(old_ip, NIL_INODE, dot2); - if (search_dir_nocheck(old_ip, dot2, &numb, ENTER) == OK) { + (void) unlink_file(old_ip, NIL_INODE, dot2); + if(search_dir(old_ip, dot2, &numb, ENTER, IGN_PERM) == OK) { /* New link created. */ new_dirp->i_nlinks++; new_dirp->i_dirt = DIRTY; @@ -984,33 +458,6 @@ printf("fs_rename_s: next_new_superdirp: %d on 0x%x\n", } -/*===========================================================================* - * fs_trunc * - *===========================================================================*/ -PUBLIC int fs_trunc() -{ - struct inode *rip; - int r = OK; - - caller_uid = fs_m_in.REQ_UID; - caller_gid = fs_m_in.REQ_GID; - - /* Temporarily open the file. */ - if ( (rip = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) { -printf("MFS(%d) get_inode by fs_chmod() failed\n", SELF_E); - return(EINVAL); - } - - if ( (rip->i_mode & I_TYPE) != I_REGULAR) - r = EINVAL; - else - r = truncate_inode(rip, fs_m_in.REQ_LENGTH); - - put_inode(rip); - - return r; -} - /*===========================================================================* * fs_ftrunc * *===========================================================================*/ @@ -1020,26 +467,19 @@ PUBLIC int fs_ftrunc(void) off_t start, end; int r; - if ( (rip = find_inode(fs_dev, fs_m_in.REQ_FD_INODE_NR)) - == NIL_INODE) { - printf("FSfreesp: couldn't find inode %d\n", - fs_m_in.REQ_FD_INODE_NR); - return EINVAL; - } + if( (rip = find_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) + return(EINVAL); - start = fs_m_in.REQ_FD_START; - end = fs_m_in.REQ_FD_END; + start = fs_m_in.REQ_TRC_START_LO; + end = fs_m_in.REQ_TRC_END_LO; - if (end == 0) { - r = truncate_inode(rip, start); - } - else { - r = freesp_inode(rip, start, end); - } + if (end == 0) + r = truncate_inode(rip, start); + else + r = freesp_inode(rip, start, end); - return r; + return(r); } - /*===========================================================================* @@ -1058,40 +498,31 @@ off_t newsize; /* inode must become this size */ * writing is done. */ zone_t zone_size; - int scale, file_type, waspipe; + int scale, file_type; dev_t dev; file_type = rip->i_mode & I_TYPE; /* check to see if file is special */ if (file_type == I_CHAR_SPECIAL || file_type == I_BLOCK_SPECIAL) - return EINVAL; + return(EINVAL); if(newsize > rip->i_sp->s_max_size) /* don't let inode grow too big */ - return EFBIG; + return(EFBIG); dev = rip->i_dev; /* device on which inode resides */ scale = rip->i_sp->s_log_zone_size; zone_size = (zone_t) rip->i_sp->s_block_size << scale; - /* Pipes can shrink, so adjust size to make sure all zones are removed. */ - waspipe = rip->i_pipe == I_PIPE; /* TRUE if this was a pipe */ - if (waspipe) { - if(newsize != 0) - return EINVAL; /* Only truncate pipes to 0. */ - rip->i_size = PIPE_SIZE(rip->i_sp->s_block_size); - } - /* Free the actual space if relevant. */ - if(newsize < rip->i_size) - freesp_inode(rip, newsize, rip->i_size); + if(newsize < rip->i_size) freesp_inode(rip, newsize, rip->i_size); /* Next correct the inode size. */ - if(!waspipe) rip->i_size = newsize; - else wipe_inode(rip); /* Pipes can only be truncated to 0. */ + rip->i_size = newsize; rip->i_update |= CTIME | MTIME; rip->i_dirt = DIRTY; - return OK; + return(OK); } + /*===========================================================================* * freesp_inode * *===========================================================================*/ @@ -1110,45 +541,47 @@ off_t start, end; /* range of bytes to free (end uninclusive) */ * implement the ftruncate() and truncate() system calls) and the F_FREESP * fcntl(). */ - off_t p, e; - int zone_size, dev; - - if(end > rip->i_size) /* freeing beyond end makes no sense */ - end = rip->i_size; - if(end <= start) /* end is uninclusive, so starti_sp->s_block_size << rip->i_sp->s_log_zone_size; - dev = rip->i_dev; /* device on which inode resides */ - - /* If freeing doesn't cross a zone boundary, then we may only zero - * a range of the block. - */ - if(start/zone_size == (end-1)/zone_size) { - zeroblock_range(rip, start, end-start); - } else { - /* First zero unused part of partly used blocks. */ - if(start%zone_size) - zeroblock_half(rip, start, LAST_HALF); - if(end%zone_size && end < rip->i_size) - zeroblock_half(rip, end, FIRST_HALF); - } + off_t p, e; + int zone_size, dev; - /* Now completely free the completely unused blocks. - * write_map() will free unused (double) indirect - * blocks too. Converting the range to zone numbers avoids - * overflow on p when doing e.g. 'p += zone_size'. - */ - e = end/zone_size; - if(end == rip->i_size && (end % zone_size)) e++; - for(p = nextblock(start, zone_size)/zone_size; p < e; p ++) - write_map(rip, p*zone_size, NO_ZONE, WMAP_FREE); + if(end > rip->i_size) /* freeing beyond end makes no sense */ + end = rip->i_size; + if(end <= start) /* end is uninclusive, so starti_update |= CTIME | MTIME; - rip->i_dirt = DIRTY; + zone_size = rip->i_sp->s_block_size << rip->i_sp->s_log_zone_size; + dev = rip->i_dev; /* device on which inode resides */ - return OK; + /* If freeing doesn't cross a zone boundary, then we may only zero + * a range of the block. + */ + if(start/zone_size == (end-1)/zone_size) { + zeroblock_range(rip, start, end-start); + } else { + /* First zero unused part of partly used blocks. */ + if(start%zone_size) + zeroblock_half(rip, start, LAST_HALF); + if(end%zone_size && end < rip->i_size) + zeroblock_half(rip, end, FIRST_HALF); + } + + /* Now completely free the completely unused blocks. + * write_map() will free unused (double) indirect + * blocks too. Converting the range to zone numbers avoids + * overflow on p when doing e.g. 'p += zone_size'. + */ + e = end/zone_size; + if(end == rip->i_size && (end % zone_size)) e++; + for(p = nextblock(start, zone_size)/zone_size; p < e; p ++) + write_map(rip, p*zone_size, NO_ZONE, WMAP_FREE); + + rip->i_update |= CTIME | MTIME; + rip->i_dirt = DIRTY; + + return(OK); } + /*===========================================================================* * nextblock * *===========================================================================*/ @@ -1160,12 +593,13 @@ int zone_size; * (unless this is the first position in the current block). * This can be done in one expression, but that can overflow pos. */ - off_t p; - p = (pos/zone_size)*zone_size; - if((pos % zone_size)) p += zone_size; /* Round up. */ - return p; + off_t p; + p = (pos/zone_size)*zone_size; + if((pos % zone_size)) p += zone_size; /* Round up. */ + return(p); } + /*===========================================================================* * zeroblock_half * *===========================================================================*/ @@ -1180,22 +614,23 @@ int half; * FIRST_HALF: 0..pos-1 will be zeroed * LAST_HALF: pos..blocksize-1 will be zeroed */ - int offset, len; + int offset, len; - /* Offset of zeroing boundary. */ - offset = pos % rip->i_sp->s_block_size; + /* Offset of zeroing boundary. */ + offset = pos % rip->i_sp->s_block_size; - if(half == LAST_HALF) { - len = rip->i_sp->s_block_size - offset; - } else { - len = offset; - pos -= offset; - offset = 0; - } + if(half == LAST_HALF) { + len = rip->i_sp->s_block_size - offset; + } else { + len = offset; + pos -= offset; + offset = 0; + } - zeroblock_range(rip, pos, len); + zeroblock_range(rip, pos, len); } + /*===========================================================================* * zeroblock_range * *===========================================================================*/ @@ -1209,20 +644,19 @@ off_t len; * FIRST_HALF of LAST_HALF. * */ - block_t b; - struct buf *bp; - off_t offset; - - if(!len) return; /* no zeroing to be done. */ - if( (b = read_map(rip, pos)) == NO_BLOCK) return; - if( (bp = get_block(rip->i_dev, b, NORMAL)) == NIL_BUF) - panic(__FILE__, "zeroblock_range: no block", NO_NUM); - offset = pos % rip->i_sp->s_block_size; - if(offset + len > rip->i_sp->s_block_size) - panic(__FILE__, "zeroblock_range: len too long", len); - memset(bp->b_data + offset, 0, len); - bp->b_dirt = DIRTY; - put_block(bp, FULL_DATA_BLOCK); + block_t b; + struct buf *bp; + off_t offset; + + if(!len) return; /* no zeroing to be done. */ + if( (b = read_map(rip, pos)) == NO_BLOCK) return; + if( (bp = get_block(rip->i_dev, b, NORMAL)) == NIL_BUF) + panic(__FILE__, "zeroblock_range: no block", NO_NUM); + offset = pos % rip->i_sp->s_block_size; + if(offset + len > rip->i_sp->s_block_size) + panic(__FILE__, "zeroblock_range: len too long", len); + memset(bp->b_data + offset, 0, len); + bp->b_dirt = DIRTY; + put_block(bp, FULL_DATA_BLOCK); } - diff --git a/servers/mfs/main.c b/servers/mfs/main.c index 5fba16e6c..38a5c12bc 100644 --- a/servers/mfs/main.c +++ b/servers/mfs/main.c @@ -1,9 +1,7 @@ - #include "inc.h" #include #include #include - #include #include "fs.h" #include "buf.h" @@ -14,9 +12,9 @@ /* Declare some local functions. */ FORWARD _PROTOTYPE(void init_server, (void) ); FORWARD _PROTOTYPE(void get_work, (message *m_in) ); - FORWARD _PROTOTYPE(void cch_check, (void) ); + /*===========================================================================* * main * *===========================================================================*/ @@ -35,114 +33,113 @@ PUBLIC int main(int argc, char *argv[]) fs_m_in.m_type = FS_READY; if (send(FS_PROC_NR, &fs_m_in) != OK) { - printf("MFS(%d): Error sending login to VFS\n", SELF_E); - return -1; + printf("MFS(%d): Error sending login to VFS\n", SELF_E); + return(-1); } while(!unmountdone || !exitsignaled) { - endpoint_t src; - /* Wait for request message. */ - get_work(&fs_m_in); - src = fs_m_in.m_source; - error = OK; - - caller_uid = -1; /* To trap errors */ - caller_gid = -1; - - /* Exit request? */ - if(src == PM_PROC_NR) { - exitsignaled = 1; - fs_sync(); - continue; - } - - /* This must be a regular VFS request. */ - assert(src == VFS_PROC_NR && !unmountdone); - - req_nr = fs_m_in.m_type; - - if (req_nr < VFS_BASE) - { - fs_m_in.m_type += VFS_BASE; - req_nr = fs_m_in.m_type; - } - ind= req_nr-VFS_BASE; - - if (ind < 0 || ind >= NREQS) { - printf("mfs: bad request %d\n", req_nr); - printf("ind = %d\n", ind); - error = EINVAL; - } - else { - error = (*fs_call_vec[ind])(); - /*cch_check();*/ - } - - fs_m_out.m_type = error; - reply(src, &fs_m_out); - - if (error == OK && rdahed_inode != NIL_INODE) { - read_ahead(); /* do block read ahead */ - } + endpoint_t src; + + /* Wait for request message. */ + get_work(&fs_m_in); + + src = fs_m_in.m_source; + error = OK; + caller_uid = -1; /* To trap errors */ + caller_gid = -1; + + /* Exit request? */ + if(src == PM_PROC_NR) { + exitsignaled = 1; + fs_sync(); + continue; + } + + /* This must be a regular VFS request. */ + assert(src == VFS_PROC_NR && !unmountdone); + + req_nr = fs_m_in.m_type; + if (req_nr < VFS_BASE) { + fs_m_in.m_type += VFS_BASE; + req_nr = fs_m_in.m_type; + } + ind = req_nr - VFS_BASE; + + if (ind < 0 || ind >= NREQS) { + printf("mfs: bad request %d\n", req_nr); + printf("ind = %d\n", ind); + error = EINVAL; + } else { + error = (*fs_call_vec[ind])(); + /*cch_check();*/ + } + + fs_m_out.m_type = error; + reply(src, &fs_m_out); + + if (error == OK && rdahed_inode != NIL_INODE) + read_ahead(); /* do block read ahead */ + } } + /*===========================================================================* * init_server * *===========================================================================*/ PRIVATE void init_server(void) { - int i; + int i; - /* Init inode table */ - for (i = 0; i < NR_INODES; ++i) { - inode[i].i_count = 0; - cch[i] = 0; - } + /* Init inode table */ + for (i = 0; i < NR_INODES; ++i) { + inode[i].i_count = 0; + cch[i] = 0; + } - init_inode_cache(); + init_inode_cache(); - /* Init driver mapping */ - for (i = 0; i < NR_DEVICES; ++i) - driver_endpoints[i].driver_e = NONE; + /* Init driver mapping */ + for (i = 0; i < NR_DEVICES; ++i) + driver_endpoints[i].driver_e = NONE; - SELF_E = getprocnr(); - buf_pool(); - fs_block_size = _MIN_BLOCK_SIZE; + SELF_E = getprocnr(); + buf_pool(); + fs_block_size = _MIN_BLOCK_SIZE; } + /*===========================================================================* * get_work * *===========================================================================*/ PRIVATE void get_work(m_in) message *m_in; /* pointer to message */ { - int srcok = 0; - endpoint_t src; - do { - int s; /* receive status */ - if (OK != (s = receive(ANY, m_in))) /* wait for message */ - panic("MFS","receive failed", s); + int r, srcok = 0; + endpoint_t src; + + do { + if ((r = receive(ANY, m_in)) != OK) /* wait for message */ + panic("MFS","receive failed", r); src = fs_m_in.m_source; if (src != FS_PROC_NR) { if(src == PM_PROC_NR) { if(is_notify(fs_m_in.m_type)) - srcok = 1; /* Normal exit request. */ + srcok = 1; /* Normal exit request. */ else printf("MFS: unexpected message from PM\n"); } else printf("MFS: unexpected source %d\n", src); } else if(src == FS_PROC_NR) { - if(unmountdone) { + if(unmountdone) printf("MFS: unmounted: unexpected message from FS\n"); - } else { - /* Normal FS request. */ - srcok = 1; - } + else + srcok = 1; /* Normal FS request. */ + } else printf("MFS: unexpected source %d\n", src); - } while(!srcok); + } while(!srcok); assert((src == FS_PROC_NR && !unmountdone) || (src == PM_PROC_NR && is_notify(fs_m_in.m_type))); @@ -156,10 +153,14 @@ PUBLIC void reply(who, m_out) int who; message *m_out; /* report result */ { - if (OK != send(who, m_out)) /* send the message */ - printf("MFS(%d) was unable to send reply\n", SELF_E); + if (OK != send(who, m_out)) /* send the message */ + printf("MFS(%d) was unable to send reply\n", SELF_E); } + +/*===========================================================================* + * cch_check * + *===========================================================================*/ PRIVATE void cch_check(void) { int i; @@ -168,10 +169,9 @@ PRIVATE void cch_check(void) if (inode[i].i_count != cch[i] && req_nr != REQ_GETNODE && req_nr != REQ_PUTNODE && - req_nr != REQ_CLONE_OPCL && req_nr != REQ_READSUPER_S && - req_nr != REQ_MOUNTPOINT_S && req_nr != REQ_UNMOUNT && - req_nr != REQ_PIPE && req_nr != REQ_SYNC && - req_nr != REQ_LOOKUP_S) + req_nr != REQ_READSUPER && + req_nr != REQ_MOUNTPOINT && req_nr != REQ_UNMOUNT && + req_nr != REQ_SYNC && req_nr != REQ_LOOKUP) printf("MFS(%d) inode(%d) cc: %d req_nr: %d\n", SELF_E, inode[i].i_num, inode[i].i_count - cch[i], req_nr); @@ -179,5 +179,3 @@ printf("MFS(%d) inode(%d) cc: %d req_nr: %d\n", } } - - diff --git a/servers/mfs/misc.c b/servers/mfs/misc.c index 4f447366d..f94d8dbba 100644 --- a/servers/mfs/misc.c +++ b/servers/mfs/misc.c @@ -1,8 +1,6 @@ - #include "fs.h" #include #include - #include "buf.h" #include "inode.h" @@ -17,17 +15,17 @@ PUBLIC int fs_sync() * blocks must be flushed last, since rw_inode() leaves its results in * the block cache. */ - register struct inode *rip; - register struct buf *bp; + struct inode *rip; + struct buf *bp; /* Write all the dirty inodes to the disk. */ - for (rip = &inode[0]; rip < &inode[NR_INODES]; rip++) - if (rip->i_count > 0 && rip->i_dirt == DIRTY) rw_inode(rip, WRITING); + for(rip = &inode[0]; rip < &inode[NR_INODES]; rip++) + if(rip->i_count > 0 && rip->i_dirt == DIRTY) rw_inode(rip, WRITING); /* Write all the dirty blocks to the disk, one drive at a time. */ - for (bp = &buf[0]; bp < &buf[NR_BUFS]; bp++) - if (bp->b_dev != NO_DEV && bp->b_dirt == DIRTY) - flushall(bp->b_dev); + for(bp = &buf[0]; bp < &buf[NR_BUFS]; bp++) + if(bp->b_dev != NO_DEV && bp->b_dirt == DIRTY) + flushall(bp->b_dev); return(OK); /* sync() can't fail */ } @@ -43,15 +41,12 @@ PUBLIC int fs_flush() */ dev_t dev; - dev= fs_m_in.REQ_DEV; - if (dev == fs_dev) - { - return EBUSY; - } + dev = fs_m_in.REQ_DEV; + if(dev == fs_dev) return(EBUSY); + flushall(dev); invalidate(dev); - + return(OK); } - diff --git a/servers/mfs/mount.c b/servers/mfs/mount.c index 37b3b4c82..f030a3f13 100644 --- a/servers/mfs/mount.c +++ b/servers/mfs/mount.c @@ -1,5 +1,3 @@ - - #include "fs.h" #include #include @@ -14,9 +12,9 @@ /*===========================================================================* - * fs_readsuper_s * + * fs_readsuper * *===========================================================================*/ -PUBLIC int fs_readsuper_s() +PUBLIC int fs_readsuper() { /* This function reads the superblock of the partition, gets the root inode * and sends back the details of them. Note, that the FS process does not @@ -32,48 +30,44 @@ PUBLIC int fs_readsuper_s() int r = OK; unsigned long tasknr; endpoint_t driver_e; + int readonly, isroot; - fs_dev = fs_m_in.REQ_DEV; - - label_gid= fs_m_in.REQ_GRANT2; - label_len= fs_m_in.REQ_PATH_LEN; + fs_dev = fs_m_in.REQ_DEV; + label_gid = fs_m_in.REQ_GRANT; + label_len = fs_m_in.REQ_PATH_LEN; + readonly = (fs_m_in.REQ_FLAGS & REQ_RDONLY) ? 1 : 0; + isroot = (fs_m_in.REQ_FLAGS & REQ_ISROOT) ? 1 : 0; if (label_len > sizeof(fs_dev_label)) - { - printf("mfs:fs_readsuper: label too long\n"); - return EINVAL; - } + return(EINVAL); - r= sys_safecopyfrom(fs_m_in.m_source, label_gid, 0, (vir_bytes)fs_dev_label, - label_len, D); - if (r != OK) - { - printf("mfs:fs_readsuper: safecopyfrom failed: %d\n", r); - return EINVAL; + r = sys_safecopyfrom(fs_m_in.m_source, label_gid, 0, + (vir_bytes)fs_dev_label, label_len, D); + if (r != OK) { + printf("%s:%d fs_readsuper: safecopyfrom failed: %d\n", + __FILE__, __LINE__, r); + return(EINVAL); } - r= ds_retrieve_u32(fs_dev_label, &tasknr); - if (r != OK) - { - printf("mfs:fs_readsuper: ds_retrieve_u32 failed for '%s': %d\n", - fs_dev_label, r); - return EINVAL; + r = ds_retrieve_u32(fs_dev_label, &tasknr); + if (r != OK) { + printf("%s:%d fs_readsuper: ds_retrieve_u32 failed for '%s': %d\n", + fs_dev_label, __FILE__, __LINE__, r); + return(EINVAL); } - driver_e= tasknr; + driver_e = tasknr; /* Map the driver endpoint for this major */ driver_endpoints[(fs_dev >> MAJOR) & BYTE].driver_e = driver_e; - use_getuptime2= TRUE; /* Should be removed with old - * getuptime call. - */ + use_getuptime2 = TRUE; /* Should be removed with old getuptime call. */ vfs_slink_storage = (char *)0xdeadbeef; /* Should be removed together * with old lookup code. */; /* Open the device the file system lives on. */ - if (dev_open(driver_e, fs_dev, driver_e, - fs_m_in.REQ_READONLY ? R_BIT : (R_BIT|W_BIT)) != OK) { + if (dev_open(driver_e, fs_dev, driver_e, + readonly ? R_BIT : (R_BIT|W_BIT)) != OK) { return(EINVAL); } @@ -91,184 +85,63 @@ PUBLIC int fs_readsuper_s() set_blocksize(superblock.s_block_size); /* Get the root inode of the mounted file system. */ - if ( (root_ip = get_inode(fs_dev, ROOT_INODE)) == NIL_INODE) { - printf("MFS: couldn't get root inode?!\n"); - superblock.s_dev = NO_DEV; - dev_close(driver_e, fs_dev); - return EINVAL; + if( (root_ip = get_inode(fs_dev, ROOT_INODE)) == NIL_INODE) { + printf("MFS: couldn't get root inode\n"); + superblock.s_dev = NO_DEV; + dev_close(driver_e, fs_dev); + return(EINVAL); } - if (root_ip != NIL_INODE && root_ip->i_mode == 0) { - printf("MFS: zero mode for root inode?!\n"); - put_inode(root_ip); - superblock.s_dev = NO_DEV; - dev_close(driver_e, fs_dev); - return EINVAL; + if(root_ip != NIL_INODE && root_ip->i_mode == 0) { + printf("%s:%d zero mode for root inode?\n", __FILE__, __LINE__); + put_inode(root_ip); + superblock.s_dev = NO_DEV; + dev_close(driver_e, fs_dev); + return(EINVAL); } - superblock.s_rd_only = fs_m_in.REQ_READONLY; - superblock.s_is_root = fs_m_in.REQ_ISROOT; + superblock.s_rd_only = readonly; + superblock.s_is_root = isroot; /* Root inode properties */ fs_m_out.RES_INODE_NR = root_ip->i_num; fs_m_out.RES_MODE = root_ip->i_mode; - fs_m_out.RES_FILE_SIZE = root_ip->i_size; + fs_m_out.RES_FILE_SIZE_LO = root_ip->i_size; fs_m_out.RES_UID = root_ip->i_uid; fs_m_out.RES_GID = root_ip->i_gid; - return r; + return(r); } /*===========================================================================* - * fs_readsuper_o * + * fs_mountpoint * *===========================================================================*/ -PUBLIC int fs_readsuper_o() -{ -/* This function reads the superblock of the partition, gets the root inode - * and sends back the details of them. Note, that the FS process does not - * know the index of the vmnt object which refers to it, whenever the pathname - * lookup leaves a partition an ELEAVEMOUNT error is transferred back - * so that the VFS knows that it has to find the vnode on which this FS - * process' partition is mounted on. - */ - struct super_block *xp; - struct inode *root_ip; - int r = OK; - phys_bytes ph; - - fs_dev = fs_m_in.REQ_DEV; - - /* Map the driver endpoint for this major */ - driver_endpoints[(fs_dev >> MAJOR) & BYTE].driver_e = fs_m_in.REQ_DRIVER_E; - boottime = fs_m_in.REQ_BOOTTIME; - vfs_slink_storage = fs_m_in.REQ_SLINK_STORAGE; - - /* Fill in the super block. */ - superblock.s_dev = fs_dev; /* read_super() needs to know which dev */ - r = read_super(&superblock); - - /* Is it recognized as a Minix filesystem? */ - if (r != OK) { - superblock.s_dev = NO_DEV; - return(r); - } - - set_blocksize(superblock.s_block_size); - - /* Get the root inode of the mounted file system. */ - root_ip = NIL_INODE; /* if 'r' not OK, make sure this is defined */ - if (r == OK) { - if ( (root_ip = get_inode(fs_dev, ROOT_INODE)) == NIL_INODE) - r = err_code; - } - - if (root_ip != NIL_INODE && root_ip->i_mode == 0) { - put_inode(root_ip); - r = EINVAL; - } - - if (r != OK) return r; - superblock.s_rd_only = fs_m_in.REQ_READONLY; - superblock.s_is_root = fs_m_in.REQ_ISROOT; - - /* Root inode properties */ - fs_m_out.RES_INODE_NR = root_ip->i_num; - fs_m_out.RES_MODE = root_ip->i_mode; - fs_m_out.RES_FILE_SIZE = root_ip->i_size; - - /* Partition properties */ - fs_m_out.RES_MAXSIZE = superblock.s_max_size; - fs_m_out.RES_BLOCKSIZE = superblock.s_block_size; - - return r; -} - - -/*===========================================================================* - * fs_mountpoint_o * - *===========================================================================*/ -PUBLIC int fs_mountpoint_o() +PUBLIC int fs_mountpoint() { /* This function looks up the mount point, it checks the condition whether - * the partition can be mounted on the inode or not. If ok, it gets the - * mountpoint inode's details and stores the mounted vmnt's index (in the - * vmnt table) so that it can be transferred back when the pathname lookup - * encounters a mountpoint. + * the partition can be mounted on the inode or not. */ register struct inode *rip; int r = OK; mode_t bits; - /* Get inode */ - caller_uid = fs_m_in.REQ_UID; - caller_gid = fs_m_in.REQ_GID; - /* Temporarily open the file. */ - if ( (rip = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) { -printf("MFS(%d) get_inode by fs_mountpoint() failed\n", SELF_E); - return(EINVAL); - } - - /* It may not be busy. */ - if (rip->i_count > 2) - { - printf("mfs:fs_mountpoint: i_count = %d\n", rip->i_count); - r = EBUSY; - } - - /* It may not be special. */ - bits = rip->i_mode & I_TYPE; - if (bits == I_BLOCK_SPECIAL || bits == I_CHAR_SPECIAL) r = ENOTDIR; - - if ((rip->i_mode & I_TYPE) != I_DIRECTORY) r = ENOTDIR; - - if (r != OK) { - put_inode(rip); - return r; - } + if( (rip = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) + return(EINVAL); - rip->i_mountpoint = TRUE; - - fs_m_out.m_source = rip->i_dev;/* Filled with the FS endp by the system */ - fs_m_out.RES_INODE_NR = rip->i_num; - fs_m_out.RES_FILE_SIZE = rip->i_size; - fs_m_out.RES_MODE = rip->i_mode; - - return r; -} - - -/*===========================================================================* - * fs_mountpoint_s * - *===========================================================================*/ -PUBLIC int fs_mountpoint_s() -{ -/* This function looks up the mount point, it checks the condition whether - * the partition can be mounted on the inode or not. - */ - register struct inode *rip; - int r = OK; - mode_t bits; - /* Temporarily open the file. */ - if ( (rip = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) { -printf("MFS(%d) get_inode by fs_mountpoint() failed\n", SELF_E); - return(EINVAL); - } - - if (rip->i_mountpoint) - r= EBUSY; + if(rip->i_mountpoint) r = EBUSY; /* It may not be special. */ bits = rip->i_mode & I_TYPE; if (bits == I_BLOCK_SPECIAL || bits == I_CHAR_SPECIAL) r = ENOTDIR; - + put_inode(rip); - if (r == OK) - rip->i_mountpoint = TRUE; - return r; + if(r == OK) rip->i_mountpoint = TRUE; + + return(r); } @@ -280,38 +153,35 @@ PUBLIC int fs_unmount() /* Unmount a file system by device number. */ struct super_block *sp1; int count; - register struct inode *rip; + struct inode *rip, *root_ip; - /* Close the device the file system lives on. */ - dev_close(driver_endpoints[(fs_dev >> MAJOR) & BYTE].driver_e, fs_dev); - - if(superblock.s_dev != fs_dev) - return EINVAL; + if(superblock.s_dev != fs_dev) return(EINVAL); /* See if the mounted device is busy. Only 1 inode using it should be - * open -- the root inode -- and that inode only 1 time. - */ + * open --the root inode-- and that inode only 1 time. */ count = 0; - for (rip = &inode[0]; rip < &inode[NR_INODES]; rip++) { - if (rip->i_count > 0 && rip->i_dev == fs_dev) { - count += rip->i_count; - } - } - - if (count > 1) { - return(EBUSY); /* can't umount a busy file system */ + for (rip = &inode[0]; rip < &inode[NR_INODES]; rip++) + if (rip->i_count > 0 && rip->i_dev == fs_dev) count += rip->i_count; + + if ((root_ip = find_inode(fs_dev, ROOT_INODE)) == NIL_INODE) { + printf("MFS: couldn't find root inode. Unmount failed.\n"); + panic(__FILE__, "MFS: couldn't find root inode", EINVAL); + return(EINVAL); } + + if (count > 1) return(EBUSY); /* can't umount a busy file system */ + put_inode(root_ip); - /* Sync the disk, and invalidate cache. */ - (void) fs_sync(); /* force any cached blocks out of memory */ + /* force any cached blocks out of memory */ + (void) fs_sync(); + + /* Close the device the file system lives on. */ + dev_close(driver_endpoints[(fs_dev >> MAJOR) & BYTE].driver_e, fs_dev); /* Finish off the unmount. */ superblock.s_dev = NO_DEV; - unmountdone = TRUE; - return OK; + return(OK); } - - diff --git a/servers/mfs/open.c b/servers/mfs/open.c index 02bdea380..72ea55c75 100644 --- a/servers/mfs/open.c +++ b/servers/mfs/open.c @@ -1,5 +1,3 @@ - - #include "fs.h" #include #include @@ -10,215 +8,17 @@ #include "buf.h" #include "inode.h" #include "super.h" - #include PRIVATE char mode_map[] = {R_BIT, W_BIT, R_BIT|W_BIT, 0}; -FORWARD _PROTOTYPE( struct inode *new_node_o, (struct inode *ldirp, +FORWARD _PROTOTYPE( struct inode *new_node, (struct inode *ldirp, char *string, mode_t bits, zone_t z0)); -FORWARD _PROTOTYPE( struct inode *new_node_s, (struct inode *ldirp, - char *string, mode_t bits, zone_t z0)); - -#if 0 -/*===========================================================================* - * fs_open * - *===========================================================================*/ -PUBLIC int fs_open() -{ - int r, b, exist = TRUE; - struct inode *ldirp; - struct inode *rip; - int oflags; - mode_t omode; - mode_t bits; - char lastc[NAME_MAX]; - - /* Read request message */ - oflags = fs_m_in.REQ_FLAGS; - omode = fs_m_in.REQ_MODE; - - - caller_uid = fs_m_in.REQ_UID; - caller_gid = fs_m_in.REQ_GID; - - /* Device number only for device special files */ - fs_m_out.RES_DEV = NO_DEV; - - /* Remap the bottom two bits of oflags. */ - bits = (mode_t) mode_map[oflags & O_ACCMODE]; - - - /* If O_CREATE is set, try to make the file. */ - if (oflags & O_CREAT) { - phys_bytes len; - /* Copy the last component */ - len = MFS_MIN(fs_m_in.REQ_PATH_LEN, sizeof(lastc)); - err_code = sys_datacopy(FS_PROC_NR, (vir_bytes) fs_m_in.REQ_PATH, - SELF, (vir_bytes) lastc, (phys_bytes) len); - if (err_code != OK) return err_code; - MFS_NUL(lastc, len, sizeof(lastc)); - - /* Get last directory inode */ - if ((ldirp = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) { -printf("MFS(%d) get_inode for parent dir by creat() failed\n", SELF_E); - return ENOENT; - } - - /* Create a new inode by calling new_node(). */ - rip = new_node(ldirp, lastc, omode, NO_ZONE); - r = err_code; - if (r == OK) exist = FALSE; /* we just created the file */ - else if (r != EEXIST) { - put_inode(ldirp); - return(r); /* other error */ - } - else exist = !(oflags & O_EXCL); /* file exists, if the O_EXCL - flag is set this is an error */ - } - else { - /* Get file inode. */ - if ( (rip = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) { -printf("MFS(%d) get_inode by open() failed\n", SELF_E); - return ENOENT; - } - ldirp = NIL_INODE; - } - - /* Only do the normal open code if we didn't just create the file. */ - if (exist) { - /* Check protections. */ - if ((r = forbidden(rip, bits)) == OK) { - /* Opening reg. files directories and special files differ. */ - switch (rip->i_mode & I_TYPE) { - case I_REGULAR: - /* Truncate regular file if O_TRUNC. */ - if (oflags & O_TRUNC) { - panic(__FILE__, "O_TRUNC in mfs.", oflags); -#if 0 - if ((r = forbidden(rip, W_BIT)) !=OK) break; - truncate_inode(rip, 0); - wipe_inode(rip); - /* Send the inode from the inode cache to the - * block cache, so it gets written on the next - * cache flush. - */ - rw_inode(rip, WRITING); -#endif - } - break; - - case I_DIRECTORY: - /* Directories may be read but not written. */ - r = (bits & W_BIT ? EISDIR : OK); - break; - - case I_CHAR_SPECIAL: - case I_BLOCK_SPECIAL: - /* Send back the device number */ - fs_m_out.RES_DEV = (Dev_t) rip->i_zone[0]; - break; - - case I_NAMED_PIPE: - rip->i_pipe = I_PIPE; - break; - } - } - } - - /* If error, release inode. */ - if (r != OK) { - put_inode(ldirp); - put_inode(rip); - return(r); - } - - /* Reply message */ - fs_m_out.m_source = rip->i_dev; /* filled with FS endpoint by the system */ - fs_m_out.RES_INODE_NR = rip->i_num; - fs_m_out.RES_MODE = rip->i_mode; - fs_m_out.RES_FILE_SIZE = rip->i_size; - fs_m_out.RES_INODE_INDEX = (rip - &inode[0]) / sizeof(struct inode); - - /* This values are needed for the execution */ - fs_m_out.RES_UID = rip->i_uid; - fs_m_out.RES_GID = rip->i_gid; - if ((rip->i_mode & I_TYPE) == I_REGULAR) fs_m_out.RES_CTIME = rip->i_ctime; - - /* Drop parent dir */ - put_inode(ldirp); - - return OK; -} -#endif - - -/*===========================================================================* - * fs_create_o * - *===========================================================================*/ -PUBLIC int fs_create_o() -{ - phys_bytes len; - int r, b; - struct inode *ldirp; - struct inode *rip; - mode_t omode; - char lastc[NAME_MAX]; - - /* Read request message */ - omode = fs_m_in.REQ_MODE; - - caller_uid = fs_m_in.REQ_UID; - caller_gid = fs_m_in.REQ_GID; - - /* Try to make the file. */ - - /* Copy the last component */ - len = MFS_MIN(fs_m_in.REQ_PATH_LEN, sizeof(lastc)); - err_code = sys_datacopy(FS_PROC_NR, (vir_bytes) fs_m_in.REQ_PATH, - SELF, (vir_bytes) lastc, (phys_bytes) len); - if (err_code != OK) return err_code; - MFS_NUL(lastc, len, sizeof(lastc)); - - /* Get last directory inode */ - if ((ldirp = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) { -printf("MFS(%d) get_inode for parent dir by creat() failed\n", SELF_E); - return ENOENT; - } - - /* Create a new inode by calling new_node(). */ - rip = new_node_o(ldirp, lastc, omode, NO_ZONE); - r = err_code; - - /* If error, release inode. */ - if (r != OK) { - put_inode(ldirp); - put_inode(rip); - return(r); - } - - /* Reply message */ - fs_m_out.m_source = rip->i_dev; /* filled with FS endpoint by the system */ - fs_m_out.RES_INODE_NR = rip->i_num; - fs_m_out.RES_MODE = rip->i_mode; - fs_m_out.RES_FILE_SIZE = rip->i_size; - fs_m_out.RES_INODE_INDEX = (rip - &inode[0]) / sizeof(struct inode); - - /* This values are needed for the execution */ - fs_m_out.RES_UID = rip->i_uid; - fs_m_out.RES_GID = rip->i_gid; - if ((rip->i_mode & I_TYPE) == I_REGULAR) fs_m_out.RES_CTIME = rip->i_ctime; - - /* Drop parent dir */ - put_inode(ldirp); - - return OK; -} /*===========================================================================* - * fs_create_s * + * fs_create * *===========================================================================*/ -PUBLIC int fs_create_s() +PUBLIC int fs_create() { phys_bytes len; int r, b; @@ -229,93 +29,54 @@ PUBLIC int fs_create_s() /* Read request message */ omode = fs_m_in.REQ_MODE; - caller_uid = fs_m_in.REQ_UID; caller_gid = fs_m_in.REQ_GID; /* Try to make the file. */ - /* Copy the last component */ + /* Copy the last component (i.e., file name) */ len = MFS_MIN(fs_m_in.REQ_PATH_LEN, sizeof(lastc)); err_code = sys_safecopyfrom(FS_PROC_NR, fs_m_in.REQ_GRANT, 0, - (vir_bytes) lastc, (phys_bytes) len, D); + (vir_bytes) lastc, (phys_bytes) len, D); if (err_code != OK) return err_code; MFS_NUL(lastc, len, sizeof(lastc)); - /* Get last directory inode */ - if ((ldirp = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) { -printf("MFS(%d) get_inode for parent dir by creat() failed\n", SELF_E); - return ENOENT; - } + /* Get last directory inode (i.e., directory that will hold the new inode) */ + if ((ldirp = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) + return(ENOENT); /* Create a new inode by calling new_node(). */ - rip = new_node_s(ldirp, lastc, omode, NO_ZONE); + rip = new_node(ldirp, lastc, omode, NO_ZONE); r = err_code; - /* If error, release inode. */ + /* If an error occurred, release inode. */ if (r != OK) { - put_inode(ldirp); - put_inode(rip); - return(r); + put_inode(ldirp); + put_inode(rip); + return(r); } - + /* Reply message */ fs_m_out.m_source = rip->i_dev; /* filled with FS endpoint by the system */ fs_m_out.RES_INODE_NR = rip->i_num; fs_m_out.RES_MODE = rip->i_mode; - fs_m_out.RES_FILE_SIZE = rip->i_size; - fs_m_out.RES_INODE_INDEX = (rip - &inode[0]) / sizeof(struct inode); + fs_m_out.RES_FILE_SIZE_LO = rip->i_size; /* This values are needed for the execution */ fs_m_out.RES_UID = rip->i_uid; fs_m_out.RES_GID = rip->i_gid; - if ((rip->i_mode & I_TYPE) == I_REGULAR) fs_m_out.RES_CTIME = rip->i_ctime; /* Drop parent dir */ put_inode(ldirp); - return OK; -} - - -/*===========================================================================* - * fs_mknod_o * - *===========================================================================*/ -PUBLIC int fs_mknod_o() -{ - struct inode *ip, *ldirp; - char lastc[NAME_MAX]; - phys_bytes len; - - /* Copy the last component and set up caller's user and group id */ - len = MFS_MIN(fs_m_in.REQ_PATH_LEN, sizeof(lastc)); - err_code = sys_datacopy(FS_PROC_NR, (vir_bytes) fs_m_in.REQ_PATH, SELF, - (vir_bytes) lastc, (phys_bytes) len); - if (err_code != OK) return err_code; - MFS_NUL(lastc, len, sizeof(lastc)); - - caller_uid = fs_m_in.REQ_UID; - caller_gid = fs_m_in.REQ_GID; - - /* Get last directory inode */ - if ((ldirp = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) { -printf("MFS(%d) get_inode for parent dir by mknod() failed\n", SELF_E); - return ENOENT; - } - - /* Try to create the new node */ - ip = new_node_o(ldirp, lastc, fs_m_in.REQ_MODE, (zone_t) fs_m_in.REQ_DEV); - - put_inode(ip); - put_inode(ldirp); - return(err_code); + return(OK); } /*===========================================================================* - * fs_mknod_s * + * fs_mknod * *===========================================================================*/ -PUBLIC int fs_mknod_s() +PUBLIC int fs_mknod() { struct inode *ip, *ldirp; char lastc[NAME_MAX]; @@ -324,21 +85,19 @@ PUBLIC int fs_mknod_s() /* Copy the last component and set up caller's user and group id */ len = MFS_MIN(fs_m_in.REQ_PATH_LEN, sizeof(lastc)); err_code = sys_safecopyfrom(FS_PROC_NR, fs_m_in.REQ_GRANT, 0, - (vir_bytes) lastc, (phys_bytes) len, D); + (vir_bytes) lastc, (phys_bytes) len, D); if (err_code != OK) return err_code; MFS_NUL(lastc, len, sizeof(lastc)); - + caller_uid = fs_m_in.REQ_UID; caller_gid = fs_m_in.REQ_GID; /* Get last directory inode */ - if ((ldirp = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) { -printf("MFS(%d) get_inode for parent dir by mknod() failed\n", SELF_E); - return ENOENT; - } + if((ldirp = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) + return(ENOENT); /* Try to create the new node */ - ip = new_node_s(ldirp, lastc, fs_m_in.REQ_MODE, (zone_t) fs_m_in.REQ_DEVx); + ip = new_node(ldirp, lastc, fs_m_in.REQ_MODE, (zone_t) fs_m_in.REQ_DEV); put_inode(ip); put_inode(ldirp); @@ -347,9 +106,9 @@ printf("MFS(%d) get_inode for parent dir by mknod() failed\n", SELF_E); /*===========================================================================* - * fs_mkdir_o * + * fs_mkdir * *===========================================================================*/ -PUBLIC int fs_mkdir_o() +PUBLIC int fs_mkdir() { int r1, r2; /* status codes */ ino_t dot, dotdot; /* inode numbers for . and .. */ @@ -359,97 +118,27 @@ PUBLIC int fs_mkdir_o() /* Copy the last component and set up caller's user and group id */ len = MFS_MIN(fs_m_in.REQ_PATH_LEN, sizeof(lastc)); - err_code = sys_datacopy(FS_PROC_NR, (vir_bytes) fs_m_in.REQ_PATH, SELF, - (vir_bytes) lastc, (phys_bytes) len); - if (err_code != OK) return err_code; + err_code = sys_safecopyfrom(FS_PROC_NR, fs_m_in.REQ_GRANT, 0, + (vir_bytes) lastc, (phys_bytes) len, D); + if(err_code != OK) return(err_code); MFS_NUL(lastc, len, sizeof(lastc)); - + caller_uid = fs_m_in.REQ_UID; caller_gid = fs_m_in.REQ_GID; /* Get last directory inode */ - if ((ldirp = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) { -printf("MFS(%d) get_inode for parent dir by mkdir() failed\n", SELF_E); - return ENOENT; - } + if((ldirp = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) + return(ENOENT); /* Next make the inode. If that fails, return error code. */ - rip = new_node_o(ldirp, lastc, fs_m_in.REQ_MODE, (zone_t) 0); - - if (rip == NIL_INODE || err_code == EEXIST) { - put_inode(rip); /* can't make dir: it already exists */ - put_inode(ldirp); - return(err_code); - } - - /* Get the inode numbers for . and .. to enter in the directory. */ - dotdot = ldirp->i_num; /* parent's inode number */ - dot = rip->i_num; /* inode number of the new dir itself */ - - /* Now make dir entries for . and .. unless the disk is completely full. */ - /* Use dot1 and dot2, so the mode of the directory isn't important. */ - rip->i_mode = fs_m_in.REQ_MODE; /* set mode */ - r1 = search_dir(rip, dot1, &dot, ENTER); /* enter . in the new dir */ - r2 = search_dir(rip, dot2, &dotdot, ENTER); /* enter .. in the new dir */ - - /* If both . and .. were successfully entered, increment the link counts. */ - if (r1 == OK && r2 == OK) { - /* Normal case. It was possible to enter . and .. in the new dir. */ - rip->i_nlinks++; /* this accounts for . */ - ldirp->i_nlinks++; /* this accounts for .. */ - ldirp->i_dirt = DIRTY; /* mark parent's inode as dirty */ - } else { - /* It was not possible to enter . or .. probably disk was full - - * links counts haven't been touched. - */ - if(search_dir(ldirp, lastc, (ino_t *) 0, DELETE) != OK) - panic(__FILE__, "Dir disappeared ", rip->i_num); - rip->i_nlinks--; /* undo the increment done in new_node() */ - } - rip->i_dirt = DIRTY; /* either way, i_nlinks has changed */ - - put_inode(ldirp); /* return the inode of the parent dir */ - put_inode(rip); /* return the inode of the newly made dir */ - return(err_code); /* new_node() always sets 'err_code' */ -} - - -/*===========================================================================* - * fs_mkdir_s * - *===========================================================================*/ -PUBLIC int fs_mkdir_s() -{ - int r1, r2; /* status codes */ - ino_t dot, dotdot; /* inode numbers for . and .. */ - struct inode *rip, *ldirp; - char lastc[NAME_MAX]; /* last component */ - phys_bytes len; - - /* Copy the last component and set up caller's user and group id */ - len = MFS_MIN(fs_m_in.REQ_PATH_LEN, sizeof(lastc)); - err_code = sys_safecopyfrom(FS_PROC_NR, fs_m_in.REQ_GRANT, 0, - (vir_bytes) lastc, (phys_bytes) len, D); - if (err_code != OK) return err_code; - MFS_NUL(lastc, len, sizeof(lastc)); + rip = new_node(ldirp, lastc, fs_m_in.REQ_MODE, (zone_t) 0); - caller_uid = fs_m_in.REQ_UID; - caller_gid = fs_m_in.REQ_GID; - - /* Get last directory inode */ - if ((ldirp = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) { -printf("MFS(%d) get_inode for parent dir by mkdir() failed\n", SELF_E); - return ENOENT; + if(rip == NIL_INODE || err_code == EEXIST) { + put_inode(rip); /* can't make dir: it already exists */ + put_inode(ldirp); + return(err_code); } - /* Next make the inode. If that fails, return error code. */ - rip = new_node_s(ldirp, lastc, fs_m_in.REQ_MODE, (zone_t) 0); - - if (rip == NIL_INODE || err_code == EEXIST) { - put_inode(rip); /* can't make dir: it already exists */ - put_inode(ldirp); - return(err_code); - } - /* Get the inode numbers for . and .. to enter in the directory. */ dotdot = ldirp->i_num; /* parent's inode number */ dot = rip->i_num; /* inode number of the new dir itself */ @@ -457,23 +146,22 @@ printf("MFS(%d) get_inode for parent dir by mkdir() failed\n", SELF_E); /* Now make dir entries for . and .. unless the disk is completely full. */ /* Use dot1 and dot2, so the mode of the directory isn't important. */ rip->i_mode = fs_m_in.REQ_MODE; /* set mode */ - r1 = search_dir_nocheck(rip, dot1, &dot, ENTER); /* enter . in the new dir */ - r2 = search_dir_nocheck(rip, dot2, &dotdot, ENTER); /* enter .. in the new - dir */ + r1 = search_dir(rip, dot1, &dot, ENTER, IGN_PERM);/* enter . in the new dir*/ + r2 = search_dir(rip, dot2, &dotdot, ENTER, IGN_PERM); /* enter .. in the new + dir */ /* If both . and .. were successfully entered, increment the link counts. */ if (r1 == OK && r2 == OK) { - /* Normal case. It was possible to enter . and .. in the new dir. */ - rip->i_nlinks++; /* this accounts for . */ - ldirp->i_nlinks++; /* this accounts for .. */ - ldirp->i_dirt = DIRTY; /* mark parent's inode as dirty */ + /* Normal case. It was possible to enter . and .. in the new dir. */ + rip->i_nlinks++; /* this accounts for . */ + ldirp->i_nlinks++; /* this accounts for .. */ + ldirp->i_dirt = DIRTY; /* mark parent's inode as dirty */ } else { - /* It was not possible to enter . or .. probably disk was full - - * links counts haven't been touched. - */ - if(search_dir_nocheck(ldirp, lastc, (ino_t *) 0, DELETE) != OK) - panic(__FILE__, "Dir disappeared ", rip->i_num); - rip->i_nlinks--; /* undo the increment done in new_node() */ + /* It was not possible to enter . or .. probably disk was full - + * links counts haven't been touched. */ + if(search_dir(ldirp, lastc, (ino_t *) 0, DELETE, IGN_PERM) != OK) + panic(__FILE__, "Dir disappeared ", rip->i_num); + rip->i_nlinks--; /* undo the increment done in new_node() */ } rip->i_dirt = DIRTY; /* either way, i_nlinks has changed */ @@ -484,84 +172,9 @@ printf("MFS(%d) get_inode for parent dir by mkdir() failed\n", SELF_E); /*===========================================================================* - * fs_slink_o * - *===========================================================================*/ -PUBLIC int fs_slink_o() -{ - phys_bytes len; - struct inode *sip; /* inode containing symbolic link */ - struct inode *ldirp; /* directory containing link */ - register int r; /* error code */ - char string[NAME_MAX]; /* last component of the new dir's path name */ - struct buf *bp; /* disk buffer for link */ - - caller_uid = fs_m_in.REQ_UID; - caller_gid = fs_m_in.REQ_GID; - - /* Copy the link name's last component */ - len = MFS_MIN(fs_m_in.REQ_PATH_LEN, sizeof(string)); - r = sys_datacopy(FS_PROC_NR, (vir_bytes) fs_m_in.REQ_PATH, - SELF, (vir_bytes) string, (phys_bytes) len); - if (r != OK) return r; - MFS_NUL(string, len, sizeof(string)); - - /* Temporarily open the dir. */ - if ( (ldirp = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) { - return(EINVAL); - } - - /* Create the inode for the symlink. */ - sip = new_node_o(ldirp, string, (mode_t) (I_SYMBOLIC_LINK | RWX_MODES), - (zone_t) 0); - - /* Allocate a disk block for the contents of the symlink. - * Copy contents of symlink (the name pointed to) into first disk block. - */ - if ((r = err_code) == OK) { - r = (bp = new_block(sip, (off_t) 0)) == NIL_BUF ? err_code : - sys_vircopy(fs_m_in.REQ_WHO_E, D, (vir_bytes) fs_m_in.REQ_USER_ADDR, - SELF, D, (vir_bytes) bp->b_data, - (vir_bytes) fs_m_in.REQ_SLENGTH); - - if(r == OK) { - bp->b_data[_MIN_BLOCK_SIZE-1] = '\0'; - sip->i_size = strlen(bp->b_data); - /*if(sip->i_size != m_in.name1_length-1) {*/ - if(sip->i_size != fs_m_in.REQ_SLENGTH) { - /* This can happen if the user provides a buffer - * with a \0 in it. This can cause a lot of trouble - * when the symlink is used later. We could just use - * the strlen() value, but we want to let the user - * know he did something wrong. ENAMETOOLONG doesn't - * exactly describe the error, but there is no - * ENAMETOOWRONG. - */ - r = ENAMETOOLONG; - } - } - - put_block(bp, DIRECTORY_BLOCK); /* put_block() accepts NIL_BUF. */ - - if (r != OK) { - sip->i_nlinks = 0; - if (search_dir(ldirp, string, (ino_t *) 0, DELETE) != OK) - panic(__FILE__, "Symbolic link vanished", NO_NUM); - } - } - - /* put_inode() accepts NIL_INODE as a noop, so the below are safe. */ - put_inode(sip); - put_inode(ldirp); - - return(r); -} - - - -/*===========================================================================* - * fs_slink_s * + * fs_slink * *===========================================================================*/ -PUBLIC int fs_slink_s() +PUBLIC int fs_slink() { phys_bytes len; struct inode *sip; /* inode containing symbolic link */ @@ -573,64 +186,60 @@ PUBLIC int fs_slink_s() caller_uid = fs_m_in.REQ_UID; caller_gid = fs_m_in.REQ_GID; -#if 0 - printf("mfs:fs_slink_s: creating link in dir inode %d dev 0x%x\n", - fs_m_in.REQ_INODE_NR, fs_dev); -#endif - /* Copy the link name's last component */ len = MFS_MIN(fs_m_in.REQ_PATH_LEN, sizeof(string)); r = sys_safecopyfrom(FS_PROC_NR, fs_m_in.REQ_GRANT, 0, - (vir_bytes) string, (phys_bytes) len, D); - if (r != OK) return r; + (vir_bytes) string, (phys_bytes) len, D); + if (r != OK) return(r); MFS_NUL(string, len, sizeof(string)); /* Temporarily open the dir. */ - if ( (ldirp = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) { - return(EINVAL); - } + if( (ldirp = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) + return(EINVAL); /* Create the inode for the symlink. */ - sip = new_node_s(ldirp, string, (mode_t) (I_SYMBOLIC_LINK | RWX_MODES), - (zone_t) 0); + sip = new_node(ldirp, string, (mode_t) (I_SYMBOLIC_LINK | RWX_MODES), + (zone_t) 0); /* Allocate a disk block for the contents of the symlink. - * Copy contents of symlink (the name pointed to) into first disk block. - */ - if ((r = err_code) == OK) { - r = (bp = new_block(sip, (off_t) 0)) == NIL_BUF ? err_code : - sys_safecopyfrom(FS_PROC_NR, fs_m_in.REQ_GRANT2, 0, - (vir_bytes) bp->b_data, (vir_bytes) fs_m_in.REQ_SLENGTH, D); - - if(r == OK) { - bp->b_data[_MIN_BLOCK_SIZE-1] = '\0'; - sip->i_size = strlen(bp->b_data); - if(sip->i_size != fs_m_in.REQ_SLENGTH) { - /* This can happen if the user provides a buffer - * with a \0 in it. This can cause a lot of trouble - * when the symlink is used later. We could just use - * the strlen() value, but we want to let the user - * know he did something wrong. ENAMETOOLONG doesn't - * exactly describe the error, but there is no - * ENAMETOOWRONG. - */ - r = ENAMETOOLONG; - } - } - - put_block(bp, DIRECTORY_BLOCK); /* put_block() accepts NIL_BUF. */ - - if (r != OK) { - sip->i_nlinks = 0; - if (search_dir_nocheck(ldirp, string, (ino_t *) 0, DELETE) != OK) - panic(__FILE__, "Symbolic link vanished", NO_NUM); - } + * Copy contents of symlink (the name pointed to) into first disk block. */ + if( (r = err_code) == OK) { + r = (bp = new_block(sip, (off_t) 0)) == NIL_BUF ? err_code : + sys_safecopyfrom(FS_PROC_NR, fs_m_in.REQ_GRANT3, 0, + (vir_bytes) bp->b_data, + (vir_bytes) fs_m_in.REQ_MEM_SIZE, D); + + if(r == OK) { + bp->b_data[_MIN_BLOCK_SIZE-1] = '\0'; + sip->i_size = strlen(bp->b_data); + if(sip->i_size != fs_m_in.REQ_MEM_SIZE) { + /* This can happen if the user provides a buffer + * with a \0 in it. This can cause a lot of trouble + * when the symlink is used later. We could just use + * the strlen() value, but we want to let the user + * know he did something wrong. ENAMETOOLONG doesn't + * exactly describe the error, but there is no + * ENAMETOOWRONG. + */ + r = ENAMETOOLONG; + } + } + + put_block(bp, DIRECTORY_BLOCK); /* put_block() accepts NIL_BUF. */ + + if(r != OK) { + sip->i_nlinks = 0; + if(search_dir(ldirp, string, (ino_t *) 0, DELETE, + IGN_PERM) != OK) + + panic(__FILE__, "Symbolic link vanished", NO_NUM); + } } /* put_inode() accepts NIL_INODE as a noop, so the below are safe. */ put_inode(sip); put_inode(ldirp); - + return(r); } @@ -646,23 +255,17 @@ PUBLIC int fs_newnode() caller_uid = fs_m_in.REQ_UID; caller_gid = fs_m_in.REQ_GID; - - bits= fs_m_in.REQ_MODE; + bits = fs_m_in.REQ_MODE; /* Try to allocate the inode */ - if ( (rip = alloc_inode(fs_dev, bits) ) == NIL_INODE) { - return err_code; - } - - switch (bits & S_IFMT) - { - case S_IFBLK: - case S_IFCHR: - rip->i_zone[0] = fs_m_in.REQ_DEVx; /* major/minor device numbers */ - break; - case S_IFIFO: - rip->i_pipe = I_PIPE; - break; + if( (rip = alloc_inode(fs_dev, bits) ) == NIL_INODE) + return err_code; + + switch (bits & S_IFMT) { + case S_IFBLK: + case S_IFCHR: + rip->i_zone[0] = fs_m_in.REQ_DEV; /* major/minor dev numbers*/ + break; } rw_inode(rip, WRITING); /* mark inode as allocated */ @@ -671,21 +274,19 @@ PUBLIC int fs_newnode() /* Fill in the fields of the response message */ fs_m_out.RES_INODE_NR = rip->i_num; fs_m_out.RES_MODE = rip->i_mode; - fs_m_out.RES_INODE_INDEX = (rip - &inode[0]); - fs_m_out.RES_FILE_SIZE = rip->i_size; + fs_m_out.RES_FILE_SIZE_LO = rip->i_size; fs_m_out.RES_UID = rip->i_uid; fs_m_out.RES_GID = rip->i_gid; fs_m_out.RES_DEV = (dev_t) rip->i_zone[0]; - return OK; + return(OK); } - /*===========================================================================* - * new_node_o * + * new_node * *===========================================================================*/ -PRIVATE struct inode *new_node_o(struct inode *ldirp, +PRIVATE struct inode *new_node(struct inode *ldirp, char *string, mode_t bits, zone_t z0) { /* New_node() is called by fs_open(), fs_mknod(), and fs_mkdir(). @@ -703,7 +304,7 @@ PRIVATE struct inode *new_node_o(struct inode *ldirp, register int r; /* Get final component of the path. */ - rip = advance_o(&ldirp, string); + rip = advance(ldirp, string, IGN_PERM); if (S_ISDIR(bits) && (ldirp)->i_nlinks >= ((ldirp)->i_sp->s_version == V1 ? @@ -730,7 +331,7 @@ PRIVATE struct inode *new_node_o(struct inode *ldirp, rw_inode(rip, WRITING); /* force inode to disk now */ /* New inode acquired. Try to make directory entry. */ - if ((r = search_dir(ldirp, string, &rip->i_num, ENTER)) != OK) { + if((r=search_dir(ldirp, string, &rip->i_num, ENTER, IGN_PERM)) != OK) { rip->i_nlinks--; /* pity, have to free disk inode */ rip->i_dirt = DIRTY; /* dirty inodes are written out */ put_inode(rip); /* this call frees the inode */ @@ -738,81 +339,11 @@ PRIVATE struct inode *new_node_o(struct inode *ldirp, return(NIL_INODE); } - } else { + } else if (err_code == EENTERMOUNT || err_code == ELEAVEMOUNT) { + r = EEXIST; + } else { /* Either last component exists, or there is some problem. */ - if (rip != NIL_INODE || err_code == EENTERMOUNT || - err_code == ELEAVEMOUNT) - r = EEXIST; - else - r = err_code; - } - - /* The caller has to return the directory inode (*ldirp). */ - err_code = r; - return(rip); -} - - -/*===========================================================================* - * new_node_s * - *===========================================================================*/ -PRIVATE struct inode *new_node_s(struct inode *ldirp, - char *string, mode_t bits, zone_t z0) -{ -/* New_node() is called by fs_open(), fs_mknod(), and fs_mkdir(). - * In all cases it allocates a new inode, makes a directory entry for it in - * the ldirp directory with string name, and initializes it. - * It returns a pointer to the inode if it can do this; - * otherwise it returns NIL_INODE. It always sets 'err_code' - * to an appropriate value (OK or an error code). - * - * The parsed path rest is returned in 'parsed' if parsed is nonzero. It - * has to hold at least NAME_MAX bytes. - */ - - register struct inode *rip; - register int r; - - /* Get final component of the path. */ - rip = advance_nocheck(&ldirp, string); - - if (S_ISDIR(bits) && - (ldirp)->i_nlinks >= ((ldirp)->i_sp->s_version == V1 ? - CHAR_MAX : SHRT_MAX)) { - /* New entry is a directory, alas we can't give it a ".." */ - put_inode(rip); - err_code = EMLINK; - return(NIL_INODE); - } - - if ( rip == NIL_INODE && err_code == ENOENT) { - /* Last path component does not exist. Make new directory entry. */ - if ( (rip = alloc_inode((ldirp)->i_dev, bits)) == NIL_INODE) { - /* Can't creat new inode: out of inodes. */ - return(NIL_INODE); - } - - /* Force inode to the disk before making directory entry to make - * the system more robust in the face of a crash: an inode with - * no directory entry is much better than the opposite. - */ - rip->i_nlinks++; - rip->i_zone[0] = z0; /* major/minor device numbers */ - rw_inode(rip, WRITING); /* force inode to disk now */ - - /* New inode acquired. Try to make directory entry. */ - if ((r = search_dir_nocheck(ldirp, string, &rip->i_num, ENTER)) != OK) { - rip->i_nlinks--; /* pity, have to free disk inode */ - rip->i_dirt = DIRTY; /* dirty inodes are written out */ - put_inode(rip); /* this call frees the inode */ - err_code = r; - return(NIL_INODE); - } - - } else { - /* Either last component exists, or there is some problem. */ - if (rip != NIL_INODE || err_code == EENTERMOUNT || - err_code == ELEAVEMOUNT) + if (rip != NIL_INODE) r = EEXIST; else r = err_code; @@ -831,14 +362,12 @@ PUBLIC int fs_inhibread() { struct inode *rip; - if ((rip = find_inode(fs_dev, fs_m_in.REQ_INODE_NR))== NIL_INODE){ - printf("FSinhibread: couldn't find inode %d\n", fs_m_in.REQ_INODE_NR); - return EINVAL; - } + if((rip = find_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) + return(EINVAL); /* inhibit read ahead */ rip->i_seek = ISEEK; - return OK; + return(OK); } diff --git a/servers/mfs/path.c b/servers/mfs/path.c index 03763214b..c9bb8514e 100644 --- a/servers/mfs/path.c +++ b/servers/mfs/path.c @@ -8,416 +8,136 @@ * search_dir: search a directory for a string and return its inode number * */ - + #include "fs.h" #include #include #include #include +#include +#include #include "buf.h" #include "inode.h" #include "super.h" - #include PUBLIC char dot1[2] = "."; /* used for search_dir to bypass the access */ PUBLIC char dot2[3] = ".."; /* permissions for . and .. */ -FORWARD _PROTOTYPE( char *get_name, (char *old_name, char string [NAME_MAX]) ); -FORWARD _PROTOTYPE( char *get_name_s, (char *name, char string[NAME_MAX+1]) ); -FORWARD _PROTOTYPE( int ltraverse, (struct inode *rip, char *path, - char *suffix, int pathlen) ); -FORWARD _PROTOTYPE( int ltraverse_s, (struct inode *rip, char *suffix) ); -FORWARD _PROTOTYPE( int advance_s1, (struct inode *dirp, - char string[NAME_MAX], struct inode **resp) ); -FORWARD _PROTOTYPE( int parse_path_s, (ino_t dir_ino, ino_t root_ino, +FORWARD _PROTOTYPE( char *get_name, (char *name, char string[NAME_MAX+1]) ); +FORWARD _PROTOTYPE( int ltraverse, (struct inode *rip, char *suffix) ); +FORWARD _PROTOTYPE( int parse_path, (ino_t dir_ino, ino_t root_ino, int flags, struct inode **res_inop, size_t *offsetp, int *symlinkp) ); /*===========================================================================* - * lookup_o * - *===========================================================================*/ -PUBLIC int lookup_o() -{ - char string[PATH_MAX]; - struct inode *rip; - int s_error, flags; - int len; - - string[0] = '\0'; - - /* Check length. */ - len = fs_m_in.REQ_PATH_LEN; - if(len > sizeof(user_path)) return E2BIG; /* too big for buffer */ - if(len < 1) return EINVAL; /* too small for \0 */ - - /* Copy the pathname and set up caller's user and group id */ - err_code = sys_datacopy(FS_PROC_NR, (vir_bytes) fs_m_in.REQ_PATH, SELF, - (vir_bytes) user_path, (phys_bytes) len); - if (err_code != OK) { - printf("mfs:%s:%d: sys_datacopy failed: %d\n", __FILE__, __LINE__, err_code); - return err_code; - } - - /* Verify this is a null-terminated path. */ - if(user_path[len-1] != '\0') { - printf("mfs:lookup: didn't get null-terminated string.\n"); - return EINVAL; - } - - caller_uid = fs_m_in.REQ_UID; - caller_gid = fs_m_in.REQ_GID; - flags = fs_m_in.REQ_FLAGS; - - /* Clear RES_OFFSET for ENOENT */ - fs_m_out.RES_OFFSET= 0; - - /* Lookup inode */ - rip = parse_path_o(user_path, string, flags); - - /* Copy back the last name if it is required */ - if (err_code != OK || (flags & PATH_PENULTIMATE)) { - s_error = sys_datacopy(SELF_E, (vir_bytes) string, FS_PROC_NR, - (vir_bytes) fs_m_in.REQ_USER_ADDR, (phys_bytes) NAME_MAX); - if (s_error != OK) { - printf("mfs:%s:%d: sys_datacopy failed: %d\n", - __FILE__, __LINE__, s_error); - return s_error; - } - } - - /* Error or mount point encountered */ - if (rip == NIL_INODE) - { - if (err_code != EENTERMOUNT) - fs_m_out.RES_INODE_NR = 0; /* signal no inode */ - return err_code; - } - - fs_m_out.RES_INODE_NR = rip->i_num; - fs_m_out.RES_MODE = rip->i_mode; - fs_m_out.RES_FILE_SIZE = rip->i_size; - - if ( (rip->i_mode & I_TYPE) == I_BLOCK_SPECIAL) { - fs_m_out.RES_DEV = (dev_t) rip->i_zone[0]; - } - - /* Drop inode (path parse increased the counter) */ - put_inode(rip); - - return err_code; -} - - -/*===========================================================================* - * fs_lookup_s * + * fs_lookup * *===========================================================================*/ -PUBLIC int fs_lookup_s() +PUBLIC int fs_lookup() { - cp_grant_id_t grant; + cp_grant_id_t grant, grant2; int r, r1, len, flags, symlinks; - size_t offset, size; + size_t offset = 0, path_size, cred_size; ino_t dir_ino, root_ino; struct inode *rip; - grant= fs_m_in.REQ_L_GRANT; - size= fs_m_in.REQ_L_PATH_SIZE; /* Size of the buffer */ - len = fs_m_in.REQ_L_PATH_LEN; /* including terminating nul */ - offset= fs_m_in.REQ_L_PATH_OFF; /* offset in buffer */ - dir_ino= fs_m_in.REQ_L_DIR_INO; - root_ino= fs_m_in.REQ_L_ROOT_INO; - flags = fs_m_in.REQ_L_FLAGS; - caller_uid = fs_m_in.REQ_L_UID; - caller_gid = fs_m_in.REQ_L_GID; + grant = fs_m_in.REQ_GRANT; + path_size = fs_m_in.REQ_PATH_SIZE; /* Size of the buffer */ + len = fs_m_in.REQ_PATH_LEN; /* including terminating nul */ + dir_ino = fs_m_in.REQ_DIR_INO; + root_ino = fs_m_in.REQ_ROOT_INO; + flags = fs_m_in.REQ_FLAGS; /* Check length. */ - if(len > sizeof(user_path)) return E2BIG; /* too big for buffer */ - if(len < 1) - { - printf("mfs:fs_lookup_s: string too small.\n"); - return EINVAL; /* too small */ - } + if(len > sizeof(user_path)) return(E2BIG); /* too big for buffer */ + if(len < 1) return(EINVAL); /* too small */ /* Copy the pathname and set up caller's user and group id */ - r = sys_safecopyfrom(FS_PROC_NR, grant, offset, + r = sys_safecopyfrom(FS_PROC_NR, grant, /*offset*/ 0, (vir_bytes) user_path, (phys_bytes) len, D); - if (r != OK) { - printf("mfs:fs_lookup_s: sys_safecopyfrom failed: %d\n", r); - return r; + if(r != OK) { + printf("MFS %s:%d sys_safecopyfrom failed: %d\n", + __FILE__, __LINE__, r); + return(r); } /* Verify this is a null-terminated path. */ - if(user_path[len-1] != '\0') { - printf("mfs:fs_lookup_s: didn't get null-terminated string.\n"); - return EINVAL; + if(user_path[len - 1] != '\0') return(EINVAL); + + if(flags & PATH_GET_UCRED) { /* Do we have to copy uid/gid credentials? */ + int i; + grant2 = fs_m_in.REQ_GRANT2; + cred_size = fs_m_in.REQ_UCRED_SIZE; + + if (cred_size > sizeof(credentials)) return(EINVAL); /* Too big. */ + r = sys_safecopyfrom(FS_PROC_NR, grant2, 0, (vir_bytes) &credentials, + (phys_bytes) cred_size, D); + if (r != OK) { + printf("MFS %s:%d sys_safecopyfrom failed: %d\n", + __FILE__, __LINE__, r); + return(r); + } + caller_uid = credentials.vu_uid; + caller_gid = credentials.vu_gid; + } else { + memset(&credentials, 0, sizeof(credentials)); + caller_uid = fs_m_in.REQ_UID; + caller_gid = fs_m_in.REQ_GID; } -#if 0 - printf("mfs:fs_lookup_s: string '%s', ino %d, root %d\n", - user_path, dir_ino, root_ino); -#endif - /* Lookup inode */ - rip= NULL; - r = parse_path_s(dir_ino, root_ino, flags, &rip, &offset, &symlinks); - - if (symlinks != 0 && (r == ELEAVEMOUNT || r == EENTERMOUNT || r == ESYMLINK)) - { - len= strlen(user_path)+1; - if (len > size) - return ENAMETOOLONG; - r1 = sys_safecopyto(FS_PROC_NR, grant, 0, - (vir_bytes) user_path, (phys_bytes) len, D); - if (r1 != OK) { - printf("mfs:fs_lookup_s: sys_safecopyto failed: %d\n", r1); - return r1; + rip = NULL; + r = parse_path(dir_ino, root_ino, flags, &rip, &offset, &symlinks); + + if(symlinks != 0 && (r == ELEAVEMOUNT || r == EENTERMOUNT || r == ESYMLINK)){ + len = strlen(user_path)+1; + if(len > path_size) return(ENAMETOOLONG); + + r1 = sys_safecopyto(FS_PROC_NR, grant, 0, (vir_bytes) user_path, + (phys_bytes) len, D); + if(r1 != OK) { + printf("%s:%d fs_lookup: sys_safecopyto failed: %d\n", + __FILE__, __LINE__, r1); + return(r1); } -#if 0 - printf("mfs:fs_lookup_s: copied back path '%s', offset %d\n", - user_path, offset); -#endif } - if (r == ELEAVEMOUNT || r == ESYMLINK) - { - /* Report offset and the error */ - fs_m_out.RES_OFFSET = offset; - fs_m_out.RES_SYMLOOP = symlinks; -#if 0 - printf("mfs:fs_lookup_s: returning %d, offset %d\n", r, offset); -#endif - if (rip) panic(__FILE__, "fs_lookup_s: rip should be clear", - (unsigned)rip); - return r; - } + if(r == ELEAVEMOUNT || r == ESYMLINK) { + /* Report offset and the error */ + fs_m_out.RES_OFFSET = offset; + fs_m_out.RES_SYMLOOP = symlinks; - if (r != OK && r != EENTERMOUNT) - { - if (rip) panic(__FILE__, "fs_lookup_s: rip should be clear", - (unsigned)rip); - return r; + return(r); } - fs_m_out.RES_INODE_NR = rip->i_num; - fs_m_out.RES_MODE = rip->i_mode; - fs_m_out.RES_FILE_SIZE = rip->i_size; - fs_m_out.RES_OFFSET = offset; - fs_m_out.RES_SYMLOOP2 = symlinks; - fs_m_out.RES_UID = rip->i_uid; - fs_m_out.RES_GID = rip->i_gid; - - /* This is only valid for block and character specials. But it doesn't - * cause any harm to set RES_DEV always. - */ - fs_m_out.RES_DEV = (dev_t) rip->i_zone[0]; - - if (r == EENTERMOUNT) - put_inode(rip); /* Only return a reference to the final object */ - - return r; -} - + if (r != OK && r != EENTERMOUNT) return(r); -/*===========================================================================* - * parse_path_o * - *===========================================================================*/ -PUBLIC struct inode *parse_path_o(path, string, action) -char *path; /* the path name to be parsed */ -char string[NAME_MAX]; /* the final component is returned here */ -int action; /* action on last part of path */ -{ -/* This is the actual code for last_dir and eat_path. Return the inode of - * the last directory and the name of object within that directory, or the - * inode of the last object (an empty name will be returned). Names are - * returned in string. If string is null the name is discarded. The action - * code determines how "last" is defined. If an error occurs, NIL_INODE - * will be returned with an error code in err_code. - */ - - struct inode *rip, *dir_ip; - struct inode *ver_rip; - char *new_name; - char lstring[NAME_MAX]; + fs_m_out.RES_INODE_NR = rip->i_num; + fs_m_out.RES_MODE = rip->i_mode; + fs_m_out.RES_FILE_SIZE_LO = rip->i_size; + fs_m_out.RES_SYMLOOP = symlinks; + fs_m_out.RES_UID = rip->i_uid; + fs_m_out.RES_GID = rip->i_gid; - /* Find starting inode inode according to the request message */ - if ((rip = find_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) { - printf("mfs:parse_path: couldn't find starting inode %d for %s\n", - fs_m_in.REQ_INODE_NR, user_path); - err_code = ENOENT; - return NIL_INODE; - } - - /* Find chroot inode according to the request message */ - if (fs_m_in.REQ_CHROOT_NR != 0) { - if ((chroot_dir = find_inode(fs_dev, fs_m_in.REQ_CHROOT_NR)) - == NIL_INODE) { - printf("FS: couldn't find chroot inode\n"); - err_code = ENOENT; - return NIL_INODE; - } - } - else chroot_dir = NIL_INODE; - - /* Set user and group ID */ - caller_uid = fs_m_in.REQ_UID; - caller_gid = fs_m_in.REQ_GID; - - /* No characters were processed yet */ - path_processed = 0; - - /* Current number of symlinks encountered */ - Xsymloop = fs_m_in.REQ_SYMLOOP; - - /* If dir has been removed return ENOENT. */ - /* Note: empty (start) path is checked in the VFS process */ - if (rip->i_nlinks == 0/* || *path == '\0'*/) { - err_code = ENOENT; - return(NIL_INODE); - } - - /* There is only one way how the starting directory of the lookup - * can be a mount point which is not a root directory, - * namely: climbing up on a mount (ELEAVEMOUNT). - * In this case the lookup is intrested in the parent dir of the mount - * point, but the last ".." component was processed in the 'previous' - * FS process. Let's do that first. - */ - if (rip->i_mountpoint && rip->i_num != ROOT_INODE) { - dir_ip = rip; - rip = advance_o(&dir_ip, ".."); - if (rip == NIL_INODE) - { - return NIL_INODE; - } - put_inode(rip); /* advance() increased the counter */ - } + /* This is only valid for block and character specials. But it doesn't + * cause any harm to set RES_DEV always. */ + fs_m_out.RES_DEV = (dev_t) rip->i_zone[0]; - dup_inode(rip); /* inode will be returned with put_inode */ - - /* Looking for the starting directory? - * Note: this happens after EENTERMOUNT or ELEAVEMOUNT - * without more path component */ - if (*path == '\0') { - return rip; + if(r == EENTERMOUNT) { + fs_m_out.RES_OFFSET = offset; + put_inode(rip); /* Only return a reference to the final object */ } - if (string == (char *) 0) string = lstring; - - /* Scan the path component by component. */ - while (TRUE) { - int slashes = 0; - /* Extract one component. Skip slashes first. */ - while (path[slashes] == '/') { - slashes++; - path_processed++; - } - fs_m_out.RES_OFFSET = path_processed; /* For ENOENT */ - if ( (new_name = get_name(path+slashes, string)) == (char*) 0) { - put_inode(rip); /* bad path in user space */ - return(NIL_INODE); - } - if (*new_name == '\0' && (action & PATH_PENULTIMATE)) { - if ( (rip->i_mode & I_TYPE) == I_DIRECTORY) { - return(rip); /* normal exit */ - } else { - /* last file of path prefix is not a directory */ - put_inode(rip); - err_code = ENOTDIR; - return(NIL_INODE); - } - } - - /* There is more path. Keep parsing. */ - dir_ip = rip; - rip = advance_o(&dir_ip, string); - - /* Mount point encountered? */ - if (rip == NIL_INODE && (err_code == EENTERMOUNT || - err_code == ELEAVEMOUNT)) { - put_inode(dir_ip); - return NIL_INODE; - } - - if (rip == NIL_INODE) { - if (*new_name == '\0' && (action & PATH_NONSYMBOLIC) != 0) - { - return(dir_ip); - } - else if (err_code == ENOENT) - { - return(dir_ip); - } - else { - put_inode(dir_ip); - return(NIL_INODE); - } - } - - /* The call to advance() succeeded. Fetch next component. */ - if (S_ISLNK(rip->i_mode)) { - if (*new_name != '\0' || (action & PATH_OPAQUE) == 0) { - - if (*new_name != '\0') new_name--; - - /* Extract path name from the symlink file */ - if (ltraverse(rip, user_path, new_name, - sizeof(user_path)) != OK) { - put_inode(dir_ip); - err_code = ENOENT; - return NIL_INODE; - } - - /* Symloop limit reached? */ - if (++Xsymloop > SYMLOOP_MAX) { - put_inode(dir_ip); - err_code = ELOOP; - return NIL_INODE; - } - - /* Start over counting */ - path_processed = 0; - - /* Check whether new path is relative or absolute */ - if (user_path[0] == '/') { - /* Go back to VFS */ - put_inode(dir_ip); - err_code = ESYMLINK; - fs_m_out.RES_OFFSET = path_processed; - fs_m_out.RES_SYMLOOP = Xsymloop; - return NIL_INODE; - } - /* Path is relative */ - else { - rip = dir_ip; - path = user_path; - continue; - } - } - } - else if (*new_name != '\0') { - put_inode(dir_ip); - path = new_name; - continue; - } - - /* Either last name reached or symbolic link is opaque */ - if ((action & PATH_NONSYMBOLIC) != 0) { - put_inode(rip); - return(dir_ip); - } else { - put_inode(dir_ip); - return(rip); - } - } + return(r); } /*===========================================================================* - * parse_path_s * + * parse_path * *===========================================================================*/ -PRIVATE int parse_path_s(dir_ino, root_ino, flags, res_inop, offsetp, symlinkp) +PRIVATE int parse_path(dir_ino, root_ino, flags, res_inop, offsetp, symlinkp) ino_t dir_ino; ino_t root_ino; int flags; @@ -434,143 +154,96 @@ int *symlinkp; */ int r, leaving_mount; struct inode *rip, *dir_ip; - char *cp, *ncp; - char string[NAME_MAX+1]; -#if 0 - struct inode *ver_rip; - char *new_name; -#endif - - /* Find starting inode inode according to the request message */ - if ((rip = find_inode(fs_dev, dir_ino)) == NIL_INODE) { - printf("mfs:parse_path_s: couldn't find starting inode\n"); - return ENOENT; - } - dup_inode(rip); + char *cp, *next_cp; /* component and next component */ + char component[NAME_MAX+1]; - /* No characters were processed yet */ - cp= user_path; + /* Start parsing path at the first component in user_path */ + cp = user_path; /* No symlinks encountered yet */ *symlinkp = 0; + /* Find starting inode inode according to the request message */ + if((rip = find_inode(fs_dev, dir_ino)) == NIL_INODE) + return(ENOENT); + /* If dir has been removed return ENOENT. */ - if (rip->i_nlinks == 0) { - put_inode(rip); - return ENOENT; - } + if (rip->i_nlinks == 0) + return(ENOENT); + + dup_inode(rip); /* If the given start inode is a mountpoint, we must be here because the file * system mounted on top returned an ELEAVEMOUNT error. In this case, we must * only accept ".." as the first path component. */ - leaving_mount = rip->i_mountpoint; + leaving_mount = rip->i_mountpoint; /* True iff rip is a mountpoint */ /* Scan the path component by component. */ while (TRUE) { - if (cp[0] == '\0') - { - /* Empty path */ - *res_inop= rip; - *offsetp += cp-user_path; + if(cp[0] == '\0') { + /* We're done; either the path was empty or we've parsed all + components of the path */ + + *res_inop = rip; + *offsetp += cp - user_path; /* Return EENTERMOUNT if we are at a mount point */ - if (rip->i_mountpoint) - { - return EENTERMOUNT; - } - return OK; + if (rip->i_mountpoint) return(EENTERMOUNT); + + return(OK); } - if (cp[0] == '/') - { - /* Special case code. If the remaining path consists of just - * slashes, we need to look up '.' - */ - while(cp[0] == '/') - cp++; - if (cp[0] == '\0') - { - strcpy(string, "."); - ncp= cp; - } - else - ncp= get_name_s(cp, string); - } - else - { - /* Just get the first component */ - ncp= get_name_s(cp, string); - } + while(cp[0] == '/') cp++; + next_cp = get_name(cp, component); /* Special code for '..'. A process is not allowed to leave a chrooted * environment. A lookup of '..' at the root of a mounted filesystem * has to return ELEAVEMOUNT. In both cases, the caller needs search * permission for the current inode, as it is used as directory. */ - if (strcmp(string, "..") == 0) - { - if (rip->i_num == root_ino) - { - /* 'rip' is now accessed as directory */ - if ((r = forbidden(rip, X_BIT)) != OK) { - put_inode(rip); - return r; - } + if(strcmp(component, "..") == 0) { + /* 'rip' is now accessed as directory */ + if ((r = forbidden(rip, X_BIT)) != OK) { + put_inode(rip); + return(r); + } - cp= ncp; - continue; /* Just ignore the '..' at a process' - * root. - */ + if (rip->i_num == root_ino) { + cp = next_cp; + continue; /* Ignore the '..' at a process' root + and move on to the next component */ } + if (rip->i_num == ROOT_INODE && !rip->i_sp->s_is_root) { - /* Climbing up mountpoint */ - - /* 'rip' is now accessed as directory */ - if ((r = forbidden(rip, X_BIT)) != OK) { - put_inode(rip); - return r; - } + /* Climbing up to parent FS */ put_inode(rip); - *offsetp += cp-user_path; - return ELEAVEMOUNT; - } - } - else - { - /* Check for misbehaving child file systems. */ - if (leaving_mount) { - printf("mfs:parse_path_s: first component after " - "leaving mount is '%s'\n", string); - - /* DO NOT pass back EENTERMOUNT. We supposedly got here - * because the child file system treated the last path - * component as "..". It is likely to do that again. - */ - put_inode(rip); - return EINVAL; + *offsetp += cp - user_path; + return(ELEAVEMOUNT); } } /* Only check for a mount point if we are not coming from one. */ - if (!leaving_mount && rip->i_mountpoint) - { - *res_inop= rip; - *offsetp += cp-user_path; - return EENTERMOUNT; + if (!leaving_mount && rip->i_mountpoint) { + /* Going to enter a child FS */ + + *res_inop = rip; + *offsetp += cp - user_path; + return(EENTERMOUNT); } /* There is more path. Keep parsing. * If we're leaving a mountpoint, skip directory permission checks. */ dir_ip = rip; - r = advance_s1(dir_ip, leaving_mount ? dot2 : string, &rip); + rip = advance(dir_ip, leaving_mount ? dot2 : component, CHK_PERM); + if(err_code == ELEAVEMOUNT || err_code == EENTERMOUNT) + err_code = OK; - if (r != OK) - { + if (err_code != OK) { put_inode(dir_ip); - return r; + return(err_code); } leaving_mount = 0; @@ -578,116 +251,49 @@ int *symlinkp; /* The call to advance() succeeded. Fetch next component. */ if (S_ISLNK(rip->i_mode)) { - if (ncp[0] == '\0' && (flags & PATH_RET_SYMLINK)) - { + if (next_cp[0] == '\0' && (flags & PATH_RET_SYMLINK)) { put_inode(dir_ip); - *res_inop= rip; - *offsetp += ncp-user_path; - - return OK; + *res_inop = rip; + *offsetp += next_cp - user_path; + return(OK); } /* Extract path name from the symlink file */ - r= ltraverse_s(rip, ncp); - ncp= user_path; + r = ltraverse(rip, next_cp); + next_cp = user_path; + *offsetp = 0; /* Symloop limit reached? */ if (++(*symlinkp) > SYMLOOP_MAX) - r= ELOOP; + r = ELOOP; - /* Extract path name from the symlink file */ - if (r != OK) - { + if (r != OK) { put_inode(dir_ip); put_inode(rip); - return r; + return(r); } - if (ncp[0] == '/') - { + if (next_cp[0] == '/') { put_inode(dir_ip); put_inode(rip); - *offsetp= 0; - return ESYMLINK; + return(ESYMLINK); } put_inode(rip); dup_inode(dir_ip); - rip= dir_ip; - + rip = dir_ip; } put_inode(dir_ip); - cp= ncp; - } -} - -/*===========================================================================* - * ltraverse * - *===========================================================================*/ -PRIVATE int ltraverse(rip, path, suffix, pathlen) -register struct inode *rip; /* symbolic link */ -char *path; /* path containing link */ -char *suffix; /* suffix following link within path */ -int pathlen; -{ -/* Traverse a symbolic link. Copy the link text from the inode and insert - * the text into the path. Return error code or report success. Base - * directory has to be determined according to the first character of the - * new pathname. - */ - - block_t b; /* block containing link text */ - struct buf *bp; /* buffer containing link text */ - size_t sl; /* length of link */ - size_t tl; /* length of suffix */ - char *sp; /* start of link text */ - int r = OK; - - bp = NIL_BUF; - - if ((b = read_map(rip, (off_t) 0)) != NO_BLOCK) { - bp = get_block(rip->i_dev, b, NORMAL); - sl = rip->i_size; - sp = bp->b_data; - - /* Insert symbolic text into path name. */ - tl = strlen(suffix); - if (sl > 0 && sl + tl <= PATH_MAX-1) { - if(sl+tl >= pathlen) - panic(__FILE__,"path too small for symlink", sl+tl); - memmove(path+sl, suffix, tl); - memmove(path, sp, sl); - path[sl+tl] = 0; - - /* Copy back to VFS layer THIS SHOULD BE IN parse_path. - * sys_datacopy() error, if any, gets returned as r later. - */ - r = sys_datacopy(SELF_E, (vir_bytes) path, FS_PROC_NR, - (vir_bytes) vfs_slink_storage, (phys_bytes) sl+tl+1); - /* - dup_inode(bip = path[0] == '/' ? chroot_dir : ldip); - */ - if(r != OK) { - printf("mfs:%s:%d: sys_datacopy failed: %d\n", - __FILE__, __LINE__, r); - } - } else panic(__FILE__,"didn't copy symlink", sl+tl); - } - else { - r = ENOENT; + cp = next_cp; /* Process subsequent component in next round */ } - - put_block(bp, DIRECTORY_BLOCK); - put_inode(rip); - return r; } /*===========================================================================* - * ltraverse_s * + * ltraverse * *===========================================================================*/ -PRIVATE int ltraverse_s(rip, suffix) +PRIVATE int ltraverse(rip, suffix) register struct inode *rip; /* symbolic link */ char *suffix; /* current remaining path. Has to point in the * user_path buffer @@ -699,193 +305,94 @@ char *suffix; /* current remaining path. Has to point in the * new pathname. */ - block_t b; /* block containing link text */ - size_t sl; /* length of link */ - size_t tl; /* length of suffix */ - struct buf *bp; /* buffer containing link text */ - char *sp; /* start of link text */ -#if 0 - int r = OK; -#endif + block_t blink; /* block containing link text */ + size_t llen; /* length of link */ + size_t slen; /* length of suffix */ + struct buf *bp; /* buffer containing link text */ + char *sp; /* start of link text */ bp = NIL_BUF; - if ((b = read_map(rip, (off_t) 0)) == NO_BLOCK) - return EIO; + if ((blink = read_map(rip, (off_t) 0)) == NO_BLOCK) + return(EIO); - bp = get_block(rip->i_dev, b, NORMAL); - sl = rip->i_size; + bp = get_block(rip->i_dev, blink, NORMAL); + llen = rip->i_size; sp = bp->b_data; - - tl = strlen(suffix); - if (tl > 0) - { + slen = strlen(suffix); + + /* The path we're parsing looks like this: + * /already/processed/path/ or + * /already/processed/path//not/yet/processed/path + * After expanding the , the path will look like + * or + * /not/yet/processed + * In both cases user_path must have enough room to hold . + * However, in the latter case we have to move /not/yet/processed to the + * right place first, before we expand . When strlen() is + * smaller than strlen(/already/processes/path), we move the suffix to the + * left. Is strlen() greater then we move it to the right. Else + * we do nothing. */ + + if (slen > 0) { /* Do we have path after the link? */ /* For simplicity we require that suffix starts with a slash */ - if (suffix[0] != '/') - { + if (suffix[0] != '/') { panic(__FILE__, - "ltraverse_s: suffix does not start with a slash", + "ltraverse: suffix does not start with a slash", NO_NUM); } - /* Move suffix to the right place */ - if (sl + tl + 1 > sizeof(user_path)) - return ENAMETOOLONG; - if (suffix-user_path != sl) - memmove(&user_path[sl], suffix, tl+1); - } - else - { + /* To be able to expand the , we have to move the 'suffix' + * to the right place. */ + if (slen + llen + 1 > sizeof(user_path)) + return(ENAMETOOLONG);/* +suffix+\0 does not fit*/ + if (suffix-user_path != llen) /* Move suffix left or right if needed */ + memmove(&user_path[llen], suffix, slen+1); + } else { + if (llen + 1 > sizeof(user_path)) + return(ENAMETOOLONG); /* + \0 does not fix */ + /* Set terminating nul */ - user_path[sl]= '\0'; + user_path[llen]= '\0'; } - memmove(user_path, sp, sl); -#if 0 - printf("mfs:ltraverse_s: new path '%s'\n", user_path); -#endif - + /* Everything is set, now copy the expanded link to user_path */ + memmove(user_path, sp, llen); + put_block(bp, DIRECTORY_BLOCK); - return OK; + return(OK); } /*===========================================================================* - * advance_nocheck * + * advance * *===========================================================================*/ -PUBLIC struct inode *advance_nocheck(pdirp, string) -struct inode **pdirp; /* inode for directory to be searched */ +PUBLIC struct inode *advance(dirp, string, chk_perm) +struct inode *dirp; /* inode for directory to be searched */ char string[NAME_MAX]; /* component name to look for */ +int chk_perm; /* check permissions when string is looked up*/ { /* Given a directory and a component of a path, look up the component in * the directory, find the inode, open it, and return a pointer to its inode - * slot. If it can't be done, return NIL_INODE. + * slot. */ - - register struct inode *rip, *dirp; - register struct super_block *sp; - int r, inumb; - dev_t mnt_dev; ino_t numb; + struct inode *rip; - dirp = *pdirp; - - /* Check for NIL_INODE. */ - if (dirp == NIL_INODE) { return(NIL_INODE); } - - /* If 'string' is empty, yield same inode straight away. */ - /* This code won't trigger anymore with the current VFS path lookup logic. */ - if (string[0] == '\0') { return(get_inode(dirp->i_dev, (int) dirp->i_num)); } - - /* If 'string' is not present in the directory, signal error. */ - if ( (r = search_dir_nocheck(dirp, string, &numb, LOOK_UP)) != OK) { - err_code = r; - return(NIL_INODE); - } - - /* Don't go beyond the current root directory, unless the string is dot2. - * Note: it has to be checked only if this FS process owns the chroot - * directory of the process */ - if (chroot_dir != NIL_INODE) { - if (dirp == chroot_dir && strcmp(string, "..") == 0 && string != dot2) - return(get_inode(dirp->i_dev, (int) dirp->i_num)); - } - - /* The component has been found in the directory. Get inode. */ - if ( (rip = get_inode(dirp->i_dev, (int) numb)) == NIL_INODE) { + /* If 'string' is empty, return an error. */ + if (string[0] == '\0') { + err_code = ENOENT; return(NIL_INODE); } - /* The following test is for "mountpoint/.." where mountpoint is a - * mountpoint. ".." will refer to the root of the mounted filesystem, - * but has to become a reference to the parent of the 'mountpoint' - * directory. - * - * This case is recognized by the looked up name pointing to a - * root inode, and the directory in which it is held being a - * root inode, _and_ the name[1] being '.'. (This is a test for '..' - * and excludes '.'.) - */ - if (rip->i_num == ROOT_INODE) { - if (dirp->i_num == ROOT_INODE) { - if (string[1] == '.') { - sp = rip->i_sp; - if (!sp->s_is_root) { -/*printf("FSadvance: ELEAVEMOUNT callnr: %d, cp: %d, restp: %s\n", - call_nr, Xpath_processed, user_path + Xpath_processed);*/ - - /* Climbing up mountpoint */ - err_code = ELEAVEMOUNT; - /* This will be the FS process endoint */ - fs_m_out.m_source = rip->i_dev; - fs_m_out.RES_OFFSET = path_processed; - fs_m_out.RES_SYMLOOP = Xsymloop; - put_inode(rip); - /*put_inode(dirp);*/ - rip = NIL_INODE; - } - } - } - } - - /* See if the inode is mounted on. If so, switch to root directory of the - * mounted file system. The super_block provides the linkage between the - * inode mounted on and the root directory of the mounted file system. - */ - if (rip != NIL_INODE && rip->i_mountpoint) { - - /* Mountpoint encountered, report it */ - err_code = EENTERMOUNT; - fs_m_out.RES_INODE_NR = rip->i_num; - fs_m_out.RES_OFFSET = path_processed; - fs_m_out.RES_SYMLOOP = Xsymloop; - put_inode(rip); - rip = NIL_INODE; - } - return(rip); /* return pointer to inode's component */ -} - - -/*===========================================================================* - * advance_o * - *===========================================================================*/ -PUBLIC struct inode *advance_o(pdirp, string) -struct inode **pdirp; /* inode for directory to be searched */ -char string[NAME_MAX]; /* component name to look for */ -{ -/* Given a directory and a component of a path, look up the component in - * the directory, find the inode, open it, and return a pointer to its inode - * slot. If it can't be done, return NIL_INODE. - */ - - register struct inode *rip, *dirp; - register struct super_block *sp; - int r, inumb; - dev_t mnt_dev; - ino_t numb; - - dirp = *pdirp; - /* Check for NIL_INODE. */ - if (dirp == NIL_INODE) { return(NIL_INODE); } - - /* If 'string' is empty, yield same inode straight away. */ - if (string[0] == '\0') { return(get_inode(dirp->i_dev, (int) dirp->i_num)); } + if (dirp == NIL_INODE) return(NIL_INODE); /* If 'string' is not present in the directory, signal error. */ - if ( (r = search_dir(dirp, string, &numb, LOOK_UP)) != OK) { - err_code = r; + if ( (err_code = search_dir(dirp, string, &numb, LOOK_UP, chk_perm)) != OK) { return(NIL_INODE); } - /* Don't go beyond the current root directory, unless the string is dot2. - * Note: it has to be checked only if this FS process owns the chroot - * directory of the process */ - if (chroot_dir != NIL_INODE) { - if (dirp == chroot_dir && strcmp(string, "..") == 0 && string != dot2) - return(get_inode(dirp->i_dev, (int) dirp->i_num)); - } - /* The component has been found in the directory. Get inode. */ if ( (rip = get_inode(dirp->i_dev, (int) numb)) == NIL_INODE) { return(NIL_INODE); @@ -904,18 +411,9 @@ char string[NAME_MAX]; /* component name to look for */ if (rip->i_num == ROOT_INODE) { if (dirp->i_num == ROOT_INODE) { if (string[1] == '.') { - sp = rip->i_sp; - if (!sp->s_is_root) { - + if (!rip->i_sp->s_is_root) { /* Climbing up mountpoint */ err_code = ELEAVEMOUNT; - /* This will be the FS process endoint */ - fs_m_out.m_source = rip->i_dev; - fs_m_out.RES_OFFSET = path_processed; - fs_m_out.RES_SYMLOOP = Xsymloop; - put_inode(rip); - /*put_inode(dirp);*/ - rip = NIL_INODE; } } } @@ -926,106 +424,18 @@ char string[NAME_MAX]; /* component name to look for */ * inode mounted on and the root directory of the mounted file system. */ if (rip != NIL_INODE && rip->i_mountpoint) { - /* Mountpoint encountered, report it */ err_code = EENTERMOUNT; - fs_m_out.RES_INODE_NR = rip->i_num; - fs_m_out.RES_OFFSET = path_processed; - fs_m_out.RES_SYMLOOP = Xsymloop; - put_inode(rip); - rip = NIL_INODE; } - return(rip); /* return pointer to inode's component */ -} - -/*===========================================================================* - * advance_s1 * - *===========================================================================*/ -PRIVATE int advance_s1(dirp, string, resp) -struct inode *dirp; /* inode for directory to be searched */ -char string[NAME_MAX]; /* component name to look for */ -struct inode **resp; /* resulting inode */ -{ -/* Given a directory and a component of a path, look up the component in - * the directory, find the inode, open it, and return a pointer to its inode - * slot. - */ - int r; - ino_t numb; - struct inode *rip; - - /* If 'string' is empty, return an error. */ - if (string[0] == '\0') return ENOENT; - - /* Check for NIL_INODE. */ - if (dirp == NIL_INODE) panic(__FILE__, "advance_s: nil dirp", NO_NUM); - - /* If 'string' is not present in the directory, signal error. */ - if ( (r = search_dir(dirp, string, &numb, LOOK_UP)) != OK) { - return(r); - } - - /* The component has been found in the directory. Get inode. */ - if ( (rip = get_inode(dirp->i_dev, (int) numb)) == NIL_INODE) { - return(err_code); - } - - *resp= rip; - return OK; + return(rip); } /*===========================================================================* * get_name * *===========================================================================*/ -PRIVATE char *get_name(old_name, string) -char *old_name; /* path name to parse */ -char string[NAME_MAX]; /* component extracted from 'old_name' */ -{ -/* Given a pointer to a path name in fs space, 'old_name', copy the next - * component to 'string' and pad with zeros. A pointer to that part of - * the name as yet unparsed is returned. Roughly speaking, - * 'get_name' = 'old_name' - 'string'. - * - * This routine follows the standard convention that /usr/ast, /usr//ast, - * //usr///ast and /usr/ast/ are all equivalent. - */ - - register int c; - register char *np, *rnp; - - np = string; /* 'np' points to current position */ - rnp = old_name; /* 'rnp' points to unparsed string */ - - c = *rnp; - /* Copy the unparsed path, 'old_name', to the array, 'string'. */ - while ( rnp < &old_name[PATH_MAX] && c != '/' && c != '\0') { - if (np < &string[NAME_MAX]) *np++ = c; - c = *++rnp; /* advance to next character */ - path_processed++; /* count characters */ - } - - /* To make /usr/ast/ equivalent to /usr/ast, skip trailing slashes. */ - while (c == '/' && rnp < &old_name[PATH_MAX]) { - c = *++rnp; - path_processed++; /* count characters */ - } - - if (np < &string[NAME_MAX]) *np = '\0'; /* Terminate string */ - - if (rnp >= &old_name[PATH_MAX]) { - err_code = ENAMETOOLONG; - return((char *) 0); - } - return(rnp); -} - - -/*===========================================================================* - * get_name_s * - *===========================================================================*/ -PRIVATE char *get_name_s(path_name, string) +PRIVATE char *get_name(path_name, string) char *path_name; /* path name to parse */ char string[NAME_MAX+1]; /* component extracted from 'old_name' */ { @@ -1033,7 +443,7 @@ char string[NAME_MAX+1]; /* component extracted from 'old_name' */ * component to 'string' (truncated if necessary, always nul terminated). * A pointer to the string after the first component of the name as yet * unparsed is returned. Roughly speaking, - * 'get_name_s' = 'path_name' - 'string'. + * 'get_name' = 'path_name' - 'string'. * * This routine follows the standard convention that /usr/ast, /usr//ast, * //usr///ast and /usr/ast/ are all equivalent. @@ -1041,46 +451,43 @@ char string[NAME_MAX+1]; /* component extracted from 'old_name' */ size_t len; char *cp, *ep; - cp= path_name; + cp = path_name; /* Skip leading slashes */ - while (cp[0] == '/') - cp++; + while (cp[0] == '/') cp++; /* Find the end of the first component */ - ep= cp; + ep = cp; while(ep[0] != '\0' && ep[0] != '/') ep++; - len= ep-cp; + len = ep - cp; /* Truncate the amount to be copied if it exceeds NAME_MAX */ if (len > NAME_MAX) - len= NAME_MAX; + len = NAME_MAX; /* Special case of the string at cp is empty */ - if (len == 0) - { - /* Return "." */ - strcpy(string, "."); - } - else - { + if (len == 0) + strcpy(string, "."); /* Return "." */ + else { memcpy(string, cp, len); string[len]= '\0'; } - return ep; + return(ep); } + /*===========================================================================* * search_dir * *===========================================================================*/ -PUBLIC int search_dir(ldir_ptr, string, numb, flag) +PUBLIC int search_dir(ldir_ptr, string, numb, flag, check_permissions) register struct inode *ldir_ptr; /* ptr to inode for dir to search */ char string[NAME_MAX]; /* component to search for */ ino_t *numb; /* pointer to inode number */ int flag; /* LOOK_UP, ENTER, DELETE or IS_EMPTY */ +int check_permissions; /* check permissions when flag is !IS_EMPTY */ { /* This function searches the directory whose inode is pointed to by 'ldip': * if (flag == ENTER) enter 'string' in the directory with inode # '*numb'; @@ -1114,157 +521,9 @@ int flag; /* LOOK_UP, ENTER, DELETE or IS_EMPTY */ if (string == dot1 || string == dot2) { if (flag != LOOK_UP) r = read_only(ldir_ptr); /* only a writable device is required. */ - } - else r = forbidden(ldir_ptr, bits); /* check access permissions */ - } - if (r != OK) return(r); - - /* Step through the directory one block at a time. */ - old_slots = (unsigned) (ldir_ptr->i_size/DIR_ENTRY_SIZE); - new_slots = 0; - e_hit = FALSE; - match = 0; /* set when a string match occurs */ - - for (pos = 0; pos < ldir_ptr->i_size; pos += ldir_ptr->i_sp->s_block_size) { - b = read_map(ldir_ptr, pos); /* get block number */ - - /* Since directories don't have holes, 'b' cannot be NO_BLOCK. */ - bp = get_block(ldir_ptr->i_dev, b, NORMAL); /* get a dir block */ - - if (bp == NO_BLOCK) - panic(__FILE__,"get_block returned NO_BLOCK", NO_NUM); - - /* Search a directory block. */ - for (dp = &bp->b_dir[0]; - dp < &bp->b_dir[NR_DIR_ENTRIES(ldir_ptr->i_sp->s_block_size)]; - dp++) { - if (++new_slots > old_slots) { /* not found, but room left */ - if (flag == ENTER) e_hit = TRUE; - break; - } - - /* Match occurs if string found. */ - if (flag != ENTER && dp->d_ino != 0) { - if (flag == IS_EMPTY) { - /* If this test succeeds, dir is not empty. */ - if (strcmp(dp->d_name, "." ) != 0 && - strcmp(dp->d_name, "..") != 0) match = 1; - } else { - if (strncmp(dp->d_name, string, NAME_MAX) == 0){ - match = 1; - } - } - } - - if (match) { - /* LOOK_UP or DELETE found what it wanted. */ - r = OK; - if (flag == IS_EMPTY) r = ENOTEMPTY; - else if (flag == DELETE) { - /* Save d_ino for recovery. */ - t = NAME_MAX - sizeof(ino_t); - *((ino_t *) &dp->d_name[t]) = dp->d_ino; - dp->d_ino = 0; /* erase entry */ - bp->b_dirt = DIRTY; - ldir_ptr->i_update |= CTIME | MTIME; - ldir_ptr->i_dirt = DIRTY; - } else { - sp = ldir_ptr->i_sp; /* 'flag' is LOOK_UP */ - *numb = conv4(sp->s_native, (int) dp->d_ino); - } - put_block(bp, DIRECTORY_BLOCK); - return(r); - } - - /* Check for free slot for the benefit of ENTER. */ - if (flag == ENTER && dp->d_ino == 0) { - e_hit = TRUE; /* we found a free slot */ - break; - } + } else if(check_permissions) { + r = forbidden(ldir_ptr, bits); /* check access permissions */ } - - /* The whole block has been searched or ENTER has a free slot. */ - if (e_hit) break; /* e_hit set if ENTER can be performed now */ - put_block(bp, DIRECTORY_BLOCK); /* otherwise, continue searching dir */ - } - - /* The whole directory has now been searched. */ - if (flag != ENTER) { - return(flag == IS_EMPTY ? OK : ENOENT); - } - - /* This call is for ENTER. If no free slot has been found so far, try to - * extend directory. - */ - if (e_hit == FALSE) { /* directory is full and no room left in last block */ - new_slots++; /* increase directory size by 1 entry */ - if (new_slots == 0) return(EFBIG); /* dir size limited by slot count */ - if ( (bp = new_block(ldir_ptr, ldir_ptr->i_size)) == NIL_BUF) - return(err_code); - dp = &bp->b_dir[0]; - extended = 1; - } - - /* 'bp' now points to a directory block with space. 'dp' points to slot. */ - (void) memset(dp->d_name, 0, (size_t) NAME_MAX); /* clear entry */ - for (i = 0; i < NAME_MAX && string[i]; i++) dp->d_name[i] = string[i]; - sp = ldir_ptr->i_sp; - dp->d_ino = conv4(sp->s_native, (int) *numb); - bp->b_dirt = DIRTY; - put_block(bp, DIRECTORY_BLOCK); - ldir_ptr->i_update |= CTIME | MTIME; /* mark mtime for update later */ - ldir_ptr->i_dirt = DIRTY; - if (new_slots > old_slots) { - ldir_ptr->i_size = (off_t) new_slots * DIR_ENTRY_SIZE; - /* Send the change to disk if the directory is extended. */ - if (extended) rw_inode(ldir_ptr, WRITING); - } - return(OK); -} - - -/*===========================================================================* - * search_dir_nocheck * - *===========================================================================*/ -PUBLIC int search_dir_nocheck(ldir_ptr, string, numb, flag) -register struct inode *ldir_ptr; /* ptr to inode for dir to search */ -char string[NAME_MAX]; /* component to search for */ -ino_t *numb; /* pointer to inode number */ -int flag; /* LOOK_UP, ENTER, DELETE or IS_EMPTY */ -{ -/* This function searches the directory whose inode is pointed to by 'ldip': - * if (flag == ENTER) enter 'string' in the directory with inode # '*numb'; - * if (flag == DELETE) delete 'string' from the directory; - * if (flag == LOOK_UP) search for 'string' and return inode # in 'numb'; - * if (flag == IS_EMPTY) return OK if only . and .. in dir else ENOTEMPTY; - * - * if 'string' is dot1 or dot2, no access permissions are checked. - */ - - register struct direct *dp = NULL; - register struct buf *bp = NULL; - int i, r, e_hit, t, match; - mode_t bits; - off_t pos; - unsigned new_slots, old_slots; - block_t b; - struct super_block *sp; - int extended = 0; - - /* If 'ldir_ptr' is not a pointer to a dir inode, error. */ - if ( (ldir_ptr->i_mode & I_TYPE) != I_DIRECTORY) { - return(ENOTDIR); - } - - r = OK; - - if (flag != IS_EMPTY) { - bits = (flag == LOOK_UP ? X_BIT : W_BIT | X_BIT); - - if (string == dot1 || string == dot2) { - if (flag != LOOK_UP) r = read_only(ldir_ptr); - /* only a writable device is required. */ - } } if (r != OK) return(r); @@ -1371,35 +630,3 @@ int flag; /* LOOK_UP, ENTER, DELETE or IS_EMPTY */ return(OK); } - -/*===========================================================================* - * eat_path_o * - *===========================================================================*/ -PUBLIC struct inode *eat_path_o(path) -char *path; /* the path name to be parsed */ -{ - /* Parse the path 'path' and put its inode in the inode table. If not possible, - * return NIL_INODE as function value and an error code in 'err_code'. - */ - - return parse_path_o(path, (char *) 0, EAT_PATH); -} - -/*===========================================================================* - * last_dir_o * - *===========================================================================*/ -PUBLIC struct inode *last_dir_o(path, string) -char *path; /* the path name to be parsed */ -char string[NAME_MAX]; /* the final component is returned here */ -{ -/* Given a path, 'path', located in the fs address space, parse it as - * far as the last directory, fetch the inode for the last directory into - * the inode table, and return a pointer to the inode. In - * addition, return the final component of the path in 'string'. - * If the last directory can't be opened, return NIL_INODE and - * the reason for failure in 'err_code'. - */ - - return parse_path_o(path, string, LAST_DIR); -} - diff --git a/servers/mfs/pipe.c b/servers/mfs/pipe.c index 1d9e4c26d..e69de29bb 100644 --- a/servers/mfs/pipe.c +++ b/servers/mfs/pipe.c @@ -1,54 +0,0 @@ - -#include "fs.h" -#include -#include -#include -#include -#include -#include -#include -#include "inode.h" -#include "super.h" - -#include - - - -/*===========================================================================* - * fs_pipe * - *===========================================================================*/ -PUBLIC int fs_pipe(void) -{ - struct inode *rip; - - /* Get caller's user and group id from the request */ - caller_uid = fs_m_in.REQ_UID; - caller_gid = fs_m_in.REQ_GID; - - /* Try to allocate the inode */ - if ( (rip = alloc_inode(fs_dev, I_REGULAR) ) == NIL_INODE) { - return err_code; - } - - /* Fill in the fields of the inode */ - rip->i_pipe = I_PIPE; - rip->i_mode &= ~I_REGULAR; - rip->i_mode |= I_NAMED_PIPE; /* pipes and FIFOs have this bit set */ - - /* We'll need it twice, nothing can go wrong here */ - rw_inode(rip, WRITING); /* mark inode as allocated */ - rip->i_update = ATIME | CTIME | MTIME; - - /* Fill in the fields of the response message */ - fs_m_out.m_source = fs_dev; /* filled with FS endpoint by the system */ - fs_m_out.RES_INODE_NR = rip->i_num; - fs_m_out.RES_MODE = rip->i_mode; - fs_m_out.RES_INODE_INDEX = (rip - &inode[0]) / sizeof(struct inode); - fs_m_out.RES_FILE_SIZE = rip->i_size; - fs_m_out.RES_UID = rip->i_uid; - fs_m_out.RES_GID = rip->i_gid; - - return OK; -} - - diff --git a/servers/mfs/protect.c b/servers/mfs/protect.c index 025e9ee95..4a451d986 100644 --- a/servers/mfs/protect.c +++ b/servers/mfs/protect.c @@ -1,14 +1,13 @@ - - #include "fs.h" #include #include #include "buf.h" #include "inode.h" #include "super.h" - #include +FORWARD _PROTOTYPE( in_group, (gid_t grp) ); + /*===========================================================================* * fs_chmod * @@ -21,10 +20,8 @@ PUBLIC int fs_chmod() register int r; /* Temporarily open the file. */ - if ( (rip = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) { -printf("MFS(%d) get_inode by fs_chmod() failed\n", SELF_E); - return(EINVAL); - } + if( (rip = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) + return(EINVAL); /* Now make the change. Clear setgid bit if file is not in caller's grp */ rip->i_mode = (rip->i_mode & ~ALL_MODES) | (fs_m_in.REQ_MODE & ALL_MODES); @@ -46,58 +43,29 @@ PUBLIC int fs_chown() { register struct inode *rip; register int r; + /* Temporarily open the file. */ - caller_uid = fs_m_in.REQ_UID; - caller_gid = fs_m_in.REQ_GID; - - /* Temporarily open the file. */ - if ( (rip = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) { -printf("MFS(%d) get_inode by fs_chown() failed\n", SELF_E); - return(EINVAL); - } + if( (rip = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) + return(EINVAL); /* Not permitted to change the owner of a file on a read-only file sys. */ r = read_only(rip); if (r == OK) { - rip->i_uid = fs_m_in.REQ_NEW_UID; - rip->i_gid = fs_m_in.REQ_NEW_GID; - rip->i_mode &= ~(I_SET_UID_BIT | I_SET_GID_BIT); - rip->i_update |= CTIME; - rip->i_dirt = DIRTY; + rip->i_uid = fs_m_in.REQ_UID; + rip->i_gid = fs_m_in.REQ_GID; + rip->i_mode &= ~(I_SET_UID_BIT | I_SET_GID_BIT); + rip->i_update |= CTIME; + rip->i_dirt = DIRTY; } /* Update caller on current mode, as it may have changed. */ fs_m_out.RES_MODE = rip->i_mode; - put_inode(rip); - - return(r); -} - -/*===========================================================================* - * fs_access_o * - *===========================================================================*/ -PUBLIC int fs_access_o() -{ - struct inode *rip; - register int r; - - /* Temporarily open the file whose access is to be checked. */ - caller_uid = fs_m_in.REQ_UID; - caller_gid = fs_m_in.REQ_GID; - /* Temporarily open the file. */ - if ( (rip = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) { -printf("MFS(%d) get_inode by fs_access() failed\n", SELF_E); - return(EINVAL); - } - - /* Now check the permissions. */ - r = forbidden(rip, (mode_t) fs_m_in.REQ_MODE); - put_inode(rip); return(r); } + /*===========================================================================* * forbidden * *===========================================================================*/ @@ -112,22 +80,7 @@ PUBLIC int forbidden(register struct inode *rip, mode_t access_desired) register struct inode *old_rip = rip; register struct super_block *sp; register mode_t bits, perm_bits; - int r, shift, type; - - if (caller_uid == (uid_t)-1 && caller_gid == (uid_t)-1) - { - printf( - "forbidden: warning caller_uid and caller_gid not initialized\n"); - } - - /* - if (rip->i_mount == I_MOUNT) - for (sp = &super_block[1]; sp < &super_block[NR_SUPERS]; sp++) - if (sp->s_imount == rip) { - rip = get_inode(sp->s_dev, ROOT_INODE); - break; - } - */ + int r, shift; /* Isolate the relevant rwx bits from the mode. */ bits = rip->i_mode; @@ -143,7 +96,8 @@ PUBLIC int forbidden(register struct inode *rip, mode_t access_desired) perm_bits = R_BIT | W_BIT; } else { if (caller_uid == rip->i_uid) shift = 6; /* owner */ - else if (caller_gid == rip->i_gid ) shift = 3; /* group */ + else if (caller_gid == rip->i_gid) shift = 3; /* group */ + else if (in_group(rip->i_gid) == OK) shift = 3; /* other groups */ else shift = 0; /* other */ perm_bits = (bits >> shift) & (R_BIT | W_BIT | X_BIT); } @@ -155,22 +109,30 @@ PUBLIC int forbidden(register struct inode *rip, mode_t access_desired) /* Check to see if someone is trying to write on a file system that is * mounted read-only. */ - type = rip->i_mode & I_TYPE; if (r == OK) if (access_desired & W_BIT) r = read_only(rip); -#if 0 - if (r != OK) printf( - "forbidden: caller uid/gid %d/%d object uid/gid %d/%d, returning %d\n", - caller_uid, caller_gid, rip->i_uid, rip->i_gid, r); -#endif - if (rip != old_rip) put_inode(rip); return(r); } + +/*===========================================================================* + * in_group * + *===========================================================================*/ +PRIVATE int in_group(gid_t grp) +{ + int i; + for(i = 0; i < credentials.vu_ngroups; i++) + if (credentials.vu_sgroups[i] == grp) + return(OK); + + return(EINVAL); +} + + /*===========================================================================* * read_only * *===========================================================================*/ @@ -187,5 +149,3 @@ struct inode *ip; /* ptr to inode whose file sys is to be cked */ return(sp->s_rd_only ? EROFS : OK); } - - diff --git a/servers/mfs/proto.h b/servers/mfs/proto.h index 96549c492..cb4a403d8 100644 --- a/servers/mfs/proto.h +++ b/servers/mfs/proto.h @@ -1,7 +1,5 @@ /* Function prototypes. */ -#include "timers.h" - /* Structs used in prototypes must be declared as such first. */ struct buf; struct filp; @@ -9,32 +7,9 @@ struct inode; struct super_block; -int fs_putnode(void); -int fs_getnode(void); -int fs_pipe(void); -int fs_clone_opcl(void); -int fs_new_driver(void); -int fs_ftrunc(void); -int fs_chown(void); -int fs_chmod(void); -int fs_inhibread(void); -int fs_stat(void); -int fs_utime(void); -int fs_fstatfs(void); - -int fs_unmount(void); -int fs_trunc(void); -int fs_sync(void); -int fs_stime(void); - -int fs_getdents_o(void); -int fs_getdents(void); -int fs_flush(void); - -void init_inode_cache(void); - /* cache.c */ _PROTOTYPE( zone_t alloc_zone, (Dev_t dev, zone_t z) ); +_PROTOTYPE( void buf_pool, (void) ); _PROTOTYPE( void flushall, (Dev_t dev) ); _PROTOTYPE( void free_zone, (Dev_t dev, zone_t numb) ); _PROTOTYPE( struct buf *get_block, (Dev_t dev, block_t block,int only_search)); @@ -43,7 +18,6 @@ _PROTOTYPE( void put_block, (struct buf *bp, int block_type) ); _PROTOTYPE( void set_blocksize, (int blocksize) ); _PROTOTYPE( void rw_scattered, (Dev_t dev, struct buf **bufq, int bufqsize, int rw_flag) ); -_PROTOTYPE( void buf_pool, (void) ); /* device.c */ _PROTOTYPE( int block_dev_io, (int op, Dev_t dev, int proc, void *buf, @@ -51,14 +25,17 @@ _PROTOTYPE( int block_dev_io, (int op, Dev_t dev, int proc, void *buf, _PROTOTYPE( int dev_open, (endpoint_t driver_e, Dev_t dev, int proc, int flags) ); _PROTOTYPE( void dev_close, (endpoint_t driver_e, Dev_t dev) ); - +_PROTOTYPE( int fs_clone_opcl, (void) ); +_PROTOTYPE( int fs_new_driver, (void) ); /* inode.c */ -_PROTOTYPE( struct inode *find_inode, (Dev_t dev, int numb) ); - _PROTOTYPE( struct inode *alloc_inode, (dev_t dev, mode_t bits) ); _PROTOTYPE( void dup_inode, (struct inode *ip) ); +_PROTOTYPE( struct inode *find_inode, (Dev_t dev, int numb) ); _PROTOTYPE( void free_inode, (Dev_t dev, Ino_t numb) ); +_PROTOTYPE( int fs_getnode, (void) ); +_PROTOTYPE( int fs_putnode, (void) ); +_PROTOTYPE( void init_inode_cache, (void) ); _PROTOTYPE( struct inode *get_inode, (Dev_t dev, int numb) ); _PROTOTYPE( void put_inode, (struct inode *rip) ); _PROTOTYPE( void update_times, (struct inode *rip) ); @@ -66,66 +43,53 @@ _PROTOTYPE( void rw_inode, (struct inode *rip, int rw_flag) ); _PROTOTYPE( void wipe_inode, (struct inode *rip) ); /* link.c */ -int fs_link_o(void); -int fs_link_s(void); -int fs_rdlink_o(void); -int fs_rdlink_so(void); -int fs_rdlink_s(void); -int fs_rename_o(void); -int fs_rename_s(void); -int fs_unlink_o(void); -int fs_unlink_s(void); -_PROTOTYPE( int truncate_inode, (struct inode *rip, off_t len) ); _PROTOTYPE( int freesp_inode, (struct inode *rip, off_t st, off_t end) ); +_PROTOTYPE( int fs_ftrunc, (void) ); +_PROTOTYPE( int fs_link, (void) ); +_PROTOTYPE( int fs_rdlink, (void) ); +_PROTOTYPE( int fs_rename, (void) ); +_PROTOTYPE( int fs_unlink, (void) ); +_PROTOTYPE( int truncate_inode, (struct inode *rip, off_t len) ); /* main.c */ _PROTOTYPE( void reply, (int who, message *m_out) ); +/* misc.c */ +_PROTOTYPE( int fs_flush, (void) ); +_PROTOTYPE( int fs_sync, (void) ); + /* mount.c */ -int fs_mountpoint_o(void); -int fs_mountpoint_s(void); -int fs_readsuper_o(void); -int fs_readsuper_s(void); -_PROTOTYPE( int unmount, (Dev_t dev) ); +_PROTOTYPE( int fs_mountpoint, (void) ); +_PROTOTYPE( int fs_readsuper, (void) ); +_PROTOTYPE( int fs_unmount, (void) ); /* open.c */ -int fs_create_o(void); -int fs_create_s(void); -int fs_mkdir_o(void); -int fs_mkdir_s(void); -int fs_mknod_o(void); -int fs_mknod_s(void); -int fs_slink_o(void); -int fs_slink_s(void); -int fs_newnode(void); +_PROTOTYPE( int fs_create, (void) ); +_PROTOTYPE( int fs_inhibread, (void) ); +_PROTOTYPE( int fs_mkdir, (void) ); +_PROTOTYPE( int fs_mknod, (void) ); +_PROTOTYPE( int fs_newnode, (void) ); +_PROTOTYPE( int fs_slink, (void) ); /* path.c */ -int lookup_o(void); -int fs_lookup_s(void); -_PROTOTYPE( struct inode *advance_o,(struct inode **dirp, - char string[NAME_MAX]) ); -_PROTOTYPE( struct inode *advance_nocheck,(struct inode **dirp, - char string[NAME_MAX]) ); -_PROTOTYPE( int search_dir, (struct inode *ldir_ptr, - char string [NAME_MAX], ino_t *numb, int flag) ); -_PROTOTYPE( int search_dir_nocheck, (struct inode *ldir_ptr, - char string [NAME_MAX], ino_t *numb, int flag) ); -_PROTOTYPE( struct inode *eat_path_o, (char *path) ); -_PROTOTYPE( struct inode *last_dir_o, (char *path, char string [NAME_MAX])); -_PROTOTYPE( struct inode *parse_path_o, (char *path, - char string[NAME_MAX], int action) ); +_PROTOTYPE( int fs_lookup, (void) ); +_PROTOTYPE( struct inode *advance, (struct inode *dirp, + char string[NAME_MAX], int chk_perm) ); +_PROTOTYPE( int search_dir, (struct inode *ldir_ptr, + char string [NAME_MAX], ino_t *numb, int flag, + int check_permissions) ); /* protect.c */ -int fs_access_o(void); +_PROTOTYPE( int fs_chmod, (void) ); +_PROTOTYPE( int fs_chown, (void) ); +_PROTOTYPE( int fs_getdents, (void) ); _PROTOTYPE( int forbidden, (struct inode *rip, mode_t access_desired) ); _PROTOTYPE( int read_only, (struct inode *ip) ); /* read.c */ -int fs_breadwrite_o(void); -int fs_breadwrite_s(void); -int fs_readwrite_o(void); -int fs_readwrite_s(void); +_PROTOTYPE( int fs_breadwrite, (void) ); +_PROTOTYPE( int fs_readwrite, (void) ); _PROTOTYPE( struct buf *rahead, (struct inode *rip, block_t baseblock, u64_t position, unsigned bytes_ahead) ); _PROTOTYPE( void read_ahead, (void) ); @@ -133,29 +97,37 @@ _PROTOTYPE( block_t read_map, (struct inode *rip, off_t pos) ); _PROTOTYPE( int read_write, (int rw_flag) ); _PROTOTYPE( zone_t rd_indir, (struct buf *bp, int index) ); +/* stadir.c */ +_PROTOTYPE( int fs_fstatfs, (void) ); +_PROTOTYPE( int fs_stat, (void) ); + /* super.c */ _PROTOTYPE( bit_t alloc_bit, (struct super_block *sp, int map, bit_t origin)); _PROTOTYPE( void free_bit, (struct super_block *sp, int map, bit_t bit_returned) ); +_PROTOTYPE( int get_block_size, (dev_t dev) ); _PROTOTYPE( struct super_block *get_super, (Dev_t dev) ); _PROTOTYPE( int mounted, (struct inode *rip) ); _PROTOTYPE( int read_super, (struct super_block *sp) ); -_PROTOTYPE( int get_block_size, (dev_t dev) ); + +/* time.c */ +_PROTOTYPE( int fs_utime, (void) ); /* utility.c */ _PROTOTYPE( time_t clock_time, (void) ); _PROTOTYPE( unsigned conv2, (int norm, int w) ); _PROTOTYPE( long conv4, (int norm, long x) ); -_PROTOTYPE( int no_sys, (void) ); -_PROTOTYPE( void mfs_nul_f, (char *file, int line, char *str, int len, int maxlen)); +_PROTOTYPE( int fetch_name, (char *path, int len, int flag) ); +_PROTOTYPE( void mfs_nul_f, (char *file, int line, char *str, int len, + int maxlen) ); _PROTOTYPE( int mfs_min_f, (char *file, int line, int len1, int len2) ); -_PROTOTYPE( void sanitycheck, (char *file, int line) ); - +_PROTOTYPE( int no_sys, (void) ); +_PROTOTYPE( int isokendpt_f, (char *f, int l, int e, int *p, int ft)); +_PROTOTYPE( void sanitycheck, (char *file, int line) ); #define SANITYCHECK sanitycheck(__FILE__, __LINE__) /* write.c */ _PROTOTYPE( void clear_zone, (struct inode *rip, off_t pos, int flag) ); -_PROTOTYPE( int do_write, (void) ); _PROTOTYPE( struct buf *new_block, (struct inode *rip, off_t position) ); _PROTOTYPE( void zero_block, (struct buf *bp) ); _PROTOTYPE( int write_map, (struct inode *, off_t, zone_t, int) ); diff --git a/servers/mfs/read.c b/servers/mfs/read.c index 5619134a2..0e74a8ebd 100644 --- a/servers/mfs/read.c +++ b/servers/mfs/read.c @@ -1,5 +1,3 @@ - - #include "fs.h" #include #include @@ -10,371 +8,132 @@ #include "buf.h" #include "inode.h" #include "super.h" - #include - - FORWARD _PROTOTYPE( int rw_chunk, (struct inode *rip, u64_t position, - unsigned off, int chunk, unsigned left, int rw_flag, - char *buff, int seg, int usr, int block_size, int *completed)); -FORWARD _PROTOTYPE( int rw_chunk_s, (struct inode *rip, u64_t position, unsigned off, int chunk, unsigned left, int rw_flag, cp_grant_id_t gid, unsigned buf_off, int block_size, int *completed)); +PRIVATE char getdents_buf[GETDENTS_BUFSIZ]; /*===========================================================================* - * fs_readwrite_o * + * fs_readwrite * *===========================================================================*/ -PUBLIC int fs_readwrite_o(void) +PUBLIC int fs_readwrite(void) { - int r, usr, seg, rw_flag, chunk, block_size, block_spec; - int partial_cnt, regular, partial_pipe, nrbytes; + int r, rw_flag, chunk, block_size, block_spec; + int partial_cnt, regular, nrbytes; + cp_grant_id_t gid; off_t position, f_size, bytes_left; unsigned int off, cum_io; mode_t mode_word; int completed, r2 = OK; - char *user_addr; struct inode *rip; - partial_pipe = 0; r = OK; - /* Try to get inode according to its index */ - if (fs_m_in.REQ_FD_INODE_INDEX >= 0 && - fs_m_in.REQ_FD_INODE_INDEX < NR_INODES && - inode[fs_m_in.REQ_FD_INODE_INDEX].i_num == fs_m_in.REQ_FD_INODE_NR) { - rip = &inode[fs_m_in.REQ_FD_INODE_INDEX]; - } - else { - /* Find the inode referred */ - rip = find_inode(fs_dev, fs_m_in.REQ_FD_INODE_NR); - if (!rip) { - printf("FS: unavaliable inode by fs_readwrite(), nr: %d\n", - fs_m_in.REQ_FD_INODE_NR); - return EINVAL; - } - } + /* Find the inode referred */ + if ((rip = find_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) + return(EINVAL); mode_word = rip->i_mode & I_TYPE; regular = (mode_word == I_REGULAR || mode_word == I_NAMED_PIPE); block_spec = (mode_word == I_BLOCK_SPECIAL ? 1 : 0); /* Determine blocksize */ - block_size = (block_spec ? get_block_size(rip->i_zone[0]) - : rip->i_sp->s_block_size); + block_size = (block_spec ? + get_block_size(rip->i_zone[0]) : rip->i_sp->s_block_size); f_size = (block_spec ? ULONG_MAX : rip->i_size); /* Get the values from the request message */ - rw_flag = (fs_m_in.m_type == REQ_READ_O ? READING : WRITING); - usr = fs_m_in.REQ_FD_WHO_E; - seg = fs_m_in.REQ_FD_SEG; - position = fs_m_in.REQ_FD_POS; - nrbytes = (unsigned) fs_m_in.REQ_FD_NBYTES; - /*partial_cnt = fs_m_in.REQ_FD_PARTIAL;*/ - user_addr = fs_m_in.REQ_FD_USER_ADDR; - - /*if (partial_cnt > 0) partial_pipe = 1;*/ + rw_flag = (fs_m_in.m_type == REQ_READ ? READING : WRITING); + gid = fs_m_in.REQ_GRANT; + position = fs_m_in.REQ_SEEK_POS_LO; + nrbytes = (unsigned) fs_m_in.REQ_NBYTES; rdwt_err = OK; /* set to EIO if disk error occurs */ if (rw_flag == WRITING && block_spec == 0) { - /* Clear the zone containing present EOF if hole about - * to be created. This is necessary because all unwritten - * blocks prior to the EOF must read as zeros. - */ - if (position > f_size) clear_zone(rip, f_size, 0); + /* Check in advance to see if file will grow too big. */ + if (position > rip->i_sp->s_max_size - nrbytes) + return(EFBIG); + + /* Clear the zone containing present EOF if hole about + * to be created. This is necessary because all unwritten + * blocks prior to the EOF must read as zeros. */ + if(position > f_size) clear_zone(rip, f_size, 0); } cum_io = 0; /* Split the transfer into chunks that don't span two blocks. */ while (nrbytes != 0) { - off = (unsigned int) (position % block_size);/* offset in blk*/ - - chunk = MIN(nrbytes, block_size - off); - if (chunk < 0) chunk = block_size - off; - - if (rw_flag == READING) { - bytes_left = f_size - position; - if (position >= f_size) break; /* we are beyond EOF */ - if (chunk > bytes_left) chunk = (int) bytes_left; - } - - /* Read or write 'chunk' bytes. */ - r = rw_chunk(rip, cvul64(position), off, chunk, (unsigned) nrbytes, - rw_flag, user_addr, seg, usr, block_size, &completed); - - if (r != OK) break; /* EOF reached */ - if (rdwt_err < 0) break; - - /* Update counters and pointers. */ - user_addr += chunk; /* user buffer address */ - nrbytes -= chunk; /* bytes yet to be read */ - cum_io += chunk; /* bytes read so far */ - position += chunk; /* position within the file */ - } + off = (unsigned int) (position % block_size);/* offset in blk*/ + chunk = MIN(nrbytes, block_size - off); - fs_m_out.RES_FD_POS = position; /* It might change later and the VFS has - to know this value */ - - /* On write, update file size and access time. */ - if (rw_flag == WRITING) { - if (regular || mode_word == I_DIRECTORY) { - if (position > f_size) rip->i_size = position; - } - } - else { - if (rip->i_pipe == I_PIPE) { - if ( position >= rip->i_size) { - /* Reset pipe pointers. */ - rip->i_size = 0; /* no data left */ - position = 0; /* reset reader(s) */ - } - } - } + if (chunk < 0) chunk = block_size - off; - /* Check to see if read-ahead is called for, and if so, set it up. */ - if (rw_flag == READING && rip->i_seek == NO_SEEK && position % block_size == 0 - && (regular || mode_word == I_DIRECTORY)) { - rdahed_inode = rip; - rdahedpos = position; - } - rip->i_seek = NO_SEEK; + if (rw_flag == READING) { + bytes_left = f_size - position; + if (position >= f_size) break; /* we are beyond EOF */ + if (chunk > bytes_left) chunk = (int) bytes_left; + } + + /* Read or write 'chunk' bytes. */ + r = rw_chunk(rip, cvul64(position), off, chunk, (unsigned) nrbytes, + rw_flag, gid, cum_io, block_size, &completed); - if (rdwt_err != OK) r = rdwt_err; /* check for disk error */ - if (rdwt_err == END_OF_FILE) r = OK; + if (r != OK) break; /* EOF reached */ + if (rdwt_err < 0) break; - /* if user-space copying failed, read/write failed. */ - if (r == OK && r2 != OK) { - r = r2; - } - - if (r == OK) { - if (rw_flag == READING) rip->i_update |= ATIME; - if (rw_flag == WRITING) rip->i_update |= CTIME | MTIME; - rip->i_dirt = DIRTY; /* inode is thus now dirty */ + /* Update counters and pointers. */ + nrbytes -= chunk; /* bytes yet to be read */ + cum_io += chunk; /* bytes read so far */ + position += chunk; /* position within the file */ } - - fs_m_out.RES_FD_CUM_IO = cum_io; - fs_m_out.RES_FD_SIZE = rip->i_size; - - return(r); -} - - -/*===========================================================================* - * fs_readwrite_s * - *===========================================================================*/ -PUBLIC int fs_readwrite_s(void) -{ - int r, rw_flag, chunk, block_size, block_spec; - int partial_cnt, regular, partial_pipe, nrbytes; - cp_grant_id_t gid; - off_t position, f_size, bytes_left; - unsigned int off, cum_io; - mode_t mode_word; - int completed, r2 = OK; - struct inode *rip; - - partial_pipe = 0; - r = OK; - - /* Try to get inode according to its index */ - if (fs_m_in.REQ_FD_INODE_INDEX >= 0 && - fs_m_in.REQ_FD_INODE_INDEX < NR_INODES && - inode[fs_m_in.REQ_FD_INODE_INDEX].i_num == fs_m_in.REQ_FD_INODE_NR) { - rip = &inode[fs_m_in.REQ_FD_INODE_INDEX]; - } - else { - /* Find the inode referred */ - rip = find_inode(fs_dev, fs_m_in.REQ_FD_INODE_NR); - if (!rip) { - printf("FS: unavaliable inode by fs_readwrite(), nr: %d\n", - fs_m_in.REQ_FD_INODE_NR); - return EINVAL; - } - } - - mode_word = rip->i_mode & I_TYPE; - regular = (mode_word == I_REGULAR || mode_word == I_NAMED_PIPE); - block_spec = (mode_word == I_BLOCK_SPECIAL ? 1 : 0); - - /* Determine blocksize */ - block_size = (block_spec ? get_block_size(rip->i_zone[0]) - : rip->i_sp->s_block_size); - - f_size = (block_spec ? ULONG_MAX : rip->i_size); - - /* Get the values from the request message */ - rw_flag = (fs_m_in.m_type == REQ_READ_S ? READING : WRITING); - gid = fs_m_in.REQ_FD_GID; - position = fs_m_in.REQ_FD_POS; - nrbytes = (unsigned) fs_m_in.REQ_FD_NBYTES; - /*partial_cnt = fs_m_in.REQ_FD_PARTIAL;*/ - /*if (partial_cnt > 0) partial_pipe = 1;*/ - - rdwt_err = OK; /* set to EIO if disk error occurs */ - - if (rw_flag == WRITING && block_spec == 0) { - /* Check in advance to see if file will grow too big. */ - if (position > rip->i_sp->s_max_size - nrbytes) - return(EFBIG); - - /* Clear the zone containing present EOF if hole about - * to be created. This is necessary because all unwritten - * blocks prior to the EOF must read as zeros. - */ - if (position > f_size) clear_zone(rip, f_size, 0); - } - - cum_io = 0; - /* Split the transfer into chunks that don't span two blocks. */ - while (nrbytes != 0) { - off = (unsigned int) (position % block_size);/* offset in blk*/ - - chunk = MIN(nrbytes, block_size - off); - if (chunk < 0) chunk = block_size - off; - - if (rw_flag == READING) { - bytes_left = f_size - position; - if (position >= f_size) break; /* we are beyond EOF */ - if (chunk > bytes_left) chunk = (int) bytes_left; - } - - /* Read or write 'chunk' bytes. */ - r = rw_chunk_s(rip, cvul64(position), off, chunk, (unsigned) nrbytes, - rw_flag, gid, cum_io, block_size, &completed); - - if (r != OK) break; /* EOF reached */ - if (rdwt_err < 0) break; - - /* Update counters and pointers. */ - nrbytes -= chunk; /* bytes yet to be read */ - cum_io += chunk; /* bytes read so far */ - position += chunk; /* position within the file */ - } - - fs_m_out.RES_FD_POS = position; /* It might change later and the VFS has - to know this value */ + fs_m_out.RES_SEEK_POS_LO = position; /* It might change later and the VFS + has to know this value */ /* On write, update file size and access time. */ if (rw_flag == WRITING) { - if (regular || mode_word == I_DIRECTORY) { - if (position > f_size) rip->i_size = position; - } + if (regular || mode_word == I_DIRECTORY) { + if (position > f_size) rip->i_size = position; + } } - else { - if (rip->i_pipe == I_PIPE) { - if ( position >= rip->i_size) { - /* Reset pipe pointers. */ - rip->i_size = 0; /* no data left */ - position = 0; /* reset reader(s) */ - } - } - } /* Check to see if read-ahead is called for, and if so, set it up. */ - if (rw_flag == READING && rip->i_seek == NO_SEEK && position % block_size == 0 - && (regular || mode_word == I_DIRECTORY)) { - rdahed_inode = rip; - rdahedpos = position; + if(rw_flag == READING && rip->i_seek == NO_SEEK && + position % block_size == 0 && (regular || mode_word == I_DIRECTORY)) { + rdahed_inode = rip; + rdahedpos = position; } + rip->i_seek = NO_SEEK; if (rdwt_err != OK) r = rdwt_err; /* check for disk error */ if (rdwt_err == END_OF_FILE) r = OK; /* if user-space copying failed, read/write failed. */ - if (r == OK && r2 != OK) { + if (r == OK && r2 != OK) r = r2; - } if (r == OK) { - if (rw_flag == READING) rip->i_update |= ATIME; - if (rw_flag == WRITING) rip->i_update |= CTIME | MTIME; - rip->i_dirt = DIRTY; /* inode is thus now dirty */ - } - - fs_m_out.RES_FD_CUM_IO = cum_io; - fs_m_out.RES_FD_SIZE = rip->i_size; - - return(r); -} - - -/*===========================================================================* - * fs_breadwrite_o * - *===========================================================================*/ -PUBLIC int fs_breadwrite_o(void) -{ - int r, usr, rw_flag, chunk, block_size; - int nrbytes; - u64_t position; - unsigned int off, cum_io; - mode_t mode_word; - int completed, r2 = OK; - char *user_addr; - - /* Pseudo inode for rw_chunk */ - struct inode rip; - - r = OK; - - /* Get the values from the request message */ - rw_flag = (fs_m_in.m_type == REQ_BREAD_O ? READING : WRITING); - usr = fs_m_in.REQ_XFD_WHO_E; - position = make64(fs_m_in.REQ_XFD_POS_LO, fs_m_in.REQ_XFD_POS_HI); - nrbytes = (unsigned) fs_m_in.REQ_XFD_NBYTES; - user_addr = fs_m_in.REQ_XFD_USER_ADDR; - - block_size = get_block_size(fs_m_in.REQ_XFD_BDEV); - - rip.i_zone[0] = fs_m_in.REQ_XFD_BDEV; - rip.i_mode = I_BLOCK_SPECIAL; - rip.i_size = 0; - - rdwt_err = OK; /* set to EIO if disk error occurs */ - - cum_io = 0; - /* Split the transfer into chunks that don't span two blocks. */ - while (nrbytes != 0) { - off = rem64u(position, block_size); /* offset in blk*/ - - chunk = MIN(nrbytes, block_size - off); - if (chunk < 0) chunk = block_size - off; - - /* Read or write 'chunk' bytes. */ - r = rw_chunk(&rip, position, off, chunk, (unsigned) nrbytes, - rw_flag, user_addr, D, usr, block_size, &completed); - - if (r != OK) break; /* EOF reached */ - if (rdwt_err < 0) break; - - /* Update counters and pointers. */ - user_addr += chunk; /* user buffer address */ - nrbytes -= chunk; /* bytes yet to be read */ - cum_io += chunk; /* bytes read so far */ - position= add64ul(position, chunk); /* position within the file */ + if (rw_flag == READING) rip->i_update |= ATIME; + if (rw_flag == WRITING) rip->i_update |= CTIME | MTIME; + rip->i_dirt = DIRTY; /* inode is thus now dirty */ } - fs_m_out.RES_XFD_POS_LO = ex64lo(position); - fs_m_out.RES_XFD_POS_HI = ex64hi(position); - - if (rdwt_err != OK) r = rdwt_err; /* check for disk error */ - if (rdwt_err == END_OF_FILE) r = OK; - - fs_m_out.RES_XFD_CUM_IO = cum_io; + fs_m_out.RES_NBYTES = cum_io; return(r); } /*===========================================================================* - * fs_breadwrite_s * + * fs_breadwrite * *===========================================================================*/ -PUBLIC int fs_breadwrite_s(void) +PUBLIC int fs_breadwrite(void) { int r, rw_flag, chunk, block_size; cp_grant_id_t gid; @@ -390,14 +149,14 @@ PUBLIC int fs_breadwrite_s(void) r = OK; /* Get the values from the request message */ - rw_flag = (fs_m_in.m_type == REQ_BREAD_S ? READING : WRITING); - gid = fs_m_in.REQ_XFD_GID; - position = make64(fs_m_in.REQ_XFD_POS_LO, fs_m_in.REQ_XFD_POS_HI); - nrbytes = (unsigned) fs_m_in.REQ_XFD_NBYTES; + rw_flag = (fs_m_in.m_type == REQ_BREAD ? READING : WRITING); + gid = fs_m_in.REQ_GRANT; + position = make64(fs_m_in.REQ_SEEK_POS_LO, fs_m_in.REQ_SEEK_POS_HI); + nrbytes = (unsigned) fs_m_in.REQ_NBYTES; - block_size = get_block_size(fs_m_in.REQ_XFD_BDEV); + block_size = get_block_size(fs_m_in.REQ_DEV2); - rip.i_zone[0] = fs_m_in.REQ_XFD_BDEV; + rip.i_zone[0] = fs_m_in.REQ_DEV2; rip.i_mode = I_BLOCK_SPECIAL; rip.i_size = 0; @@ -406,31 +165,31 @@ PUBLIC int fs_breadwrite_s(void) cum_io = 0; /* Split the transfer into chunks that don't span two blocks. */ while (nrbytes != 0) { - off = rem64u(position, block_size); /* offset in blk*/ + off = rem64u(position, block_size); /* offset in blk*/ - chunk = MIN(nrbytes, block_size - off); - if (chunk < 0) chunk = block_size - off; + chunk = MIN(nrbytes, block_size - off); + if (chunk < 0) chunk = block_size - off; - /* Read or write 'chunk' bytes. */ - r = rw_chunk_s(&rip, position, off, chunk, (unsigned) nrbytes, - rw_flag, gid, cum_io, block_size, &completed); + /* Read or write 'chunk' bytes. */ + r = rw_chunk(&rip, position, off, chunk, (unsigned) nrbytes, + rw_flag, gid, cum_io, block_size, &completed); - if (r != OK) break; /* EOF reached */ - if (rdwt_err < 0) break; + if (r != OK) break; /* EOF reached */ + if (rdwt_err < 0) break; - /* Update counters and pointers. */ - nrbytes -= chunk; /* bytes yet to be read */ - cum_io += chunk; /* bytes read so far */ - position= add64ul(position, chunk); /* position within the file */ + /* Update counters and pointers. */ + nrbytes -= chunk; /* bytes yet to be read */ + cum_io += chunk; /* bytes read so far */ + position= add64ul(position, chunk); /* position within the file */ } - fs_m_out.RES_XFD_POS_LO = ex64lo(position); - fs_m_out.RES_XFD_POS_HI = ex64hi(position); + fs_m_out.RES_SEEK_POS_LO = ex64lo(position); + fs_m_out.RES_SEEK_POS_HI = ex64hi(position); if (rdwt_err != OK) r = rdwt_err; /* check for disk error */ if (rdwt_err == END_OF_FILE) r = OK; - fs_m_out.RES_XFD_CUM_IO = cum_io; + fs_m_out.RES_NBYTES = cum_io; return(r); } @@ -439,104 +198,7 @@ PUBLIC int fs_breadwrite_s(void) /*===========================================================================* * rw_chunk * *===========================================================================*/ -PRIVATE int rw_chunk(rip, position, off, chunk, left, rw_flag, buff, - seg, usr, block_size, completed) -register struct inode *rip; /* pointer to inode for file to be rd/wr */ -u64_t position; /* position within file to read or write */ -unsigned off; /* off within the current block */ -int chunk; /* number of bytes to read or write */ -unsigned left; /* max number of bytes wanted after position */ -int rw_flag; /* READING or WRITING */ -char *buff; /* virtual address of the user buffer */ -int seg; /* T or D segment in user space */ -int usr; /* which user process */ -int block_size; /* block size of FS operating on */ -int *completed; /* number of bytes copied */ -{ -/* Read or write (part of) a block. */ - - register struct buf *bp; - register int r = OK; - int n, block_spec; - block_t b; - dev_t dev; - - *completed = 0; - - block_spec = (rip->i_mode & I_TYPE) == I_BLOCK_SPECIAL; - - if (block_spec) { - b = div64u(position, block_size); - dev = (dev_t) rip->i_zone[0]; - } - else { - if (ex64hi(position) != 0) - panic(__FILE__, "rw_chunk: position too high", NO_NUM); - b = read_map(rip, ex64lo(position)); - dev = rip->i_dev; - } - - if (!block_spec && b == NO_BLOCK) { - if (rw_flag == READING) { - /* Reading from a nonexistent block. Must read as all zeros.*/ - bp = get_block(NO_DEV, NO_BLOCK, NORMAL); /* get a buffer */ - zero_block(bp); - } - else { - /* Writing to a nonexistent block. Create and enter in inode.*/ - if ((bp= new_block(rip, ex64lo(position))) == NIL_BUF) - return(err_code); - } - } - else if (rw_flag == READING) { - /* Read and read ahead if convenient. */ - bp = rahead(rip, b, position, left); - } - else { - /* Normally an existing block to be partially overwritten is first read - * in. However, a full block need not be read in. If it is already in - * the cache, acquire it, otherwise just acquire a free buffer. - */ - n = (chunk == block_size ? NO_READ : NORMAL); - if (!block_spec && off == 0 && ex64lo(position) >= rip->i_size) - n = NO_READ; - bp = get_block(dev, b, n); - } - - /* In all cases, bp now points to a valid buffer. */ - if (bp == NIL_BUF) { - panic(__FILE__,"bp not valid in rw_chunk, this can't happen", NO_NUM); - } - - if (rw_flag == WRITING && chunk != block_size && !block_spec && - ex64lo(position) >= rip->i_size && off == 0) { - zero_block(bp); - } - - if (rw_flag == READING) { - /* Copy a chunk from the block buffer to user space. */ - r = sys_vircopy(SELF_E, D, (phys_bytes) (bp->b_data+off), - usr, seg, (phys_bytes) buff, - (phys_bytes) chunk); - } - else { - /* Copy a chunk from user space to the block buffer. */ - r = sys_vircopy(usr, seg, (phys_bytes) buff, - SELF_E, D, (phys_bytes) (bp->b_data+off), - (phys_bytes) chunk); - bp->b_dirt = DIRTY; - } - n = (off + chunk == block_size ? FULL_DATA_BLOCK : PARTIAL_DATA_BLOCK); - put_block(bp, n); - - return(r); -} - - -/*===========================================================================* - * rw_chunk_s * - *===========================================================================*/ -PRIVATE int rw_chunk_s(rip, position, off, chunk, left, rw_flag, gid, +PRIVATE int rw_chunk(rip, position, off, chunk, left, rw_flag, gid, buf_off, block_size, completed) register struct inode *rip; /* pointer to inode for file to be rd/wr */ u64_t position; /* position within file to read or write */ @@ -564,8 +226,7 @@ int *completed; /* number of bytes copied */ if (block_spec) { b = div64u(position, block_size); dev = (dev_t) rip->i_zone[0]; - } - else { + } else { if (ex64hi(position) != 0) panic(__FILE__, "rw_chunk: position too high", NO_NUM); b = read_map(rip, ex64lo(position)); @@ -577,18 +238,15 @@ int *completed; /* number of bytes copied */ /* Reading from a nonexistent block. Must read as all zeros.*/ bp = get_block(NO_DEV, NO_BLOCK, NORMAL); /* get a buffer */ zero_block(bp); - } - else { + } else { /* Writing to a nonexistent block. Create and enter in inode.*/ if ((bp= new_block(rip, ex64lo(position))) == NIL_BUF) return(err_code); } - } - else if (rw_flag == READING) { + } else if (rw_flag == READING) { /* Read and read ahead if convenient. */ bp = rahead(rip, b, position, left); - } - else { + } else { /* Normally an existing block to be partially overwritten is first read * in. However, a full block need not be read in. If it is already in * the cache, acquire it, otherwise just acquire a free buffer. @@ -600,9 +258,8 @@ int *completed; /* number of bytes copied */ } /* In all cases, bp now points to a valid buffer. */ - if (bp == NIL_BUF) { + if (bp == NIL_BUF) panic(__FILE__,"bp not valid in rw_chunk, this can't happen", NO_NUM); - } if (rw_flag == WRITING && chunk != block_size && !block_spec && ex64lo(position) >= rip->i_size && off == 0) { @@ -611,19 +268,15 @@ int *completed; /* number of bytes copied */ if (rw_flag == READING) { /* Copy a chunk from the block buffer to user space. */ -#if 0 - printf("sys_safecopyto: proc %d, gid %d, off %d, size %d\n", - FS_PROC_NR, gid, buf_off, chunk); -#endif r = sys_safecopyto(FS_PROC_NR, gid, buf_off, (vir_bytes) (bp->b_data+off), (phys_bytes) chunk, D); - } - else { + } else { /* Copy a chunk from user space to the block buffer. */ r = sys_safecopyfrom(FS_PROC_NR, gid, buf_off, (vir_bytes) (bp->b_data+off), (phys_bytes) chunk, D); bp->b_dirt = DIRTY; } + n = (off + chunk == block_size ? FULL_DATA_BLOCK : PARTIAL_DATA_BLOCK); put_block(bp, n); @@ -697,6 +350,7 @@ off_t position; /* position in file whose blk wanted */ return(b); } + /*===========================================================================* * rd_indir * *===========================================================================*/ @@ -729,9 +383,11 @@ int index; /* index into *bp */ (long) zone, index); panic(__FILE__,"check file system", NO_NUM); } + return(zone); } + /*===========================================================================* * read_ahead * *===========================================================================*/ @@ -751,6 +407,7 @@ PUBLIC void read_ahead() put_block(bp, PARTIAL_DATA_BLOCK); } + /*===========================================================================* * rahead * *===========================================================================*/ @@ -781,11 +438,11 @@ unsigned bytes_ahead; /* bytes beyond position for immediate use */ STATICINIT(read_q, NR_BUFS); block_spec = (rip->i_mode & I_TYPE) == I_BLOCK_SPECIAL; - if (block_spec) { + if (block_spec) dev = (dev_t) rip->i_zone[0]; - } else { + else dev = rip->i_dev; - } + block_size = get_block_size(dev); block = baseblock; @@ -870,10 +527,6 @@ unsigned bytes_ahead; /* bytes beyond position for immediate use */ } -#define GETDENTS_BUFSIZ 257 - -PRIVATE char getdents_buf[GETDENTS_BUFSIZ]; - /*===========================================================================* * fs_getdents * *===========================================================================*/ @@ -891,155 +544,124 @@ PUBLIC int fs_getdents(void) struct dirent *dep; char *cp; - ino= fs_m_in.REQ_GDE_INODE; - gid= fs_m_in.REQ_GDE_GRANT; - size= fs_m_in.REQ_GDE_SIZE; - pos= fs_m_in.REQ_GDE_POS; + ino = fs_m_in.REQ_INODE_NR; + gid = fs_m_in.REQ_GRANT; + size = fs_m_in.REQ_MEM_SIZE; + pos = fs_m_in.REQ_SEEK_POS_LO; /* Check whether the position is properly aligned */ - if (pos % DIR_ENTRY_SIZE) - return ENOENT; + if(pos % DIR_ENTRY_SIZE) + return(ENOENT); - if ( (rip = get_inode(fs_dev, ino)) == NIL_INODE) { -printf("MFS(%d) get_inode by fs_getdents() failed\n", SELF_E); - return(EINVAL); - } + if( (rip = get_inode(fs_dev, ino)) == NIL_INODE) + return(EINVAL); - block_size= rip->i_sp->s_block_size; - off= (pos % block_size); /* Offset in block */ - block_pos= pos-off; - done= FALSE; /* Stop processing directory blocks - * when done is set. - */ + block_size = rip->i_sp->s_block_size; + off = (pos % block_size); /* Offset in block */ + block_pos = pos - off; + done = FALSE; /* Stop processing directory blocks when done is set */ - tmpbuf_off= 0; /* Offset in getdents_buf */ + tmpbuf_off = 0; /* Offset in getdents_buf */ memset(getdents_buf, '\0', GETDENTS_BUFSIZ); /* Avoid leaking any data */ - userbuf_off= 0; /* Offset in the user's buffer */ + userbuf_off = 0; /* Offset in the user's buffer */ /* The default position for the next request is EOF. If the user's buffer - * fills up before EOF, new_pos will be modified. - */ - new_pos= rip->i_size; - - for (; block_pos < rip->i_size; block_pos += block_size) { - b = read_map(rip, block_pos); /* get block number */ - - /* Since directories don't have holes, 'b' cannot be NO_BLOCK. */ - bp = get_block(rip->i_dev, b, NORMAL); /* get a dir block */ - - if (bp == NO_BLOCK) - panic(__FILE__,"get_block returned NO_BLOCK", NO_NUM); - - /* Search a directory block. */ - if (block_pos < pos) - dp = &bp->b_dir[off / DIR_ENTRY_SIZE]; - else - dp = &bp->b_dir[0]; - for (; dp < &bp->b_dir[NR_DIR_ENTRIES(block_size)]; dp++) { - if (dp->d_ino == 0) - continue; /* Entry is not in use */ - - /* Compute the length of the name */ - cp= memchr(dp->d_name, '\0', NAME_MAX); - if (cp == NULL) - len= NAME_MAX; - else - len= cp-dp->d_name; + * fills up before EOF, new_pos will be modified. */ + new_pos = rip->i_size; + + for(; block_pos < rip->i_size; block_pos += block_size) { + b = read_map(rip, block_pos); /* get block number */ + + /* Since directories don't have holes, 'b' cannot be NO_BLOCK. */ + bp = get_block(rip->i_dev, b, NORMAL); /* get a dir block */ + + if(bp == NO_BLOCK) + panic(__FILE__,"get_block returned NO_BLOCK", NO_NUM); + + /* Search a directory block. */ + if (block_pos < pos) + dp = &bp->b_dir[off / DIR_ENTRY_SIZE]; + else + dp = &bp->b_dir[0]; + for (; dp < &bp->b_dir[NR_DIR_ENTRIES(block_size)]; dp++) { + if (dp->d_ino == 0) + continue; /* Entry is not in use */ + + /* Compute the length of the name */ + cp = memchr(dp->d_name, '\0', NAME_MAX); + if (cp == NULL) + len = NAME_MAX; + else + len = cp-dp->d_name; - - /* Compute record length */ - reclen= offsetof(struct dirent, d_name) + len + 1; - o= (reclen % sizeof(long)); - if (o != 0) - reclen += sizeof(long)-o; - - /* Need the postition of this entry in the directory */ - ent_pos= block_pos + ((char *)dp - bp->b_data); - - if (tmpbuf_off + reclen > GETDENTS_BUFSIZ) - { - r= sys_safecopyto(FS_PROC_NR, gid, userbuf_off, - (vir_bytes)getdents_buf, tmpbuf_off, D); - if (r != OK) - { - panic(__FILE__, + /* Compute record length */ + reclen = offsetof(struct dirent, d_name) + len + 1; + o = (reclen % sizeof(long)); + if (o != 0) + reclen += sizeof(long) - o; + + /* Need the postition of this entry in the directory */ + ent_pos = block_pos + ((char *)dp - bp->b_data); + + if(tmpbuf_off + reclen > GETDENTS_BUFSIZ) { + r = sys_safecopyto(FS_PROC_NR, gid, userbuf_off, + (vir_bytes)getdents_buf, + tmpbuf_off, D); + if (r != OK) + panic(__FILE__, "fs_getdents: sys_safecopyto failed\n", r); - } - - userbuf_off += tmpbuf_off; - tmpbuf_off= 0; - } - - if (userbuf_off + tmpbuf_off + reclen > size) - { - /* The user has no space for one more record */ - done= TRUE; - - /* Record the postion of this entry, it is the - * starting point of the next request (unless the - * postion is modified with lseek). - */ - new_pos= ent_pos; - break; - } - dep= (struct dirent *)&getdents_buf[tmpbuf_off]; - dep->d_ino= dp->d_ino; - dep->d_off= ent_pos; - dep->d_reclen= reclen; - memcpy(dep->d_name, dp->d_name, len); - dep->d_name[len]= '\0'; - tmpbuf_off += reclen; - } - put_block(bp, DIRECTORY_BLOCK); - if (done) - break; - } - - if (tmpbuf_off != 0) - { - r= sys_safecopyto(FS_PROC_NR, gid, userbuf_off, - (vir_bytes)getdents_buf, tmpbuf_off, D); - if (r != OK) - panic(__FILE__, "fs_getdents: sys_safecopyto failed\n", r); - - userbuf_off += tmpbuf_off; - } - - if (done && userbuf_off == 0) - r= EINVAL; /* The user's buffer is too small */ - else - { - fs_m_out.RES_GDE_CUM_IO= userbuf_off; - if (new_pos >= pos) - fs_m_out.RES_GDE_POS_CHANGE= new_pos-pos; - else - fs_m_out.RES_GDE_POS_CHANGE= 0; - - rip->i_update |= ATIME; - rip->i_dirt = DIRTY; - r= OK; + userbuf_off += tmpbuf_off; + tmpbuf_off = 0; + } + + if(userbuf_off + tmpbuf_off + reclen > size) { + /* The user has no space for one more record */ + done = TRUE; + + /* Record the postion of this entry, it is the + * starting point of the next request (unless the + * postion is modified with lseek). + */ + new_pos = ent_pos; + break; + } + + dep = (struct dirent *)&getdents_buf[tmpbuf_off]; + dep->d_ino = dp->d_ino; + dep->d_off = ent_pos; + dep->d_reclen = reclen; + memcpy(dep->d_name, dp->d_name, len); + dep->d_name[len] = '\0'; + tmpbuf_off += reclen; + } + + put_block(bp, DIRECTORY_BLOCK); + if(done) + break; + } + + if(tmpbuf_off != 0) { + r = sys_safecopyto(FS_PROC_NR, gid, userbuf_off, + (vir_bytes) getdents_buf, tmpbuf_off, D); + if (r != OK) + panic(__FILE__, "fs_getdents: sys_safecopyto failed\n", r); + + userbuf_off += tmpbuf_off; + } + + if(done && userbuf_off == 0) + r = EINVAL; /* The user's buffer is too small */ + else { + fs_m_out.RES_NBYTES = userbuf_off; + fs_m_out.RES_SEEK_POS_LO = new_pos; + rip->i_update |= ATIME; + rip->i_dirt = DIRTY; + r = OK; } put_inode(rip); /* release the inode */ return(r); } -/*===========================================================================* - * fs_getdents_o * - *===========================================================================*/ -PUBLIC int fs_getdents_o(void) -{ -/* Legacy support: wrapper around new getdents, returning the resulting number - * of bytes in the m_type field of the reply message instead. - */ - int r; - - r = fs_getdents(); - - if (r == OK) - r = fs_m_out.RES_GDE_CUM_IO; - - return(r); -} diff --git a/servers/mfs/stadir.c b/servers/mfs/stadir.c index 47221bdfd..00968084d 100644 --- a/servers/mfs/stadir.c +++ b/servers/mfs/stadir.c @@ -1,5 +1,3 @@ - - #include "fs.h" #include #include @@ -8,20 +6,17 @@ #include "buf.h" #include "inode.h" #include "super.h" - #include - -FORWARD _PROTOTYPE( int stat_inode, (struct inode *rip, int pipe_pos, - int who_e, cp_grant_id_t gid) ); +FORWARD _PROTOTYPE( int stat_inode, (struct inode *rip, int who_e, + cp_grant_id_t gid) ); /*===========================================================================* * stat_inode * *===========================================================================*/ -PRIVATE int stat_inode(rip, pipe_pos, who_e, gid) +PRIVATE int stat_inode(rip, who_e, gid) register struct inode *rip; /* pointer to inode to stat */ -int pipe_pos; /* position in a pipe, supplied by fstat() */ int who_e; /* Caller endpoint */ cp_grant_id_t gid; /* grant for the stat buf */ { @@ -48,12 +43,6 @@ cp_grant_id_t gid; /* grant for the stat buf */ statbuf.st_gid = rip->i_gid; statbuf.st_rdev = (dev_t) (s ? rip->i_zone[0] : NO_DEV); statbuf.st_size = rip->i_size; - - if (rip->i_pipe == I_PIPE) { - statbuf.st_mode &= ~I_REGULAR; /* wipe out I_REGULAR bit for pipes */ - statbuf.st_size -= pipe_pos; - } - statbuf.st_atime = rip->i_atime; statbuf.st_mtime = rip->i_mtime; statbuf.st_ctime = rip->i_ctime; @@ -75,20 +64,19 @@ PUBLIC int fs_fstatfs() struct inode *rip; int r; - if ((rip = find_inode(fs_dev, ROOT_INODE)) == NIL_INODE) { - printf("mfs:fstatfs: couldn't find inode %d\n", ROOT_INODE); - return EINVAL; - } - + if((rip = find_inode(fs_dev, ROOT_INODE)) == NIL_INODE) + return(EINVAL); + st.f_bsize = rip->i_sp->s_block_size; /* Copy the struct to user space. */ - r = sys_safecopyto(fs_m_in.m_source, fs_m_in.REQ_GRANT, 0, - (vir_bytes) &st, (phys_bytes) sizeof(st), D); + r = sys_safecopyto(fs_m_in.m_source, fs_m_in.REQ_GRANT, 0, (vir_bytes) &st, + (phys_bytes) sizeof(st), D); return(r); } + /*===========================================================================* * fs_stat * *===========================================================================*/ @@ -97,15 +85,11 @@ PUBLIC int fs_stat() register int r; /* return value */ register struct inode *rip; /* target inode */ - if ( (rip = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) { -printf("MFS(%d) get_inode by fs_stat() failed\n", SELF_E); - return(EINVAL); - } + if ((rip = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) + return(EINVAL); - r = stat_inode(rip, 0, fs_m_in.m_source, fs_m_in.REQ_GRANT); + r = stat_inode(rip, fs_m_in.m_source, fs_m_in.REQ_GRANT); put_inode(rip); /* release the inode */ return(r); } - - diff --git a/servers/mfs/super.c b/servers/mfs/super.c index 3133101da..45090a250 100644 --- a/servers/mfs/super.c +++ b/servers/mfs/super.c @@ -142,6 +142,7 @@ bit_t bit_returned; /* number of bit to insert into the map */ put_block(bp, MAP_BLOCK); } + /*===========================================================================* * get_super * *===========================================================================*/ @@ -154,9 +155,10 @@ dev_t dev; /* device number whose super_block is sought */ if(superblock.s_dev != dev) panic(__FILE__,"wrong superblock", (int) dev); - return &superblock; + return(&superblock); } + /*===========================================================================* * get_block_size * *===========================================================================*/ @@ -165,43 +167,11 @@ PUBLIC int get_block_size(dev_t dev) if (dev == NO_DEV) panic(__FILE__,"request for block size of NO_DEV", NO_NUM); - return fs_block_size; - -#if 0 - if(superblock.s_dev == dev) { - if(superblock.s_block_size != fs_block_size) { - printf("mounted blocksize: %d my blocksize: %d\n", - superblock.s_block_size, fs_block_size); - } - ASSERT(superblock.s_block_size == fs_block_size); - return(superblock.s_block_size); - } + return(fs_block_size); - /* not the mounted filesystem? use this block size then. */ - return _MIN_BLOCK_SIZE; -#endif } -/*===========================================================================* - * mounted * - *===========================================================================*/ -/* Report on whether the given inode is on a mounted (or ROOT) file system. */ -/* -PUBLIC int mounted(rip) -register struct inode *rip; -{ - - register dev_t dev; - - dev = (dev_t) rip->i_zone[0]; - if (dev == root_dev) return(TRUE); - - if(superblock.s_dev == dev) - return TRUE; - return(FALSE); -} -*/ /*===========================================================================* * read_super * *===========================================================================*/ @@ -222,9 +192,9 @@ register struct super_block *sp; /* pointer to a superblock */ r = block_dev_io(MFS_DEV_READ, dev, SELF_E, sbbuf, cvu64(SUPER_BLOCK_BYTES), _MIN_BLOCK_SIZE, 0); - if (r != _MIN_BLOCK_SIZE) { - return EINVAL; - } + if (r != _MIN_BLOCK_SIZE) + return(EINVAL); + memcpy(sp, sbbuf, sizeof(*sp)); sp->s_dev = NO_DEV; /* restore later */ magic = sp->s_magic; /* determines file system type */ @@ -282,26 +252,23 @@ register struct super_block *sp; /* pointer to a superblock */ sp->s_nindirs = V2_INDIRECTS(sp->s_block_size); } - if (sp->s_block_size < _MIN_BLOCK_SIZE) { - return EINVAL; - } - if ((sp->s_block_size % 512) != 0) { - return EINVAL; - } - if (SUPER_SIZE > sp->s_block_size) { - return EINVAL; - } + if (sp->s_block_size < _MIN_BLOCK_SIZE) + return(EINVAL); + + if ((sp->s_block_size % 512) != 0) + return(EINVAL); + + if (SUPER_SIZE > sp->s_block_size) + return(EINVAL); + if ((sp->s_block_size % V2_INODE_SIZE) != 0 || (sp->s_block_size % V1_INODE_SIZE) != 0) { - return EINVAL; + return(EINVAL); } /* Limit s_max_size to LONG_MAX */ - if ((unsigned long)sp->s_max_size > LONG_MAX) - { - printf("read_super: reducing s_max_size to LONG_MAX\n"); - sp->s_max_size= LONG_MAX; - } + if ((unsigned long)sp->s_max_size > LONG_MAX) + sp->s_max_size = LONG_MAX; sp->s_isearch = 0; /* inode searches initially start at 0 */ sp->s_zsearch = 0; /* zone searches initially start at 0 */ @@ -322,3 +289,4 @@ register struct super_block *sp; /* pointer to a superblock */ sp->s_dev = dev; /* restore device number */ return(OK); } + diff --git a/servers/mfs/table.c b/servers/mfs/table.c index 75ca006d7..53c04f8d6 100644 --- a/servers/mfs/table.c +++ b/servers/mfs/table.c @@ -15,59 +15,36 @@ PUBLIC _PROTOTYPE (int (*fs_call_vec[]), (void) ) = { no_sys, /* 0 not used */ - fs_getnode, /* 1 */ + no_sys, /* 1 */ /* Was: fs_getnode */ fs_putnode, /* 2 */ - fs_slink_s, /* 3 */ - fs_pipe, /* 4 */ - fs_readwrite_o, /* 5 */ /* read() */ - fs_readwrite_o, /* 6 */ /* write() */ - fs_clone_opcl, /* 7 */ - fs_ftrunc, /* 8 */ - fs_chown, /* 9 */ - fs_chmod, /* 10 */ - fs_access_o, /* 11 */ - fs_mknod_o, /* 12 */ - fs_mkdir_o, /* 13 */ - fs_inhibread, /* 14 */ /* for lseek() */ - fs_stat, /* 15 */ - fs_create_o, /* 16 */ - fs_unlink_o, /* 17 */ /* unlink() */ - fs_unlink_o, /* 18 */ /* rmdir() */ - fs_utime, /* 19 */ - fs_rdlink_so, /* 20 */ - fs_fstatfs, /* 21 */ - fs_breadwrite_s, /* 22 */ - fs_breadwrite_s, /* 23 */ - fs_unlink_s, /* 24 */ /* unlink() */ - fs_link_o, /* 25 */ - fs_slink_o, /* 26 */ - fs_rdlink_o, /* 27 */ - fs_rename_o, /* 28 */ - fs_unlink_s, /* 29 */ /* rmdir() */ - fs_mountpoint_o, /* 30 */ - fs_readsuper_o, /* 31 */ - fs_unmount, /* 32 */ - fs_trunc, /* 33 */ - fs_sync, /* 34 */ - lookup_o, /* 35 */ - fs_stime, /* 36 */ - fs_new_driver, /* 37 */ - fs_breadwrite_o, /* 38 */ - fs_breadwrite_o, /* 39 */ - fs_getdents_o, /* 40 */ - fs_flush, /* 41 */ - fs_readwrite_s, /* 42 */ - fs_readwrite_s, /* 43 */ - fs_mknod_s, /* 44 */ - fs_mkdir_s, /* 45 */ - fs_create_s, /* 46 */ - fs_link_s, /* 47 */ - fs_rename_s, /* 48 */ - fs_lookup_s, /* 49 */ - fs_mountpoint_s, /* 50 */ - fs_readsuper_s, /* 51 */ - fs_newnode, /* 52 */ - fs_rdlink_s, /* 53 */ - fs_getdents, /* 54 */ + fs_slink, /* 3 */ + fs_ftrunc, /* 4 */ + fs_chown, /* 5 */ + fs_chmod, /* 6 */ + fs_inhibread, /* 7 */ + fs_stat, /* 8 */ + fs_utime, /* 9 */ + fs_fstatfs, /* 10 */ + fs_breadwrite, /* 11 */ + fs_breadwrite, /* 12 */ + fs_unlink, /* 13 */ + fs_unlink, /* 14 */ + fs_unmount, /* 15 */ + fs_sync, /* 16 */ + fs_new_driver, /* 17 */ + fs_flush, /* 18 */ + fs_readwrite, /* 19 */ + fs_readwrite, /* 20 */ + fs_mknod, /* 21 */ + fs_mkdir, /* 22 */ + fs_create, /* 23 */ + fs_link, /* 24 */ + fs_rename, /* 25 */ + fs_lookup, /* 26 */ + fs_mountpoint, /* 27 */ + fs_readsuper, /* 28 */ + fs_newnode, /* 29 */ + fs_rdlink, /* 30 */ + fs_getdents, /* 31 */ }; diff --git a/servers/mfs/time.c b/servers/mfs/time.c index adb4c6bb0..7feb193b7 100644 --- a/servers/mfs/time.c +++ b/servers/mfs/time.c @@ -1,11 +1,7 @@ - - - #include "fs.h" #include #include #include "inode.h" - #include @@ -18,29 +14,20 @@ PUBLIC int fs_utime() register int r; /* Temporarily open the file. */ - if ( (rip = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) { -printf("MFS(%d) get_inode by fs_utime() failed\n", SELF_E); + if( (rip = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) return(EINVAL); - } /* Only the owner of a file or the super_user can change its time. */ r = OK; - if (read_only(rip) != OK) r = EROFS; /* not even su can touch if R/O */ - if (r == OK) { - rip->i_atime = fs_m_in.REQ_ACTIME; - rip->i_mtime = fs_m_in.REQ_MODTIME; - - rip->i_update = CTIME; /* discard any stale ATIME and MTIME flags */ - rip->i_dirt = DIRTY; + if(read_only(rip) != OK) r = EROFS; /* not even su can touch if R/O */ + if(r == OK) { + rip->i_atime = fs_m_in.REQ_ACTIME; + rip->i_mtime = fs_m_in.REQ_MODTIME; + rip->i_update = CTIME; /* discard any stale ATIME and MTIME flags */ + rip->i_dirt = DIRTY; } put_inode(rip); return(r); } -PUBLIC int fs_stime() -{ - boottime = fs_m_in.REQ_BOOTTIME; - return OK; -} - diff --git a/servers/mfs/utility.c b/servers/mfs/utility.c index 24ca6bac1..d8a75c5f9 100644 --- a/servers/mfs/utility.c +++ b/servers/mfs/utility.c @@ -1,17 +1,15 @@ - #include "fs.h" #include #include #include #include #include - #include "buf.h" #include "inode.h" #include "super.h" - #include + /*===========================================================================* * no_sys * *===========================================================================*/ @@ -22,6 +20,7 @@ PUBLIC int no_sys() return(EINVAL); } + /*===========================================================================* * conv2 * *===========================================================================*/ @@ -34,6 +33,7 @@ int w; /* promotion of 16-bit word to be swapped */ return( ((w&BYTE) << 8) | ( (w>>8) & BYTE)); } + /*===========================================================================* * conv4 * *===========================================================================*/ @@ -52,6 +52,7 @@ long x; /* 32-bit long to be byte swapped */ return(l); } + /*===========================================================================* * clock_time * *===========================================================================*/ @@ -65,20 +66,22 @@ PUBLIC time_t clock_time() register int k; clock_t uptime; - if (use_getuptime2) - { + if (use_getuptime2) { if ( (k=getuptime2(&uptime,&boottime)) != OK) panic(__FILE__,"clock_time: getuptme2 failed", k); - } - else - { + } else { if ( (k=getuptime(&uptime)) != OK) panic(__FILE__,"clock_time err", k); } + return( (time_t) (boottime + (uptime/sys_hz()))); } -int mfs_min_f(char *file, int line, int v1, int v2) + +/*===========================================================================* + * mfs_min * + *===========================================================================*/ +PUBLIC int mfs_min_f(char *file, int line, int v1, int v2) { if(v1 < 0 || v2 < 0) { printf("mfs:%s:%d: strange string lengths: %d, %d\n", @@ -86,14 +89,15 @@ int mfs_min_f(char *file, int line, int v1, int v2) panic(file, "strange string lengths", NO_NUM); } if(v2 >= v1) return v1; -#if 0 - printf("mfs:%s:%d: truncated %d to %d\n", - file, line, v1, v2); -#endif + return v2; } -void mfs_nul_f(char *file, int line, char *str, int len, int maxlen) + +/*===========================================================================* + * mfs_nul * + *===========================================================================*/ +PUBLIC void mfs_nul_f(char *file, int line, char *str, int len, int maxlen) { if(len < 1) { printf("mfs:%s:%d: %d-length string?!\n", file, line, len); @@ -109,7 +113,11 @@ void mfs_nul_f(char *file, int line, char *str, int len, int maxlen) #define MYASSERT(c) if(!(c)) { printf("MFS:%s:%d: sanity check: %s failed\n", \ file, line, #c); panic("MFS", "sanity check " #c " failed", __LINE__); } -void sanitycheck(char *file, int line) + +/*===========================================================================* + * sanity_check * + *===========================================================================*/ +PUBLIC void sanitycheck(char *file, int line) { MYASSERT(SELF_E > 0); if(superblock.s_dev != NO_DEV) { diff --git a/servers/mfs/write.c b/servers/mfs/write.c index 73b2b923e..797a6e45d 100644 --- a/servers/mfs/write.c +++ b/servers/mfs/write.c @@ -1,14 +1,12 @@ - /* This file is the counterpart of "read.c". It contains the code for writing * insofar as this is not contained in read_write(). * * The entry points into this file are - * do_write: call read_write to perform the WRITE system call + * write_map: write a new zone into an inode * clear_zone: erase a zone in the middle of a file * new_block: acquire a new block + * zero_block: overwrite a block with zeroes * - * Updates: - * 2007-06-01: jfdsmit@gmail.com added i_zsearch optimalization */ #include "fs.h" @@ -181,6 +179,7 @@ int op; /* special actions */ return(OK); } + /*===========================================================================* * wr_indir * *===========================================================================*/ @@ -205,6 +204,7 @@ zone_t zone; /* zone to write */ bp->b_v2_ind[index] = (zone_t) conv4(sp->s_native, (long) zone); } + /*===========================================================================* * empty_indir * *===========================================================================*/ @@ -215,20 +215,21 @@ struct super_block *sb; /* superblock of device block resides on */ /* Return nonzero if the indirect block pointed to by bp contains * only NO_ZONE entries. */ - int i; - if(sb->s_version == V1) { - for(i = 0; i < V1_INDIRECTS; i++) - if(bp->b_v1_ind[i] != NO_ZONE) - return 0; - } else { - for(i = 0; i < V2_INDIRECTS(sb->s_block_size); i++) - if(bp->b_v2_ind[i] != NO_ZONE) - return 0; - } + int i; + if(sb->s_version == V1) { + for(i = 0; i < V1_INDIRECTS; i++) + if(bp->b_v1_ind[i] != NO_ZONE) + return(0); + } else { + for(i = 0; i < V2_INDIRECTS(sb->s_block_size); i++) + if(bp->b_v2_ind[i] != NO_ZONE) + return(0); + } - return 1; + return(1); } + /*===========================================================================* * clear_zone * *===========================================================================*/ @@ -269,6 +270,7 @@ int flag; /* 0 if called by read_write, 1 by new_block */ } } + /*===========================================================================* * new_block * *===========================================================================*/ @@ -323,6 +325,7 @@ off_t position; /* file pointer */ return(bp); } + /*===========================================================================* * zero_block * *===========================================================================*/ diff --git a/servers/pm/getset.c b/servers/pm/getset.c index 5fb6e8c73..a2da959d7 100644 --- a/servers/pm/getset.c +++ b/servers/pm/getset.c @@ -7,6 +7,7 @@ #include "pm.h" #include #include +#include #include #include #include "mproc.h" @@ -22,8 +23,32 @@ PUBLIC int do_get() register struct mproc *rmp = mp; int r, proc; + int ngroups; switch(call_nr) { + case GETGROUPS: + ngroups = m_in.grp_no; + if (ngroups > NGROUPS_MAX || ngroups < 0) + return(EINVAL); + + if (ngroups == 0) { + r = rmp->mp_ngroups; + break; + } + + if (ngroups < rmp->mp_ngroups) + /* Asking for less groups than available */ + return(EINVAL); + + + r = sys_datacopy(SELF, (vir_bytes) rmp->mp_sgroups, who_e, + (vir_bytes) m_in.groupsp, ngroups * sizeof(gid_t)); + + if (r != OK) + return(r); + + r = rmp->mp_ngroups; + break; case GETUID: r = rmp->mp_realuid; rmp->mp_reply.reply_res2 = rmp->mp_effuid; @@ -60,7 +85,8 @@ PUBLIC int do_set() */ register struct mproc *rmp = mp; message m; - int r; + int r, i; + int ngroups; switch(call_nr) { case SETUID: @@ -92,7 +118,34 @@ PUBLIC int do_set() m.PM_RID = rmp->mp_realgid; break; + case SETGROUPS: + if (rmp->mp_effuid != SUPER_USER) + return(EPERM); + + ngroups = m_in.grp_no; + + if (ngroups > NGROUPS_MAX || ngroups < 0) + return(EINVAL); + + if (m_in.groupsp == NULL) + return(EFAULT); + + r = sys_datacopy(who_e, (vir_bytes) m_in.groupsp, SELF, + (vir_bytes) rmp->mp_sgroups, + ngroups * sizeof(gid_t)); + if (r != OK) + return(r); + for (i = ngroups; i < NGROUPS_MAX; i++) + rmp->mp_sgroups[i] = 0; + rmp->mp_ngroups = ngroups; + + m.m_type = PM_SETGROUPS; + m.PM_PROC = rmp->mp_endpoint; + m.PM_GROUP_NO = rmp->mp_ngroups; + m.PM_GROUP_ADDR = rmp->mp_sgroups; + + break; case SETSID: if (rmp->mp_procgrp == rmp->mp_pid) return(EPERM); rmp->mp_procgrp = rmp->mp_pid; diff --git a/servers/pm/main.c b/servers/pm/main.c index 4d18b0ca7..4c5623448 100644 --- a/servers/pm/main.c +++ b/servers/pm/main.c @@ -102,6 +102,7 @@ PUBLIC int main() case PM_FORK_NB_REPLY: case PM_UNPAUSE_REPLY: case PM_REBOOT_REPLY: + case PM_SETGROUPS_REPLY: if (who_e == FS_PROC_NR) { handle_fs_reply(); @@ -441,6 +442,7 @@ PRIVATE void handle_fs_reply() switch (call_nr) { case PM_SETUID_REPLY: case PM_SETGID_REPLY: + case PM_SETGROUPS_REPLY: /* Wake up the original caller */ setreply(rmp-mproc, OK); diff --git a/servers/pm/mproc.h b/servers/pm/mproc.h index 9b6e9b48e..7da8d8b0a 100644 --- a/servers/pm/mproc.h +++ b/servers/pm/mproc.h @@ -4,6 +4,7 @@ * systems have tables that are also indexed by process, with the contents * of corresponding slots referring to the same process in all three. */ +#include #include #include @@ -30,6 +31,10 @@ EXTERN struct mproc { gid_t mp_realgid; /* process' real gid */ gid_t mp_effgid; /* process' effective gid */ + /* Supplemental groups. */ + int mp_ngroups; /* number of supplemental groups */ + gid_t mp_sgroups[NGROUPS_MAX];/* process' supplemental groups */ + /* Signal handling information. */ sigset_t mp_ignore; /* 1 means ignore the signal, 0 means don't */ sigset_t mp_catch; /* 1 means catch the signal, 0 means don't */ diff --git a/servers/pm/param.h b/servers/pm/param.h index 9a1a18432..1fc1ceec6 100644 --- a/servers/pm/param.h +++ b/servers/pm/param.h @@ -3,6 +3,8 @@ #define exec_len m1_i1 #define func m6_f1 #define grp_id m1_i1 +#define grp_no m1_i1 +#define groupsp m1_p1 #define namelen m1_i2 #define pid m1_i1 #define seconds m1_i1 diff --git a/servers/pm/table.c b/servers/pm/table.c index 1ba34d1c1..d705ac1e0 100644 --- a/servers/pm/table.c +++ b/servers/pm/table.c @@ -76,8 +76,8 @@ _PROTOTYPE (int (*call_vec[]), (void) ) = { do_set, /* 62 = setsid */ do_get, /* 63 = getpgrp */ do_itimer, /* 64 = itimer */ - no_sys, /* 65 = unused */ - no_sys, /* 66 = unused */ + do_get, /* 65 = getgroups */ + do_set, /* 66 = setgroups */ no_sys, /* 67 = unused */ no_sys, /* 68 = unused */ no_sys, /* 69 = unused */ diff --git a/servers/rs/table.c b/servers/rs/table.c index 4264c8719..4ed3d1a9c 100644 --- a/servers/rs/table.c +++ b/servers/rs/table.c @@ -44,6 +44,7 @@ PUBLIC struct boot_image_priv boot_image_priv_table[] = { { MEM_PROC_NR, SRV_F, SRV_T, SRV_M, mem_kc }, { LOG_PROC_NR, SRV_F, SRV_T, SRV_M, drv_kc }, { MFS_PROC_NR, SRV_F, SRV_T, SRV_M, fs_kc }, + { PFS_PROC_NR, SRV_F, SRV_T, SRV_M, fs_kc }, { INIT_PROC_NR, RUSR_F, RUSR_T, RUSR_M, rusr_kc }, { NULL_BOOT_NR, 0, 0, 0, no_kc } /* null entry */ }; @@ -53,6 +54,7 @@ PUBLIC struct boot_image_sys boot_image_sys_table[] = { /*endpoint, sys flags */ { LOG_PROC_NR, SRVC_SF }, { MFS_PROC_NR, SRVC_SF }, + { PFS_PROC_NR, SRVC_SF }, { DEFAULT_BOOT_NR, SRV_SF } /* default entry */ }; diff --git a/servers/vfs/device.c b/servers/vfs/device.c index 5ffebf4bd..6cd9468d1 100644 --- a/servers/vfs/device.c +++ b/servers/vfs/device.c @@ -27,7 +27,6 @@ #include #include "file.h" #include "fproc.h" - #include #include "vnode.h" #include "vmnt.h" @@ -35,11 +34,12 @@ #define ELEMENTS(a) (sizeof(a)/sizeof((a)[0])) -FORWARD _PROTOTYPE( int safe_io_conversion, (endpoint_t, - cp_grant_id_t *, int *, cp_grant_id_t *, int, endpoint_t *, - void **, int *, vir_bytes, u32_t *)); +FORWARD _PROTOTYPE( int safe_io_conversion, (endpoint_t, cp_grant_id_t *, + int *, cp_grant_id_t *, int, + endpoint_t *, void **, int *, + vir_bytes, u32_t *) ); FORWARD _PROTOTYPE( void safe_io_cleanup, (cp_grant_id_t, cp_grant_id_t *, - int)); + int) ); FORWARD _PROTOTYPE( void restart_reopen, (int maj) ); extern int dmap_size; @@ -64,8 +64,7 @@ int flags; /* mode bits and flags */ major = (dev >> MAJOR) & BYTE; if (major >= NR_DEVICES) major = 0; dp = &dmap[major]; - if (dp->dmap_driver == NONE) - return ENXIO; + if (dp->dmap_driver == NONE) return(ENXIO); r = (*dp->dmap_opcl)(DEV_OPEN, dev, proc, flags); return(r); } @@ -89,11 +88,10 @@ int flags; /* mode bits and flags */ major = (dev >> MAJOR) & BYTE; if (major >= NR_DEVICES) major = 0; dp = &dmap[major]; - if (dp->dmap_driver == NONE) - return ENXIO; + if (dp->dmap_driver == NONE) return(ENXIO); r = (*dp->dmap_opcl)(DEV_REOPEN, dev, filp_no, flags); if (r == OK) panic(__FILE__,"OK on reopen from", dp->dmap_driver); - if (r == SUSPEND) r= OK; + if (r == SUSPEND) r = OK; return(r); } @@ -108,13 +106,12 @@ int filp_no; int r; /* See if driver is roughly valid. */ - if (dmap[(dev >> MAJOR)].dmap_driver == NONE) { - return ENXIO; - } - r= (*dmap[(dev >> MAJOR) & BYTE].dmap_opcl)(DEV_CLOSE, dev, filp_no, 0); - return r; + if (dmap[(dev >> MAJOR)].dmap_driver == NONE) return(ENXIO); + r = (*dmap[(dev >> MAJOR) & BYTE].dmap_opcl)(DEV_CLOSE, dev, filp_no, 0); + return(r); } + /*===========================================================================* * suspended_ep * *===========================================================================*/ @@ -123,40 +120,34 @@ endpoint_t suspended_ep(endpoint_t driver, cp_grant_id_t g) /* A process is suspended on a driver for which FS issued * a grant. Find out which process it was. */ - struct fproc *rfp; - for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) { - if(rfp->fp_pid == PID_FREE) - continue; + struct fproc *rfp; + for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) { + if(rfp->fp_pid == PID_FREE) continue; if(rfp->fp_blocked_on == FP_BLOCKED_ON_OTHER && - rfp->fp_task == driver && rfp->fp_grant == g) { - return rfp->fp_endpoint; - } + rfp->fp_task == driver && rfp->fp_grant == g) + return rfp->fp_endpoint; } - return NONE; + return(NONE); } + /*===========================================================================* * dev_status * *===========================================================================*/ PUBLIC void dev_status(message *m) { - message st; - int d, get_more = 1; - endpoint_t endpt; + message st; + int d, get_more = 1; + endpoint_t endpt; - for(d = 0; d < NR_DEVICES; d++) - if (dmap[d].dmap_driver != NONE && - dmap[d].dmap_driver == m->m_source) - break; + for(d = 0; d < NR_DEVICES; d++) + if (dmap[d].dmap_driver != NONE && dmap[d].dmap_driver == m->m_source) + break; - if (d >= NR_DEVICES) - return; - - if (dmap[d].dmap_async_driver) - { - printf( - "dev_status: not doing dev_status for async driver %d\n", + if (d >= NR_DEVICES) return; + if (dmap[d].dmap_async_driver) { + printf("dev_status: not doing dev_status for async driver %d\n", m->m_source); return; } @@ -164,7 +155,7 @@ PUBLIC void dev_status(message *m) do { int r; st.m_type = DEV_STATUS; - if ((r=sendrec(m->m_source, &st)) != OK) { + if ((r = sendrec(m->m_source, &st)) != OK) { printf("DEV_STATUS failed to %d: %d\n", m->m_source, r); if (r == EDEADSRCDST) return; if (r == EDSTDIED) return; @@ -179,10 +170,9 @@ PUBLIC void dev_status(message *m) endpt = suspended_ep(m->m_source, st.REP_IO_GRANT); if(endpt == NONE) { - printf("FS: proc with " - "grant %d from %d not found (revive)\n", - st.REP_IO_GRANT, - st.m_source); + printf("FS: proc with grant %d" + " from %d not found (revive)\n", + st.REP_IO_GRANT, st.m_source); continue; } } @@ -205,6 +195,7 @@ PUBLIC void dev_status(message *m) return; } + /*===========================================================================* * safe_io_conversion * *===========================================================================*/ @@ -221,106 +212,97 @@ int *vec_grants; vir_bytes bytes; u32_t *pos_lo; { - int access = 0, size; - int j; - iovec_t *v; - static iovec_t new_iovec[NR_IOREQS]; - - /* Number of grants allocated in vector I/O. */ - *vec_grants = 0; - - /* Driver can handle it - change request to a safe one. */ - - *gid = GRANT_INVALID; - - switch(*op) { - case VFS_DEV_READ: - case VFS_DEV_WRITE: - /* Change to safe op. */ - *op = *op == VFS_DEV_READ ? DEV_READ_S : DEV_WRITE_S; - - if((*gid=cpf_grant_magic(driver, *io_ept, - (vir_bytes) *buf, bytes, - *op == DEV_READ_S ? CPF_WRITE : CPF_READ)) < 0) { - panic(__FILE__, - "cpf_grant_magic of buffer failed\n", NO_NUM); - } - - break; - case VFS_DEV_GATHER: - case VFS_DEV_SCATTER: - /* Change to safe op. */ - *op = *op == VFS_DEV_GATHER ? - DEV_GATHER_S : DEV_SCATTER_S; - - /* Grant access to my new i/o vector. */ - if((*gid = cpf_grant_direct(driver, - (vir_bytes) new_iovec, bytes * sizeof(iovec_t), - CPF_READ | CPF_WRITE)) < 0) { - panic(__FILE__, - "cpf_grant_direct of vector failed", NO_NUM); - } - v = (iovec_t *) *buf; - /* Grant access to i/o buffers. */ - for(j = 0; j < bytes; j++) { - if(j >= NR_IOREQS) - panic(__FILE__, "vec too big", bytes); - new_iovec[j].iov_addr = gids[j] = - cpf_grant_direct(driver, (vir_bytes) - v[j].iov_addr, v[j].iov_size, - *op == DEV_GATHER_S ? CPF_WRITE : CPF_READ); - if(!GRANT_VALID(gids[j])) { - panic(__FILE__, "grant to iovec buf failed", - NO_NUM); - } - new_iovec[j].iov_size = v[j].iov_size; - (*vec_grants)++; - } - - /* Set user's vector to the new one. */ - *buf = new_iovec; - break; - case VFS_DEV_IOCTL: - *pos_lo = *io_ept; /* Old endpoint in POSITION field. */ - *op = DEV_IOCTL_S; - if(_MINIX_IOCTL_IOR(m_in.REQUEST)) access |= CPF_WRITE; - if(_MINIX_IOCTL_IOW(m_in.REQUEST)) access |= CPF_READ; - if(_MINIX_IOCTL_BIG(m_in.REQUEST)) - size = _MINIX_IOCTL_SIZE_BIG(m_in.REQUEST); - else - size = _MINIX_IOCTL_SIZE(m_in.REQUEST); - - - /* Do this even if no I/O happens with the ioctl, in - * order to disambiguate requests with DEV_IOCTL_S. - */ - if((*gid=cpf_grant_magic(driver, *io_ept, - (vir_bytes) *buf, size, access)) < 0) { - panic(__FILE__, - "cpf_grant_magic failed (ioctl)\n", - NO_NUM); - } - break; - case VFS_DEV_SELECT: - *op = DEV_SELECT; - break; - default: - panic(__FILE__,"safe_io_conversion: unknown operation", - *op); - } - - /* If we have converted to a safe operation, I/O - * endpoint becomes FS if it wasn't already. - */ - if(GRANT_VALID(*gid)) { - *io_ept = FS_PROC_NR; - return 1; - } + int access = 0, size, j; + iovec_t *v; + static iovec_t new_iovec[NR_IOREQS]; + + /* Number of grants allocated in vector I/O. */ + *vec_grants = 0; + + /* Driver can handle it - change request to a safe one. */ + *gid = GRANT_INVALID; + + switch(*op) { + case VFS_DEV_READ: + case VFS_DEV_WRITE: + /* Change to safe op. */ + *op = *op == VFS_DEV_READ ? DEV_READ_S : DEV_WRITE_S; + + *gid = cpf_grant_magic(driver, *io_ept, (vir_bytes) *buf, bytes, + *op == DEV_READ_S ? CPF_WRITE : CPF_READ); + if (*gid < 0) + panic(__FILE__, "cpf_grant_magic of buffer failed\n", NO_NUM); + break; + case VFS_DEV_GATHER: + case VFS_DEV_SCATTER: + /* Change to safe op. */ + *op = *op == VFS_DEV_GATHER ? DEV_GATHER_S : DEV_SCATTER_S; + + /* Grant access to my new i/o vector. */ + *gid = cpf_grant_direct(driver, (vir_bytes) new_iovec, + bytes * sizeof(iovec_t), CPF_READ|CPF_WRITE); + if (*gid < 0) + panic(__FILE__, "cpf_grant_direct of vector failed", NO_NUM); + + v = (iovec_t *) *buf; + /* Grant access to i/o buffers. */ + for(j = 0; j < bytes; j++) { + if(j >= NR_IOREQS) panic(__FILE__, "vec too big", bytes); + + new_iovec[j].iov_addr = + gids[j] = + cpf_grant_direct(driver, (vir_bytes) v[j].iov_addr, v[j].iov_size, + *op == DEV_GATHER_S ? CPF_WRITE : CPF_READ); + + if(!GRANT_VALID(gids[j])) + panic(__FILE__, "grant to iovec buf failed", NO_NUM); + + new_iovec[j].iov_size = v[j].iov_size; + (*vec_grants)++; + } + + /* Set user's vector to the new one. */ + *buf = new_iovec; + break; + case VFS_DEV_IOCTL: + *pos_lo = *io_ept; /* Old endpoint in POSITION field. */ + *op = DEV_IOCTL_S; + if(_MINIX_IOCTL_IOR(m_in.REQUEST)) access |= CPF_WRITE; + if(_MINIX_IOCTL_IOW(m_in.REQUEST)) access |= CPF_READ; + if(_MINIX_IOCTL_BIG(m_in.REQUEST)) + size = _MINIX_IOCTL_SIZE_BIG(m_in.REQUEST); + else + size = _MINIX_IOCTL_SIZE(m_in.REQUEST); + + + /* Do this even if no I/O happens with the ioctl, in + * order to disambiguate requests with DEV_IOCTL_S. + */ + *gid = cpf_grant_magic(driver, *io_ept, (vir_bytes) *buf, size, + access); + if (*gid < 0) + panic(__FILE__, "cpf_grant_magic failed (ioctl)\n", NO_NUM); + + break; + case VFS_DEV_SELECT: + *op = DEV_SELECT; + break; + default: + panic(__FILE__,"safe_io_conversion: unknown operation", *op); + } - /* Not converted to a safe operation (because there is no - * copying involved in this operation). - */ - return 0; + /* If we have converted to a safe operation, I/O + * endpoint becomes FS if it wasn't already. + */ + if(GRANT_VALID(*gid)) { + *io_ept = FS_PROC_NR; + return 1; + } + + /* Not converted to a safe operation (because there is no + * copying involved in this operation). + */ + return 0; } /*===========================================================================* @@ -332,14 +314,11 @@ cp_grant_id_t *gids; int gids_size; { /* Free resources (specifically, grants) allocated by safe_io_conversion(). */ - int j; - - cpf_revoke(gid); + int j; - for(j = 0; j < gids_size; j++) - cpf_revoke(gids[j]); - - return; + cpf_revoke(gid); + for(j = 0; j < gids_size; j++) + cpf_revoke(gids[j]); } @@ -376,11 +355,10 @@ int suspend_reopen; /* Just suspend the process */ /* See if driver is roughly valid. */ if (dp->dmap_driver == NONE) { printf("FS: dev_io: no driver for dev %x\n", dev); - return ENXIO; + return(ENXIO); } - if (suspend_reopen) - { + if (suspend_reopen) { /* Suspend user. */ fp->fp_grant = GRANT_INVALID; fp->fp_ioproc = NONE; @@ -390,9 +368,8 @@ int suspend_reopen; /* Just suspend the process */ } if(isokendpt(dp->dmap_driver, &dummyproc) != OK) { - printf("FS: dev_io: old driver for dev %x (%d)\n", - dev, dp->dmap_driver); - return ENXIO; + printf("FS: dev_io: old driver for dev %x (%d)\n",dev,dp->dmap_driver); + return(ENXIO); } /* By default, these are right. */ @@ -401,9 +378,9 @@ int suspend_reopen; /* Just suspend the process */ /* Convert DEV_* to DEV_*_S variants. */ buf_used = buf; - safe = safe_io_conversion(dp->dmap_driver, &gid, - &op, gids, NR_IOREQS, (endpoint_t*) &dev_mess.IO_ENDPT, &buf_used, - &vec_grants, bytes, &pos_lo); + safe = safe_io_conversion(dp->dmap_driver, &gid, &op, gids, NR_IOREQS, + (endpoint_t*) &dev_mess.IO_ENDPT, &buf_used, + &vec_grants, bytes, &pos_lo); if(buf != buf_used) panic(__FILE__,"dev_io: safe_io_conversion changed buffer", NO_NUM); @@ -430,17 +407,15 @@ int suspend_reopen; /* Just suspend the process */ /* Driver has vanished. */ printf("Driver gone?\n"); if(safe) safe_io_cleanup(gid, gids, vec_grants); - return EIO; + return(EIO); } /* Task has completed. See if call completed. */ if (dev_mess.REP_STATUS == SUSPEND) { - if(vec_grants > 0) { - panic(__FILE__,"SUSPEND on vectored i/o", NO_NUM); - } + if(vec_grants > 0) panic(__FILE__,"SUSPEND on vectored i/o", NO_NUM); + /* fp is uninitialized at init time. */ - if(!fp) - panic(__FILE__,"SUSPEND on NULL fp", NO_NUM); + if(!fp) panic(__FILE__,"SUSPEND on NULL fp", NO_NUM); if ((flags & O_NONBLOCK) && !dp->dmap_async_driver) { /* Not supposed to block. */ @@ -452,8 +427,8 @@ int suspend_reopen; /* Just suspend the process */ * logic. Mode is expected in the COUNT field. */ dev_mess.COUNT = 0; - if(call_nr == READ) dev_mess.COUNT = R_BIT; - else if(call_nr == WRITE) dev_mess.COUNT = W_BIT; + if (call_nr == READ) dev_mess.COUNT = R_BIT; + else if (call_nr == WRITE) dev_mess.COUNT = W_BIT; dev_mess.DEVICE = (dev >> MINOR) & BYTE; (*dp->dmap_io)(dp->dmap_driver, &dev_mess); if (dev_mess.REP_STATUS == EINTR) dev_mess.REP_STATUS = EAGAIN; @@ -518,12 +493,12 @@ int flags; /* mode bits and flags */ if (dp->dmap_driver == NONE) { printf("FS: gen_opcl: no driver for dev %x\n", dev); - return ENXIO; + return(ENXIO); } /* Call the task. */ r= (*dp->dmap_io)(dp->dmap_driver, &dev_mess); - if (r != OK) return r; + if (r != OK) return(r); return(dev_mess.REP_STATUS); } @@ -565,6 +540,7 @@ int flags; /* mode bits and flags */ return(r); } + /*===========================================================================* * ctty_opcl * *===========================================================================*/ @@ -581,6 +557,7 @@ int flags; /* mode bits and flags */ return(fp->fp_tty == 0 ? ENXIO : OK); } + /*===========================================================================* * pm_setsid * *===========================================================================*/ @@ -600,6 +577,7 @@ int proc_e; rfp->fp_tty = 0; } + /*===========================================================================* * do_ioctl * *===========================================================================*/ @@ -612,17 +590,18 @@ PUBLIC int do_ioctl() register struct vnode *vp; dev_t dev; - if ( (f = get_filp(m_in.ls_fd)) == NIL_FILP) return(err_code); + if ((f = get_filp(m_in.ls_fd)) == NIL_FILP) return(err_code); vp = f->filp_vno; /* get vnode pointer */ - if ( (vp->v_mode & I_TYPE) != I_CHAR_SPECIAL - && (vp->v_mode & I_TYPE) != I_BLOCK_SPECIAL) return(ENOTTY); + if ((vp->v_mode & I_TYPE) != I_CHAR_SPECIAL && + (vp->v_mode & I_TYPE) != I_BLOCK_SPECIAL) return(ENOTTY); suspend_reopen= (f->filp_state != FS_NORMAL); dev = (dev_t) vp->v_sdev; - return (dev_io(VFS_DEV_IOCTL, dev, who_e, m_in.ADDRESS, cvu64(0), - m_in.REQUEST, f->filp_flags, suspend_reopen)); + return dev_io(VFS_DEV_IOCTL, dev, who_e, m_in.ADDRESS, cvu64(0), + m_in.REQUEST, f->filp_flags, suspend_reopen); } + /*===========================================================================* * gen_io * *===========================================================================*/ @@ -636,40 +615,35 @@ message *mess_ptr; /* pointer to message for task */ int r, proc_e; - if(task_nr == SYSTEM) { - printf("VFS: sending %d to SYSTEM\n", mess_ptr->m_type); - } + if(task_nr == SYSTEM) printf("VFS: sending %d to SYSTEM\n", mess_ptr->m_type); proc_e = mess_ptr->IO_ENDPT; - r = sendrec(task_nr, mess_ptr); - if (r != OK) { - if (r == EDEADSRCDST || r == EDSTDIED || r == ESRCDIED) { - printf("fs: dead driver %d\n", task_nr); - dmap_unmap_by_endpt(task_nr); - return r; - } - if (r == ELOCKED) { - printf("fs: ELOCKED talking to %d\n", task_nr); - return r; - } - panic(__FILE__,"call_task: can't send/receive", r); + if (r != OK) { + if (r == EDEADSRCDST || r == EDSTDIED || r == ESRCDIED) { + printf("fs: dead driver %d\n", task_nr); + dmap_unmap_by_endpt(task_nr); + return(r); } - - /* Did the process we did the sendrec() for get a result? */ - if (mess_ptr->REP_ENDPT != proc_e) { - printf( - "fs: strange device reply from %d, type = %d, proc = %d (not %d) (2) ignored\n", - mess_ptr->m_source, - mess_ptr->m_type, - proc_e, - mess_ptr->REP_ENDPT); - return EIO; + if (r == ELOCKED) { + printf("fs: ELOCKED talking to %d\n", task_nr); + return(r); } + panic(__FILE__,"call_task: can't send/receive", r); + } + + /* Did the process we did the sendrec() for get a result? */ + if (mess_ptr->REP_ENDPT != proc_e) { + printf("fs: strange device reply from %d, type = %d, proc = %d " + "(not %d) (2) ignored\n", mess_ptr->m_source, mess_ptr->m_type, + proc_e, mess_ptr->REP_ENDPT); + return(EIO); + } - return OK; + return(OK); } + /*===========================================================================* * asyn_io * *===========================================================================*/ @@ -685,15 +659,15 @@ message *mess_ptr; /* pointer to message for task */ proc_e = mess_ptr->IO_ENDPT; - r= asynsend(task_nr, mess_ptr); - if (r != OK) - panic(__FILE__, "asyn_io: asynsend failed", r); + r = asynsend(task_nr, mess_ptr); + if (r != OK) panic(__FILE__, "asyn_io: asynsend failed", r); /* Fake a SUSPEND */ - mess_ptr->REP_STATUS= SUSPEND; - return OK; + mess_ptr->REP_STATUS = SUSPEND; + return(OK); } + /*===========================================================================* * ctty_io * *===========================================================================*/ @@ -716,20 +690,19 @@ message *mess_ptr; /* pointer to message for task */ dp = &dmap[(fp->fp_tty >> MAJOR) & BYTE]; mess_ptr->DEVICE = (fp->fp_tty >> MINOR) & BYTE; - if (dp->dmap_driver == NONE) { - printf("FS: ctty_io: no driver for dev\n"); - return EIO; - } + if (dp->dmap_driver == NONE) { + printf("FS: ctty_io: no driver for dev\n"); + return(EIO); + } if(isokendpt(dp->dmap_driver, &dummyproc) != OK) { - printf("FS: ctty_io: old driver %d\n", - dp->dmap_driver); - return EIO; + printf("FS: ctty_io: old driver %d\n", dp->dmap_driver); + return(EIO); } (*dp->dmap_io)(dp->dmap_driver, mess_ptr); } - return OK; + return(OK); } @@ -753,10 +726,9 @@ PUBLIC int no_dev_io(int proc, message *m) { /* Called when doing i/o on a nonexistent device. */ printf("VFS: I/O on unmapped device number\n"); - return EIO; + return(EIO); } - /*===========================================================================* * clone_opcl * @@ -787,20 +759,19 @@ int flags; /* mode bits and flags */ if (dp->dmap_driver == NONE) { - printf("vfs:clone_opcl: no driver for dev %x\n", dev); - return ENXIO; + printf("VFS clone_opcl: no driver for dev %x\n", dev); + return(ENXIO); } if(isokendpt(dp->dmap_driver, &dummyproc) != OK) { - printf("vfs:clone_opcl: bad driver endpoint for dev %x (%d)\n", - dev, dp->dmap_driver); - return ENXIO; + printf("VFS clone_opcl: bad driver endpoint for dev %x (%d)\n", dev, + dp->dmap_driver); + return(ENXIO); } /* Call the task. */ - r= (*dp->dmap_io)(dp->dmap_driver, &dev_mess); - if (r != OK) - return r; + r = (*dp->dmap_io)(dp->dmap_driver, &dev_mess); + if (r != OK) return(r); if (op == DEV_OPEN && dev_mess.REP_STATUS >= 0) { if (dev_mess.REP_STATUS != minor) { @@ -814,8 +785,7 @@ int flags; /* mode bits and flags */ */ /* Device number of the new device. */ - dev = (dev & ~(BYTE << MINOR)) | - (dev_mess.REP_STATUS << MINOR); + dev = (dev & ~(BYTE << MINOR)) | (dev_mess.REP_STATUS << MINOR); /* Issue request */ r = req_newnode(ROOT_FS_E, fp->fp_effuid, fp->fp_effgid, @@ -829,19 +799,15 @@ int flags; /* mode bits and flags */ vp = fp->fp_filp[m_in.fd]->filp_vno; put_vnode(vp); - if ((vp = get_free_vnode(__FILE__, __LINE__)) == NIL_VNODE) { - printf( - "vfs:clone_opcl: failed to get a free vnode..\n"); + if ((vp = get_free_vnode()) == NIL_VNODE) vp = fp->fp_filp[m_in.fd]->filp_vno; - } vp->v_fs_e = res.fs_e; if ((vmp = find_vmnt(vp->v_fs_e)) == NIL_VMNT) - printf("vfs:clone_opcl: no vmnt found\n"); + printf("VFS clone_opcl: no vmnt found\n"); vp->v_vmnt = vmp; vp->v_dev = vmp->m_dev; - vp->v_fs_e = res.fs_e; vp->v_inode_nr = res.inode_nr; vp->v_mode = res.fmode; @@ -891,25 +857,22 @@ PUBLIC void dev_up(int maj) /* Send new driver endpoint */ if (OK != req_newdriver(vmp->m_fs_e, vmp->m_dev, new_driver_e)) - printf( - "VFSdev_up: error sending new driver endpoint. FS_e: %d req_nr: %d\n", - vmp->m_fs_e, REQ_NEW_DRIVER); + printf("VFSdev_up: error sending new driver endpoint." + " FS_e: %d req_nr: %d\n", vmp->m_fs_e, REQ_NEW_DRIVER); } /* Look for processes that are suspened in an OPEN call. Set SUSP_REOPEN * to indicate that this process was suspended before the call to dev_up. */ for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) { - if(rfp->fp_pid == PID_FREE) - continue; - if(rfp->fp_blocked_on != FP_BLOCKED_ON_DOPEN) - continue; + if(rfp->fp_pid == PID_FREE) continue; + if(rfp->fp_blocked_on != FP_BLOCKED_ON_DOPEN) continue; printf("dev_up: found process in FP_BLOCKED_ON_DOPEN, fd %d\n", rfp->fp_fd >> 8); - fd_nr= (rfp->fp_fd >> 8); - fp= rfp->fp_filp[fd_nr]; - vp= fp->filp_vno; + fd_nr = (rfp->fp_fd >> 8); + fp = rfp->fp_filp[fd_nr]; + vp = fp->filp_vno; if (!vp) panic(__FILE__, "restart_reopen: no vp", NO_NUM); if ((vp->v_mode & I_TYPE) != I_CHAR_SPECIAL) continue; if (((vp->v_sdev >> MAJOR) & BYTE) != maj) continue; @@ -926,8 +889,8 @@ PUBLIC void dev_up(int maj) if(((vp->v_sdev >> MAJOR) & BYTE) != maj) continue; if(!(vp->v_mode & (I_BLOCK_SPECIAL|I_CHAR_SPECIAL))) continue; - fp->filp_state= FS_NEEDS_REOPEN; - needs_reopen= TRUE; + fp->filp_state = FS_NEEDS_REOPEN; + needs_reopen = TRUE; } if (needs_reopen) @@ -935,6 +898,7 @@ PUBLIC void dev_up(int maj) } + /*===========================================================================* * restart_reopen * *===========================================================================*/ @@ -952,19 +916,12 @@ int maj; if (fp->filp_state != FS_NEEDS_REOPEN) continue; if (((vp->v_sdev >> MAJOR) & BYTE) != maj) continue; if ((vp->v_mode & I_TYPE) != I_CHAR_SPECIAL) continue; + minor = ((vp->v_sdev >> MINOR) & BYTE); - if (!(fp->filp_flags & O_REOPEN)) - { + if (!(fp->filp_flags & O_REOPEN)) { /* File descriptor is to be closed when driver restarts. */ - - /* The function inval_filp will set the fp_filp[]s of - * processes holding that fp to NULL, but _not_ clear - * fp_filp_inuse, so that fd can't be recycled until - * it's close()d. - */ - n = inval_filp(fp); - if (n != fp->filp_count) - { + n = invalidate(fp); + if (n != fp->filp_count) { printf("VFS: warning: invalidate/count " "discrepancy (%d, %d)\n", n, fp->filp_count); } @@ -972,20 +929,12 @@ int maj; continue; } - minor = ((vp->v_sdev >> MINOR) & BYTE); - r = dev_reopen(vp->v_sdev, fp-filp, vp->v_mode & (R_BIT|W_BIT)); - if (r == OK) - return; + if (r == OK) return; - /* This function will set the fp_filp[]s of processes - * holding that fp to NULL, but _not_ clear - * fp_filp_inuse, so that fd can't be recycled until - * it's close()d. - */ - n = inval_filp(fp); - if (n != fp->filp_count) - { + /* Device could not be reopened. Invalidate all filps on that device.*/ + n = invalidate(fp); + if (n != fp->filp_count) { printf("VFS: warning: invalidate/count " "discrepancy (%d, %d)\n", n, fp->filp_count); } @@ -998,12 +947,9 @@ int maj; driver_e= dmap[maj].dmap_driver; for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) { - if(rfp->fp_pid == PID_FREE) - continue; + if(rfp->fp_pid == PID_FREE) continue; if(rfp->fp_blocked_on == FP_BLOCKED_ON_OTHER && - rfp->fp_task == driver_e && - (rfp->fp_flags & SUSP_REOPEN)) - { + rfp->fp_task == driver_e && (rfp->fp_flags & SUSP_REOPEN)) { rfp->fp_flags &= ~SUSP_REOPEN; rfp->fp_blocked_on = FP_BLOCKED_ON_NONE; reply(rfp->fp_endpoint, ERESTART); @@ -1012,19 +958,16 @@ int maj; /* Look for processes that are suspened in an OPEN call */ for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) { - if (rfp->fp_pid == PID_FREE) - continue; + if (rfp->fp_pid == PID_FREE) continue; if (rfp->fp_blocked_on == FP_BLOCKED_ON_DOPEN || - !(rfp->fp_flags & SUSP_REOPEN)) - continue; + !(rfp->fp_flags & SUSP_REOPEN)) continue; printf("restart_reopen: found process in FP_BLOCKED_ON_DOPEN, fd %d\n", rfp->fp_fd >> 8); - fd_nr= (rfp->fp_fd >> 8); - fp= rfp->fp_filp[fd_nr]; + fd_nr = (rfp->fp_fd >> 8); + fp = rfp->fp_filp[fd_nr]; - if (!fp) - { + if (!fp) { /* Open failed, and automatic reopen was not requested */ rfp->fp_blocked_on = FP_BLOCKED_ON_NONE; FD_CLR(fd_nr, &rfp->fp_filp_inuse); @@ -1032,7 +975,7 @@ int maj; continue; } - vp= fp->filp_vno; + vp = fp->filp_vno; if (!vp) panic(__FILE__, "restart_reopen: no vp", NO_NUM); if ((vp->v_mode & I_TYPE) != I_CHAR_SPECIAL) continue; if (((vp->v_sdev >> MAJOR) & BYTE) != maj) continue; @@ -1042,81 +985,71 @@ int maj; } } + /*===========================================================================* * reopen_reply * *===========================================================================*/ PUBLIC void reopen_reply() { - endpoint_t driver_e; - int filp_no, status, maj; - struct filp *fp; - struct vnode *vp; - struct dmap *dp; + endpoint_t driver_e; + int filp_no, status, maj; + struct filp *fp; + struct vnode *vp; + struct dmap *dp; - driver_e= m_in.m_source; - filp_no= m_in.REP_ENDPT; - status= m_in.REP_STATUS; + driver_e = m_in.m_source; + filp_no = m_in.REP_ENDPT; + status = m_in.REP_STATUS; - if (filp_no < 0 || filp_no >= NR_FILPS) - { - printf("reopen_reply: bad filp number %d from driver %d\n", - filp_no, driver_e); - return; - } - fp= &filp[filp_no]; - if (fp->filp_count < 1) - { - printf( - "reopen_reply: filp number %d not inuse (from driver %d)\n", - filp_no, driver_e); - return; - } + if (filp_no < 0 || filp_no >= NR_FILPS) { + printf("reopen_reply: bad filp number %d from driver %d\n", filp_no, + driver_e); + return; + } - vp= fp->filp_vno; - if (!vp) - { - printf( - "reopen_reply: no vnode for filp number %d (from driver %d)\n", - filp_no, driver_e); - return; - } + fp = &filp[filp_no]; + if (fp->filp_count < 1) { + printf("reopen_reply: filp number %d not inuse (from driver %d)\n", + filp_no, driver_e); + return; + } - if (fp->filp_state != FS_NEEDS_REOPEN) - { - printf( - "reopen_reply: bad state %d for filp number %d (from driver %d)\n", - fp->filp_state, filp_no, driver_e); - return; - } + vp = fp->filp_vno; + if (!vp) { + printf("reopen_reply: no vnode for filp number %d (from driver %d)\n", + filp_no, driver_e); + return; + } - if ((vp->v_mode & I_TYPE) != I_CHAR_SPECIAL) - { - printf( - "reopen_reply: bad mode 0%o for filp number %d (from driver %d)\n", - vp->v_mode, filp_no, driver_e); - return; - } + if (fp->filp_state != FS_NEEDS_REOPEN) { + printf("reopen_reply: bad state %d for filp number %d" + " (from driver %d)\n", fp->filp_state, filp_no, driver_e); + return; + } - maj= ((vp->v_sdev >> MAJOR) & BYTE); - dp = &dmap[maj]; - if (dp->dmap_driver != driver_e) - { - printf("reopen_reply: bad major %d for filp number %d " - "(from driver %d, current driver is %d)\n", - maj, filp_no, driver_e, dp->dmap_driver); - return; - } + if ((vp->v_mode & I_TYPE) != I_CHAR_SPECIAL) { + printf("reopen_reply: bad mode 0%o for filp number %d" + " (from driver %d)\n", vp->v_mode, filp_no, driver_e); + return; + } - if (status == OK) - { - fp->filp_state= FS_NORMAL; - } - else - { - printf("reopen_reply: should handle error status\n"); - return; - } - restart_reopen(maj); + maj = ((vp->v_sdev >> MAJOR) & BYTE); + dp = &dmap[maj]; + if (dp->dmap_driver != driver_e) { + printf("reopen_reply: bad major %d for filp number %d " + "(from driver %d, current driver is %d)\n", maj, filp_no, + driver_e, dp->dmap_driver); + return; + } + + if (status == OK) { + fp->filp_state= FS_NORMAL; + } else { + printf("reopen_reply: should handle error status\n"); + return; + } + + restart_reopen(maj); } #if 0 diff --git a/servers/vfs/exec.c b/servers/vfs/exec.c index afc219152..f854e002d 100644 --- a/servers/vfs/exec.c +++ b/servers/vfs/exec.c @@ -12,9 +12,6 @@ * * The entry points into this file are: * pm_exec: perform the EXEC system call - * - * Changes for VFS: - * Aug 2006 (Balazs Gerofi) */ #include "fs.h" @@ -29,7 +26,6 @@ #include #include "fproc.h" #include "param.h" - #include "vnode.h" #include "vmnt.h" #include @@ -71,193 +67,139 @@ vir_bytes frame_len; * complete stack image, including pointers, args, environ, etc. The stack * is copied to a buffer inside FS, and then to the new core image. */ - int r, sep_id, round, proc_s, hdrlen, load_text, allow_setuid; - vir_bytes text_bytes, data_bytes, bss_bytes, pc; - phys_bytes tot_bytes; /* total space for program, including gap */ - vir_bytes stack_top, vsp; - off_t off; - uid_t new_uid; - gid_t new_gid; - struct fproc *rfp; - struct vnode *vp; - time_t v_ctime; - char *cp; - struct stat sb; - char progname[PROC_NAME_LEN]; - static char mbuf[ARG_MAX]; /* buffer for stack and zeroes */ - - okendpt(proc_e, &proc_s); - rfp= fp= &fproc[proc_s]; - who_e= proc_e; - who_p= proc_s; - super_user = (fp->fp_effuid == SU_UID ? TRUE : FALSE); /* su? */ - - /* Get the exec file name. */ - r= fetch_name(path, path_len, 0); - if (r != OK) - { - printf("pm_exec: fetch_name failed\n"); -printf("return at %s, %d\n", __FILE__, __LINE__); - return(r); /* file name not in user data segment */ - } - - /* Fetch the stack from the user before destroying the old core image. */ - if (frame_len > ARG_MAX) - { - return(ENOMEM); /* stack too big */ - } - r = sys_datacopy(proc_e, (vir_bytes) frame, - SELF, (vir_bytes) mbuf, (phys_bytes)frame_len); - /* can't fetch stack (e.g. bad virtual addr) */ - if (r != OK) - { + int r, r1, sep_id, round, proc_s, hdrlen, load_text, allow_setuid; + vir_bytes text_bytes, data_bytes, bss_bytes, pc; + phys_bytes tot_bytes; /* total space for program, including gap */ + vir_bytes stack_top, vsp; + off_t off; + uid_t new_uid; + gid_t new_gid; + struct fproc *rfp; + struct vnode *vp; + time_t v_ctime; + char *cp; + struct stat sb; + char progname[PROC_NAME_LEN]; + static char mbuf[ARG_MAX]; /* buffer for stack and zeroes */ + + okendpt(proc_e, &proc_s); + rfp = fp = &fproc[proc_s]; + who_e = proc_e; + who_p = proc_s; + super_user = (fp->fp_effuid == SU_UID ? TRUE : FALSE); /* su? */ + + /* Get the exec file name. */ + if ((r = fetch_name(path, path_len, 0)) != OK) return(r); + + /* Fetch the stack from the user before destroying the old core image. */ + if (frame_len > ARG_MAX) return(ENOMEM); /* stack too big */ + r = sys_datacopy(proc_e, (vir_bytes) frame, SELF, (vir_bytes) mbuf, + (phys_bytes) frame_len); + if (r != OK) { /* can't fetch stack (e.g. bad virtual addr) */ printf("pm_exec: sys_datacopy failed\n"); -printf("return at %s, %d\n", __FILE__, __LINE__); return(r); - } + } - /* The default is the keep the original user and group IDs */ - new_uid= rfp->fp_effuid; - new_gid= rfp->fp_effgid; + /* The default is to keep the original user and group IDs */ + new_uid = rfp->fp_effuid; + new_gid = rfp->fp_effgid; - for (round= 0; round < 2; round++) - /* round = 0 (first attempt), or 1 (interpreted script) */ - { -#if 0 - printf("vfs:pm_exec: round %d, name '%s'\n", round, user_fullpath); -#endif + for (round= 0; round < 2; round++) { + /* round = 0 (first attempt), or 1 (interpreted script) */ - /* Save the name of the program */ - (cp= strrchr(user_fullpath, '/')) ? cp++ : (cp= user_fullpath); + /* Save the name of the program */ + (cp= strrchr(user_fullpath, '/')) ? cp++ : (cp= user_fullpath); - strncpy(progname, cp, PROC_NAME_LEN-1); - progname[PROC_NAME_LEN-1] = '\0'; + strncpy(progname, cp, PROC_NAME_LEN-1); + progname[PROC_NAME_LEN-1] = '\0'; - /* Request lookup */ - if ((r = lookup_vp(0 /*flags*/, 0 /*!use_realuid*/, &vp)) != OK) - return r; - - if ((vp->v_mode & I_TYPE) != I_REGULAR) { - put_vnode(vp); - return ENOEXEC; - } + /* Open executable */ + if ((vp = eat_path(PATH_NOFLAGS)) == NIL_VNODE) return(err_code); - /* Check access. */ - if ((r = forbidden(vp, X_BIT, 0 /*!use_realuid*/)) != OK) - { + if ((vp->v_mode & I_TYPE) != I_REGULAR) + r = ENOEXEC; + else if ((r1 = forbidden(vp, X_BIT)) != OK) + r = r1; + else + r = req_stat(vp->v_fs_e, vp->v_inode_nr, FS_PROC_NR, + (char *) &sb, 0); + if (r != OK) { put_vnode(vp); - return r; + return(r); } - /* Get ctime */ - r= req_stat(vp->v_fs_e, vp->v_inode_nr, FS_PROC_NR, (char *)&sb, 0); - if (r != OK) - { - put_vnode(vp); - return r; - } v_ctime = sb.st_ctime; - -#if 0 - printf("vfs:pm_exec: round %d, mode 0%o, uid %d, gid %d\n", - round, vp->v_mode, vp->v_uid, vp->v_gid); -#endif - if (round == 0) - { + if (round == 0) { /* Deal with setuid/setgid executables */ - if (vp->v_mode & I_SET_UID_BIT) - new_uid = vp->v_uid; - if (vp->v_mode & I_SET_GID_BIT) - new_gid = vp->v_gid; + if (vp->v_mode & I_SET_UID_BIT) new_uid = vp->v_uid; + if (vp->v_mode & I_SET_GID_BIT) new_gid = vp->v_gid; } /* Read the file header and extract the segment sizes. */ - r = read_header(vp, &sep_id, &text_bytes, &data_bytes, &bss_bytes, - &tot_bytes, &pc, &hdrlen); - if (r != ESCRIPT || round != 0) - break; - - /* Get fresh copy of the file name. */ - r= fetch_name(path, path_len, 0); - if (r != OK) - { - printf("pm_exec: 2nd fetch_name failed\n"); - put_vnode(vp); - return(r); /* strange */ - } - r= patch_stack(vp, mbuf, &frame_len); - put_vnode(vp); - if (r != OK) - { - printf("pm_exec: patch stack\n"); -printf("return at %s, %d\n", __FILE__, __LINE__); - return r; - } - } + r = read_header(vp, &sep_id, &text_bytes, &data_bytes, &bss_bytes, + &tot_bytes, &pc, &hdrlen); + if (r != ESCRIPT || round != 0) + break; + + /* Get fresh copy of the file name. */ + if ((r = fetch_name(path, path_len, 0)) != OK) + printf("VFS pm_exec: 2nd fetch_name failed\n"); + else if ((r = patch_stack(vp, mbuf, &frame_len)) != OK) + printf("VFS pm_exec: patch_stack failed\n"); + put_vnode(vp); + if (r != OK) return(r); + } - if (r != OK) - { - printf("pm_exec: returning ENOEXEC, r = %d\n", r); - printf("pm_exec: progname = '%s'\n", progname); - put_vnode(vp); - return ENOEXEC; - } - - r= exec_newmem(proc_e, text_bytes, data_bytes, bss_bytes, tot_bytes, - frame_len, sep_id, vp->v_dev, vp->v_inode_nr, v_ctime, - progname, new_uid, new_gid, &stack_top, &load_text, &allow_setuid); - if (r != OK) - { + if (r != OK) { + put_vnode(vp); + return(ENOEXEC); + } + + r = exec_newmem(proc_e, text_bytes, data_bytes, bss_bytes, tot_bytes, + frame_len, sep_id, vp->v_dev, vp->v_inode_nr, v_ctime, + progname, new_uid, new_gid, &stack_top, &load_text, + &allow_setuid); + if (r != OK) { printf("VFS: pm_exec: exec_newmem failed: %d\n", r); put_vnode(vp); - return r; - } - - /* Patch up stack and copy it from FS to new core image. */ - vsp = stack_top; - vsp -= frame_len; - patch_ptr(mbuf, vsp); - r = sys_datacopy(SELF, (vir_bytes) mbuf, - proc_e, (vir_bytes) vsp, (phys_bytes)frame_len); - if (r != OK) { - printf("vfs: datacopy returns %d trying to copy to %p\n", r, vsp); - return r; - } - - off = hdrlen; - - /* Read in text and data segments. */ - if (load_text) { - r= read_seg(vp, off, proc_e, T, text_bytes); - } - off += text_bytes; - if (r == OK) - r= read_seg(vp, off, proc_e, D, data_bytes); - - put_vnode(vp); - - if (r != OK) - { - return r; - } - - clo_exec(rfp); - - if (allow_setuid) - { - rfp->fp_effuid= new_uid; - rfp->fp_effgid= new_gid; - } - - /* This child has now exec()ced. */ - rfp->fp_execced = 1; - - /* Check if this is a driver that can now be useful. */ - dmap_endpt_up(rfp->fp_endpoint); - - return OK; + return(r); + } + + /* Patch up stack and copy it from FS to new core image. */ + vsp = stack_top; + vsp -= frame_len; + patch_ptr(mbuf, vsp); + if ((r = sys_datacopy(SELF, (vir_bytes) mbuf, proc_e, (vir_bytes) vsp, + (phys_bytes)frame_len)) != OK) { + printf("VFS: datacopy failed (%d) trying to copy to %p\n", r, vsp); + return(r); + } + + off = hdrlen; + + /* Read in text and data segments. */ + if (load_text) r = read_seg(vp, off, proc_e, T, text_bytes); + off += text_bytes; + if (r == OK) r = read_seg(vp, off, proc_e, D, data_bytes); + put_vnode(vp); + if (r != OK) return(r); + clo_exec(rfp); + + if (allow_setuid) { + rfp->fp_effuid = new_uid; + rfp->fp_effgid = new_gid; + } + + /* This child has now exec()ced. */ + rfp->fp_execced = 1; + + /* Check if this is a driver that can now be useful. */ + dmap_endpt_up(rfp->fp_endpoint); + + return(OK); } + /*===========================================================================* * exec_newmem * *===========================================================================*/ @@ -281,41 +223,34 @@ vir_bytes *stack_topp; int *load_textp; int *allow_setuidp; { - int r; - struct exec_newmem e; - message m; - - e.text_bytes= text_bytes; - e.data_bytes= data_bytes; - e.bss_bytes= bss_bytes; - e.tot_bytes= tot_bytes; - e.args_bytes= frame_len; - e.sep_id= sep_id; - e.st_dev= st_dev; - e.st_ino= st_ino; - e.st_ctime= st_ctime; - e.new_uid= new_uid; - e.new_gid= new_gid; - strncpy(e.progname, progname, sizeof(e.progname)-1); - e.progname[sizeof(e.progname)-1]= '\0'; - - m.m_type= EXEC_NEWMEM; - m.EXC_NM_PROC= proc_e; - m.EXC_NM_PTR= (char *)&e; - r= sendrec(PM_PROC_NR, &m); - if (r != OK) - return r; -#if 0 - printf("exec_newmem: r = %d, m_type = %d\n", r, m.m_type); -#endif - *stack_topp= m.m1_i1; - *load_textp= !!(m.m1_i2 & EXC_NM_RF_LOAD_TEXT); - *allow_setuidp= !!(m.m1_i2 & EXC_NM_RF_ALLOW_SETUID); -#if 0 - printf("exec_newmem: stack_top = 0x%x\n", *stack_topp); - printf("exec_newmem: load_text = %d\n", *load_textp); -#endif - return m.m_type; + int r; + struct exec_newmem e; + message m; + + e.text_bytes = text_bytes; + e.data_bytes = data_bytes; + e.bss_bytes = bss_bytes; + e.tot_bytes = tot_bytes; + e.args_bytes = frame_len; + e.sep_id = sep_id; + e.st_dev = st_dev; + e.st_ino = st_ino; + e.st_ctime = st_ctime; + e.new_uid = new_uid; + e.new_gid = new_gid; + strncpy(e.progname, progname, sizeof(e.progname)-1); + e.progname[sizeof(e.progname)-1] = '\0'; + + m.m_type = EXEC_NEWMEM; + m.EXC_NM_PROC = proc_e; + m.EXC_NM_PTR = (char *)&e; + if ((r = sendrec(PM_PROC_NR, &m)) != OK) return(r); + + *stack_topp = m.m1_i1; + *load_textp = !!(m.m1_i2 & EXC_NM_RF_LOAD_TEXT); + *allow_setuidp = !!(m.m1_i2 & EXC_NM_RF_ALLOW_SETUID); + + return(m.m_type); } @@ -337,7 +272,7 @@ int *hdrlenp; off_t pos; int r; u64_t new_pos; - unsigned int cum_io_incr; + unsigned int cum_io; struct exec hdr; /* a.out header is read in here */ /* Read the header and check the magic number. The standard MINIX header @@ -370,14 +305,13 @@ int *hdrlenp; pos= 0; /* Read from the start of the file */ /* Issue request */ - r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, vp->v_index, - cvul64(pos), READING, FS_PROC_NR, (char*)&hdr, sizeof(hdr), &new_pos, - &cum_io_incr); + r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, cvul64(pos), READING, + FS_PROC_NR, (char*)&hdr, sizeof(hdr), &new_pos, &cum_io); if (r != OK) return r; /* Interpreted script? */ if (((char*)&hdr)[0] == '#' && ((char*)&hdr)[1] == '!' && vp->v_size >= 2) - return ESCRIPT; + return(ESCRIPT); if (vp->v_size < A_MINHDR) return(ENOEXEC); @@ -411,6 +345,7 @@ int *hdrlenp; return(OK); } + /*===========================================================================* * patch_stack * *===========================================================================*/ @@ -428,7 +363,7 @@ vir_bytes *stk_bytes; /* size of initial stack */ off_t pos; char *sp, *interp = NULL; u64_t new_pos; - unsigned int cum_io_incr; + unsigned int cum_io; char buf[_MAX_BLOCK_SIZE]; /* Make user_fullpath the new argv[0]. */ @@ -437,9 +372,9 @@ vir_bytes *stk_bytes; /* size of initial stack */ pos = 0; /* Read from the start of the file */ /* Issue request */ - r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, vp->v_index, cvul64(pos), - READING, FS_PROC_NR, buf, _MAX_BLOCK_SIZE, &new_pos, &cum_io_incr); - if (r != OK) return r; + r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, cvul64(pos), READING, + FS_PROC_NR, buf, _MAX_BLOCK_SIZE, &new_pos, &cum_io); + if (r != OK) return(r); n = vp->v_size; if (n > _MAX_BLOCK_SIZE) @@ -534,6 +469,7 @@ int replace; return(TRUE); } + /*===========================================================================* * patch_ptr * *===========================================================================*/ @@ -566,6 +502,7 @@ vir_bytes base; /* virtual address of stack base inside user */ } } + /*===========================================================================* * read_seg * *===========================================================================*/ @@ -584,74 +521,53 @@ phys_bytes seg_bytes; /* how much is to be transferred? */ int r; unsigned n, o; u64_t new_pos; - unsigned int cum_io_incr; + unsigned int cum_io; char buf[1024]; /* Make sure that the file is big enough */ - if (vp->v_size < off+seg_bytes) { - return EIO; - } + if (vp->v_size < off+seg_bytes) return(EIO); - if (seg != D) - { + if (seg != D) { /* We have to use a copy loop until safecopies support segments */ - o= 0; - while (o < seg_bytes) - { - n= seg_bytes-o; + o = 0; + while (o < seg_bytes) { + n = seg_bytes - o; if (n > sizeof(buf)) - n= sizeof(buf); + n = sizeof(buf); -#if 0 -printf("read_seg for user %d, seg %d: buf 0x%x, size %d, pos %d\n", - proc_e, seg, buf, n, off+o); -#endif - - /* Issue request */ - r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, vp->v_index, - cvul64(off+o), READING, FS_PROC_NR, buf, n, &new_pos, - &cum_io_incr); - if (r != OK) { + if ((r = req_readwrite(vp->v_fs_e,vp->v_inode_nr,cvul64(off+o), READING, FS_PROC_NR, buf, + n, &new_pos, &cum_io)) != OK) { printf("VFS: read_seg: req_readwrite failed (text)\n"); - return r; + return(r); } - if (cum_io_incr != n) - { + if (cum_io != n) { printf( "VFSread_seg segment has not been read properly by exec() \n"); - return EIO; + return(EIO); } - r= sys_vircopy(FS_PROC_NR, D, (vir_bytes)buf, proc_e, seg, o, - n); - if (r != OK) { + if ((r = sys_vircopy(FS_PROC_NR, D, (vir_bytes)buf, proc_e, + seg, o, n)) != OK) { printf("VFS: read_seg: copy failed (text)\n"); - return r; + return(r); } o += n; } - return OK; + return(OK); } -#if 0 -printf("read_seg for user %d, seg %d: buf 0x%x, size %d, pos %d\n", - proc_e, seg, 0, seg_bytes, off); -#endif - - /* Issue request */ - r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, vp->v_index, cvul64(off), - READING, proc_e, 0, seg_bytes, &new_pos, &cum_io_incr); - if (r != OK) { + if ((r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, cvul64(off), READING, + proc_e, 0, seg_bytes, &new_pos, &cum_io)) != OK) { printf("VFS: read_seg: req_readwrite failed (data)\n"); - return r; + return(r); } - if (r == OK && cum_io_incr != seg_bytes) - printf("VFSread_seg segment has not been read properly by exec() \n"); + if (r == OK && cum_io != seg_bytes) + printf("VFSread_seg segment has not been read properly by exec()\n"); - return r; + return(r); } @@ -665,11 +581,9 @@ struct fproc *rfp; */ int i; - /* Check the file desriptors one by one for presence of FD_CLOEXEC. */ - for (i = 0; i < OPEN_MAX; i++) - if ( FD_ISSET(i, &rfp->fp_cloexec_set)) + /* Check the file desriptors one by one for presence of FD_CLOEXEC. */ + for (i = 0; i < OPEN_MAX; i++) + if ( FD_ISSET(i, &rfp->fp_cloexec_set)) (void) close_fd(rfp, i); } - - diff --git a/servers/vfs/filedes.c b/servers/vfs/filedes.c index 332b37957..3a363069a 100644 --- a/servers/vfs/filedes.c +++ b/servers/vfs/filedes.c @@ -11,11 +11,9 @@ #include #include #include - #include "fs.h" #include "file.h" #include "fproc.h" - #include "vnode.h" /*===========================================================================* @@ -64,6 +62,7 @@ PUBLIC int get_fd(int start, mode_t bits, int *k, struct filp **fpt) return(ENFILE); } + /*===========================================================================* * get_filp * *===========================================================================*/ @@ -75,6 +74,7 @@ int fild; /* file descriptor */ return get_filp2(fp, fild); } + /*===========================================================================* * get_filp2 * *===========================================================================*/ @@ -86,16 +86,14 @@ int fild; /* file descriptor */ err_code = EBADF; if (fild < 0 || fild >= OPEN_MAX ) return(NIL_FILP); - if (rfp->fp_filp[fild] == NIL_FILP && FD_ISSET(fild, &rfp->fp_filp_inuse)) - { - printf("get_filp2: setting err_code to EIO for proc %d fd %d\n", - rfp->fp_endpoint, fild); + if (rfp->fp_filp[fild] == NIL_FILP && FD_ISSET(fild, &rfp->fp_filp_inuse)) err_code = EIO; /* The filedes is not there, but is not closed either. */ - } + return(rfp->fp_filp[fild]); /* may also be NIL_FILP */ } + /*===========================================================================* * find_filp * *===========================================================================*/ @@ -121,20 +119,23 @@ PUBLIC struct filp *find_filp(register struct vnode *vp, mode_t bits) } /*===========================================================================* - * inval_filp * + * invalidate * *===========================================================================*/ -PUBLIC int inval_filp(struct filp *fp) +PUBLIC int invalidate(struct filp *fp) { - int f, fd, n = 0; - for(f = 0; f < NR_PROCS; f++) { - if(fproc[f].fp_pid == PID_FREE) continue; - for(fd = 0; fd < OPEN_MAX; fd++) { - if(fproc[f].fp_filp[fd] && fproc[f].fp_filp[fd] == fp) { - fproc[f].fp_filp[fd] = NIL_FILP; - n++; - } - } - } - - return n; +/* Invalidate filp. fp_filp_inuse is not cleared, so filp can't be reused + until it is closed first. */ + + int f, fd, n = 0; + for(f = 0; f < NR_PROCS; f++) { + if(fproc[f].fp_pid == PID_FREE) continue; + for(fd = 0; fd < OPEN_MAX; fd++) { + if(fproc[f].fp_filp[fd] && fproc[f].fp_filp[fd] == fp) { + fproc[f].fp_filp[fd] = NIL_FILP; + n++; + } + } + } + + return(n); /* Report back how often this filp has been invalidated. */ } diff --git a/servers/vfs/fproc.h b/servers/vfs/fproc.h index 51584ac03..27ed9f535 100644 --- a/servers/vfs/fproc.h +++ b/servers/vfs/fproc.h @@ -23,6 +23,8 @@ EXTERN struct fproc { uid_t fp_effuid; /* effective user id */ gid_t fp_realgid; /* real group id */ gid_t fp_effgid; /* effective group id */ + int fp_ngroups; /* number of supplemental groups */ + gid_t fp_sgroups[NGROUPS_MAX];/* supplemental groups */ dev_t fp_tty; /* major/minor of controlling tty */ int fp_fd; /* place to save fd if rd/wr can't finish */ char *fp_buffer; /* place to save buffer if rd/wr can't finish*/ diff --git a/servers/vfs/link.c b/servers/vfs/link.c index fd342593d..a7d28a65d 100644 --- a/servers/vfs/link.c +++ b/servers/vfs/link.c @@ -9,9 +9,6 @@ * do_truncate: perform the TRUNCATE system call * do_ftruncate: perform the FTRUNCATE system call * do_rdlink: perform the RDLNK system call - * - * Changes for VFS: - * Jul 2006 (Balazs Gerofi) */ #include "fs.h" @@ -23,7 +20,6 @@ #include "file.h" #include "fproc.h" #include "param.h" - #include #include "vnode.h" @@ -33,66 +29,40 @@ PUBLIC int do_link() { /* Perform the link(name1, name2) system call. */ - int r; + int r = OK; endpoint_t linked_fs_e, link_lastdir_fs_e; - struct vnode *vp_o, *vp_d; - - if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) - return(err_code); - - /* Request lookup */ - if ((r = lookup_vp(0 /*flags*/, 0 /*!use_realuid*/, &vp_o)) != OK) return r; + struct vnode *vp, *vp_d; - linked_fs_e = vp_o->v_fs_e; + /* See if 'name1' (file to be linked to) exists. */ + if(fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code); + if ((vp = eat_path(PATH_NOFLAGS)) == NIL_VNODE) return(err_code); /* Does the final directory of 'name2' exist? */ - if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK) { - put_vnode(vp_o); - return(err_code); - } - - /* Request lookup */ - if ((r = lookup_lastdir(0 /*!use_realuid*/, &vp_d)) != OK) - { - put_vnode(vp_o); - return r; + if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK) + r = err_code; + else if ((vp_d = last_dir()) == NIL_VNODE) + r = err_code; + if (r != OK) { + put_vnode(vp); + return(r); } - link_lastdir_fs_e = vp_d->v_fs_e; - /* Check for links across devices. */ - if (linked_fs_e != link_lastdir_fs_e) - { - put_vnode(vp_o); - put_vnode(vp_d); - return EXDEV; - } + if(vp->v_fs_e != vp_d->v_fs_e) + r = EXDEV; + else + r = forbidden(vp_d, W_BIT | X_BIT); - /* Make sure that the object is a directory */ - if ((vp_d->v_mode & I_TYPE) != I_DIRECTORY) - { - put_vnode(vp_o); - put_vnode(vp_d); - return ENOTDIR; - } + if (r == OK) + r = req_link(vp->v_fs_e, vp_d->v_inode_nr, user_fullpath, + vp->v_inode_nr); - r= forbidden(vp_d, W_BIT|X_BIT, 0 /*!use_realuid*/); - if (r != OK) - { - put_vnode(vp_o); - put_vnode(vp_d); - return r; - } - - /* Issue request */ - r= req_link(linked_fs_e, vp_d->v_inode_nr, user_fullpath, vp_o->v_inode_nr); - put_vnode(vp_o); + put_vnode(vp); put_vnode(vp_d); - return r; + return(r); } - /*===========================================================================* * do_unlink * *===========================================================================*/ @@ -103,42 +73,49 @@ PUBLIC int do_unlink() * may be used by the superuser to do dangerous things; rmdir() may not. */ register struct fproc *rfp; - struct vnode *vp; + struct vnode *vldirp, *vp; int r; - if (fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code); - - r= lookup_lastdir(0 /*!use_realuid*/, &vp); - if (r != OK) - return r; + /* Get the last directory in the path. */ + if(fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code); + if ((vldirp = last_dir()) == NIL_VNODE) return(err_code); /* Make sure that the object is a directory */ - if ((vp->v_mode & I_TYPE) != I_DIRECTORY) - { - put_vnode(vp); - return ENOTDIR; + if((vldirp->v_mode & I_TYPE) != I_DIRECTORY) { + put_vnode(vldirp); + return(ENOTDIR); } /* The caller must have both search and execute permission */ - r= forbidden(vp, X_BIT|W_BIT, 0 /*!use_realuid*/); - if (r != OK) - { - put_vnode(vp); - return r; + if ((r = forbidden(vldirp, X_BIT | W_BIT)) != OK) { + put_vnode(vldirp); + return(r); } - /* If a directory file has to be removed the following conditions have to met: - * - The directory must not be the root of a mounted file system - * - The directory must not be anybody's root/working directory - */ + /* Also, if the sticky bit is set, only the owner of the file or a privileged + user is allowed to unlink */ + if (vldirp->v_mode & S_ISVTX == S_ISVTX) { + /* Look up inode of file to unlink to retrieve owner */ + vp = advance(vldirp, PATH_RET_SYMLINK); + if (vp != NIL_VNODE) { + if(vp->v_uid != fp->fp_effuid && fp->fp_effuid != SU_UID) + r = EPERM; + put_vnode(vp); + } else + r = err_code; + if (r != OK) { + put_vnode(vldirp); + return(r); + } + } - /* Issue request */ - r= ((call_nr == UNLINK) ? req_unlink : req_rmdir)(vp->v_fs_e, - vp->v_inode_nr, user_fullpath); - - put_vnode(vp); - - return r; + if(call_nr == UNLINK) + r = req_unlink(vldirp->v_fs_e, vldirp->v_inode_nr, user_fullpath); + else + r = req_rmdir(vldirp->v_fs_e, vldirp->v_inode_nr, user_fullpath); + + put_vnode(vldirp); + return(r); } @@ -148,81 +125,62 @@ PUBLIC int do_unlink() PUBLIC int do_rename() { /* Perform the rename(name1, name2) system call. */ - int r; - int old_dir_inode; - int old_fs_e; - int new_dir_inode; - int new_fs_e; + int r = OK, r1; size_t len; - struct vnode *vp_od, *vp_nd; + struct vnode *old_dirp, *new_dirp, *vp; char old_name[PATH_MAX+1]; /* See if 'name1' (existing file) exists. Get dir and file inodes. */ - if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code); - - /* Request lookup */ - if ((r = lookup_lastdir(0 /*!use_realuid*/, &vp_od)) != OK) return r; - - r= forbidden(vp_od, W_BIT|X_BIT, 0 /*!use_realuid*/); - if (r != OK) - { - put_vnode(vp_od); - return r; + if(fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code); + if ((old_dirp = last_dir()) == NIL_VNODE) return(err_code); + + /* If the sticky bit is set, only the owner of the file or a privileged + user is allowed to rename */ + if(old_dirp->v_mode & S_ISVTX == S_ISVTX) { + /* Look up inode of file to unlink to retrieve owner */ + vp = advance(old_dirp, PATH_RET_SYMLINK); + if (vp != NIL_VNODE) { + if(vp->v_uid != fp->fp_effuid && fp->fp_effuid != SU_UID) + r = EPERM; + put_vnode(vp); + } else + r = err_code; + if (r != OK) { + put_vnode(old_dirp); + return(r); + } } - /* Remeber FS endpoint */ - old_fs_e = vp_od->v_fs_e; - /* Save the last component of the old name */ - len= strlen(user_fullpath); - if (len >= sizeof(old_name)) - { - put_vnode(vp_od); - return ENAMETOOLONG; - } - memcpy(old_name, user_fullpath, len+1); - - /* See if 'name2' (new name) exists. Get dir inode */ - if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK) - { - put_vnode(vp_od); - return err_code; + if(strlen(user_fullpath) >= sizeof(old_name)) { + put_vnode(old_dirp); + return(ENAMETOOLONG); } + strcpy(old_name, user_fullpath); - /* Request lookup */ - r = lookup_lastdir(0 /*!use_realuid*/, &vp_nd); - if (r != OK) - { - put_vnode(vp_od); - return r; + /* See if 'name2' (new name) exists. Get dir inode */ + if(fetch_name(m_in.name2, m_in.name2_length, M1) != OK) + r = err_code; + else if ((new_dirp = last_dir()) == NIL_VNODE) + r = err_code; + if (r != OK) { + put_vnode(old_dirp); + return r; } - r= forbidden(vp_nd, W_BIT|X_BIT, 0 /*!use_realuid*/); - if (r != OK) - { - put_vnode(vp_od); - put_vnode(vp_nd); - return r; - } - - - /* Remeber FS endpoint */ - new_fs_e = vp_nd->v_fs_e; - /* Both parent directories must be on the same device. */ - if (old_fs_e != new_fs_e) - { - put_vnode(vp_od); - put_vnode(vp_nd); - return EXDEV; - } + if(old_dirp->v_fs_e != new_dirp->v_fs_e) r = EXDEV; - /* Issue request */ - r= req_rename(old_fs_e, vp_od->v_inode_nr, old_name, vp_nd->v_inode_nr, - user_fullpath); - put_vnode(vp_od); - put_vnode(vp_nd); - return r; + /* Parent dirs must be writable, searchable and on a writable device */ + if ((r1 = forbidden(old_dirp, W_BIT|X_BIT)) != OK || + (r1 = forbidden(new_dirp, W_BIT|X_BIT)) != OK) r = r1; + + if(r == OK) + r = req_rename(old_dirp->v_fs_e, old_dirp->v_inode_nr, old_name, + new_dirp->v_inode_nr, user_fullpath); + put_vnode(old_dirp); + put_vnode(new_dirp); + return(r); } @@ -231,7 +189,7 @@ PUBLIC int do_rename() *===========================================================================*/ PUBLIC int do_truncate() { -/* truncate_inode() does the actual work of do_truncate() and do_ftruncate(). +/* truncate_vnode() does the actual work of do_truncate() and do_ftruncate(). * do_truncate() and do_ftruncate() have to get hold of the inode, either * by name or fd, do checks on it, and call truncate_inode() to do the * work. @@ -239,138 +197,106 @@ PUBLIC int do_truncate() struct vnode *vp; int r; - printf("in do_truncate\n"); - - if (fetch_name(m_in.m2_p1, m_in.m2_i1, M1) != OK) return err_code; + /* Temporarily open file */ + if (fetch_name(m_in.m2_p1, m_in.m2_i1, M1) != OK) return(err_code); + if ((vp = eat_path(PATH_NOFLAGS)) == NIL_VNODE) return(err_code); - /* Request lookup */ - if ((r = lookup_vp(0 /*flags*/, 0 /*!use_realuid*/, &vp)) != OK) return r; + /* Ask FS to truncate the file */ + if ((r = forbidden(vp, W_BIT)) == OK) + r = truncate_vnode(vp, m_in.flength); - if ((r = forbidden(vp, W_BIT, 0 /*!use_realuid*/)) == OK) - r = truncate_vn(vp, m_in.m2_l1); - put_vnode(vp); - - return r; + return(r); } - /*===========================================================================* * do_ftruncate * *===========================================================================*/ PUBLIC int do_ftruncate() { -/* As with do_truncate(), truncate_inode() does the actual work. */ +/* As with do_truncate(), truncate_vnode() does the actual work. */ int r; struct filp *rfilp; - if ( (rfilp = get_filp(m_in.m2_i1)) == NIL_FILP) - return err_code; - if (!(rfilp->filp_mode & W_BIT)) - return EBADF; - return truncate_vn(rfilp->filp_vno, m_in.m2_l1); + /* File is already opened; get a vnode pointer from filp */ + if ((rfilp = get_filp(m_in.m2_i1)) == NIL_FILP) return(err_code); + if (!(rfilp->filp_mode & W_BIT)) return(EBADF); + return truncate_vnode(rfilp->filp_vno, m_in.m2_l1); } /*===========================================================================* - * truncate_vn * + * truncate_vnode * *===========================================================================*/ -PUBLIC int truncate_vn(vp, newsize) +PUBLIC int truncate_vnode(vp, newsize) struct vnode *vp; off_t newsize; { - int r; + int r, file_type; - if ( (vp->v_mode & I_TYPE) != I_REGULAR && - (vp->v_mode & I_TYPE) != I_NAMED_PIPE) { - return EINVAL; - } + file_type = vp->v_mode & I_TYPE; + if (file_type != I_REGULAR && file_type != I_NAMED_PIPE) return(EINVAL); - /* Issue request */ - if ((r = req_ftrunc(vp->v_fs_e, vp->v_inode_nr, newsize, 0)) != OK) return r; - - vp->v_size = newsize; - return OK; + if ((r = req_ftrunc(vp->v_fs_e, vp->v_inode_nr, newsize, 0)) == OK) + vp->v_size = newsize; + + return(r); } + /*===========================================================================* * do_slink * *===========================================================================*/ PUBLIC int do_slink() { /* Perform the symlink(name1, name2) system call. */ - int r; + int r, linklen; struct vnode *vp; char string[NAME_MAX]; /* last component of the new dir's path name */ - if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK) - return(err_code); - - if (m_in.name1_length <= 1 || m_in.name1_length >= _MIN_BLOCK_SIZE) - return(ENAMETOOLONG); - - /* Request lookup */ - if ((r = lookup_lastdir(0 /*!use_realuid*/, &vp)) != OK) - { - printf("vfs:do_slink: lookup_lastdir failed with %d\n", r); - return r; - } - -#if 0 - printf("vfs:do_slink: got dir inode %d on dev 0x%x, fs %d\n", - vp->v_inode_nr, vp->v_dev, vp->v_fs_e); -#endif - - r= forbidden(vp, W_BIT|X_BIT, 0 /*!use_realuid*/); - if (r != OK) - { - put_vnode(vp); - return r; + if(m_in.name1_length <= 1) return(ENOENT); + if(m_in.name1_length >= SYMLINK_MAX) return(ENAMETOOLONG); + + /* Get dir inode of 'name2' */ + if(fetch_name(m_in.name2, m_in.name2_length, M1) != OK) return(err_code); + if ((vp = last_dir()) == NIL_VNODE) return(err_code); + + if ((r = forbidden(vp, W_BIT|X_BIT)) == OK) { + r = req_slink(vp->v_fs_e, vp->v_inode_nr, user_fullpath, who_e, + m_in.name1, m_in.name1_length - 1, fp->fp_effuid, + fp->fp_effgid); } - /* Issue request */ - r= req_slink(vp->v_fs_e, vp->v_inode_nr, user_fullpath, who_e, m_in.name1, - m_in.name1_length - 1, fp->fp_effuid, fp->fp_effgid); - put_vnode(vp); - - return r; + return(r); } + /*===========================================================================* * do_rdlink * *===========================================================================*/ PUBLIC int do_rdlink() { -/* Perform the readlink(name, buf) system call. */ +/* Perform the readlink(name, buf, bufsize) system call. */ int r, copylen; struct vnode *vp; - copylen = m_in.m1_i2; - if(copylen < 0) return EINVAL; + copylen = m_in.nbytes; + if(copylen < 0) return(EINVAL); - if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code); - - /* Request lookup */ - r = lookup_vp(PATH_RET_SYMLINK, 0 /*!use_realuid*/, &vp); - if (r != OK) return r; + /* Temporarily open the file containing the symbolic link */ + if(fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code); + if ((vp = eat_path(PATH_RET_SYMLINK)) == NIL_VNODE) return(err_code); /* Make sure this is a symbolic link */ - if ((vp->v_mode & I_TYPE) != I_SYMBOLIC_LINK) { - put_vnode(vp); - - return EINVAL; - } - - /* Issue request */ - r= req_rdlink(vp->v_fs_e, vp->v_inode_nr, who_e, (vir_bytes)m_in.name2, - copylen); + if((vp->v_mode & I_TYPE) != I_SYMBOLIC_LINK) + r = EINVAL; + else + r = req_rdlink(vp->v_fs_e, vp->v_inode_nr, who_e, m_in.name2, copylen); put_vnode(vp); - - return r; + return(r); } - diff --git a/servers/vfs/lock.c b/servers/vfs/lock.c index 7742f131b..56da0b004 100644 --- a/servers/vfs/lock.c +++ b/servers/vfs/lock.c @@ -14,7 +14,6 @@ #include "fproc.h" #include "lock.h" #include "param.h" - #include "vnode.h" /*===========================================================================* @@ -35,8 +34,8 @@ int req; /* either F_SETLK or F_SETLKW */ /* Fetch the flock structure from user space. */ user_flock = (vir_bytes) m_in.name1; - r = sys_datacopy(who_e, (vir_bytes) user_flock, - FS_PROC_NR, (vir_bytes) &flock, (phys_bytes) sizeof(flock)); + r = sys_datacopy(who_e, (vir_bytes) user_flock, FS_PROC_NR, + (vir_bytes) &flock, (phys_bytes) sizeof(flock)); if (r != OK) return(EINVAL); /* Make some error checks. */ @@ -52,12 +51,10 @@ int req; /* either F_SETLK or F_SETLKW */ switch (flock.l_whence) { case SEEK_SET: first = 0; break; case SEEK_CUR: - if (ex64hi(f->filp_pos) != 0) - { - panic(__FILE__, "lock_op: position in file too high", - NO_NUM); - } - first = ex64lo(f->filp_pos); break; + if (ex64hi(f->filp_pos) != 0) + panic(__FILE__, "lock_op: position in file too high", NO_NUM); + first = ex64lo(f->filp_pos); + break; case SEEK_END: first = f->filp_vno->v_size; break; default: return(EINVAL); } @@ -72,10 +69,10 @@ int req; /* either F_SETLK or F_SETLKW */ if (last < first) return(EINVAL); /* Check if this region conflicts with any existing lock. */ - empty = (struct file_lock *) 0; + empty = NIL_LOCK; for (flp = &file_lock[0]; flp < & file_lock[NR_LOCKS]; flp++) { if (flp->lock_type == 0) { - if (empty == (struct file_lock *) 0) empty = flp; + if (empty == NIL_LOCK) empty = flp; continue; /* 0 means unused slot */ } if (flp->lock_vnode != f->filp_vno) continue; /* different file */ @@ -167,6 +164,7 @@ int req; /* either F_SETLK or F_SETLKW */ return(OK); } + /*===========================================================================* * lock_revive * *===========================================================================*/ @@ -190,3 +188,4 @@ PUBLIC void lock_revive() } } } + diff --git a/servers/vfs/lock.h b/servers/vfs/lock.h index e4453a7a3..40500033c 100644 --- a/servers/vfs/lock.h +++ b/servers/vfs/lock.h @@ -8,3 +8,6 @@ EXTERN struct file_lock { off_t lock_first; /* offset of first byte locked */ off_t lock_last; /* offset of last byte locked */ } file_lock[NR_LOCKS]; + +#define NIL_LOCK (struct file_lock *) 0 + diff --git a/servers/vfs/main.c b/servers/vfs/main.c index 962c98d99..ba47955b5 100644 --- a/servers/vfs/main.c +++ b/servers/vfs/main.c @@ -425,7 +425,7 @@ PRIVATE void init_root() struct dmap *dp; char *label; message m; - struct node_details resX; + struct node_details res; /* Open the root device. */ root_dev = DEV_IMGRD; @@ -454,9 +454,9 @@ PRIVATE void init_root() vmp = &vmnt[0]; /* We'll need a vnode for the root inode, check whether there is one */ - if ((root_node = get_free_vnode(__FILE__, __LINE__)) == NIL_VNODE) { + if ((root_node = get_free_vnode()) == NIL_VNODE) panic(__FILE__,"Cannot get free vnode", r); - } + /* Get driver process' endpoint */ dp = &dmap[(root_dev >> MAJOR) & BYTE]; @@ -472,22 +472,22 @@ PRIVATE void init_root() /* Issue request */ r = req_readsuper(ROOT_FS_E, label, root_dev, 0 /*!readonly*/, - 1 /*isroot*/, &resX); + 1 /*isroot*/, &res); if (r != OK) { panic(__FILE__,"Cannot read superblock from root", r); } /* Fill in root node's fields */ - root_node->v_fs_e = resX.fs_e; - root_node->v_inode_nr = resX.inode_nr; - root_node->v_mode = resX.fmode; - root_node->v_size = resX.fsize; + root_node->v_fs_e = res.fs_e; + root_node->v_inode_nr = res.inode_nr; + root_node->v_mode = res.fmode; + root_node->v_size = res.fsize; root_node->v_sdev = NO_DEV; root_node->v_fs_count = 1; root_node->v_ref_count = 1; /* Fill in max file size and blocksize for the vmnt */ - vmp->m_fs_e = resX.fs_e; + vmp->m_fs_e = res.fs_e; vmp->m_dev = root_dev; vmp->m_flags = 0; @@ -570,6 +570,13 @@ PRIVATE void service_pm() m_out.m_type = (call_nr == PM_FORK) ? PM_FORK_REPLY : PM_FORK_NB_REPLY; m_out.PM_PROC = m_in.PM_PROC; + break; + case PM_SETGROUPS: + pm_setgroups(m_in.PM_PROC, m_in.PM_GROUP_NO, m_in.PM_GROUP_ADDR); + + m_out.m_type = PM_SETGROUPS_REPLY; + m_out.PM_PROC = m_in.PM_PROC; + break; case PM_UNPAUSE: @@ -597,4 +604,6 @@ PRIVATE void service_pm() r = send(PM_PROC_NR, &m_out); if (r != OK) panic(__FILE__, "service_pm: send failed", r); + } + diff --git a/servers/vfs/misc.c b/servers/vfs/misc.c index c98f8bd09..ab3c0fc5f 100644 --- a/servers/vfs/misc.c +++ b/servers/vfs/misc.c @@ -32,7 +32,6 @@ #include "file.h" #include "fproc.h" #include "param.h" - #include #include "vnode.h" #include "vmnt.h" @@ -44,13 +43,14 @@ PUBLIC unsigned long calls_stats[NCALLS]; #endif -FORWARD _PROTOTYPE( void free_proc, (struct fproc *freed, int flags)); +FORWARD _PROTOTYPE( void free_proc, (struct fproc *freed, int flags) ); +FORWARD _PROTOTYPE( void unmount_all, (void) ); /* -FORWARD _PROTOTYPE( int dumpcore, (int proc_e, struct mem_map *seg_ptr)); +FORWARD _PROTOTYPE( int dumpcore, (int proc_e, struct mem_map *seg_ptr) ); FORWARD _PROTOTYPE( int write_bytes, (struct inode *rip, off_t off, - char *buf, size_t bytes)); + char *buf, size_t bytes) ); FORWARD _PROTOTYPE( int write_seg, (struct inode *rip, off_t off, int proc_e, - int seg, off_t seg_off, phys_bytes seg_bytes)); + int seg, off_t seg_off, phys_bytes seg_bytes) ); */ #define FP_EXITING 1 @@ -66,14 +66,11 @@ PUBLIC int do_getsysinfo() size_t len; int s; - if (!super_user) - { - printf("FS: unauthorized call of do_getsysinfo by proc %d\n", who_e); - return(EPERM); /* only su may call do_getsysinfo. This call may leak - * information (and is not stable enough to be part - * of the API/ABI). - */ - } + /* Only su may call do_getsysinfo. This call may leak information (and is not + * stable enough to be part of the API/ABI). + */ + + if (!super_user) return(EPERM); switch(m_in.info_what) { case SI_PROC_ADDR: @@ -100,8 +97,7 @@ PUBLIC int do_getsysinfo() } dst_addr = (vir_bytes) m_in.info_where; - if (OK != (s=sys_datacopy(SELF, src_addr, who_e, dst_addr, len))) - return(s); + if (OK != (s = sys_datacopy(SELF, src_addr, who_e, dst_addr, len))) return(s); return(OK); } @@ -129,7 +125,7 @@ PUBLIC int do_dup() /* Distinguish between dup and dup2. */ if (m_in.fd == rfd) { /* bit not on */ /* dup(fd) */ - if ( (r = get_fd(0, 0, &m_in.fd2, &dummy)) != OK) return(r); + if ((r = get_fd(0, 0, &m_in.fd2, &dummy)) != OK) return(r); } else { /* dup2(fd, fd2) */ if (m_in.fd2 < 0 || m_in.fd2 >= OPEN_MAX) return(EBADF); @@ -146,7 +142,6 @@ PUBLIC int do_dup() } - /*===========================================================================* * do_fcntl * *===========================================================================*/ @@ -161,10 +156,7 @@ PUBLIC int do_fcntl() struct filp *dummy; /* Is the file descriptor valid? */ - if ((f = get_filp(m_in.fd)) == NIL_FILP) { -/*printf("VFSfcntl: invalid filedesc %d\n", m_in.fd); */ - return(err_code); - } + if ((f = get_filp(m_in.fd)) == NIL_FILP) return(err_code); switch (m_in.request) { case F_DUPFD: @@ -207,62 +199,52 @@ PUBLIC int do_fcntl() case F_FREESP: { - /* Free a section of a file. Preparation is done here, - * actual freeing in freesp_inode(). + /* Free a section of a file. Preparation is done here, actual freeing + * in freesp_inode(). */ off_t start, end; struct flock flock_arg; signed long offset; /* Check if it's a regular file. */ - if((f->filp_vno->v_mode & I_TYPE) != I_REGULAR) { - return EINVAL; - } - - if (!(f->filp_mode & W_BIT)) - return EBADF; + if((f->filp_vno->v_mode & I_TYPE) != I_REGULAR) return(EINVAL); + if (!(f->filp_mode & W_BIT)) return(EBADF); /* Copy flock data from userspace. */ - if((r = sys_datacopy(who_e, (vir_bytes) m_in.name1, - SELF, (vir_bytes) &flock_arg, - (phys_bytes) sizeof(flock_arg))) != OK) - return r; + if((r = sys_datacopy(who_e, (vir_bytes) m_in.name1, SELF, + (vir_bytes) &flock_arg, (phys_bytes) sizeof(flock_arg))) != OK) + return(r); /* Convert starting offset to signed. */ offset = (signed long) flock_arg.l_start; /* Figure out starting position base. */ switch(flock_arg.l_whence) { - case SEEK_SET: start = 0; if(offset < 0) return EINVAL; break; - case SEEK_CUR: - if (ex64hi(f->filp_pos) != 0) - { - panic(__FILE__, - "do_fcntl: position in file too high", + case SEEK_SET: start = 0; if(offset < 0) return EINVAL; break; + case SEEK_CUR: + if (ex64hi(f->filp_pos) != 0) + panic(__FILE__, "do_fcntl: position in file too high", NO_NUM); - } - start = ex64lo(f->filp_pos); break; - case SEEK_END: start = f->filp_vno->v_size; break; - default: return EINVAL; + + start = ex64lo(f->filp_pos); + break; + case SEEK_END: start = f->filp_vno->v_size; break; + default: return EINVAL; } /* Check for overflow or underflow. */ - if(offset > 0 && start + offset < start) { return EINVAL; } - if(offset < 0 && start + offset > start) { return EINVAL; } + if(offset > 0 && start + offset < start) return EINVAL; + if(offset < 0 && start + offset > start) return EINVAL; start += offset; if(flock_arg.l_len > 0) { end = start + flock_arg.l_len; - if(end <= start) { - return EINVAL; - } - } - else { + if(end <= start) return EINVAL; + } else { end = 0; } - /* Issue request */ - return req_ftrunc(f->filp_vno->v_fs_e, f->filp_vno->v_inode_nr, - start, end); + return req_ftrunc(f->filp_vno->v_fs_e, f->filp_vno->v_inode_nr, start, + end); } default: @@ -277,13 +259,11 @@ PUBLIC int do_fcntl() PUBLIC int do_sync() { struct vmnt *vmp; - for (vmp = &vmnt[1]; vmp < &vmnt[NR_MNTS]; ++vmp) { - if (vmp->m_dev != NO_DEV) { - /* Send sync request */ + for (vmp = &vmnt[1]; vmp < &vmnt[NR_MNTS]; ++vmp) + if (vmp->m_dev != NO_DEV) req_sync(vmp->m_fs_e); - } - } - return OK; + + return(OK); } /*===========================================================================* @@ -294,31 +274,26 @@ PUBLIC int do_fsync() /* Perform the fsync() system call. For now, don't be unnecessarily smart. */ do_sync(); - return(OK); } -void unmount_all(void) +/*===========================================================================* + * unmount_all * + *===========================================================================*/ +PRIVATE void unmount_all(void) { - int i; - int found = 0, worked = 0, remain = 0; - /* Unmount all filesystems. File systems are mounted on other file systems, - * so you have to pull off the loose bits repeatedly to get it all undone. - */ +/* Unmount all filesystems. File systems are mounted on other file systems, + * so you have to pull off the loose bits repeatedly to get it all undone. + */ + + int i; for (i= 0; i < NR_MNTS; i++) { struct vmnt *vmp; + /* Unmount at least one. */ - worked = remain = 0; for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; vmp++) { - if (vmp->m_dev != NO_DEV) { - found++; - SANITYCHECK; - if(unmount(vmp->m_dev) == OK) - worked++; - else - remain++; - SANITYCHECK; - } + if (vmp->m_dev != NO_DEV) + unmount(vmp->m_dev); } } } @@ -542,6 +517,29 @@ int rgid; } +/*===========================================================================* + * pm_setgroups * + *===========================================================================*/ +PUBLIC void pm_setgroups(proc_e, ngroups, groups) +int proc_e; +int ngroups; +gid_t *groups; +{ + struct fproc *rfp; + int slot, i; + + okendpt(proc_e, &slot); + rfp = &fproc[slot]; + if (ngroups * sizeof(gid_t) > sizeof(rfp->fp_sgroups)) + panic(__FILE__, "VFS: pm_setgroups: too much data to copy\n", NO_NUM); + if(sys_datacopy(who_e, (vir_bytes) groups, SELF, (vir_bytes) rfp->fp_sgroups, + ngroups * sizeof(gid_t)) == OK) { + rfp->fp_ngroups = ngroups; + } else + panic(__FILE__, "VFS: pm_setgroups: datacopy failed\n", NO_NUM); +} + + /*===========================================================================* * pm_setuid * *===========================================================================*/ diff --git a/servers/vfs/mmap.c b/servers/vfs/mmap.c index 101ae0dbf..4793c53dd 100644 --- a/servers/vfs/mmap.c +++ b/servers/vfs/mmap.c @@ -18,13 +18,12 @@ #include "param.h" #include #include - #include #include "vnode.h" #include "vmnt.h" /*===========================================================================* - * do_vm_mmap * + * do_vm_mmap * *===========================================================================*/ PUBLIC int do_vm_mmap() { diff --git a/servers/vfs/mount.c b/servers/vfs/mount.c index 0324704b3..3d6725fb9 100644 --- a/servers/vfs/mount.c +++ b/servers/vfs/mount.c @@ -3,9 +3,6 @@ * The entry points into this file are * do_mount: perform the MOUNT system call * do_umount: perform the UMOUNT system call - * - * Changes for VFS: - * Jul 2006 (Balazs Gerofi) */ #include "fs.h" @@ -23,7 +20,6 @@ #include "file.h" #include "fproc.h" #include "param.h" - #include #include "vnode.h" #include "vmnt.h" @@ -34,36 +30,40 @@ PRIVATE int allow_newroot = 1; FORWARD _PROTOTYPE( dev_t name_to_dev, (void) ); FORWARD _PROTOTYPE( int mount_fs, (endpoint_t fs_e) ); + /*===========================================================================* * do_fslogin * *===========================================================================*/ PUBLIC int do_fslogin() { + int r; + /* Login before mount request */ if ((unsigned long)mount_m_in.m1_p3 != who_e) { last_login_fs_e = who_e; - return SUSPEND; + r = SUSPEND; } /* Login after a suspended mount */ else { - /* Copy back original mount request message */ - m_in = mount_m_in; - - /* Set up last login FS */ - last_login_fs_e = who_e; - - /* Set up endpoint and call nr */ - who_e = m_in.m_source; - who_p = _ENDPOINT_P(who_e); - call_nr = m_in.m_type; - fp = &fproc[who_p]; /* pointer to proc table struct */ - super_user = (fp->fp_effuid == SU_UID ? TRUE : FALSE); /* su? */ - + /* Copy back original mount request message */ + m_in = mount_m_in; + + /* Set up last login FS */ + last_login_fs_e = who_e; + + /* Set up endpoint and call nr */ + who_e = m_in.m_source; + who_p = _ENDPOINT_P(who_e); + call_nr = m_in.m_type; + fp = &fproc[who_p]; /* pointer to proc table struct */ + super_user = (fp->fp_effuid == SU_UID ? TRUE : FALSE); /* su? */ - return do_mount(); + r = do_mount(); } + return(r); } + /*===========================================================================* * do_mount * *===========================================================================*/ @@ -71,17 +71,15 @@ PUBLIC int do_mount() { endpoint_t fs_e; - SANITYCHECK; - /* Only the super-user may do MOUNT. */ if (!super_user) return(EPERM); /* FS process' endpoint number */ - fs_e = (unsigned long)m_in.m1_p3; + fs_e = (unsigned long) m_in.fs_endpt; /* Sanity check on process number. */ if(fs_e <= 0) { - printf("vfs: warning: got process number %d for mount call.\n", fs_e); + printf("VFS: warning: got process number %d for mount call.\n", fs_e); return EINVAL; } @@ -102,73 +100,66 @@ PRIVATE int mount_fs(endpoint_t fs_e) struct dmap *dp; dev_t dev; message m; - struct vnode *root_node, *mounted_on = NULL, *bspec; + struct vnode *root_node, *vp = NULL, *bspec; struct vmnt *vmp; char *label; struct node_details res; - SANITYCHECK; - /* Only the super-user may do MOUNT. */ if (!super_user) return(EPERM); /* If FS not yet logged in, save message and suspend mount */ if (last_login_fs_e != fs_e) { - mount_m_in = m_in; - return SUSPEND; + mount_m_in = m_in; + return(SUSPEND); } - /* Mount request got after FS login or - * FS login arrived after a suspended mount */ + /* Mount request got after FS login or FS login arrived after a suspended mount */ last_login_fs_e = NONE; /* Clear endpoint field */ - mount_m_in.m1_p3 = (char *) NONE; + mount_m_in.fs_endpt = (char *) NONE; /* If 'name' is not for a block special file, return error. */ if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code); - - /* Convert name to device number */ if ((dev = name_to_dev()) == NO_DEV) return(err_code); /* Check whether there is a block special file open which uses the * same device (partition) */ for (bspec = &vnode[0]; bspec < &vnode[NR_VNODES]; ++bspec) { - if (bspec->v_ref_count > 0 && bspec->v_sdev == dev) { - /* Found, sync the buffer cache */ - req_sync(bspec->v_fs_e); - break; - /* Note: there are probably some blocks in the FS process' buffer - * cache which contain data on this minor, although they will be - * purged since the handling moves to the new FS process (if - * everything goes well with the mount...) - */ - } + if (bspec->v_ref_count > 0 && bspec->v_sdev == dev) { + /* Found, sync the buffer cache */ + req_sync(bspec->v_fs_e); + break; + /* Note: there are probably some blocks in the FS process' + * buffer cache which contain data on this minor, although + * they will be purged since the handling moves to the new + * FS process (if everything goes well with the mount...) + */ + } } /* Didn't find? */ if (bspec == &vnode[NR_VNODES] && bspec->v_sdev != dev) - bspec = NULL; + bspec = NULL; - /* Scan vmnt table to see if dev already mounted, if not, - * find a free slot.*/ + /* Scan vmnt table to see if dev already mounted. If not, find a free slot.*/ found = FALSE; vmp = NIL_VMNT; for (i = 0; i < NR_MNTS; ++i) { - if (vmnt[i].m_dev == dev) { - vmp = &vmnt[i]; - found = TRUE; - break; - } - else if (!vmp && vmnt[i].m_dev == NO_DEV) { - vmp = &vmnt[i]; - } + if (vmnt[i].m_dev == dev) { + vmp = &vmnt[i]; + found = TRUE; + break; + } else if (!vmp && vmnt[i].m_dev == NO_DEV) { + vmp = &vmnt[i]; + } } /* Partition was/is already mounted */ if (found) { /* It is possible that we have an old root lying around that * needs to be remounted. */ - if (vmp->m_mounted_on || vmp->m_mounted_on == fproc[FS_PROC_NR].fp_rd) { + if(vmp->m_mounted_on || vmp->m_mounted_on == fproc[FS_PROC_NR].fp_rd) { /* Normally, m_mounted_on refers to the mount point. For a * root filesystem, m_mounted_on is equal to the root vnode. * We assume that the root of FS is always the real root. If @@ -176,60 +167,40 @@ PRIVATE int mount_fs(endpoint_t fs_e) * to the root of the filesystem we found, we found a * filesystem that is in use. */ - return EBUSY; /* already mounted */ + return(EBUSY); /* already mounted */ } - + if(vmp->m_mounted_on) panic("vfs", "root unexpectedly mounted somewhere", NO_NUM); - + if (root_dev == vmp->m_dev) - panic("fs", "inconsistency remounting old root", NO_NUM); - + panic("vfs", "inconsistency remounting old root", NO_NUM); + /* Now get the inode of the file to be mounted on. */ - if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK) { - return(err_code); + if (fetch_name(m_in.name2, m_in.name2_length, M1)!=OK) return(err_code); + if ((vp = eat_path(PATH_NOFLAGS)) == NIL_VNODE) return(err_code); + if (vp->v_ref_count != 1) { + put_vnode(vp); + return(EBUSY); } - /* Request lookup */ - r = lookup_vp(0 /*flags*/, 0 /*!use_realuid*/, &mounted_on); - if (r != OK) return r; - - if (mounted_on->v_ref_count != 1) - { - put_vnode(mounted_on); - printf("vfs:mount_fs: mount point is busy\n"); - return EBUSY; - } - - /* Issue mountpoint request */ - r = req_mountpoint(mounted_on->v_fs_e, mounted_on->v_inode_nr); - if (r != OK) - { - put_vnode(mounted_on); - printf("vfs:mount_fs: req_mountpoint_s failed with %d\n", r); - return r; - } + /* Tell FS on which vnode it is mounted (glue into mount tree) */ + if ((r = req_mountpoint(vp->v_fs_e, vp->v_inode_nr)) == OK) { + root_node = vmp->m_root_node; - /* Get the root inode of the mounted file system. */ - root_node = vmp->m_root_node; - - /* File types may not conflict. */ - if (r == OK) { - mdir = ((mounted_on->v_mode & I_TYPE) == I_DIRECTORY); - /* TRUE iff dir */ + /* File types of 'vp' and 'root_node' may not conflict. */ + mdir = ((vp->v_mode & I_TYPE) == I_DIRECTORY);/* TRUE iff dir*/ rdir = ((root_node->v_mode & I_TYPE) == I_DIRECTORY); - if (!mdir && rdir) r = EISDIR; + if(!mdir && rdir) r = EISDIR; } - /* If error, return the mount point. */ if (r != OK) { - put_vnode(mounted_on); - + put_vnode(vp); return(r); } /* Nothing else can go wrong. Perform the mount. */ - vmp->m_mounted_on = mounted_on; + vmp->m_mounted_on = vp; vmp->m_flags = m_in.rd_only; allow_newroot = 0; /* The root is now fixed */ @@ -237,61 +208,39 @@ PRIVATE int mount_fs(endpoint_t fs_e) } /* Fetch the name of the mountpoint */ - if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK) { - return(err_code); - } + if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK) return(err_code); + isroot = (strcmp(user_fullpath, "/") == 0); + replace_root = (isroot && allow_newroot); - isroot= (strcmp(user_fullpath, "/") == 0); - replace_root= (isroot && allow_newroot); + if(!replace_root) { + /* Get vnode of mountpoint */ + if ((vp = eat_path(PATH_NOFLAGS)) == NIL_VNODE) return(err_code); - if (!replace_root) - { - /* Get mount point and inform the FS it is on. */ -#if 0 - printf("vfs:mount_fs: mount point at '%s'\n", user_fullpath); -#endif - - r = lookup_vp(0 /*flags*/, 0 /*!use_realuid*/, &mounted_on); - if (r != OK) - return r; - - /* Issue mountpoint request */ - r = req_mountpoint(mounted_on->v_fs_e, mounted_on->v_inode_nr); - if (r != OK) { - put_vnode(mounted_on); - printf("vfs:mount_fs: req_mountpoint_s failed with %d\n", r); + /* Tell FS on which vnode it is mounted (glue into mount tree) */ + if ((r = req_mountpoint(vp->v_fs_e, vp->v_inode_nr)) != OK) { + put_vnode(vp); return r; } } /* We'll need a vnode for the root inode, check whether there is one */ - if ((root_node = get_free_vnode(__FILE__, __LINE__)) == NIL_VNODE) { - printf("VFSmount: no free vnode available\n"); - return ENFILE; - } - + if ((root_node = get_free_vnode()) == NIL_VNODE) return(ENFILE); /* Get driver process' endpoint */ dp = &dmap[(dev >> MAJOR) & BYTE]; if (dp->dmap_driver == NONE) { - printf("VFSmount: no driver for dev %x\n", dev); - return(EINVAL); + printf("VFS: no driver for dev %x\n", dev); + return(EINVAL); } - label= dp->dmap_label; + + label = dp->dmap_label; if (strlen(label) == 0) - { - panic(__FILE__, "vfs:mount_fs: no label for major", dev >> MAJOR); - } -#if 0 - printf("vfs:mount_fs: label = '%s'\n", label); -#endif + panic(__FILE__, "VFS mount_fs: no label for major", dev >> MAJOR); - /* Issue request */ - r = req_readsuper(fs_e, label, dev, m_in.rd_only, isroot, &res); - if (r != OK) { - if (mounted_on) - put_vnode(mounted_on); - return r; + /* Tell FS which device to mount */ + if ((r = req_readsuper(fs_e, label, dev, m_in.rd_only, isroot, &res)) != OK){ + if (vp != NIL_VNODE) put_vnode(vp); + return(r); } /* Fill in root node's fields */ @@ -304,7 +253,7 @@ PRIVATE int mount_fs(endpoint_t fs_e) root_node->v_sdev = NO_DEV; root_node->v_fs_count = 1; root_node->v_ref_count = 1; - + /* Fill in max file size and blocksize for the vmnt */ vmp->m_fs_e = res.fs_e; vmp->m_dev = dev; @@ -314,68 +263,63 @@ PRIVATE int mount_fs(endpoint_t fs_e) root_node->v_vmnt = vmp; root_node->v_dev = vmp->m_dev; - if (replace_root) { - /* Superblock and root node already read. - * Nothing else can go wrong. Perform the mount. */ - vmp->m_root_node = root_node; - vmp->m_mounted_on = NULL; + if(replace_root) { + /* Superblock and root node already read. + * Nothing else can go wrong. Perform the mount. */ + vmp->m_root_node = root_node; + vmp->m_mounted_on = NULL; - root_dev = dev; - ROOT_FS_E = fs_e; + root_dev = dev; + ROOT_FS_E = fs_e; - /* Replace all root and working directories */ - for (i= 0, tfp= fproc; ifp_pid == PID_FREE) - continue; + /* Replace all root and working directories */ + for (i= 0, tfp= fproc; ifp_pid == PID_FREE) + continue; #define MAKEROOT(what) { \ put_vnode(what); \ dup_vnode(root_node); \ what = root_node; \ - } - - if(tfp->fp_rd) MAKEROOT(tfp->fp_rd); - if(tfp->fp_wd) MAKEROOT(tfp->fp_wd); - } + } - SANITYCHECK; + if(tfp->fp_rd) MAKEROOT(tfp->fp_rd); + if(tfp->fp_wd) MAKEROOT(tfp->fp_wd); + } - return(OK); + return(OK); } - + /* File types may not conflict. */ if (r == OK) { - mdir = ((mounted_on->v_mode & I_TYPE) == I_DIRECTORY);/* TRUE iff dir */ - rdir = ((root_node->v_mode & I_TYPE) == I_DIRECTORY); - if (!mdir && rdir) r = EISDIR; + mdir = ((vp->v_mode & I_TYPE) == I_DIRECTORY); /*TRUE iff dir*/ + rdir = ((root_node->v_mode & I_TYPE) == I_DIRECTORY); + if (!mdir && rdir) r = EISDIR; } /* If error, return the super block and both inodes; release the vmnt. */ if (r != OK) { - put_vnode(mounted_on); - put_vnode(root_node); - - vmp->m_dev = NO_DEV; - return(r); + put_vnode(vp); + put_vnode(root_node); + vmp->m_dev = NO_DEV; + return(r); } /* Nothing else can go wrong. Perform the mount. */ - vmp->m_mounted_on = mounted_on; + vmp->m_mounted_on = vp; vmp->m_root_node = root_node; - + /* The root is now fixed */ allow_newroot = 0; /* There was a block spec file open, and it should be handled by the * new FS proc now */ - if (bspec) { - printf("VFSmount: moving opened block spec to new FS_e: %d...\n", fs_e); - bspec->v_bfs_e = fs_e; - } - SANITYCHECK; + if (bspec) bspec->v_bfs_e = fs_e; + return(OK); } + /*===========================================================================* * do_umount * *===========================================================================*/ @@ -383,19 +327,14 @@ PUBLIC int do_umount() { /* Perform the umount(name) system call. */ dev_t dev; - SANITYCHECK; - - /* Only the super-user may do UMOUNT. */ + + /* Only the super-user may do umount. */ if (!super_user) return(EPERM); - SANITYCHECK; - + /* If 'name' is not for a block special file, return error. */ - if (fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code); - SANITYCHECK; - if ( (dev = name_to_dev()) == NO_DEV) return(err_code); - SANITYCHECK; - - return(unmount(dev)); + if(fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code); + if((dev = name_to_dev()) == NO_DEV) return(err_code); + return unmount(dev); } @@ -411,132 +350,74 @@ Dev_t dev; int count, r; int fs_e; - SANITYCHECK; - - /* Find vmnt */ - for (vmp_i = &vmnt[0]; vmp_i < &vmnt[NR_MNTS]; ++vmp_i) { - if (vmp_i->m_dev == dev) { - if(vmp) panic(__FILE__, "device mounted more than once", dev); - vmp = vmp_i; - } + /* Find vmnt that is to be unmounted */ + for(vmp_i = &vmnt[0]; vmp_i < &vmnt[NR_MNTS]; ++vmp_i) { + if (vmp_i->m_dev == dev) { + if(vmp) panic(__FILE__,"device mounted more than once", dev); + vmp = vmp_i; + } } - /* Device mounted? */ - if(!vmp) - return EINVAL; - + /* Did we find the vmnt (i.e., was dev a mounted device)? */ + if(!vmp) return(EINVAL); + /* See if the mounted device is busy. Only 1 vnode using it should be - * open -- the root vnode -- and that inode only 1 time. - */ + * open -- the root vnode -- and that inode only 1 time. */ count = 0; - for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; vp++) { - if (vp->v_ref_count > 0 && vp->v_dev == dev) { - -#if 0 - int i; - struct fproc *tfp; - printf("unmount: vnode 0x%x/%d in use %d times\n", - dev, vp->v_inode_nr, vp->v_ref_count); - for (i= 0, tfp= fproc; ifp_pid == PID_FREE) - continue; - if(tfp->fp_wd == vp) - printf("\tvnode %d: wd of pid %d\n", - vp->v_inode_nr, tfp->fp_pid); - if(tfp->fp_rd == vp) - printf("\tvnode %d: rd of pid %d\n", - vp->v_inode_nr, tfp->fp_pid); - for(n = 0; n < OPEN_MAX; n++) { - if(tfp->fp_filp[n] && tfp->fp_filp[n]->filp_vno == vp) - printf("\tvnode %d: fd %d of pid %d\n", - vp->v_inode_nr, n, tfp->fp_pid); - } - } - - for (vmp_i = &vmnt[0]; vmp_i < &vmnt[NR_MNTS]; ++vmp_i) { - if (vmp_i->m_dev != NO_DEV) { - if(vmp_i->m_mounted_on == vp) { - printf("\tvnode %d: is a mount point\n", - vp->v_inode_nr); - } -#if 1 - if(vmp_i->m_root_node == vp) { - printf("\tvnode %d: is a root node\n", - vp->v_inode_nr); - } -#endif - } - } -#endif - - count += vp->v_ref_count; - } - } - SANITYCHECK; - - if (count > 1) { - return(EBUSY); /* can't umount a busy file system */ - } - - SANITYCHECK; + for(vp = &vnode[0]; vp < &vnode[NR_VNODES]; vp++) + if(vp->v_ref_count > 0 && vp->v_dev == dev) count += vp->v_ref_count; + if(count > 1) return(EBUSY); /* can't umount a busy file system */ + + /* Tell FS to drop all inode references for root inode except 1. */ vnode_clean_refs(vmp->m_root_node); - SANITYCHECK; - + if (vmp->m_mounted_on) { - put_vnode(vmp->m_mounted_on); - vmp->m_mounted_on->v_fs_count--; - vmp->m_mounted_on = NIL_VNODE; + put_vnode(vmp->m_mounted_on); + vmp->m_mounted_on = NIL_VNODE; } - - put_vnode(vmp->m_root_node); - vmp->m_root_node->v_ref_count = 0; - vmp->m_root_node = NIL_VNODE; - - /* Request FS the unmount */ + + /* Tell FS to unmount */ if(vmp->m_fs_e <= 0 || vmp->m_fs_e == NONE) panic(__FILE__, "unmount: strange fs endpoint", vmp->m_fs_e); - if ((r = req_unmount(vmp->m_fs_e)) != OK) { - /* Not recoverable. */ - printf("VFS: ignoring unmount failure %d from %d\n", r, vmp->m_fs_e); - } + if ((r = req_unmount(vmp->m_fs_e)) != OK) /* Not recoverable. */ + printf("VFS: ignoring failed umount attempt (%d)\n", r); + + vmp->m_root_node->v_ref_count = 0; + vmp->m_root_node->v_fs_count = 0; + vmp->m_root_node->v_sdev = NO_DEV; + vmp->m_root_node = NIL_VNODE; vmp->m_dev = NO_DEV; vmp->m_fs_e = NONE; - - SANITYCHECK; - + /* Is there a block special file that was handled by that partition? */ for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; vp++) { - if ((vp->v_mode & I_TYPE) == I_BLOCK_SPECIAL && - vp->v_bfs_e == vmp->m_fs_e) { - - /* Get the driver endpoint of the block spec device */ - dp = &dmap[(dev >> MAJOR) & BYTE]; - if (dp->dmap_driver == NONE) { - printf("VFSblock_spec_open: driver not found for device %d\n", - dev); - /* What should be done, panic??? */ - continue; - } - - printf("VFSunmount: moving block spec %d to root FS\n", dev); - vp->v_bfs_e = ROOT_FS_E; - - /* Send the driver endpoint (even if it is known already...) */ - if ((r = req_newdriver(vp->v_bfs_e, vp->v_sdev, dp->dmap_driver)) - != OK) { - printf("VFSunmount: error sending driver endpoint for block spec\n"); - } - } - } - - SANITYCHECK; + if((vp->v_mode & I_TYPE)==I_BLOCK_SPECIAL && vp->v_bfs_e==vmp->m_fs_e){ + + /* Get the driver endpoint of the block spec device */ + dp = &dmap[(dev >> MAJOR) & BYTE]; + if (dp->dmap_driver == NONE) { + printf("VFS: driver not found for device %d\n", dev); + continue; + } + printf("VFS: umount moving block spec %d to root FS\n", dev); + vp->v_bfs_e = ROOT_FS_E; + + /* Send the (potentially new) driver endpoint */ + r = req_newdriver(vp->v_bfs_e, vp->v_sdev, dp->dmap_driver); + if (r != OK) + printf("VFS: error sending driver endpoint for" + " moved block spec\n"); + + } + } + return(OK); } + /*===========================================================================* * name_to_dev * *===========================================================================*/ @@ -549,20 +430,18 @@ PRIVATE dev_t name_to_dev() struct vnode *vp; /* Request lookup */ - if ((r = lookup_vp(0 /*flags*/, 0 /*!use_realuid*/, &vp)) != OK) { - printf("vfs: name_to_dev: lookup of '%s' failed\n", user_fullpath); - return NO_DEV; + if ((vp = eat_path(PATH_NOFLAGS)) == NIL_VNODE) { + printf("VFS: name_to_dev: lookup of '%s' failed\n", user_fullpath); + return(NO_DEV); } if ((vp->v_mode & I_TYPE) != I_BLOCK_SPECIAL) { err_code = ENOTBLK; - dev= NO_DEV; - } - else - dev= vp->v_sdev; + dev = NO_DEV; + } else + dev = vp->v_sdev; put_vnode(vp); - - return dev; + return(dev); } diff --git a/servers/vfs/open.c b/servers/vfs/open.c index 0f1e9e856..7caaf1fa0 100644 --- a/servers/vfs/open.c +++ b/servers/vfs/open.c @@ -8,9 +8,6 @@ * do_mkdir: perform the MKDIR system call * do_close: perform the CLOSE system call * do_lseek: perform the LSEEK system call - * - * Changes for VFS: - * Jul 2006 (Balazs Gerofi) */ #include "fs.h" @@ -27,21 +24,17 @@ #include "param.h" #include #include - #include #include "vnode.h" #include "vmnt.h" -#define offset_lo m2_l1 -#define offset_high m2_l2 - +PRIVATE char mode_map[] = {R_BIT, W_BIT, R_BIT|W_BIT, 0}; + FORWARD _PROTOTYPE( int common_open, (int oflags, mode_t omode) ); -FORWARD _PROTOTYPE( int create_open, (_mnx_Mode_t omode, int excl, - struct vnode **vpp, int *created) ); -FORWARD _PROTOTYPE( int exists_open, (struct vnode *vp, _mnx_Mode_t bits, - int oflags)); +FORWARD _PROTOTYPE( struct vnode *new_node, (mode_t bits) ); FORWARD _PROTOTYPE( int pipe_open, (struct vnode *vp,mode_t bits,int oflags)); + /*===========================================================================* * do_creat * *===========================================================================*/ @@ -55,6 +48,7 @@ PUBLIC int do_creat() return(r); } + /*===========================================================================* * do_open * *===========================================================================*/ @@ -72,20 +66,20 @@ PUBLIC int do_open() r = fetch_name(m_in.name, m_in.name_length, M3); } - if (r != OK) { - return(err_code); /* name was bad */ - } + if (r != OK) return(err_code); /* name was bad */ r = common_open(m_in.mode, create_mode); return(r); } + /*===========================================================================* * common_open * *===========================================================================*/ PRIVATE int common_open(register int oflags, mode_t omode) { /* Common code from do_creat and do_open. */ - int b, m, r, created, found; + int b, r, exist = TRUE; + dev_t dev; mode_t bits; struct filp *fil_ptr, *filp2; struct vnode *vp; @@ -93,131 +87,135 @@ PRIVATE int common_open(register int oflags, mode_t omode) struct dmap *dp; /* Remap the bottom two bits of oflags. */ - m = oflags & O_ACCMODE; - switch(m) { - case O_RDONLY: bits = R_BIT; break; - case O_WRONLY: bits = W_BIT; break; - case O_RDWR: bits = R_BIT | W_BIT; break; - default: return EINVAL; - } + bits = (mode_t) mode_map[oflags & O_ACCMODE]; + if (!bits) return(EINVAL); /* See if file descriptor and filp slots are available. */ if ((r = get_fd(0, bits, &m_in.fd, &fil_ptr)) != OK) return(r); - /* If O_CREATE, set umask */ + /* If O_CREATE is set, try to make the file. */ if (oflags & O_CREAT) { omode = I_REGULAR | (omode & ALL_MODES & fp->fp_umask); - } - - if (oflags & O_CREAT) - r= create_open(omode, !!(oflags & O_EXCL), &vp, &created); - else - { -#if 0 - printf("vfs:common_open: path '%s'\n", user_fullpath); -#endif - created= FALSE; - r= lookup_vp(0 /*flags*/, 0 /*!use_realuid*/, &vp); - } - if (r != OK) - return r; - - if (!created) - { - r= exists_open(vp, bits, oflags); - if (r != OK) - { - put_vnode(vp); - return r; - } + vp = new_node(omode); + r = err_code; + if (r == OK) exist = FALSE; /* We just created the file */ + else if (r != EEXIST) return(r); /* other error */ + else exist = !(oflags & O_EXCL); /* file exists, if the O_EXCL + flag is set this is an error */ + } else { + /* Scan path name */ + if ((vp = eat_path(PATH_NOFLAGS)) == NIL_VNODE) return(err_code); } /* Claim the file descriptor and filp slot and fill them in. */ fp->fp_filp[m_in.fd] = fil_ptr; FD_SET(m_in.fd, &fp->fp_filp_inuse); fil_ptr->filp_count = 1; - fil_ptr->filp_flags = oflags; fil_ptr->filp_vno = vp; - - switch (vp->v_mode & I_TYPE) { - case I_CHAR_SPECIAL: - /* Invoke the driver for special processing. */ - r = dev_open(vp->v_sdev, who_e, bits | (oflags & ~O_ACCMODE)); - if (r == SUSPEND) - suspend(FP_BLOCKED_ON_DOPEN); /* suspend caller */ - break; - - case I_BLOCK_SPECIAL: - /* Invoke the driver for special processing. */ - r = dev_open(vp->v_sdev, who_e, bits | (oflags & ~O_ACCMODE)); - if (r != OK) - break; - - /* Check whether the device is mounted or not */ - found = 0; - for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; ++vmp) { - if (vmp->m_dev == vp->v_sdev) { - found = 1; - break; - } - } - - /* Who is going to be responsible for this device? */ - if (found) { - vp->v_bfs_e = vmp->m_fs_e; - } - else { /* To be handled in the root FS proc if not mounted */ - vp->v_bfs_e = ROOT_FS_E; - } - - /* Get the driver endpoint of the block spec device */ - dp = &dmap[(vp->v_sdev >> MAJOR) & BYTE]; - if (dp->dmap_driver == NONE) { - printf("VFSblock_spec_open: driver not found for device %d\n", - vp->v_sdev); - r = EINVAL; - break; - } - - /* Send the driver endpoint (even if it is known already...) */ - if ((r = req_newdriver(vp->v_bfs_e, vp->v_sdev, dp->dmap_driver)) - != OK) { - printf("VFSblock_spec_open: error sending driver endpoint\n"); - } - break; - - case I_NAMED_PIPE: - vp->v_pipe = I_PIPE; - oflags |= O_APPEND; /* force append mode */ - fil_ptr->filp_flags = oflags; - r = pipe_open(vp, bits, oflags); - if (r != ENXIO) { - /* See if someone else is doing a rd or wt on - * the FIFO. If so, use its filp entry so the - * file position will be automatically shared. - */ - b = (bits & R_BIT ? R_BIT : W_BIT); - assert(fil_ptr->filp_count == 1); - fil_ptr->filp_count = 0; /* don't find self */ - if ((filp2 = find_filp(vp, b)) != NIL_FILP) { - /* Co-reader or writer found. Use it.*/ - fp->fp_filp[m_in.fd] = filp2; - filp2->filp_count++; - filp2->filp_vno = vp; - filp2->filp_flags = oflags; - - /* v_count was incremented after the vnode has - * been found, i_count was incremented incorrectly - * by eatpath in FS, not knowing that we were going to - * use an existing filp entry. Correct this error. - */ - put_vnode(vp); - } else { - /* Nobody else found. Claim filp. */ - fil_ptr->filp_count = 1; - } - } - break; + fil_ptr->filp_flags = oflags; + + /* Only do the normal open code if didn't just create the file. */ + if(exist) { + /* Check protections. */ + if ((r = forbidden(vp, bits)) == OK) { + /* Opening reg. files, directories, and special files differ */ + switch (vp->v_mode & I_TYPE) { + case I_REGULAR: + /* Truncate regular file if O_TRUNC. */ + if (oflags & O_TRUNC) { + if ((r = forbidden(vp, W_BIT)) != OK) + break; + truncate_vnode(vp, 0); + } + break; + case I_DIRECTORY: + /* Directories may be read but not written. */ + r = (bits & W_BIT ? EISDIR : OK); + break; + case I_CHAR_SPECIAL: + /* Invoke the driver for special processing. */ + dev = (dev_t) vp->v_sdev; + r = dev_open(dev, who_e, bits | (oflags & ~O_ACCMODE)); + if (r == SUSPEND) suspend(FP_BLOCKED_ON_DOPEN); + break; + case I_BLOCK_SPECIAL: + /* Invoke the driver for special processing. */ + dev = (dev_t) vp->v_sdev; + r = dev_open(dev, who_e, bits | (oflags & ~O_ACCMODE)); + + /* Check whether the device is mounted or not. If so, + then that FS is responsible for this device. Else + we default to ROOT_FS. */ + vp->v_bfs_e = ROOT_FS_E; /* By default */ + for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; ++vmp) + if (vmp->m_dev == vp->v_sdev) + vp->v_bfs_e = vmp->m_fs_e; + + /* Get the driver endpoint of the block spec device */ + dp = &dmap[(vp->v_sdev >> MAJOR) & BYTE]; + if (dp->dmap_driver == NONE) { + printf("VFS: driver not found for device %d\n", + vp->v_sdev); + r = ENXIO; + break; + } + + /* Send the driver endpoint (even when known already)*/ + if ((r = req_newdriver(vp->v_bfs_e, vp->v_sdev, + dp->dmap_driver)) != OK) { + printf("VFS: error sending driver endpoint\n"); + r = ENXIO; + } + break; + + case I_NAMED_PIPE: + /* Create a mapped inode on PFS which handles reads + and writes to this named pipe. */ + r = map_vnode(vp); + if (r == OK) { + vp->v_pipe = I_PIPE; + if (vp->v_ref_count == 1) { + vp->v_pipe_rd_pos = 0; + vp->v_pipe_wr_pos = 0; + if (vp->v_size != 0) + r = truncate_vnode(vp, 0); + } + oflags |= O_APPEND; /* force append mode */ + fil_ptr->filp_flags = oflags; + } + if (r == OK) { + r = pipe_open(vp, bits, oflags); + } + if (r != ENXIO) { + /* See if someone else is doing a rd or wt on + * the FIFO. If so, use its filp entry so the + * file position will be automatically shared. + */ + b = (bits & R_BIT ? R_BIT : W_BIT); + fil_ptr->filp_count = 0; /* don't find self */ + if ((filp2 = find_filp(vp, b)) != NIL_FILP) { + /* Co-reader or writer found. Use it.*/ + fp->fp_filp[m_in.fd] = filp2; + filp2->filp_count++; + filp2->filp_vno = vp; + filp2->filp_flags = oflags; + + /* v_count was incremented after the + * vnode has been found. i_count was + * incremented incorrectly in FS, not + * knowing that we were going to use an + * existing filp entry. Correct this + * error. + */ + put_vnode(vp); + } else { + /* Nobody else found. Restore filp. */ + fil_ptr->filp_count = 1; + } + } + break; + } + } } /* If error, release inode. */ @@ -236,251 +234,60 @@ PRIVATE int common_open(register int oflags, mode_t omode) /*===========================================================================* - * create_open * - *===========================================================================*/ -PRIVATE int create_open(omode, excl, vpp, created) -mode_t omode; -int excl; -struct vnode **vpp; -int *created; -{ - int i, r, r1; - size_t len; - struct vnode *vp, *dir_vp, *new_vp, *start_vp; - - struct node_details res; - char lastc[PATH_MAX+1]; - - if(!fp->fp_rd || !fp->fp_wd) { - printf("VFS: %d: no rd/wd\n", fp->fp_endpoint); - return ENOENT; - } - - start_vp = (user_fullpath[0] == '/' ? fp->fp_rd : fp->fp_wd); - dup_vnode(start_vp); - - for (i= 0; i sizeof(lastc)) - { - put_vnode(dir_vp); - return ENAMETOOLONG; - } - memcpy(lastc, user_fullpath, len); - - /* Get a free vnode */ - new_vp = get_free_vnode(__FILE__, __LINE__); - if (new_vp == NIL_VNODE) { - put_vnode(dir_vp); - printf("vfs:create_open: no free vnode available\n"); - return EINVAL; - } - - r= forbidden(dir_vp, W_BIT|X_BIT, 0 /*!use_realuid*/); - if (r == OK) - { - /* Try to create the file */ - r= req_create(dir_vp->v_fs_e, dir_vp->v_inode_nr, - omode, fp->fp_effuid, fp->fp_effgid, lastc, - &res); - } - - if (r != EEXIST && r != EACCES) - { - put_vnode(dir_vp); - - if (r != OK) - return r; - - /* Check whether vnode is already in use or not */ - vp = find_vnode(res.fs_e, res.inode_nr); - if (vp != NIL_VNODE) { - vp->v_ref_count++; - vp->v_fs_count++; - } - else - { - vp= new_vp; - - /* Fill in the free vnode's fields */ - vp->v_fs_e = res.fs_e; - vp->v_inode_nr = res.inode_nr; - vp->v_mode = res.fmode; - vp->v_size = res.fsize; - vp->v_uid = res.uid; - vp->v_gid = res.gid; - vp->v_sdev = res.dev; - - vp->v_vmnt = dir_vp->v_vmnt; - vp->v_dev = vp->v_vmnt->m_dev; - vp->v_fs_count = 1; - vp->v_ref_count = 1; - } - - *vpp= vp; - *created= TRUE; - - return OK; - - } - - if (r == EEXIST && excl) - { -#if 0 - printf( - "vfs:create_open: creating existing file with O_EXCL\n"); -#endif - put_vnode(dir_vp); - return r; - } - - /* Try a regular lookup */ - memcpy(user_fullpath, lastc, len); - r1= lookup_rel_vp(dir_vp, 0 /*flags*/, 0 /*!use_realuid*/, &vp); - if (r1 != ENOENT) - { - put_vnode(dir_vp); - if (r1 == OK) - { - *vpp= vp; - *created= FALSE; - } - - return r1; - } - if (r == EACCES) - { - /* We cannot create a new file and the file does not - * already exist. - */ - put_vnode(dir_vp); - return r; - } - - /* The create failed with EEXIST and the regular lookup - * failed with ENOENT. We have to see whether the object - * we try to access actually exists, but is a symlink that - * cannot be resolved. If the symlink exists, we start - * with the contents of the symlink. - */ - memcpy(user_fullpath, lastc, len); - r= lookup_rel_vp(dir_vp, PATH_RET_SYMLINK, 0 /*!use_realuid*/, - &vp); - if (r != OK) - { - put_vnode(dir_vp); - return r; - } - - if (!S_ISLNK(vp->v_mode)) - { - /* Strange, we got an object, but it is not a symlink. - * Well, just return the object. - */ - put_vnode(dir_vp); - *vpp= vp; - *created= FALSE; - return OK; - } - - /* Get the contents of the link */ - len= sizeof(user_fullpath); - r= req_rdlink(vp->v_fs_e, vp->v_inode_nr, FS_PROC_NR, - (vir_bytes)user_fullpath, len-1); - put_vnode(vp); - if (r < 0) - { - printf("vfs:create_open: req_rdlink failed with %d\n", - r); - put_vnode(dir_vp); - return r; - } - if (r >= len) - { - printf( - "vfs:create_open: got bad length %d from req_rdlink\n", - r); - r= len-1; - } - user_fullpath[r]= '\0'; - - printf("got link target '%s'\n", user_fullpath); - if (user_fullpath[0] == '/') - { - put_vnode(dir_vp); - start_vp= fp->fp_rd; - dup_vnode(start_vp); - } - else - start_vp= dir_vp; - } - - put_vnode(start_vp); - return ELOOP; -} - - -/*===========================================================================* - * exists_open * + * new_node * *===========================================================================*/ -PRIVATE int exists_open(vp, bits, oflags /*, omode, lastc, vpp */) -struct vnode *vp; -mode_t bits; -int oflags; +PRIVATE struct vnode *new_node(mode_t bits) { + struct vnode *dirp, *vp; int r; - - /* Check protections. */ - if ((r = forbidden(vp, bits, 0 /*!use_realuid*/)) != OK) - return r; - - /* Opening reg. files directories and special files differ. */ - switch (vp->v_mode & I_TYPE) { - case I_REGULAR: - /* Truncate regular file if O_TRUNC. */ - if (oflags & O_TRUNC) { - if ((r = forbidden(vp, W_BIT, 0 /*!use_realuid*/)) !=OK) break; - truncate_vn(vp, 0); + struct node_details res; + struct vnode *rest; + + /* See if the path can be opened down to the last directory. */ + if ((dirp = last_dir()) == NIL_VNODE) return(NIL_VNODE); + + /* The final directory is accessible. Get final component of the path. */ + vp = advance(dirp, 0); + if (vp == NIL_VNODE && err_code == ENOENT) { + /* Last path component does not exist. Make a new directory entry. */ + if ((vp = get_free_vnode()) == NIL_VNODE) { + /* Can't create new vnode: out of vnodes. */ + put_vnode(dirp); + return(NIL_VNODE); } - break; - - case I_DIRECTORY: - /* Directories may be read but not written. */ - r = (bits & W_BIT ? EISDIR : OK); - break; - - case I_CHAR_SPECIAL: - case I_BLOCK_SPECIAL: - if (vp->v_sdev == (dev_t)-1) - panic(__FILE__, "vfs:exists_open: bad special", NO_NUM); - break; - - case I_NAMED_PIPE: -#if 0 - printf("vfs:exists_open: fifo vp 0x%x, for %s\n", - vp, ((bits & W_BIT) ? "writing" : "reading")); -#endif - if (vp->v_ref_count == 1) - { - vp->v_pipe_rd_pos= 0; - vp->v_pipe_wr_pos= 0; - if (vp->v_size != 0) - r= truncate_vn(vp, 0); + if ((r = forbidden(dirp, W_BIT|X_BIT)) != OK || + (r = req_create(dirp->v_fs_e, dirp->v_inode_nr,bits, fp->fp_effuid, + fp->fp_effgid, user_fullpath, &res)) != OK ) { + /* Can't create new directory entry: either no permission or + something else is wrong. */ + put_vnode(dirp); + err_code = r; + return(NIL_VNODE); } - break; + + /* Store results and mark vnode in use */ + vp->v_fs_e = res.fs_e; + vp->v_inode_nr = res.inode_nr; + vp->v_mode = res.fmode; + vp->v_size = res.fsize; + vp->v_uid = res.uid; + vp->v_gid = res.gid; + vp->v_sdev = res.dev; + vp->v_vmnt = dirp->v_vmnt; + vp->v_dev = vp->v_vmnt->m_dev; + vp->v_fs_count = 1; + vp->v_ref_count = 1; + } else { + /* Either last component exists, or there is some other problem. */ + if (vp != NIL_VNODE) + r = EEXIST; + else + r = err_code; } - return(r); + err_code = r; + put_vnode(dirp); + return(vp); } @@ -498,10 +305,7 @@ PRIVATE int pipe_open(register struct vnode *vp, register mode_t bits, vp->v_pipe = I_PIPE; - if((bits & (R_BIT|W_BIT)) == (R_BIT|W_BIT)) { - printf("pipe opened RW.\n"); - return ENXIO; - } + if((bits & (R_BIT|W_BIT)) == (R_BIT|W_BIT)) return(ENXIO); if (find_filp(vp, bits & W_BIT ? R_BIT : W_BIT) == NIL_FILP) { if (oflags & O_NONBLOCK) { @@ -510,7 +314,7 @@ PRIVATE int pipe_open(register struct vnode *vp, register mode_t bits, suspend(FP_BLOCKED_ON_POPEN); /* suspend caller */ return(SUSPEND); } - } else if (susp_count > 0) {/* revive blocked processes */ + } else if (susp_count > 0) { /* revive blocked processes */ release(vp, OPEN, susp_count); release(vp, CREAT, susp_count); } @@ -527,35 +331,29 @@ PUBLIC int do_mknod() register mode_t bits, mode_bits; int r; struct vnode *vp; - + /* Only the super_user may make nodes other than fifos. */ mode_bits = (mode_t) m_in.mk_mode; /* mode of the inode */ - if (!super_user && ((mode_bits & I_TYPE) != I_NAMED_PIPE)) return(EPERM); - if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code); + if(!super_user && ((mode_bits & I_TYPE) != I_NAMED_PIPE)) return(EPERM); bits = (mode_bits & I_TYPE) | (mode_bits & ALL_MODES & fp->fp_umask); - - /* Request lookup */ - if ((r = lookup_lastdir(0 /*!use_realuid*/, &vp)) != OK) return r; + + /* Open directory that's going to hold the new node. */ + if(fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code); + if((vp = last_dir()) == NIL_VNODE) return(err_code); /* Make sure that the object is a directory */ - if ((vp->v_mode & I_TYPE) != I_DIRECTORY) - { - put_vnode(vp); - return ENOTDIR; + if((vp->v_mode & I_TYPE) != I_DIRECTORY) { + put_vnode(vp); + return(ENOTDIR); } - r= forbidden(vp, W_BIT|X_BIT, 0 /*!use_realuid*/); - if (r != OK) - { - put_vnode(vp); - return r; + if ((r = forbidden(vp, W_BIT|X_BIT)) == OK) { + r = req_mknod(vp->v_fs_e, vp->v_inode_nr, user_fullpath, fp->fp_effuid, + fp->fp_effgid, bits, m_in.mk_z0); } - /* Issue request */ - r= req_mknod(vp->v_fs_e, vp->v_inode_nr, user_fullpath, - fp->fp_effuid, fp->fp_effgid, bits, m_in.mk_z0); put_vnode(vp); - return r; + return(r); } @@ -569,37 +367,29 @@ PUBLIC int do_mkdir() int r; struct vnode *vp; - if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code); + if(fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code); bits = I_DIRECTORY | (m_in.mode & RWX_MODES & fp->fp_umask); /* Request lookup */ - if ((r = lookup_lastdir(0 /*!use_realuid*/, &vp)) != OK) return r; + if((vp = last_dir()) == NIL_VNODE) return(err_code); /* Make sure that the object is a directory */ - if ((vp->v_mode & I_TYPE) != I_DIRECTORY) - { - put_vnode(vp); - return ENOTDIR; + if ((vp->v_mode & I_TYPE) != I_DIRECTORY) { + put_vnode(vp); + return(ENOTDIR); } - r= forbidden(vp, W_BIT|X_BIT, 0 /*!use_realuid*/); - if (r != OK) - { - put_vnode(vp); - return r; + if ((r = forbidden(vp, W_BIT|X_BIT)) == OK) { + r = req_mkdir(vp->v_fs_e, vp->v_inode_nr, user_fullpath, fp->fp_effuid, + fp->fp_effgid, bits); } - - /* Issue request */ - r= req_mkdir(vp->v_fs_e, vp->v_inode_nr, user_fullpath, - fp->fp_effuid, fp->fp_effgid, bits); + put_vnode(vp); - return r; + return(r); } - - /*===========================================================================* * do_lseek * *===========================================================================*/ @@ -625,7 +415,7 @@ PUBLIC int do_lseek() default: return(EINVAL); } - offset= m_in.offset_lo; + offset = m_in.offset_lo; if (offset >= 0) newpos= add64ul(pos, offset); else @@ -633,11 +423,11 @@ PUBLIC int do_lseek() /* Check for overflow. */ if (ex64hi(newpos) != 0) - return EINVAL; + return(EINVAL); if (cmp64(newpos, rfilp->filp_pos) != 0) { /* Inhibit read ahead request */ r = req_inhibread(rfilp->filp_vno->v_fs_e, rfilp->filp_vno->v_inode_nr); - if (r != OK) return r; + if (r != OK) return(r); } rfilp->filp_pos = newpos; @@ -673,7 +463,7 @@ PUBLIC int do_llseek() default: return(EINVAL); } - newpos= add64(pos, make64(m_in.offset_lo, m_in.offset_high)); + newpos = add64(pos, make64(m_in.offset_lo, m_in.offset_high)); /* Check for overflow. */ if (((long)m_in.offset_high > 0) && cmp64(newpos, pos) < 0) @@ -683,7 +473,7 @@ PUBLIC int do_llseek() if (cmp64(newpos, rfilp->filp_pos) != 0) { /* Inhibit read ahead request */ r = req_inhibread(rfilp->filp_vno->v_fs_e, rfilp->filp_vno->v_inode_nr); - if (r != OK) return r; + if (r != OK) return(r); } rfilp->filp_pos = newpos; @@ -757,14 +547,13 @@ struct filp *fp; if (mode_word == I_CHAR_SPECIAL || mode_word == I_BLOCK_SPECIAL) { dev = (dev_t) vp->v_sdev; if (mode_word == I_BLOCK_SPECIAL) { - if (vp->v_bfs_e == ROOT_FS_E) - { + if (vp->v_bfs_e == ROOT_FS_E) { /* Invalidate the cache unless the special is * mounted. Assume that the root filesystem's * is open only for fsck. */ req_flush(vp->v_bfs_e, dev); - } + } } /* Do any special processing on device close. */ (void) dev_close(dev, fp-filp); @@ -785,14 +574,14 @@ struct filp *fp; /* Last reader or writer is going. Tell MFS about latest * pipe size. */ - truncate_vn(vp, vp->v_size); + truncate_vnode(vp, vp->v_size); } put_vnode(fp->filp_vno); } - } + /*===========================================================================* * close_reply * *===========================================================================*/ @@ -807,72 +596,73 @@ PUBLIC void close_reply() *===========================================================================*/ PUBLIC int do_vm_open() { - int len, r, n; - endpoint_t ep; + int len, r, n; + endpoint_t ep; - len = m_in.VMVO_NAME_LENGTH; - m_out.VMV_ENDPOINT = ep = m_in.VMVO_ENDPOINT; + len = m_in.VMVO_NAME_LENGTH; + m_out.VMV_ENDPOINT = ep = m_in.VMVO_ENDPOINT; - /* Do open() call on behalf of any process, performed by VM. */ - if(len < 2 || len > sizeof(user_fullpath)) { - printf("do_vm_open: strange length %d\n", len); - m_out.VMVRO_FD = EINVAL; - return VM_VFS_REPLY_OPEN; - } + /* Do open() call on behalf of any process, performed by VM. */ + if(len < 2 || len > sizeof(user_fullpath)) { + printf("do_vm_open: strange length %d\n", len); + m_out.VMVRO_FD = EINVAL; + return(VM_VFS_REPLY_OPEN); + } - /* Do open on behalf of which process? */ - if(isokendpt(ep, &n) != OK) { - printf("do_vm_open: strange endpoint %d\n", ep); - m_out.VMVRO_FD = EINVAL; - return VM_VFS_REPLY_OPEN; - } + /* Do open on behalf of which process? */ + if(isokendpt(ep, &n) != OK) { + printf("do_vm_open: strange endpoint %d\n", ep); + m_out.VMVRO_FD = EINVAL; + return(VM_VFS_REPLY_OPEN); + } - /* XXX - do open on behalf of this process */ - fp = &fproc[n]; + /* XXX - do open on behalf of this process */ + fp = &fproc[n]; - /* Get path name from VM address space. */ - if((r=sys_safecopyfrom(VM_PROC_NR, m_in.VMVO_NAME_GRANT, 0, - (vir_bytes) user_fullpath, len, D)) != OK) { - printf("do_vm_open: sys_safecopyfrom failed: %d\n", r); - m_out.VMVRO_FD = EPERM; - return VM_VFS_REPLY_OPEN; - } + /* Get path name from VM address space. */ + if((r=sys_safecopyfrom(VM_PROC_NR, m_in.VMVO_NAME_GRANT, 0, + (vir_bytes) user_fullpath, len, D)) != OK) { + printf("do_vm_open: sys_safecopyfrom failed: %d\n", r); + m_out.VMVRO_FD = EPERM; + return(VM_VFS_REPLY_OPEN); + } - /* Check if path is null-terminated. */ - if(user_fullpath[len-1] != '\0') { - printf("do_vm_open: name (len %d) not 0-terminated\n", len); - m_out.VMVRO_FD = EINVAL; - return VM_VFS_REPLY_OPEN; - } + /* Check if path is null-terminated. */ + if(user_fullpath[len-1] != '\0') { + printf("do_vm_open: name (len %d) not 0-terminated\n", len); + m_out.VMVRO_FD = EINVAL; + return(VM_VFS_REPLY_OPEN); + } - /* Perform open(). */ - m_out.VMVRO_FD = common_open(m_in.VMVO_FLAGS, m_in.VMVO_MODE); - m_out.VMV_ENDPOINT = ep; + /* Perform open(). */ + m_out.VMVRO_FD = common_open(m_in.VMVO_FLAGS, m_in.VMVO_MODE); + m_out.VMV_ENDPOINT = ep; - /* Send open() reply. */ - return VM_VFS_REPLY_OPEN; + /* Send open() reply. */ + return(VM_VFS_REPLY_OPEN); } + /*===========================================================================* * do_vm_close * *===========================================================================*/ PUBLIC int do_vm_close() { - int len, r, n; - endpoint_t ep; + int len, r, n; + endpoint_t ep; - len = m_in.VMVO_NAME_LENGTH; + len = m_in.VMVO_NAME_LENGTH; - /* Do close() call on behalf of any process, performed by VM. */ - m_out.VMV_ENDPOINT = ep = m_in.VMVC_ENDPOINT; - if(isokendpt(ep, &n) != OK) { - printf("do_vm_close: strange endpoint %d\n", ep); - return VM_VFS_REPLY_CLOSE; - } + /* Do close() call on behalf of any process, performed by VM. */ + m_out.VMV_ENDPOINT = ep = m_in.VMVC_ENDPOINT; + if(isokendpt(ep, &n) != OK) { + printf("do_vm_close: strange endpoint %d\n", ep); + return(VM_VFS_REPLY_CLOSE); + } - /* Perform close(). */ - r = close_fd(&fproc[n], m_in.VMVC_FD); + /* Perform close(). */ + r = close_fd(&fproc[n], m_in.VMVC_FD); - return VM_VFS_REPLY_CLOSE; + return(VM_VFS_REPLY_CLOSE); } diff --git a/servers/vfs/param.h b/servers/vfs/param.h index a298a92e0..057b2dfab 100644 --- a/servers/vfs/param.h +++ b/servers/vfs/param.h @@ -13,6 +13,7 @@ #define c_mode m1_i3 #define c_name m1_p1 #define name m3_p1 +#define flength m2_l1 #define name1 m1_p1 #define name2 m1_p2 #define name_length m3_i1 @@ -23,6 +24,8 @@ #define pathname m3_ca1 #define pid m1_i3 #define ENDPT m1_i1 +#define offset_lo m2_l1 +#define offset_high m2_l2 #define ctl_req m4_l1 #define driver_nr m4_l2 #define dev_nr m4_l3 @@ -32,6 +35,7 @@ #define request m1_i2 #define sig m1_i2 #define endpt1 m1_i1 +#define fs_endpt m1_p3 #define tp m2_l1 #define utime_actime m2_l1 #define utime_modtime m2_l2 diff --git a/servers/vfs/path.c b/servers/vfs/path.c index e19f98a58..3c36ad1e8 100644 --- a/servers/vfs/path.c +++ b/servers/vfs/path.c @@ -1,9 +1,6 @@ - /* lookup() is the main routine that controls the path name lookup. It * handles mountpoints and symbolic links. The actual lookup requests * are sent through the req_lookup wrapper function. - * - * Jul 2006 (Balazs Gerofi) */ #include "fs.h" @@ -14,7 +11,6 @@ #include #include #include - #include #include "fproc.h" #include "vmnt.h" @@ -31,47 +27,36 @@ */ #define DO_POSIX_PATHNAME_RES 0 -FORWARD _PROTOTYPE( int lookup_rel, (struct vnode *start_node, - int flags, int use_realuid, node_details_t *node) ); +FORWARD _PROTOTYPE( int lookup, (struct vnode *dirp, int flags, + node_details_t *node) ); /*===========================================================================* - * lookup_rel_vp * + * advance * *===========================================================================*/ -PUBLIC int lookup_rel_vp(start_node, flags, use_realuid, vpp) -struct vnode *start_node; +PUBLIC struct vnode *advance(dirp, flags) +struct vnode *dirp; int flags; -int use_realuid; -struct vnode **vpp; { - /* Resolve a pathname (in user_fullpath) starting at start_node to a vnode. */ - int r, lookup_res; +/* Resolve a pathname (in user_fullpath) starting at dirp to a vnode. */ + int r; struct vnode *new_vp, *vp; struct vmnt *vmp; struct node_details res; - /* See if free vnode is available */ - if ((new_vp = get_free_vnode(__FILE__, __LINE__)) == NIL_VNODE) { - printf("vfs:lookup_rel_vp: no free vnode available\n"); - *vpp= NULL; - return EINVAL; - } - - lookup_res = lookup_rel(start_node, flags, use_realuid, &res); - - if (lookup_res != OK) - { -#if 0 - printf("vfs:lookup_rel_vp: lookup_rel failed with %d\n", lookup_res); -#endif - return lookup_res; + /* Get a free vnode */ + if((new_vp = get_free_vnode()) == NIL_VNODE) return(NIL_VNODE); + + /* Lookup vnode belonging to the file. */ + if ((r = lookup(dirp, flags, &res)) != OK) { + err_code = r; + return(NIL_VNODE); } - + /* Check whether vnode is already in use or not */ if ((vp = find_vnode(res.fs_e, res.inode_nr)) != NIL_VNODE) { - vp->v_ref_count++; - vp->v_fs_count++; /* We got a reference from the FS */ - *vpp= vp; - return OK; + dup_vnode(vp); + vp->v_fs_count++; /* We got a reference from the FS */ + return(vp); } /* Fill in the free vnode's fields */ @@ -82,159 +67,115 @@ struct vnode **vpp; new_vp->v_uid = res.uid; new_vp->v_gid = res.gid; new_vp->v_sdev = res.dev; - - if ( (vmp = find_vmnt(new_vp->v_fs_e)) == NIL_VMNT) - panic(__FILE__, "vfs:lookup_rel_vp: vmnt not found", NO_NUM); + + if( (vmp = find_vmnt(new_vp->v_fs_e)) == NIL_VMNT) + panic(__FILE__, "VFS advance: vmnt not found", NO_NUM); new_vp->v_vmnt = vmp; new_vp->v_dev = vmp->m_dev; new_vp->v_fs_count = 1; new_vp->v_ref_count = 1; - - *vpp= new_vp; - return OK; + + return(new_vp); } /*===========================================================================* - * lookup_vp * + * eat_path * *===========================================================================*/ -PUBLIC int lookup_vp(flags, use_realuid, vpp) +PUBLIC struct vnode *eat_path(flags) int flags; -int use_realuid; -struct vnode **vpp; { - /* Resolve a pathname (in user_fullpath) starting to a vnode. Call - * lookup_rel_vp to do the actual work. - */ +/* Resolve 'user_fullpath' to a vnode. advance does the actual work. */ struct vnode *vp; - if(!fp->fp_rd || !fp->fp_wd) { - printf("VFS: lookup_vp %d: no rd/wd\n", fp->fp_endpoint); - return ENOENT; - } - - vp= (user_fullpath[0] == '/' ? fp->fp_rd : fp->fp_wd); - - return lookup_rel_vp(vp, flags, use_realuid, vpp); + vp = (user_fullpath[0] == '/' ? fp->fp_rd : fp->fp_wd); + return advance(vp, flags); } /*===========================================================================* - * lookup_lastdir_rel * + * last_dir * *===========================================================================*/ -PUBLIC int lookup_lastdir_rel(start_node, use_realuid, vpp) -struct vnode *start_node; -int use_realuid; -struct vnode **vpp; +PUBLIC struct vnode *last_dir(void) { - /* This function is for calls that insert or delete entries from a - * directory. The path name (implicitly taken from user_fullpath) - * is split into to parts: the name of the directory and the - * directory entry. The name of the directory is resolved to a - * vnode. The directory entry is copied back to user_fullpath. - * The lookup starts at start_node. - */ - int r; - size_t len; - char *cp; - char dir_entry[PATH_MAX+1]; - - len= strlen(user_fullpath); - if (len == 0) - { - /* Empty path, always fail */ - return ENOENT; - } - -#if !DO_POSIX_PATHNAME_RES - /* Remove trailing slashes */ - while (len > 1 && user_fullpath[len-1] == '/') - { - len--; - user_fullpath[len]= '\0'; - } -#endif - - cp= strrchr(user_fullpath, '/'); - if (cp == NULL) - { - /* Just one entry in the current working directory */ - dup_vnode(start_node); - *vpp= start_node; - - return OK; - } - else if (cp[1] == '\0') - { - /* Path ends in a slash. The directory entry is '.' */ - strcpy(dir_entry, "."); - } - else - { - /* A path name for the directory and a directory entry */ - strcpy(dir_entry, cp+1); - cp[1]= '\0'; - } - - /* Remove trailing slashes */ - while(cp > user_fullpath && cp[0] == '/') - { - cp[0]= '\0'; - cp--; - } - - /* Request lookup */ - r = lookup_rel_vp(start_node, 0 /*no flags*/, use_realuid, vpp); - if (r != OK) - return r; +/* Parse a path, 'user_fullpath', as far as the last directory, fetch the vnode + * for the last directory into the vnode table, and return a pointer to the + * vnode. In addition, return the final component of the path in 'string'. If + * the last directory can't be opened, return NIL_VNODE and the reason for + * failure in 'err_code'. We can't parse component by component as that would + * be too expensive. Alternatively, we cut off the last component of the path, + * and parse the path up to the penultimate component. + */ + + int r; + size_t len; + char *cp; + char dir_entry[PATH_MAX+1]; + struct vnode *vp, *res; + + /* Is the path absolute or relative? Initialize 'vp' accordingly. */ + vp = (user_fullpath[0] == '/' ? fp->fp_rd : fp->fp_wd); - /* Copy the directory entry back to user_fullpath */ - strcpy(user_fullpath, dir_entry); + len = strlen(user_fullpath); - return OK; -} + /* If path is empty, return ENOENT. */ + if (len == 0) { + err_code = ENOENT; + return(NIL_VNODE); + } +#if !DO_POSIX_PATHNAME_RES + /* Remove trailing slashes */ + while (len > 1 && user_fullpath[len-1] == '/') { + len--; + user_fullpath[len]= '\0'; + } +#endif -/*===========================================================================* - * lookup_lastdir * - *===========================================================================*/ -PUBLIC int lookup_lastdir(use_realuid, vpp) -int use_realuid; -struct vnode **vpp; -{ - /* This function is for calls that insert or delete entries from a - * directory. The path name (implicitly taken from user_fullpath) - * is split into to parts: the name of the directory and the - * directory entry. The name of the directory is resolved to a - * vnode. The directory entry is copied back to user_fullpath. - * Just call lookup_lastdir_rel with the appropriate starting vnode. - */ - struct vnode *vp; + cp = strrchr(user_fullpath, '/'); + if (cp == NULL) { + /* Just one entry in the current working directory */ + dup_vnode(vp); + return(vp); + } else if (cp[1] == '\0') { + /* Path ends in a slash. The directory entry is '.' */ + strcpy(dir_entry, "."); + } else { + /* A path name for the directory and a directory entry */ + strcpy(dir_entry, cp+1); + cp[1]= '\0'; + } - if(!fp->fp_rd || !fp->fp_wd) { - printf("VFS: lookup_lastdir %d: no rd/wd\n", fp->fp_endpoint); - return ENOENT; + /* Remove trailing slashes */ + while(cp > user_fullpath && cp[0] == '/') { + cp[0]= '\0'; + cp--; } - vp= (user_fullpath[0] == '/' ? fp->fp_rd : fp->fp_wd); - return lookup_lastdir_rel(vp, use_realuid, vpp); + res = advance(vp, PATH_NOFLAGS); + if (res == NIL_VNODE) return(NIL_VNODE); + + /* Copy the directory entry back to user_fullpath */ + strcpy(user_fullpath, dir_entry); + + return(res); } /*===========================================================================* - * lookup_rel * + * lookup * *===========================================================================*/ -PRIVATE int lookup_rel(start_node, flags, use_realuid, node) +PRIVATE int lookup(start_node, flags, node) struct vnode *start_node; int flags; -int use_realuid; node_details_t *node; { - /* Resolve a pathname (in user_fullpath) relative to start_node. */ +/* Resolve a pathname (in user_fullpath) relative to start_node. */ + int r, symloop; endpoint_t fs_e; - size_t path_off; + size_t path_off, path_left_len; ino_t dir_ino, root_ino; uid_t uid; gid_t gid; @@ -245,102 +186,90 @@ node_details_t *node; /* Empty (start) path? */ if (user_fullpath[0] == '\0') { node->inode_nr = 0; -#if 0 - printf("vfs:lookup_rel: returning ENOENT\n"); -#endif - return ENOENT; + return(ENOENT); } if(!fp->fp_rd || !fp->fp_wd) { printf("VFS: lookup_rel %d: no rd/wd\n", fp->fp_endpoint); - return ENOENT; + return(ENOENT); } fs_e = start_node->v_fs_e; - path_off = 0; dir_ino = start_node->v_inode_nr; + /* Is the process' root directory on the same partition?, * if so, set the chroot directory too. */ if (fp->fp_rd->v_dev == fp->fp_wd->v_dev) - root_ino = fp->fp_rd->v_inode_nr; + root_ino = fp->fp_rd->v_inode_nr; else - root_ino = 0; + root_ino = 0; /* Set user and group ids according to the system call */ - uid = (use_realuid ? fp->fp_realuid : fp->fp_effuid); - gid = (use_realuid ? fp->fp_realgid : fp->fp_effgid); + uid = (call_nr == ACCESS ? fp->fp_realuid : fp->fp_effuid); + gid = (call_nr == ACCESS ? fp->fp_realgid : fp->fp_effgid); - symloop= 0; /* Number of symlinks seen so far */ + symloop = 0; /* Number of symlinks seen so far */ /* Issue the request */ - r = req_lookup(fs_e, path_off, dir_ino, root_ino, uid, gid, flags, &res); + r = req_lookup(fs_e, dir_ino, root_ino, uid, gid, flags, &res); if (r != OK && r != EENTERMOUNT && r != ELEAVEMOUNT && r != ESYMLINK) - { -#if 0 - printf("vfs:lookup_rel: req_lookup_s failed with %d\n", r); -#endif - return r; - } + return(r); /* i.e., an error occured */ /* While the response is related to mount control set the * new requests respectively */ - while (r == EENTERMOUNT || r == ELEAVEMOUNT || r == ESYMLINK) { - /* Save the place in the (possibly updated) path where we have to - * continue witht henext lookup request. - */ - path_off= res.char_processed; + while(r == EENTERMOUNT || r == ELEAVEMOUNT || r == ESYMLINK) { + /* Update user_fullpath to reflect what's left to be parsed. */ + path_off = res.char_processed; + path_left_len = strlen(&user_fullpath[path_off]); + memmove(user_fullpath, &user_fullpath[path_off], path_left_len); + user_fullpath[path_left_len] = '\0'; /* terminate string */ /* Update the current value of the symloop counter */ symloop += res.symloop; if (symloop > SYMLOOP_MAX) - { - printf("vfs:lookup_rel: returning ELOOP\n"); - return ELOOP; - } + return(ELOOP); /* Symlink encountered with absolute path */ if (r == ESYMLINK) { dir_vp = fp->fp_rd; - } - else if (r == EENTERMOUNT) { + } else if (r == EENTERMOUNT) { /* Entering a new partition */ dir_vp = 0; /* Start node is now the mounted partition's root node */ for (vmp = &vmnt[0]; vmp != &vmnt[NR_MNTS]; ++vmp) { if (vmp->m_dev != NO_DEV) { - if(vmp->m_mounted_on && - vmp->m_mounted_on->v_inode_nr == - res.inode_nr && - vmp->m_mounted_on->v_fs_e == res.fs_e) { + if (vmp->m_mounted_on->v_inode_nr == res.inode_nr && + vmp->m_mounted_on->v_fs_e == res.fs_e) { dir_vp = vmp->m_root_node; - if(!dir_vp) { - panic(__FILE__, - "vfs: root_node NULL", NO_NUM); - } break; } } } + if (!dir_vp) { - printf( - "vfs:lookup_rel: res.inode_nr = %d, res.fs_e = %d\n", - res.inode_nr, res.fs_e); panic(__FILE__, - "vfs:lookup_s: mounted partition couldn't be found", - NO_NUM); + "VFS lookup: can't find mounted partition", + NO_NUM); } - - } - else { + } else { /* Climbing up mount */ /* Find the vmnt that represents the partition on * which we "climb up". */ if ((vmp = find_vmnt(res.fs_e)) == NIL_VMNT) { panic(__FILE__, - "vfs:lookup_s: couldn't find vmnt during the climbup", - NO_NUM); + "VFS lookup: can't find parent vmnt",NO_NUM); } + + /* Make sure that the child FS does not feed a bogus path + * to the parent FS. That is, when we climb up the tree, we + * must've encountered ".." in the path, and that is exactly + * what we're going to feed to the parent */ + if(strncmp(user_fullpath, "..", 2) != 0) { + printf("VFS: bogus path: %s\n", user_fullpath); + return(ENOENT); + } + /* Start node is the vnode on which the partition is * mounted */ dir_vp = vmp->m_mounted_on; @@ -349,24 +278,18 @@ node_details_t *node; /* Set the starting directories inode number and FS endpoint */ fs_e = dir_vp->v_fs_e; dir_ino = dir_vp->v_inode_nr; + /* Is the process' root directory on the same partition?, * if so, set the chroot directory too. */ - if (dir_vp->v_dev == fp->fp_rd->v_dev) + if(dir_vp->v_dev == fp->fp_rd->v_dev) root_ino = fp->fp_rd->v_inode_nr; else root_ino = 0; - /* Issue the request */ - r = req_lookup(fs_e, path_off, dir_ino, root_ino, uid, gid, flags, - &res); + r = req_lookup(fs_e, dir_ino, root_ino, uid, gid, flags, &res); - if (r != OK && r != EENTERMOUNT && r != ELEAVEMOUNT && r != ESYMLINK) - { -#if 0 - printf("vfs:lookup_rel: req_lookup_s failed with %d\n", r); -#endif - return r; - } + if(r != OK && r != EENTERMOUNT && r != ELEAVEMOUNT && r != ESYMLINK) + return(r); } /* Fill in response fields */ @@ -378,5 +301,5 @@ node_details_t *node; node->uid = res.uid; node->gid = res.gid; - return r; + return(r); } diff --git a/servers/vfs/pipe.c b/servers/vfs/pipe.c index 5baa26b9f..f466c68e2 100644 --- a/servers/vfs/pipe.c +++ b/servers/vfs/pipe.c @@ -13,9 +13,6 @@ * revive: mark a suspended process as able to run again * unsuspend_by_endpt: revive all processes blocking on a given process * do_unpause: a signal has been sent to a process; see if it suspended - * - * Changes for VFS: - * Jul 2006 (Balazs Gerofi) */ #include "fs.h" @@ -32,14 +29,11 @@ #include "fproc.h" #include "param.h" #include "select.h" - #include #include "vnode.h" #include "vmnt.h" - - /*===========================================================================* * do_pipe * *===========================================================================*/ @@ -56,62 +50,53 @@ PUBLIC int do_pipe() struct node_details res; /* See if a free vnode is available */ - if ( (vp = get_free_vnode(__FILE__, __LINE__)) == NIL_VNODE) { - printf("VFS: no vnode available!\n"); - return err_code; - } + if ( (vp = get_free_vnode()) == NIL_VNODE) return(err_code); /* Acquire two file descriptors. */ rfp = fp; - if ( (r = get_fd(0, R_BIT, &fil_des[0], &fil_ptr0)) != OK) return(r); + if ((r = get_fd(0, R_BIT, &fil_des[0], &fil_ptr0)) != OK) return(r); rfp->fp_filp[fil_des[0]] = fil_ptr0; FD_SET(fil_des[0], &rfp->fp_filp_inuse); fil_ptr0->filp_count = 1; - if ( (r = get_fd(0, W_BIT, &fil_des[1], &fil_ptr1)) != OK) { - rfp->fp_filp[fil_des[0]] = NIL_FILP; - FD_CLR(fil_des[0], &rfp->fp_filp_inuse); - fil_ptr0->filp_count = 0; - return(r); + if ((r = get_fd(0, W_BIT, &fil_des[1], &fil_ptr1)) != OK) { + rfp->fp_filp[fil_des[0]] = NIL_FILP; + FD_CLR(fil_des[0], &rfp->fp_filp_inuse); + fil_ptr0->filp_count = 0; + return(r); } rfp->fp_filp[fil_des[1]] = fil_ptr1; FD_SET(fil_des[1], &rfp->fp_filp_inuse); fil_ptr1->filp_count = 1; - /* Send request */ - r = req_newnode(ROOT_FS_E, fp->fp_effuid, fp->fp_effgid, I_NAMED_PIPE, - (dev_t)0, &res); + /* Create a named pipe inode on PipeFS */ + r = req_newnode(PFS_PROC_NR, fp->fp_effuid, fp->fp_effgid, I_NAMED_PIPE, + (dev_t) 0, &res); - /* Handle error */ if (r != OK) { - rfp->fp_filp[fil_des[0]] = NIL_FILP; - FD_CLR(fil_des[0], &rfp->fp_filp_inuse); - fil_ptr0->filp_count = 0; - rfp->fp_filp[fil_des[1]] = NIL_FILP; - FD_CLR(fil_des[1], &rfp->fp_filp_inuse); - fil_ptr1->filp_count = 0; - return r; + rfp->fp_filp[fil_des[0]] = NIL_FILP; + FD_CLR(fil_des[0], &rfp->fp_filp_inuse); + fil_ptr0->filp_count = 0; + rfp->fp_filp[fil_des[1]] = NIL_FILP; + FD_CLR(fil_des[1], &rfp->fp_filp_inuse); + fil_ptr1->filp_count = 0; + return(r); } /* Fill in vnode */ vp->v_fs_e = res.fs_e; + vp->v_mapfs_e = res.fs_e; vp->v_inode_nr = res.inode_nr; + vp->v_mapinode_nr = res.inode_nr; vp->v_mode = res.fmode; - vp->v_index = res.inode_index; vp->v_pipe = I_PIPE; vp->v_pipe_rd_pos= 0; vp->v_pipe_wr_pos= 0; vp->v_fs_count = 1; + vp->v_mapfs_count = 1; vp->v_ref_count = 1; vp->v_size = 0; - - if ( (vmp = find_vmnt(vp->v_fs_e)) == NIL_VMNT) { - printf("VFS: vmnt not found by pipe() ==>> USING ROOT VMNT\n"); - vp->v_vmnt = &vmnt[0]; - } - else { - vp->v_vmnt = vmp; - vp->v_dev = vmp->m_dev; - } + vp->v_vmnt = NIL_VMNT; + vp->v_dev = NO_DEV; /* Fill in filp objects */ fil_ptr0->filp_vno = vp; @@ -126,10 +111,36 @@ PUBLIC int do_pipe() return(OK); } + +/*===========================================================================* + * map_vnode * + *===========================================================================*/ +PUBLIC int map_vnode(vp) +struct vnode *vp; +{ + int r; + struct node_details res; + + if(vp->v_mapfs_e != 0) return(OK); /* Already mapped; nothing to do. */ + + /* Create a temporary mapping of this inode to PipeFS. Read and write + * operations on data will be handled by PipeFS. The rest by the 'original' + * FS that holds the inode. */ + if ((r = req_newnode(PFS_PROC_NR, fp->fp_effuid, fp->fp_effgid, I_NAMED_PIPE, + vp->v_dev, &res)) == OK) { + vp->v_mapfs_e = res.fs_e; + vp->v_mapinode_nr = res.inode_nr; + vp->v_mapfs_count = 1; + } + + return(r); +} + + /*===========================================================================* * pipe_check * *===========================================================================*/ -PUBLIC int Xpipe_check(vp, rw_flag, oflags, bytes, position, notouch) +PUBLIC int pipe_check(vp, rw_flag, oflags, bytes, position, notouch) register struct vnode *vp; /* the inode of the pipe */ int rw_flag; /* READING or WRITING */ int oflags; /* flags set by open or fcntl */ @@ -143,52 +154,51 @@ int notouch; /* check only */ * pipe and no one is reading from it, give a broken pipe error. */ off_t pos; + int r = OK; if (ex64hi(position) != 0) panic(__FILE__, "pipe_check: position too large in pipe", NO_NUM); - pos= ex64lo(position); + pos = ex64lo(position); /* If reading, check for empty pipe. */ if (rw_flag == READING) { if (pos >= vp->v_size) { /* Process is reading from an empty pipe. */ - int r = 0; if (find_filp(vp, W_BIT) != NIL_FILP) { /* Writer exists */ - if (oflags & O_NONBLOCK) { + if (oflags & O_NONBLOCK) r = EAGAIN; - } else { + else r = SUSPEND; - } + /* If need be, activate sleeping writers. */ if (susp_count > 0) release(vp, WRITE, susp_count); } return(r); } - - return bytes; + return(bytes); } /* Process is writing to a pipe. */ if (find_filp(vp, R_BIT) == NIL_FILP) { - /* Tell kernel to generate a SIGPIPE signal. */ - if (!notouch) { - sys_kill(fp->fp_endpoint, SIGPIPE); - } + /* Process is writing, but there is no reader. Tell kernel to generate + * a SIGPIPE signal. */ + if (!notouch) sys_kill(fp->fp_endpoint, SIGPIPE); + return(EPIPE); } + /* Calculate how many bytes can be written. */ if (pos + bytes > PIPE_BUF) { - if (oflags & O_NONBLOCK) - { + if (oflags & O_NONBLOCK) { if (bytes <= PIPE_BUF) { /* Write has to be atomic */ return(EAGAIN); } /* Compute available space */ - bytes= PIPE_BUF-pos; + bytes = PIPE_BUF - pos; if (bytes > 0) { /* Do a partial write. Need to wakeup reader */ @@ -203,7 +213,7 @@ int notouch; /* check only */ if (bytes > PIPE_BUF) { /* Compute available space */ - bytes= PIPE_BUF-pos; + bytes = PIPE_BUF - pos; if (bytes > 0) { /* Do a partial write. Need to wakeup reader @@ -215,7 +225,7 @@ int notouch; /* check only */ } } - /* Pipe is full, or we need an atomic write */ + /* Pipe is full */ return(SUSPEND); } @@ -224,9 +234,10 @@ int notouch; /* check only */ release(vp, READ, susp_count); /* Requested amount fits */ - return bytes; + return(bytes); } + /*===========================================================================* * suspend * *===========================================================================*/ @@ -269,14 +280,19 @@ PUBLIC void suspend(int why) } } + +/*===========================================================================* + * wait_for * + *===========================================================================*/ PUBLIC void wait_for(endpoint_t who) { - if(who == NONE || who == ANY) - panic(__FILE__,"suspend on NONE or ANY",NO_NUM); - suspend(FP_BLOCKED_ON_OTHER); - fp->fp_task = who; + if(who == NONE || who == ANY) + panic(__FILE__,"suspend on NONE or ANY",NO_NUM); + suspend(FP_BLOCKED_ON_OTHER); + fp->fp_task = who; } + /*===========================================================================* * pipe_suspend * *===========================================================================*/ @@ -305,6 +321,7 @@ size_t size; fp->fp_nbytes = size; } + /*===========================================================================* * unsuspend_by_endpt * *===========================================================================*/ @@ -347,10 +364,6 @@ int count; /* max number of processes to release */ register struct fproc *rp; struct filp *f; -#if 0 - printf("vfs:release: vp 0x%x, call %d, count %d\n", vp, call_nr, count); -#endif - /* Trying to perform the call also includes SELECTing on it with that * operation. */ @@ -372,9 +385,8 @@ int count; /* max number of processes to release */ /* Search the proc table. */ for (rp = &fproc[0]; rp < &fproc[NR_PROCS] && count > 0; rp++) { if (rp->fp_pid != PID_FREE && fp_is_blocked(rp) && - rp->fp_revived == NOT_REVIVING && - (rp->fp_fd & BYTE) == call_nr && - rp->fp_filp[rp->fp_fd>>8]->filp_vno == vp) { + rp->fp_revived == NOT_REVIVING && (rp->fp_fd & BYTE) == call_nr && + rp->fp_filp[rp->fp_fd>>8]->filp_vno == vp) { revive(rp->fp_endpoint, 0); susp_count--; /* keep track of who is suspended */ if(susp_count < 0) @@ -384,6 +396,7 @@ int count; /* max number of processes to release */ } } + /*===========================================================================* * revive * *===========================================================================*/ @@ -399,12 +412,10 @@ int returned; /* if hanging on task, how many bytes read */ int fd_nr, proc_nr; struct filp *fil_ptr; - if(isokendpt(proc_nr_e, &proc_nr) != OK) - return; + if(isokendpt(proc_nr_e, &proc_nr) != OK) return; rfp = &fproc[proc_nr]; - if (!fp_is_blocked(rfp) || rfp->fp_revived == REVIVING) - return; + if (!fp_is_blocked(rfp) || rfp->fp_revived == REVIVING) return; /* The 'reviving' flag only applies to pipes. Processes waiting for TTY get * a message right away. The revival process is different for TTY and pipes. @@ -416,38 +427,31 @@ int returned; /* if hanging on task, how many bytes read */ /* Revive a process suspended on a pipe or lock. */ rfp->fp_revived = REVIVING; reviving++; /* process was waiting on pipe or lock */ - } - else if (blocked_on == FP_BLOCKED_ON_DOPEN) - { + } else if (blocked_on == FP_BLOCKED_ON_DOPEN) { rfp->fp_blocked_on = FP_BLOCKED_ON_NONE; - fd_nr= rfp->fp_fd>>8; - if (returned < 0) - { - fil_ptr= rfp->fp_filp[fd_nr]; + fd_nr = rfp->fp_fd>>8; + if (returned < 0) { + fil_ptr = rfp->fp_filp[fd_nr]; rfp->fp_filp[fd_nr] = NIL_FILP; FD_CLR(fd_nr, &rfp->fp_filp_inuse); - if (fil_ptr->filp_count != 1) - { + if (fil_ptr->filp_count != 1) { panic(__FILE__, "revive: bad count in filp", fil_ptr->filp_count); } - fil_ptr->filp_count= 0; + fil_ptr->filp_count = 0; put_vnode(fil_ptr->filp_vno); fil_ptr->filp_vno = NIL_VNODE; reply(proc_nr_e, returned); - } - else + } else reply(proc_nr_e, fd_nr); - } - else { + } else { rfp->fp_blocked_on = FP_BLOCKED_ON_NONE; - if (blocked_on == FP_BLOCKED_ON_POPEN) + if (blocked_on == FP_BLOCKED_ON_POPEN) { /* process blocked in open or create */ reply(proc_nr_e, rfp->fp_fd>>8); - else if (blocked_on == FP_BLOCKED_ON_SELECT) { + } else if (blocked_on == FP_BLOCKED_ON_SELECT) { reply(proc_nr_e, returned); - } - else { + } else { /* Revive a process suspended on TTY or other device. * Pretend it wants only what there is. */ @@ -491,18 +495,15 @@ int proc_nr_e; } rfp = &fproc[proc_nr_p]; - if (!fp_is_blocked(rfp)) - return; + if (!fp_is_blocked(rfp)) return; blocked_on = rfp->fp_blocked_on; - if (rfp->fp_revived == REVIVING) - { + if (rfp->fp_revived == REVIVING) { rfp->fp_revived = NOT_REVIVING; reviving--; wasreviving = 1; } - switch (blocked_on) { case FP_BLOCKED_ON_PIPE:/* process trying to read or write a pipe */ break; @@ -522,13 +523,12 @@ int proc_nr_e; return; case FP_BLOCKED_ON_OTHER: /* process trying to do device I/O (e.g. tty)*/ - if (rfp->fp_flags & SUSP_REOPEN) - { + if (rfp->fp_flags & SUSP_REOPEN) { /* Process is suspended while waiting for a reopen. * Just reply EINTR. */ rfp->fp_flags &= ~SUSP_REOPEN; - status= EINTR; + status = EINTR; break; } @@ -585,7 +585,7 @@ PUBLIC int select_request_pipe(struct filp *f, int *ops, int block) int orig_ops, r = 0, err, canwrite; orig_ops = *ops; if ((*ops & (SEL_RD|SEL_ERR))) { - if ((err = Xpipe_check(f->filp_vno, READING, 0, + if ((err = pipe_check(f->filp_vno, READING, 0, 1, f->filp_pos, 1)) != SUSPEND) r |= SEL_RD; if (err < 0 && err != SUSPEND) @@ -597,8 +597,9 @@ PUBLIC int select_request_pipe(struct filp *f, int *ops, int block) r &= ~SEL_ERR; } } + if ((*ops & (SEL_WR|SEL_ERR))) { - if ((err = Xpipe_check(f->filp_vno, WRITING, 0, + if ((err = pipe_check(f->filp_vno, WRITING, 0, 1, f->filp_pos, 1)) != SUSPEND) r |= SEL_WR; if (err < 0 && err != SUSPEND) @@ -618,9 +619,10 @@ PUBLIC int select_request_pipe(struct filp *f, int *ops, int block) f->filp_pipe_select_ops |= orig_ops; } - return SEL_OK; + return(SEL_OK); } + /*===========================================================================* * select_match_pipe * *===========================================================================*/ diff --git a/servers/vfs/protect.c b/servers/vfs/protect.c index c579c9655..b72828c4f 100644 --- a/servers/vfs/protect.c +++ b/servers/vfs/protect.c @@ -1,4 +1,3 @@ - /* This file deals with protection in the file system. It contains the code * for four system calls that relate to protection. * @@ -7,9 +6,6 @@ * do_chown: perform the CHOWN and FCHOWN system calls * do_umask: perform the UMASK system call * do_access: perform the ACCESS system call - * - * Changes for VFS: - * Jul 2006 (Balazs Gerofi) */ #include "fs.h" @@ -18,47 +14,39 @@ #include "file.h" #include "fproc.h" #include "param.h" - #include #include "vnode.h" #include "vmnt.h" - +FORWARD _PROTOTYPE( in_group, (gid_t grp) ); /*===========================================================================* * do_chmod * *===========================================================================*/ PUBLIC int do_chmod() { +/* Perform the chmod(name, mode) and fchmod(fd, mode) system calls. */ + struct filp *flp; struct vnode *vp; int r; - uid_t uid; - gid_t gid; mode_t new_mode; if (call_nr == CHMOD) { - /* Perform the chmod(name, mode) system call. */ - if (fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code); - - /* Request lookup */ - r = lookup_vp(0 /*flags*/, 0 /*!use_realuid*/, &vp); - if (r != OK) return r; + /* Temporarily open the file */ + if(fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code); + if ((vp = eat_path(PATH_NOFLAGS)) == NIL_VNODE) return(err_code); + } else { /* call_nr == FCHMOD */ + /* File is already opened; get a pointer to vnode from filp. */ + if (!(flp = get_filp(m_in.fd))) return(err_code); + vp = flp->filp_vno; + dup_vnode(vp); } - else if (call_nr == FCHMOD) { - if (!(flp = get_filp(m_in.m3_i1))) return err_code; - vp= flp->filp_vno; - dup_vnode(vp); - } - else panic(__FILE__, "do_chmod called with strange call_nr", call_nr); - - uid= fp->fp_effuid; - gid= fp->fp_effgid; /* Only the owner or the super_user may change the mode of a file. * No one may change the mode of a file on a read-only file system. */ - if (vp->v_uid != uid && uid != SU_UID) + if (vp->v_uid != fp->fp_effuid && fp->fp_effuid != SU_UID) r = EPERM; else r = read_only(vp); @@ -70,24 +58,23 @@ PUBLIC int do_chmod() } /* Now make the change. Clear setgid bit if file is not in caller's grp */ - if (uid != SU_UID && vp->v_gid != gid) + if (fp->fp_effuid != SU_UID && vp->v_gid != fp->fp_effgid) m_in.mode &= ~I_SET_GID_BIT; - /* Issue request */ - r = req_chmod(vp->v_fs_e, vp->v_inode_nr, m_in.mode, &new_mode); + if ((r = req_chmod(vp->v_fs_e, vp->v_inode_nr, m_in.mode, &new_mode)) == OK) + vp->v_mode = new_mode; - if (r == OK) - vp->v_mode = new_mode; put_vnode(vp); - - return OK; + return(OK); } + /*===========================================================================* * do_chown * *===========================================================================*/ PUBLIC int do_chown() { +/* Perform the chmod(name, mode) and fchmod(fd, mode) system calls. */ int inode_nr; int fs_e; struct filp *flp; @@ -98,56 +85,43 @@ PUBLIC int do_chown() mode_t new_mode; if (call_nr == CHOWN) { - /* Perform the chmod(name, mode) system call. */ - if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code); - - /* Request lookup */ - r = lookup_vp(0 /*flags*/, 0 /*!use_realuid*/, &vp); - if (r != OK) return r; - } - else if (call_nr == FCHOWN) { - if (!(flp = get_filp(m_in.m1_i1))) return err_code; - vp= flp->filp_vno; + /* Temporarily open the file. */ + if(fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code); + if ((vp = eat_path(PATH_NOFLAGS)) == NIL_VNODE) return(err_code); + } else { /* call_nr == FCHOWN */ + /* File is already opened; get a pointer to the vnode from filp. */ + if (!(flp = get_filp(m_in.fd))) return(err_code); + vp = flp->filp_vno; dup_vnode(vp); } - else panic(__FILE__, "do_chmod called with strange call_nr", call_nr); - - uid= fp->fp_effuid; - gid= fp->fp_effgid; - - r= OK; - if (uid == SU_UID) { - /* The super user can do anything. */ - } else { - /* Regular users can only change groups of their own files. */ - if (vp->v_uid != uid) - r = EPERM; /* File does not belong to the caller */ - if (vp->v_uid != m_in.owner) - r = EPERM; /* no giving away */ - if (gid != m_in.group) - r = EPERM; /* only change to the current gid */ - } - if (r == OK) - r = read_only(vp); - - if (r != OK) { - put_vnode(vp); - return r; + r = read_only(vp); + if (r == OK) { + /* FS is R/W. Whether call is allowed depends on ownership, etc. */ + /* The super user can do anything, so check permissions only if we're + a regular user. */ + if (fp->fp_effuid != SU_UID) { + /* Regular users can only change groups of their own files. */ + if (vp->v_uid != fp->fp_effuid) r = EPERM; + if (vp->v_uid != m_in.owner) r = EPERM; /* no giving away */ + if (fp->fp_effgid != m_in.group) r = EPERM; + } } - /* Issue request */ - r = req_chown(vp->v_fs_e, vp->v_inode_nr, m_in.owner, m_in.group, &new_mode); - - if(r == OK) { - vp->v_uid = m_in.owner; - vp->v_gid = m_in.group; - vp->v_mode = new_mode; + if (r == OK) { + /* Do not change uid/gid if new uid/gid is -1. */ + uid = (m_in.owner == (uid_t)-1 ? vp->v_uid : m_in.owner); + gid = (m_in.group == (gid_t)-1 ? vp->v_gid : m_in.group); + if ((r = req_chown(vp->v_fs_e, vp->v_inode_nr, uid, gid, + &new_mode)) == OK) { + vp->v_uid = uid; + vp->v_gid = gid; + vp->v_mode = new_mode; + } } put_vnode(vp); - - return r; + return(r); } @@ -178,24 +152,22 @@ PUBLIC int do_access() if ( (m_in.mode & ~(R_OK | W_OK | X_OK)) != 0 && m_in.mode != F_OK) return(EINVAL); + /* Temporarily open the file. */ if (fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code); + if ((vp = eat_path(PATH_NOFLAGS)) == NIL_VNODE) return(err_code); - /* Request lookup */ - r = lookup_vp(0 /*flags*/, TRUE /*use_realuid*/, &vp); - if (r != OK) return r; - - r= forbidden(vp, m_in.mode, 1 /*use_realuid*/); + r = forbidden(vp, m_in.mode); put_vnode(vp); - return r; + return(r); } /*===========================================================================* * forbidden * *===========================================================================*/ -PUBLIC int forbidden(struct vnode *vp, mode_t access_desired, int use_realuid) +PUBLIC int forbidden(struct vnode *vp, mode_t access_desired) { -/* Given a pointer to an inode, 'rip', and the access desired, determine +/* Given a pointer to an vnode, 'vp', and the access desired, determine * if the access is allowed, and if not why not. The routine looks up the * caller's uid in the 'fproc' table. If access is allowed, OK is returned * if it is forbidden, EACCES is returned. @@ -207,26 +179,13 @@ PUBLIC int forbidden(struct vnode *vp, mode_t access_desired, int use_realuid) gid_t gid; int r, shift, type; - if (vp->v_uid == (uid_t)-1 || vp->v_gid == (gid_t)-1) - { - printf("forbidden: bad uid/gid in vnode: inode %d on dev 0x%x\n", - vp->v_inode_nr, vp->v_dev); - printf("forbidden: last allocated at %s, %d\n", vp->v_file, vp->v_line); - return EACCES; - } + if (vp->v_uid == (uid_t) -1 || vp->v_gid == (gid_t) -1) return(EACCES); /* Isolate the relevant rwx bits from the mode. */ bits = vp->v_mode; - if (use_realuid) - { - uid= fp->fp_realuid; - gid= fp->fp_realgid; - } - else - { - uid= fp->fp_effuid; - gid= fp->fp_effgid; - } + uid = (call_nr == ACCESS ? fp->fp_realuid : fp->fp_effuid); + gid = (call_nr == ACCESS ? fp->fp_realgid : fp->fp_effgid); + if (uid == SU_UID) { /* Grant read and write permission. Grant search permission for * directories. Grant execute permission (for non-directories) if @@ -238,17 +197,16 @@ PUBLIC int forbidden(struct vnode *vp, mode_t access_desired, int use_realuid) else perm_bits = R_BIT | W_BIT; } else { - if (uid == vp->v_uid) shift = 6; /* owner */ - else if (gid == vp->v_gid ) shift = 3; /* group */ + if (uid == vp->v_uid) shift = 6; /* owner */ + else if (gid == vp->v_gid) shift = 3; /* group */ + else if (in_group(vp->v_gid) == OK) shift = 3; /* suppl. groups */ else shift = 0; /* other */ perm_bits = (bits >> shift) & (R_BIT | W_BIT | X_BIT); } /* If access desired is not a subset of what is allowed, it is refused. */ r = OK; - if ((perm_bits | access_desired) != perm_bits) { - r = EACCES; - } + if ((perm_bits | access_desired) != perm_bits) r = EACCES; /* Check to see if someone is trying to write on a file system that is * mounted read-only. @@ -261,6 +219,21 @@ PUBLIC int forbidden(struct vnode *vp, mode_t access_desired, int use_realuid) } +/*===========================================================================* + * in_group * + *===========================================================================*/ +PRIVATE int in_group(gid_t grp) +{ + int i; + + for (i = 0; i < fp->fp_ngroups; i++) + if (fp->fp_sgroups[i] == grp) + return(OK); + + return(EINVAL); +} + + /*===========================================================================* * read_only * *===========================================================================*/ diff --git a/servers/vfs/proto.h b/servers/vfs/proto.h index ead5a86ac..fc6686f1f 100644 --- a/servers/vfs/proto.h +++ b/servers/vfs/proto.h @@ -51,10 +51,10 @@ _PROTOTYPE( int pm_exec, (int proc_e, char *path, vir_bytes path_len, /* filedes.c */ _PROTOTYPE( struct filp *find_filp, (struct vnode *vp, mode_t bits) ); _PROTOTYPE( int get_fd, (int start, mode_t bits, int *k, - struct filp **fpt) ); + struct filp **fpt) ); _PROTOTYPE( struct filp *get_filp, (int fild) ); _PROTOTYPE( struct filp *get_filp2, (struct fproc *rfp, int fild) ); -_PROTOTYPE( int inval_filp, (struct filp *) ); +_PROTOTYPE( int invalidate, (struct filp *) ); /* fscall.c */ _PROTOTYPE( void nested_fs_call, (message *m) ); @@ -65,7 +65,7 @@ _PROTOTYPE( int do_unlink, (void) ); _PROTOTYPE( int do_rename, (void) ); _PROTOTYPE( int do_truncate, (void) ); _PROTOTYPE( int do_ftruncate, (void) ); -_PROTOTYPE( int truncate_vn, (struct vnode *vp, off_t newsize) ); +_PROTOTYPE( int truncate_vnode, (struct vnode *vp, off_t newsize) ); /* lock.c */ _PROTOTYPE( int lock_op, (struct filp *f, int req) ); @@ -82,6 +82,7 @@ _PROTOTYPE( int do_fcntl, (void) ); _PROTOTYPE( void pm_fork, (int pproc, int cproc, int cpid) ); _PROTOTYPE( void pm_setgid, (int proc_e, int egid, int rgid) ); _PROTOTYPE( void pm_setuid, (int proc_e, int euid, int ruid) ); +_PROTOTYPE( void pm_setgroups, (int proc_e, int ngroups, gid_t *addr) ); _PROTOTYPE( int do_sync, (void) ); _PROTOTYPE( int do_fsync, (void) ); _PROTOTYPE( void pm_reboot, (void) ); @@ -114,18 +115,15 @@ _PROTOTYPE( int do_vm_open, (void) ); _PROTOTYPE( int do_vm_close, (void) ); /* path.c */ -_PROTOTYPE( int lookup_rel_vp, (struct vnode *start_node, int flags, - int use_realuid, struct vnode **vpp) ); -_PROTOTYPE( int lookup_vp, (int flags, int use_realuid, - struct vnode **vpp) ); -_PROTOTYPE( int lookup_lastdir_rel, (struct vnode *start_node, - int use_realuid, struct vnode **vpp) ); -_PROTOTYPE( int lookup_lastdir, (int use_realuid, struct vnode **vpp) ); +_PROTOTYPE( struct vnode *advance, (struct vnode *dirp, int flags) ); +_PROTOTYPE( struct vnode *eat_path, (int flags) ); +_PROTOTYPE( struct vnode *last_dir, (void) ); /* pipe.c */ _PROTOTYPE( int do_pipe, (void) ); +_PROTOTYPE( int map_vnode, (struct vnode *vp) ); _PROTOTYPE( void unpause, (int proc_nr_e) ); -_PROTOTYPE( int Xpipe_check, (struct vnode *vp, int rw_flag, +_PROTOTYPE( int pipe_check, (struct vnode *vp, int rw_flag, int oflags, int bytes, u64_t position, int notouch) ); _PROTOTYPE( void release, (struct vnode *vp, int call_nr, int count) ); _PROTOTYPE( void revive, (int proc_nr, int bytes) ); @@ -147,8 +145,7 @@ _PROTOTYPE( int do_access, (void) ); _PROTOTYPE( int do_chmod, (void) ); _PROTOTYPE( int do_chown, (void) ); _PROTOTYPE( int do_umask, (void) ); -_PROTOTYPE( int forbidden, (struct vnode *vp, - mode_t access_desired, int use_realuid) ); +_PROTOTYPE( int forbidden, (struct vnode *vp, mode_t access_desired) ); _PROTOTYPE( int read_only, (struct vnode *vp) ); /* read.c */ @@ -173,14 +170,14 @@ _PROTOTYPE( int req_flush, (endpoint_t fs_e, Dev_t dev) ); _PROTOTYPE( int req_fstatfs, (int fs_e, int who_e, char *buf) ); _PROTOTYPE( int req_ftrunc, (endpoint_t fs_e, ino_t inode_nr, off_t start, off_t end) ); -_PROTOTYPE( int req_getdents, (endpoint_t fs_e, ino_t inode_nr, - off_t pos, cp_grant_id_t gid, size_t size, off_t *pos_change) ); +_PROTOTYPE( int req_getdents, (endpoint_t fs_e, ino_t inode_nr, u64_t pos, + char *buf, size_t size, u64_t *new_pos) ); _PROTOTYPE( int req_inhibread, (endpoint_t fs_e, ino_t inode_nr) ); _PROTOTYPE( int req_link, (endpoint_t fs_e, ino_t link_parent, char *lastc, ino_t linked_file) ); -_PROTOTYPE( int req_lookup, (endpoint_t fs_e, size_t path_off, - ino_t dir_ino, ino_t root_ino, _mnx_Uid_t uid, - _mnx_Gid_t gid, int flags, lookup_res_t *res) ); +_PROTOTYPE( int req_lookup, (endpoint_t fs_e, ino_t dir_ino, ino_t root_ino, + _mnx_Uid_t uid, _mnx_Gid_t gid, int flags, + lookup_res_t *res) ); _PROTOTYPE( int req_mkdir, (endpoint_t fs_e, ino_t inode_nr, char *lastc, _mnx_Uid_t uid, _mnx_Gid_t gid, _mnx_Mode_t dmode) ); _PROTOTYPE( int req_mknod, (endpoint_t fs_e, ino_t inode_nr, @@ -192,15 +189,15 @@ _PROTOTYPE( int req_newnode, (endpoint_t fs_e, _mnx_Uid_t uid, Dev_t dev, struct node_details *res) ); _PROTOTYPE( int req_putnode, (int fs_e, ino_t inode_nr, int count) ); _PROTOTYPE( int req_rdlink, (endpoint_t fs_e, ino_t inode_nr, - endpoint_t who_e, vir_bytes buf, size_t len) ); + endpoint_t who_e, char *buf, size_t len) ); _PROTOTYPE( int req_readsuper, (endpoint_t fs_e, char *driver_name, Dev_t dev, int readonly, int isroot, struct node_details *res_nodep) ); _PROTOTYPE( int req_readwrite, (endpoint_t fs_e, ino_t inode_nr, - int inode_index, u64_t pos, int rw_flag, - endpoint_t user_e, char *user_addr, - unsigned int num_of_bytes, u64_t *new_posp, - unsigned int *cum_iop) ); + u64_t pos, int rw_flag, + endpoint_t user_e, char *user_addr, + unsigned int num_of_bytes, u64_t *new_posp, + unsigned int *cum_iop) ); _PROTOTYPE( int req_rename, (endpoint_t fs_e, ino_t old_dir, char *old_name, ino_t new_dir, char *new_name) ); _PROTOTYPE( int req_rmdir, (endpoint_t fs_e, ino_t inode_nr, @@ -249,7 +246,7 @@ _PROTOTYPE( struct vmnt *get_free_vmnt, (short *index) ); _PROTOTYPE( struct vmnt *find_vmnt, (int fs_e) ); /* vnode.c */ -_PROTOTYPE( struct vnode *get_free_vnode, (char *file, int line) ); +_PROTOTYPE( struct vnode *get_free_vnode, (void) ); _PROTOTYPE( struct vnode *find_vnode, (int fs_e, int numb) ); _PROTOTYPE( void dup_vnode, (struct vnode *vp) ); _PROTOTYPE( void put_vnode, (struct vnode *vp) ); diff --git a/servers/vfs/read.c b/servers/vfs/read.c index 65657e799..5f52eff1f 100644 --- a/servers/vfs/read.c +++ b/servers/vfs/read.c @@ -8,8 +8,6 @@ * do_getdents: read entries from a directory (GETDENTS) * read_write: actually do the work of READ and WRITE * - * Changes for VFS: - * Jul 2006 (Balazs Gerofi) */ #include "fs.h" @@ -22,11 +20,11 @@ #include "param.h" #include #include - #include #include "vnode.h" #include "vmnt.h" + /*===========================================================================* * do_read * *===========================================================================*/ @@ -47,7 +45,7 @@ int rw_flag; /* READING or WRITING */ register struct vnode *vp; off_t bytes_left; u64_t position, res_pos, new_pos; - unsigned int off, cum_io, cum_io_incr, res_cum_io, num_of_bytes; + unsigned int off, cum_io, cum_io_incr, res_cum_io; int op, oflags, r, chunk, usr, block_spec, char_spec; int regular; mode_t mode_word; @@ -60,152 +58,104 @@ int rw_flag; /* READING or WRITING */ panic(__FILE__, "read_write: special read/write calls by PM no longer supported", NO_NUM); - } - else { - usr = who_e; /* normal case */ + } else { + usr = who_e; /* normal case */ } /* If the file descriptor is valid, get the vnode, size and mode. */ - if (m_in.nbytes < 0) - return(EINVAL); - - if ((f = get_filp(m_in.fd)) == NIL_FILP) { - return(err_code); - } + if (m_in.nbytes < 0) return(EINVAL); + if ((f = get_filp(m_in.fd)) == NIL_FILP) return(err_code); if (((f->filp_mode) & (rw_flag == READING ? R_BIT : W_BIT)) == 0) { -#if 0 - printf("vfs:read_write: returning error\n"); -#endif - return(f->filp_mode == FILP_CLOSED ? EIO : EBADF); + return(f->filp_mode == FILP_CLOSED ? EIO : EBADF); } - if (m_in.nbytes == 0) - return(0); /* so char special files need not check for 0*/ + return(0); /* so char special files need not check for 0*/ position = f->filp_pos; oflags = f->filp_flags; - vp = f->filp_vno; + r = OK; + cum_io = 0; - if (vp->v_pipe == I_PIPE) - { - if (fp->fp_cum_io_partial != 0) - { + if (vp->v_pipe == I_PIPE) { + if (fp->fp_cum_io_partial != 0) { panic(__FILE__, "read_write: fp_cum_io_partial not clear", - NO_NUM); + NO_NUM); } return rw_pipe(rw_flag, usr, m_in.fd, f, m_in.buffer, m_in.nbytes); } - r = OK; - cum_io = 0; - op = (rw_flag == READING ? VFS_DEV_READ : VFS_DEV_WRITE); mode_word = vp->v_mode & I_TYPE; regular = mode_word == I_REGULAR; if ((char_spec = (mode_word == I_CHAR_SPECIAL ? 1 : 0))) { - if (vp->v_sdev == NO_DEV) - panic(__FILE__,"read_write tries to read from " - "character device NO_DEV", NO_NUM); + if (vp->v_sdev == NO_DEV) + panic(__FILE__, "read_write tries to read from " + "character device NO_DEV", NO_NUM); + } if ((block_spec = (mode_word == I_BLOCK_SPECIAL ? 1 : 0))) { - if (vp->v_sdev == NO_DEV) - panic(__FILE__,"read_write tries to read from " - " block device NO_DEV", NO_NUM); + if (vp->v_sdev == NO_DEV) + panic(__FILE__, "read_write tries to read from " + " block device NO_DEV", NO_NUM); } - /* Character special files. */ - if (char_spec) { + if (char_spec) { /* Character special files. */ dev_t dev; int suspend_reopen; - suspend_reopen= (f->filp_state != FS_NORMAL); - + suspend_reopen = (f->filp_state != FS_NORMAL); dev = (dev_t) vp->v_sdev; + r = dev_io(op, dev, usr, m_in.buffer, position, m_in.nbytes, oflags, - suspend_reopen); + suspend_reopen); if (r >= 0) { cum_io = r; position = add64ul(position, r); r = OK; } - } - /* Block special files. */ - else if (block_spec) { - - /* Issue request */ - r = req_breadwrite(vp->v_bfs_e, usr, vp->v_sdev, position, - m_in.nbytes, m_in.buffer, rw_flag, &res_pos, &res_cum_io); - - position = res_pos; - cum_io += res_cum_io; - } - /* Regular files */ - else { - if (rw_flag == WRITING && block_spec == 0) { - /* Check for O_APPEND flag. */ - if (oflags & O_APPEND) position = cvul64(vp->v_size); - } - - - /* Fill in request structure */ - num_of_bytes = m_in.nbytes; - -#if 0 /* Don't truncate read request at size. The filesystem process will - * do this itself. - */ - if((rw_flag == READING) && - cmp64ul(add64ul(position, num_of_bytes), vp->v_size) > 0) { - /* Position always should fit in an off_t (LONG_MAX). */ - off_t pos32; - assert(cmp64ul(position, LONG_MAX) <= 0); - pos32 = cv64ul(position); - assert(pos32 >= 0); - assert(pos32 <= LONG_MAX); - num_of_bytes = vp->v_size - pos32; - assert(num_of_bytes >= 0); - } -#endif + } else if (block_spec) { /* Block special files. */ + r = req_breadwrite(vp->v_bfs_e, usr, vp->v_sdev, position, m_in.nbytes, + m_in.buffer, rw_flag, &res_pos, &res_cum_io); + position = res_pos; + cum_io += res_cum_io; + } else { /* Regular files */ + if (rw_flag == WRITING && block_spec == 0) { + /* Check for O_APPEND flag. */ + if (oflags & O_APPEND) position = cvul64(vp->v_size); + } - /* Issue request */ - r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, vp->v_index, position, - rw_flag, usr, m_in.buffer, num_of_bytes, &new_pos, &cum_io_incr); + /* Issue request */ + r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, position, rw_flag, usr, + m_in.buffer, m_in.nbytes, &new_pos, &cum_io_incr); - if (r >= 0) - { - if (ex64hi(new_pos)) - panic(__FILE__, "read_write: bad new pos", NO_NUM); + if (r >= 0) { + if (ex64hi(new_pos)) + panic(__FILE__, "read_write: bad new pos", NO_NUM); - position = new_pos; - cum_io += cum_io_incr; - } + position = new_pos; + cum_io += cum_io_incr; + } } /* On write, update file size and access time. */ if (rw_flag == WRITING) { - if (regular || mode_word == I_DIRECTORY) { - if (cmp64ul(position, vp->v_size) > 0) - { - if (ex64hi(position) != 0) - { - panic(__FILE__, - "read_write: file size too big for v_size", - NO_NUM); + if (regular || mode_word == I_DIRECTORY) { + if (cmp64ul(position, vp->v_size) > 0) { + if (ex64hi(position) != 0) { + panic(__FILE__, + "read_write: file size too big ", NO_NUM); + } + vp->v_size = ex64lo(position); } - vp->v_size = ex64lo(position); - } - } + } } f->filp_pos = position; - - if (r == OK) { - return cum_io; - } - - return r; + if (r == OK) return(cum_io); + return(r); } @@ -216,7 +166,7 @@ PUBLIC int do_getdents() { /* Perform the getdents(fd, buf, size) system call. */ int r; - off_t pos_change; + u64_t new_pos; cp_grant_id_t gid; register struct filp *rfilp; @@ -226,78 +176,55 @@ PUBLIC int do_getdents() } if (!(rfilp->filp_mode & R_BIT)) - return EBADF; + return(EBADF); if ((rfilp->filp_vno->v_mode & I_TYPE) != I_DIRECTORY) - return EBADF; - - gid=cpf_grant_magic(rfilp->filp_vno->v_fs_e, who_e, (vir_bytes) m_in.buffer, - m_in.nbytes, CPF_WRITE); - if (gid < 0) panic(__FILE__, "cpf_grant_magic failed", gid); + return(EBADF); - /* Issue request */ if (ex64hi(rfilp->filp_pos) != 0) panic(__FILE__, "do_getdents: should handle large offsets", NO_NUM); - r= req_getdents(rfilp->filp_vno->v_fs_e, rfilp->filp_vno->v_inode_nr, - ex64lo(rfilp->filp_pos), gid, m_in.nbytes, &pos_change); - - cpf_revoke(gid); + r = req_getdents(rfilp->filp_vno->v_fs_e, rfilp->filp_vno->v_inode_nr, + rfilp->filp_pos, m_in.buffer, m_in.nbytes, &new_pos); if (r > 0) - rfilp->filp_pos= add64ul(rfilp->filp_pos, pos_change); - return r; + rfilp->filp_pos = new_pos; + return(r); } /*===========================================================================* * rw_pipe * *===========================================================================*/ -PUBLIC int rw_pipe(rw_flag, usr, fd_nr, f, buf, req_size) +PUBLIC int rw_pipe(rw_flag, usr_e, fd_nr, f, buf, req_size) int rw_flag; /* READING or WRITING */ -endpoint_t usr; +endpoint_t usr_e; int fd_nr; struct filp *f; char *buf; size_t req_size; { - int r, oflags, op, partial_pipe; - size_t size, cum_io, cum_io_incr; + int r, oflags, op, partial_pipe = 0, r2; + size_t size, size2, cum_io, cum_io_incr, cum_io_incr2; struct vnode *vp; - u64_t position, new_pos; + u64_t position, new_pos, new_pos2; oflags = f->filp_flags; - vp = f->filp_vno; position = cvu64((rw_flag == READING) ? vp->v_pipe_rd_pos : vp->v_pipe_wr_pos); - -#if 0 - printf("vfs:rw_pipe: filp 0x%x pipe %s, buf 0x%x, size %d\n", - f, rw_flag == READING ? "read" : "write", buf, req_size); - printf("vfs:rw_pipe: pipe vp 0x%x, dev/num 0x%x/%d size %d, pos 0x%x:%08x\n", - vp, vp->v_dev, vp->v_inode_nr, - vp->v_size, ex64hi(position), ex64lo(position)); -#endif - /* fp->fp_cum_io_partial is only nonzero when doing partial writes */ cum_io = fp->fp_cum_io_partial; - op = (rw_flag == READING ? VFS_DEV_READ : VFS_DEV_WRITE); - r = Xpipe_check(vp, rw_flag, oflags, req_size, position, 0); - if (r <= 0) - { - if (r == SUSPEND) - pipe_suspend(rw_flag, fd_nr, buf, req_size); + r = pipe_check(vp, rw_flag, oflags, req_size, position, 0); + if (r <= 0) { + if (r == SUSPEND) pipe_suspend(rw_flag, fd_nr, buf, req_size); return(r); } size = r; - if (r < req_size) - partial_pipe = 1; - else - partial_pipe = 0; + if (size < req_size) partial_pipe = 1; /* Truncate read request at size. */ if((rw_flag == READING) && @@ -309,14 +236,22 @@ size_t req_size; pos32 = cv64ul(position); assert(pos32 >= 0); assert(pos32 <= LONG_MAX); + size2 = size; size = vp->v_size - pos32; } - /* Issue request */ - r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, vp->v_index, position, - rw_flag, usr, buf, size, &new_pos, &cum_io_incr); - if (r >= 0) - { + if (vp->v_mapfs_e != 0) { + r = req_readwrite(vp->v_mapfs_e, vp->v_mapinode_nr, position, rw_flag, + usr_e, buf, size, &new_pos, &cum_io_incr); + } +#if 0 + + r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, position, rw_flag, usr_e, + buf, size, &new_pos, &cum_io_incr); + } +#endif + + if (r >= 0) { if (ex64hi(new_pos)) panic(__FILE__, "read_write: bad new pos", NO_NUM); @@ -325,26 +260,20 @@ size_t req_size; buf += cum_io_incr; req_size -= cum_io_incr; } - + /* On write, update file size and access time. */ if (rw_flag == WRITING) { - if (cmp64ul(position, vp->v_size) > 0) - { - if (ex64hi(position) != 0) - { + if (cmp64ul(position, vp->v_size) > 0) { + if (ex64hi(position) != 0) { panic(__FILE__, - "read_write: file size too big for v_size", - NO_NUM); + "read_write: file size too big for v_size", + NO_NUM); } vp->v_size = ex64lo(position); } - } - else { + } else { if (cmp64ul(position, vp->v_size) >= 0) { /* Reset pipe pointers */ -#if 0 - printf("vfs:rw_pipe: resetting pipe size/positions\n"); -#endif vp->v_size = 0; vp->v_pipe_rd_pos= 0; vp->v_pipe_wr_pos= 0; @@ -371,11 +300,9 @@ size_t req_size; } } fp->fp_cum_io_partial = 0; - return cum_io; + return(cum_io); } - return r; + return(r); } - - diff --git a/servers/vfs/request.c b/servers/vfs/request.c index 8649a5949..c28e42d6e 100644 --- a/servers/vfs/request.c +++ b/servers/vfs/request.c @@ -5,14 +5,13 @@ * back the response. * The low-level fs_sendrec handles the recovery mechanism from * a dead driver and reissues the request. - * - * Sep 2006 (Balazs Gerofi) */ #include "fs.h" #include #include #include +#include #include #include #include @@ -20,14 +19,14 @@ #include #include #include - #include #include "fproc.h" #include "vmnt.h" #include "vnode.h" #include "param.h" -FORWARD _PROTOTYPE(int fs_sendrec_f, (char *file, int line, endpoint_t fs_e, message *reqm)); +FORWARD _PROTOTYPE(int fs_sendrec_f, (char *file, int line, endpoint_t fs_e, + message *reqm) ); #define fs_sendrec(e, m) fs_sendrec_f(__FILE__, __LINE__, (e), (m)) @@ -47,35 +46,33 @@ int rw_flag; u64_t *new_posp; unsigned int *cum_iop; { - int r; - cp_grant_id_t gid; - message m; - - gid= cpf_grant_magic(fs_e, user_e, (vir_bytes)user_addr, - num_of_bytes, (rw_flag == READING ? CPF_WRITE : CPF_READ)); - if (gid == -1) - panic(__FILE__, "req_breadwrite: cpf_grant_magic failed", NO_NUM); - - /* Fill in request message */ - m.m_type = rw_flag == READING ? REQ_BREAD_S : REQ_BWRITE_S; - m.REQ_XFD_BDEV = dev; - m.REQ_XFD_GID = gid; - m.REQ_XFD_POS_LO = ex64lo(pos); - m.REQ_XFD_POS_HI = ex64hi(pos); - m.REQ_XFD_NBYTES = num_of_bytes; + int r; + cp_grant_id_t grant_id; + message m; - /* Send/rec request */ - r = fs_sendrec(fs_e, &m); + grant_id = cpf_grant_magic(fs_e, user_e, (vir_bytes) user_addr, num_of_bytes, + (rw_flag == READING ? CPF_WRITE : CPF_READ)); + if(grant_id == -1) + panic(__FILE__, "req_breadwrite: cpf_grant_magic failed", NO_NUM); - cpf_revoke(gid); + /* Fill in request message */ + m.m_type = rw_flag == READING ? REQ_BREAD : REQ_BWRITE; + m.REQ_DEV2 = dev; + m.REQ_GRANT = grant_id; + m.REQ_SEEK_POS_LO = ex64lo(pos); + m.REQ_SEEK_POS_HI = ex64hi(pos); + m.REQ_NBYTES = num_of_bytes; - if (r != OK) return r; + /* Send/rec request */ + r = fs_sendrec(fs_e, &m); + cpf_revoke(grant_id); + if (r != OK) return(r); - /* Fill in response structure */ - *new_posp = make64(m.RES_XFD_POS_LO, m.RES_XFD_POS_HI); - *cum_iop = m.RES_XFD_CUM_IO; + /* Fill in response structure */ + *new_posp = make64(m.RES_SEEK_POS_LO, m.RES_SEEK_POS_HI); + *cum_iop = m.RES_NBYTES; - return OK; + return(OK); } @@ -88,23 +85,21 @@ ino_t inode_nr; mode_t rmode; mode_t *new_modep; { - message m; - int r; - - /* Fill in request message */ - m.m_type = REQ_CHMOD; - m.REQ_INODE_NR = inode_nr; - m.REQ_MODE = rmode; - m.REQ_UID = fp->fp_effuid; - m.REQ_GID = fp->fp_effgid; + message m; + int r; - /* Send/rec request */ - r = fs_sendrec(fs_e, &m); + /* Fill in request message */ + m.m_type = REQ_CHMOD; + m.REQ_INODE_NR = inode_nr; + m.REQ_MODE = rmode; - /* Copy back actual mode. */ - *new_modep = m.RES_MODE; + /* Send/rec request */ + r = fs_sendrec(fs_e, &m); + + /* Copy back actual mode. */ + *new_modep = m.RES_MODE; - return r; + return(r); } @@ -118,28 +113,22 @@ uid_t newuid; gid_t newgid; mode_t *new_modep; { - message m; - int r; - - /* Fill in request message */ - m.m_type = REQ_CHOWN; - m.REQ_INODE_NR = inode_nr; - m.REQ_UID = fp->fp_effuid; - m.REQ_GID = fp->fp_effgid; - if (newuid == -1) - newuid = fp->fp_effuid; - m.REQ_NEW_UID = newuid; - if (newgid == -1) - newgid = fp->fp_effgid; - m.REQ_NEW_GID = newgid; - - /* Send/rec request */ - r = fs_sendrec(fs_e, &m); - - /* Return new mode to caller. */ - *new_modep = m.RES_MODE; - - return r; + message m; + int r; + + /* Fill in request message */ + m.m_type = REQ_CHOWN; + m.REQ_INODE_NR = inode_nr; + m.REQ_UID = newuid; + m.REQ_GID = newgid; + + /* Send/rec request */ + r = fs_sendrec(fs_e, &m); + + /* Return new mode to caller. */ + *new_modep = m.RES_MODE; + + return(r); } @@ -155,43 +144,40 @@ gid_t gid; char *path; node_details_t *res; { - int r; - cp_grant_id_t grant_id; - size_t len; - message m; - - len= strlen(path) + 1; - grant_id= cpf_grant_direct(fs_e, (vir_bytes)path, len, CPF_READ); - if (grant_id == -1) - panic(__FILE__, "req_create: cpf_grant_direct failed", NO_NUM); - - /* Fill in request message */ - m.m_type = REQ_CREATE_S; - m.REQ_INODE_NR = inode_nr; - m.REQ_MODE = omode; - m.REQ_UID = uid; - m.REQ_GID = gid; - m.REQ_GRANT = grant_id; - m.REQ_PATH_LEN = len; - - /* Send/rec request */ - r = fs_sendrec(fs_e, &m); - - cpf_revoke(grant_id); - - if (r != OK) return r; - - /* Fill in response structure */ - res->fs_e = m.m_source; - res->inode_nr = m.RES_INODE_NR; - res->fmode = m.RES_MODE; - res->fsize = m.RES_FILE_SIZE; - res->uid = m.RES_UID; - res->gid = m.RES_GID; - res->dev = m.RES_DEV; - res->inode_index = m.RES_INODE_INDEX; - - return OK; + int r; + cp_grant_id_t grant_id; + size_t len; + message m; + + len = strlen(path) + 1; + grant_id = cpf_grant_direct(fs_e, (vir_bytes) path, len, CPF_READ); + if (grant_id == -1) + panic(__FILE__, "req_create: cpf_grant_direct failed", NO_NUM); + + /* Fill in request message */ + m.m_type = REQ_CREATE; + m.REQ_INODE_NR = inode_nr; + m.REQ_MODE = omode; + m.REQ_UID = uid; + m.REQ_GID = gid; + m.REQ_GRANT = grant_id; + m.REQ_PATH_LEN = len; + + /* Send/rec request */ + r = fs_sendrec(fs_e, &m); + cpf_revoke(grant_id); + if (r != OK) return(r); + + /* Fill in response structure */ + res->fs_e = m.m_source; + res->inode_nr = m.RES_INODE_NR; + res->fmode = m.RES_MODE; + res->fsize = m.RES_FILE_SIZE_LO; + res->uid = m.RES_UID; + res->gid = m.RES_GID; + res->dev = m.RES_DEV; + + return(OK); } @@ -202,14 +188,14 @@ PUBLIC int req_flush(fs_e, dev) endpoint_t fs_e; dev_t dev; { - message m; + message m; - /* Fill in request message */ - m.m_type = REQ_FLUSH; - m.REQ_DEV = dev; + /* Fill in request message */ + m.m_type = REQ_FLUSH; + m.REQ_DEV = dev; - /* Send/rec request */ - return fs_sendrec(fs_e, &m); + /* Send/rec request */ + return fs_sendrec(fs_e, &m); } @@ -222,24 +208,23 @@ int who_e; char *buf; { int r; - cp_grant_id_t gid; + cp_grant_id_t grant_id; message m; - gid= cpf_grant_magic(fs_e, who_e, (vir_bytes)buf, sizeof(struct statfs), - CPF_WRITE); - if (gid < 0) - return gid; + grant_id = cpf_grant_magic(fs_e, who_e, (vir_bytes) buf, sizeof(struct statfs), + CPF_WRITE); + if(grant_id == -1) + panic(__FILE__, "req_fstatfs: cpf_grant_magic failed", NO_NUM); /* Fill in request message */ m.m_type = REQ_FSTATFS; - m.REQ_GRANT = gid; + m.REQ_GRANT = grant_id; /* Send/rec request */ - r= fs_sendrec(fs_e, &m); + r = fs_sendrec(fs_e, &m); + cpf_revoke(grant_id); - cpf_revoke(gid); - - return r; + return(r); } @@ -252,61 +237,56 @@ ino_t inode_nr; off_t start; off_t end; { - message m; - - /* Fill in request message */ - m.m_type = REQ_FTRUNC; - m.REQ_FD_INODE_NR = inode_nr; - m.REQ_FD_START = start; - m.REQ_FD_END = end; + message m; - /* Send/rec request */ - return fs_sendrec(fs_e, &m); + /* Fill in request message */ + m.m_type = REQ_FTRUNC; + m.REQ_INODE_NR = inode_nr; + m.REQ_TRC_START_LO = start; + m.REQ_TRC_START_HI = 0; /* Not used for now, so clear it. */ + m.REQ_TRC_END_LO = end; + m.REQ_TRC_END_HI = 0; /* Not used for now, so clear it. */ + + /* Send/rec request */ + return fs_sendrec(fs_e, &m); } /*===========================================================================* * req_getdents * *===========================================================================*/ -PUBLIC int req_getdents(fs_e, inode_nr, pos, gid, size, pos_change) +PUBLIC int req_getdents(fs_e, inode_nr, pos, buf, size, new_pos) endpoint_t fs_e; ino_t inode_nr; -off_t pos; -cp_grant_id_t gid; +u64_t pos; +char *buf; size_t size; -off_t *pos_change; +u64_t *new_pos; { - int r; - message m; - - m.m_type= REQ_GETDENTS; - m.REQ_GDE_INODE= inode_nr; - m.REQ_GDE_GRANT= gid; - m.REQ_GDE_SIZE= size; - m.REQ_GDE_POS= pos; - - r = fs_sendrec(fs_e, &m); - - if (r != ENOSYS && r != EINVAL) { - *pos_change= m.RES_GDE_POS_CHANGE; - - if (r == OK) - r = m.RES_GDE_CUM_IO; - - return r; - } - - /* Legacy support: try the old getdents */ - m.m_type = REQ_GETDENTS_O; - m.REQ_GDE_INODE= inode_nr; - m.REQ_GDE_GRANT= gid; - m.REQ_GDE_SIZE= size; - m.REQ_GDE_POS= pos; + int r; + message m; + cp_grant_id_t grant_id; + + grant_id = cpf_grant_magic(fs_e, who_e, (vir_bytes) buf, size, CPF_WRITE); + if (grant_id < 0) + panic(__FILE__, "req_getdents: cpf_grant_magic failed", grant_id); - r = fs_sendrec(fs_e, &m); + m.m_type = REQ_GETDENTS; + m.REQ_INODE_NR = inode_nr; + m.REQ_GRANT = grant_id; + m.REQ_MEM_SIZE = size; + m.REQ_SEEK_POS_LO = ex64lo(pos); + m.REQ_SEEK_POS_HI = 0; /* Not used for now, so clear it. */ + + r = fs_sendrec(fs_e, &m); + cpf_revoke(grant_id); + + if (r == OK) { + *new_pos = cvul64(m.RES_SEEK_POS_LO); + r = m.RES_NBYTES; + } - *pos_change= m.RES_GDE_POS_CHANGE; - return r; + return(r); } @@ -317,14 +297,14 @@ PUBLIC int req_inhibread(fs_e, inode_nr) endpoint_t fs_e; ino_t inode_nr; { - message m; - - /* Fill in request message */ - m.m_type = REQ_INHIBREAD; - m.REQ_INODE_NR = inode_nr; + message m; - /* Send/rec request */ - return fs_sendrec(fs_e, &m); + /* Fill in request message */ + m.m_type = REQ_INHIBREAD; + m.REQ_INODE_NR = inode_nr; + + /* Send/rec request */ + return fs_sendrec(fs_e, &m); } @@ -337,38 +317,36 @@ ino_t link_parent; char *lastc; ino_t linked_file; { - int r; - cp_grant_id_t gid; - size_t len; - message m; - - len= strlen(lastc) + 1; - gid= cpf_grant_direct(fs_e, (vir_bytes)lastc, len, CPF_READ); - if (gid == -1) - panic(__FILE__, "req_link: cpf_grant_direct failed", NO_NUM); - - /* Fill in request message */ - m.m_type = REQ_LINK_S; - m.REQ_LINKED_FILE = linked_file; - m.REQ_LINK_PARENT = link_parent; - m.REQ_GRANT = gid; - m.REQ_PATH_LEN = len; + int r; + cp_grant_id_t grant_id; + size_t len; + message m; - /* Send/rec request */ - r = fs_sendrec(fs_e, &m); + len = strlen(lastc) + 1; + grant_id = cpf_grant_direct(fs_e, (vir_bytes)lastc, len, CPF_READ); + if(grant_id == -1) + panic(__FILE__, "req_link: cpf_grant_direct failed", NO_NUM); - cpf_revoke(gid); + /* Fill in request message */ + m.m_type = REQ_LINK; + m.REQ_INODE_NR = linked_file; + m.REQ_DIR_INO = link_parent; + m.REQ_GRANT = grant_id; + m.REQ_PATH_LEN = len; - return r; + /* Send/rec request */ + r = fs_sendrec(fs_e, &m); + cpf_revoke(grant_id); + + return(r); } /*===========================================================================* * req_lookup * *===========================================================================*/ -PUBLIC int req_lookup(fs_e, path_off, dir_ino, root_ino, uid, gid, flags, res) +PUBLIC int req_lookup(fs_e, dir_ino, root_ino, uid, gid, flags, res) endpoint_t fs_e; -size_t path_off; ino_t dir_ino; ino_t root_ino; uid_t uid; @@ -376,68 +354,89 @@ gid_t gid; int flags; lookup_res_t *res; { - int r; - size_t len; - cp_grant_id_t grant_id; - message m; + int r; + size_t len; + cp_grant_id_t grant_id, grant_id2; + message m; + vfs_ucred_t credentials; + + grant_id = cpf_grant_direct(fs_e, (vir_bytes) user_fullpath, + sizeof(user_fullpath), CPF_READ | CPF_WRITE); + if(grant_id == -1) + panic(__FILE__, "req_lookup: cpf_grant_direct failed", NO_NUM); + + len = strlen(user_fullpath) + 1; + + m.m_type = REQ_LOOKUP; + m.REQ_GRANT = grant_id; + m.REQ_PATH_LEN = len; + m.REQ_PATH_SIZE = sizeof(user_fullpath); + m.REQ_DIR_INO = dir_ino; + m.REQ_ROOT_INO = root_ino; + + if(fp->fp_ngroups > 0) { /* Is the process member of multiple groups? */ + /* In that case the FS has to copy the uid/gid credentials */ + int i; + + /* Set credentials */ + credentials.vu_uid = fp->fp_effuid; + credentials.vu_gid = fp->fp_effgid; + credentials.vu_ngroups = fp->fp_ngroups; + for (i = 0; i < fp->fp_ngroups; i++) + credentials.vu_sgroups[i] = fp->fp_sgroups[i]; + + grant_id2 = cpf_grant_direct(fs_e, (vir_bytes) &credentials, + sizeof(credentials), CPF_READ); + if(grant_id2 == -1) + panic(__FILE__, "req_lookup: cpf_grant_direct failed", NO_NUM); + + m.REQ_GRANT2 = grant_id2; + m.REQ_UCRED_SIZE= sizeof(credentials); + flags |= PATH_GET_UCRED; + } else { + /* When there's only one gid, we can send it directly */ + m.REQ_UID = uid; + m.REQ_GID = gid; + flags &= ~PATH_GET_UCRED; + } -#if 0 - printf("req_lookup_s: fs %d, ino %d, root %d, string (off %d) '%s'\n", - fs_e, dir_ino, root_ino, path_off, user_fullpath+path_off); -#endif + m.REQ_FLAGS = flags; - grant_id= cpf_grant_direct(fs_e, (vir_bytes)user_fullpath, - sizeof(user_fullpath), CPF_READ|CPF_WRITE); - if (grant_id == -1) - panic(__FILE__, "req_lookup_s: cpf_grant_direct failed", NO_NUM); - len= strlen(user_fullpath+path_off) + 1; - - /* Fill in request message */ - m.m_type = REQ_LOOKUP_S; - m.REQ_L_GRANT = grant_id; - m.REQ_L_PATH_LEN = len; - m.REQ_L_PATH_SIZE = sizeof(user_fullpath); - m.REQ_L_PATH_OFF = path_off; - m.REQ_L_DIR_INO = dir_ino; - m.REQ_L_ROOT_INO = root_ino; - m.REQ_L_FLAGS = flags; - m.REQ_L_UID = uid; - m.REQ_L_GID = gid; - - /* Send/rec request */ - r = fs_sendrec(fs_e, &m); - - cpf_revoke(grant_id); - - /* Fill in response according to the return value */ - res->fs_e = m.m_source; - switch (r) { - case OK: - res->inode_nr = m.RES_INODE_NR; - res->fmode = m.RES_MODE; - res->fsize = m.RES_FILE_SIZE; - res->dev = m.RES_DEV; - res->uid= m.RES_UID; - res->gid= m.RES_GID; - break; - case EENTERMOUNT: - res->inode_nr = m.RES_INODE_NR; - res->char_processed = m.RES_OFFSET; - res->symloop = m.RES_SYMLOOP2; - break; - case ELEAVEMOUNT: - res->char_processed = m.RES_OFFSET; - res->symloop = m.RES_SYMLOOP2; - break; - case ESYMLINK: - res->char_processed = m.RES_OFFSET; - res->symloop = m.RES_SYMLOOP2; - break; - default: - break; - } - - return r; + /* Send/rec request */ + r = fs_sendrec(fs_e, &m); + cpf_revoke(grant_id); + if(fp->fp_ngroups > 0) cpf_revoke(grant_id2); + + /* Fill in response according to the return value */ + res->fs_e = m.m_source; + + switch (r) { + case OK: + res->inode_nr = m.RES_INODE_NR; + res->fmode = m.RES_MODE; + res->fsize = m.RES_FILE_SIZE_LO; + res->dev = m.RES_DEV; + res->uid= m.RES_UID; + res->gid= m.RES_GID; + break; + case EENTERMOUNT: + res->inode_nr = m.RES_INODE_NR; + res->char_processed = m.RES_OFFSET; + res->symloop = m.RES_SYMLOOP; + break; + case ELEAVEMOUNT: + res->char_processed = m.RES_OFFSET; + res->symloop = m.RES_SYMLOOP; + break; + case ESYMLINK: + res->char_processed = m.RES_OFFSET; + res->symloop = m.RES_SYMLOOP; + break; + default: + break; + } + + return(r); } @@ -452,31 +451,30 @@ uid_t uid; gid_t gid; mode_t dmode; { - int r; - cp_grant_id_t grant_id; - size_t len; - message m; - - len= strlen(lastc) + 1; - grant_id= cpf_grant_direct(fs_e, (vir_bytes)lastc, len, CPF_READ); - if (grant_id == -1) - panic(__FILE__, "req_mkdir: cpf_grant_direct failed", NO_NUM); - - /* Fill in request message */ - m.m_type = REQ_MKDIR_S; - m.REQ_INODE_NR = inode_nr; - m.REQ_MODE = dmode; - m.REQ_UID = uid; - m.REQ_GID = gid; - m.REQ_GRANT = grant_id; - m.REQ_PATH_LEN = len; - - /* Send/rec request */ - r = fs_sendrec(fs_e, &m); - - cpf_revoke(grant_id); - - return r; + int r; + cp_grant_id_t grant_id; + size_t len; + message m; + + len = strlen(lastc) + 1; + grant_id = cpf_grant_direct(fs_e, (vir_bytes)lastc, len, CPF_READ); + if(grant_id == -1) + panic(__FILE__, "req_mkdir: cpf_grant_direct failed", NO_NUM); + + /* Fill in request message */ + m.m_type = REQ_MKDIR; + m.REQ_INODE_NR = inode_nr; + m.REQ_MODE = dmode; + m.REQ_UID = uid; + m.REQ_GID = gid; + m.REQ_GRANT = grant_id; + m.REQ_PATH_LEN = len; + + /* Send/rec request */ + r = fs_sendrec(fs_e, &m); + cpf_revoke(grant_id); + + return(r); } @@ -492,32 +490,31 @@ gid_t gid; mode_t dmode; dev_t dev; { - int r; - size_t len; - cp_grant_id_t grant_id; - message m; - - len= strlen(lastc) + 1; - grant_id= cpf_grant_direct(fs_e, (vir_bytes)lastc, len, CPF_READ); - if (grant_id == -1) - panic(__FILE__, "req_mknod: cpf_grant_direct failed", NO_NUM); - - /* Fill in request message */ - m.m_type = REQ_MKNOD_S; - m.REQ_INODE_NR = inode_nr; - m.REQ_MODE = dmode; - m.REQ_DEVx = dev; - m.REQ_UID = uid; - m.REQ_GID = gid; - m.REQ_GRANT = grant_id; - m.REQ_PATH_LEN = len; - - /* Send/rec request */ - r = fs_sendrec(fs_e, &m); - - cpf_revoke(grant_id); - - return r; + int r; + size_t len; + cp_grant_id_t grant_id; + message m; + + len = strlen(lastc) + 1; + grant_id = cpf_grant_direct(fs_e, (vir_bytes)lastc, len, CPF_READ); + if(grant_id == -1) + panic(__FILE__, "req_mknod: cpf_grant_direct failed", NO_NUM); + + /* Fill in request message */ + m.m_type = REQ_MKNOD; + m.REQ_INODE_NR = inode_nr; + m.REQ_MODE = dmode; + m.REQ_DEV = dev; + m.REQ_UID = uid; + m.REQ_GID = gid; + m.REQ_GRANT = grant_id; + m.REQ_PATH_LEN = len; + + /* Send/rec request */ + r = fs_sendrec(fs_e, &m); + cpf_revoke(grant_id); + + return(r); } @@ -528,15 +525,15 @@ PUBLIC int req_mountpoint(fs_e, inode_nr) endpoint_t fs_e; ino_t inode_nr; { - int r; - message m; + int r; + message m; - /* Fill in request message */ - m.m_type = REQ_MOUNTPOINT_S; - m.REQ_INODE_NR = inode_nr; + /* Fill in request message */ + m.m_type = REQ_MOUNTPOINT; + m.REQ_INODE_NR = inode_nr; - /* Send/rec request */ - return fs_sendrec(fs_e, &m); + /* Send/rec request */ + return fs_sendrec(fs_e, &m); } @@ -551,28 +548,28 @@ mode_t dmode; dev_t dev; struct node_details *res; { - int r; - message m; - - /* Fill in request message */ - m.m_type = REQ_NEWNODE; - m.REQ_MODE = dmode; - m.REQ_DEVx = dev; - m.REQ_UID = uid; - m.REQ_GID = gid; - - /* Send/rec request */ - r = fs_sendrec(fs_e, &m); - - res->fs_e = m.m_source; - res->inode_nr = m.RES_INODE_NR; - res->fmode = m.RES_MODE; - res->fsize = m.RES_FILE_SIZE; - res->dev = m.RES_DEV; - res->uid= m.RES_UID; - res->gid= m.RES_GID; - - return r; + int r; + message m; + + /* Fill in request message */ + m.m_type = REQ_NEWNODE; + m.REQ_MODE = dmode; + m.REQ_DEV = dev; + m.REQ_UID = uid; + m.REQ_GID = gid; + + /* Send/rec request */ + r = fs_sendrec(fs_e, &m); + + res->fs_e = m.m_source; + res->inode_nr = m.RES_INODE_NR; + res->fmode = m.RES_MODE; + res->fsize = m.RES_FILE_SIZE_LO; + res->dev = m.RES_DEV; + res->uid = m.RES_UID; + res->gid = m.RES_GID; + + return(r); } @@ -589,22 +586,23 @@ endpoint_t driver_e; * driver recovery mechanism here. This function is actually called * during the recovery. */ - message m; - int r; - - /* Fill in request message */ - m.m_type = REQ_NEW_DRIVER; - m.REQ_DEV = dev; - m.REQ_DRIVER_E = driver_e; - - /* Issue request */ - if ((r = sendrec(fs_e, &m)) != OK) { - printf("VFSreq_newdriver: error sending message to %d: %d\n", fs_e, r); - util_stacktrace(); - return r; - } - - return OK; + message m; + int r; + + /* Fill in request message */ + m.m_type = REQ_NEW_DRIVER; + m.REQ_DEV = dev; + m.REQ_DRIVER_E = driver_e; + + /* Issue request */ + if((r = sendrec(fs_e, &m)) != OK) { + printf("%s:%d VFS req_newdriver: error sending message %d to %d\n", + __FILE__, __LINE__, r, fs_e); + util_stacktrace(); + return(r); + } + + return(OK); } @@ -617,15 +615,15 @@ int fs_e; ino_t inode_nr; int count; { - message m; + message m; - /* Fill in request message */ - m.m_type = REQ_PUTNODE; - m.REQ_INODE_NR = inode_nr; - m.REQ_COUNT = count; + /* Fill in request message */ + m.m_type = REQ_PUTNODE; + m.REQ_INODE_NR = inode_nr; + m.REQ_COUNT = count; - /* Send/rec request */ - return fs_sendrec(fs_e, &m); + /* Send/rec request */ + return fs_sendrec(fs_e, &m); } @@ -636,46 +634,30 @@ PUBLIC int req_rdlink(fs_e, inode_nr, who_e, buf, len) endpoint_t fs_e; ino_t inode_nr; endpoint_t who_e; -vir_bytes buf; +char *buf; size_t len; { - message m; - int r; - cp_grant_id_t gid; - - gid= cpf_grant_magic(fs_e, who_e, buf, len, CPF_WRITE); - if (gid == -1) - panic(__FILE__, "req_rdlink: cpf_grant_magic failed", NO_NUM); - - /* Fill in request message */ - m.m_type = REQ_RDLINK_S; - m.REQ_INODE_NR = inode_nr; - m.REQ_GRANT = gid; - m.REQ_SLENGTH = len; - - /* Send/rec request */ - r= fs_sendrec(fs_e, &m); - - if (r != ENOSYS && r != EINVAL) { - cpf_revoke(gid); - - if (r == OK) - r = m.RES_RDL_LENGTH; - - return r; - } + message m; + int r; + cp_grant_id_t grant_id; - /* Legacy support: try the old rdlink */ - m.m_type = REQ_RDLINK_SO; - m.REQ_INODE_NR = inode_nr; - m.REQ_GRANT = gid; - m.REQ_SLENGTH = len; + grant_id = cpf_grant_magic(fs_e, who_e, (vir_bytes) buf, len, CPF_WRITE); + if(grant_id == -1) + panic(__FILE__, "req_rdlink: cpf_grant_magic failed", NO_NUM); - r= fs_sendrec(fs_e, &m); + /* Fill in request message */ + m.m_type = REQ_RDLINK; + m.REQ_INODE_NR = inode_nr; + m.REQ_GRANT = grant_id; + m.REQ_MEM_SIZE = len; + + /* Send/rec request */ + r = fs_sendrec(fs_e, &m); + cpf_revoke(grant_id); - cpf_revoke(gid); + if(r == OK) r = m.RES_NBYTES; - return r; + return(r); } @@ -690,51 +672,50 @@ int readonly; int isroot; struct node_details *res_nodep; { - int r; - cp_grant_id_t gid; - size_t len; - message m; - - len= strlen(label)+1; - gid= cpf_grant_direct(fs_e, (vir_bytes)label, len, CPF_READ); - if (gid == -1) - panic(__FILE__, "req_req_readsuper: cpf_grant_direct failed", NO_NUM); - - /* Fill in request message */ - m.m_type = REQ_READSUPER_S; - m.REQ_READONLY = readonly; - m.REQ_GRANT2 = gid; - m.REQ_DEV = dev; - m.REQ_ISROOT = isroot; - m.REQ_PATH_LEN = len; - - /* Send/rec request */ - r = fs_sendrec(fs_e, &m); - - cpf_revoke(gid); - - if(r != OK) return r; - - /* Fill in response structure */ - res_nodep->fs_e = m.m_source; - res_nodep->inode_nr = m.RES_INODE_NR; - res_nodep->fmode = m.RES_MODE; - res_nodep->fsize = m.RES_FILE_SIZE; - res_nodep->uid = m.RES_UID; - res_nodep->gid = m.RES_GID; - - return OK; + int r; + cp_grant_id_t grant_id; + size_t len; + message m; + + len = strlen(label)+1; + grant_id = cpf_grant_direct(fs_e, (vir_bytes) label, len, CPF_READ); + if (grant_id == -1) + panic(__FILE__, "req_readsuper: cpf_grant_direct failed", NO_NUM); + + /* Fill in request message */ + m.m_type = REQ_READSUPER; + m.REQ_FLAGS = 0; + if(readonly) m.REQ_FLAGS |= REQ_RDONLY; + if(isroot) m.REQ_FLAGS |= REQ_ISROOT; + m.REQ_GRANT = grant_id; + m.REQ_DEV = dev; + m.REQ_PATH_LEN = len; + + /* Send/rec request */ + r = fs_sendrec(fs_e, &m); + cpf_revoke(grant_id); + + if(r == OK) { + /* Fill in response structure */ + res_nodep->fs_e = m.m_source; + res_nodep->inode_nr = m.RES_INODE_NR; + res_nodep->fmode = m.RES_MODE; + res_nodep->fsize = m.RES_FILE_SIZE_LO; + res_nodep->uid = m.RES_UID; + res_nodep->gid = m.RES_GID; + } + + return(r); } /*===========================================================================* * req_readwrite * *===========================================================================*/ -PUBLIC int req_readwrite(fs_e, inode_nr, inode_index, pos, rw_flag, user_e, +PUBLIC int req_readwrite(fs_e, inode_nr, pos, rw_flag, user_e, user_addr, num_of_bytes, new_posp, cum_iop) endpoint_t fs_e; ino_t inode_nr; -unsigned short inode_index; u64_t pos; int rw_flag; endpoint_t user_e; @@ -743,38 +724,37 @@ unsigned int num_of_bytes; u64_t *new_posp; unsigned int *cum_iop; { - int r; - cp_grant_id_t gid; - message m; - - if (ex64hi(pos) != 0) - panic(__FILE__, "req_readwrite: pos too large", NO_NUM); - - gid= cpf_grant_magic(fs_e, user_e, (vir_bytes)user_addr, - num_of_bytes, (rw_flag == READING ? CPF_WRITE : CPF_READ)); - if (gid == -1) - panic(__FILE__, "req_readwrite: cpf_grant_magic failed", NO_NUM); - - /* Fill in request message */ - m.m_type = rw_flag == READING ? REQ_READ_S : REQ_WRITE_S; - m.REQ_FD_INODE_NR = inode_nr; - m.REQ_FD_GID = gid; - m.REQ_FD_POS = ex64lo(pos); - m.REQ_FD_NBYTES = num_of_bytes; - m.REQ_FD_INODE_INDEX = inode_index; - - /* Send/rec request */ - r = fs_sendrec(fs_e, &m); + int r; + cp_grant_id_t grant_id; + message m; - cpf_revoke(gid); + if (ex64hi(pos) != 0) + panic(__FILE__, "req_readwrite: pos too large", NO_NUM); - if (r != OK) return r; + grant_id = cpf_grant_magic(fs_e, user_e, (vir_bytes) user_addr, num_of_bytes, + (rw_flag==READING ? CPF_WRITE:CPF_READ)); + if (grant_id == -1) + panic(__FILE__, "req_readwrite: cpf_grant_magic failed", NO_NUM); - /* Fill in response structure */ - *new_posp = cvul64(m.RES_FD_POS); - *cum_iop = m.RES_FD_CUM_IO; + /* Fill in request message */ + m.m_type = rw_flag == READING ? REQ_READ : REQ_WRITE; + m.REQ_INODE_NR = inode_nr; + m.REQ_GRANT = grant_id; + m.REQ_SEEK_POS_LO = ex64lo(pos); + m.REQ_SEEK_POS_HI = 0; /* Not used for now, so clear it. */ + m.REQ_NBYTES = num_of_bytes; + + /* Send/rec request */ + r = fs_sendrec(fs_e, &m); + cpf_revoke(grant_id); - return OK; + if (r == OK) { + /* Fill in response structure */ + *new_posp = cvul64(m.RES_SEEK_POS_LO); + *cum_iop = m.RES_NBYTES; + } + + return(r); } @@ -788,38 +768,36 @@ char *old_name; ino_t new_dir; char *new_name; { - int r; - cp_grant_id_t gid_old, gid_new; - size_t len_old, len_new; - message m; - - len_old= strlen(old_name) + 1; - gid_old= cpf_grant_direct(fs_e, (vir_bytes)old_name, len_old, - CPF_READ); - if (gid_old == -1) - panic(__FILE__, "req_rename: cpf_grant_direct failed", NO_NUM); - len_new= strlen(new_name) + 1; - gid_new= cpf_grant_direct(fs_e, (vir_bytes)new_name, len_new, - CPF_READ); - if (gid_new == -1) - panic(__FILE__, "req_rename: cpf_grant_direct failed", NO_NUM); - - /* Fill in request message */ - m.m_type = REQ_RENAME_S; - m.REQ_REN_OLD_DIR = old_dir; - m.REQ_REN_NEW_DIR = new_dir; - m.REQ_REN_GRANT_OLD = gid_old; - m.REQ_REN_LEN_OLD = len_old; - m.REQ_REN_GRANT_NEW = gid_new; - m.REQ_REN_LEN_NEW = len_new; - - /* Send/rec request */ - r = fs_sendrec(fs_e, &m); - - cpf_revoke(gid_old); - cpf_revoke(gid_new); - - return r; + int r; + cp_grant_id_t gid_old, gid_new; + size_t len_old, len_new; + message m; + + len_old = strlen(old_name) + 1; + gid_old = cpf_grant_direct(fs_e, (vir_bytes) old_name, len_old, CPF_READ); + if(gid_old == -1) + panic(__FILE__, "req_rename: cpf_grant_direct failed", NO_NUM); + + len_new = strlen(new_name) + 1; + gid_new = cpf_grant_direct(fs_e, (vir_bytes) new_name, len_new, CPF_READ); + if(gid_new == -1) + panic(__FILE__, "req_rename: cpf_grant_direct failed", NO_NUM); + + /* Fill in request message */ + m.m_type = REQ_RENAME; + m.REQ_REN_OLD_DIR = old_dir; + m.REQ_REN_NEW_DIR = new_dir; + m.REQ_REN_GRANT_OLD = gid_old; + m.REQ_REN_LEN_OLD = len_old; + m.REQ_REN_GRANT_NEW = gid_new; + m.REQ_REN_LEN_NEW = len_new; + + /* Send/rec request */ + r = fs_sendrec(fs_e, &m); + cpf_revoke(gid_old); + cpf_revoke(gid_new); + + return(r); } @@ -831,28 +809,27 @@ endpoint_t fs_e; ino_t inode_nr; char *lastc; { - int r; - cp_grant_id_t gid; - size_t len; - message m; - - len= strlen(lastc) + 1; - gid= cpf_grant_direct(fs_e, (vir_bytes)lastc, len, CPF_READ); - if (gid == -1) - panic(__FILE__, "req_rmdir: cpf_grant_direct failed", NO_NUM); - - /* Fill in request message */ - m.m_type = REQ_RMDIR_S; - m.REQ_INODE_NR = inode_nr; - m.REQ_GRANT = gid; - m.REQ_PATH_LEN = len; + int r; + cp_grant_id_t grant_id; + size_t len; + message m; + + len = strlen(lastc) + 1; + grant_id = cpf_grant_direct(fs_e, (vir_bytes) lastc, len, CPF_READ); + if(grant_id == -1) + panic(__FILE__, "req_rmdir: cpf_grant_direct failed", NO_NUM); - /* Send/rec request */ - r = fs_sendrec(fs_e, &m); + /* Fill in request message */ + m.m_type = REQ_RMDIR; + m.REQ_INODE_NR = inode_nr; + m.REQ_GRANT = grant_id; + m.REQ_PATH_LEN = len; - cpf_revoke(gid); + /* Send/rec request */ + r = fs_sendrec(fs_e, &m); + cpf_revoke(grant_id); - return r; + return(r); } @@ -860,7 +837,7 @@ char *lastc; * req_slink * *===========================================================================*/ PUBLIC int req_slink(fs_e, inode_nr, lastc, who_e, path_addr, path_length, - uid, gid) + uid, gid) endpoint_t fs_e; ino_t inode_nr; char *lastc; @@ -870,42 +847,39 @@ unsigned short path_length; uid_t uid; gid_t gid; { - int r; - size_t len; - cp_grant_id_t gid_name, gid_buf; - message m; - - len= strlen(lastc) + 1; - gid_name= cpf_grant_direct(fs_e, (vir_bytes)lastc, len, - CPF_READ); - if (gid_name == -1) - panic(__FILE__, "req_slink: cpf_grant_direct failed", NO_NUM); - - gid_buf= cpf_grant_magic(fs_e, who_e, (vir_bytes)path_addr, - path_length, CPF_READ); - if (gid_buf == -1) - { - cpf_revoke(gid_name); - panic(__FILE__, "req_slink: cpf_grant_magic failed", NO_NUM); - } - - /* Fill in request message */ - m.m_type = REQ_SLINK_S; - m.REQ_INODE_NR = inode_nr; - m.REQ_UID = uid; - m.REQ_GID = gid; - m.REQ_GRANT = gid_name; - m.REQ_PATH_LEN = len; - m.REQ_GRANT2 = gid_buf; - m.REQ_SLENGTH = path_length; - - /* Send/rec request */ - r = fs_sendrec(fs_e, &m); - - cpf_revoke(gid_name); - cpf_revoke(gid_buf); - - return r; + int r; + size_t len; + cp_grant_id_t gid_name, gid_buf; + message m; + + len = strlen(lastc) + 1; + gid_name = cpf_grant_direct(fs_e, (vir_bytes) lastc, len, CPF_READ); + if(gid_name == -1) + panic(__FILE__, "req_slink: cpf_grant_direct failed", NO_NUM); + + gid_buf = cpf_grant_magic(fs_e, who_e, (vir_bytes) path_addr, path_length, + CPF_READ); + if(gid_buf == -1) { + cpf_revoke(gid_name); + panic(__FILE__, "req_slink: cpf_grant_magic failed", NO_NUM); + } + + /* Fill in request message */ + m.m_type = REQ_SLINK; + m.REQ_INODE_NR = inode_nr; + m.REQ_UID = uid; + m.REQ_GID = gid; + m.REQ_GRANT = gid_name; + m.REQ_PATH_LEN = len; + m.REQ_GRANT3 = gid_buf; + m.REQ_MEM_SIZE = path_length; + + /* Send/rec request */ + r = fs_sendrec(fs_e, &m); + cpf_revoke(gid_name); + cpf_revoke(gid_buf); + + return(r); } @@ -919,42 +893,37 @@ int who_e; char *buf; int pos; { - cp_grant_id_t gid; + cp_grant_id_t grant_id; int r; message m; struct stat sb; if (pos != 0) - { - gid= cpf_grant_direct(fs_e, (vir_bytes)&sb, sizeof(struct stat), - CPF_WRITE); - } + grant_id = cpf_grant_direct(fs_e, (vir_bytes) &sb, + sizeof(struct stat), CPF_WRITE); else - { - gid= cpf_grant_magic(fs_e, who_e, (vir_bytes)buf, sizeof(struct stat), - CPF_WRITE); - } - if (gid < 0) + grant_id = cpf_grant_magic(fs_e, who_e, (vir_bytes) buf, + sizeof(struct stat), CPF_WRITE); + + if (grant_id < 0) panic(__FILE__, "req_stat: cpf_grant_* failed", NO_NUM); /* Fill in request message */ m.m_type = REQ_STAT; m.REQ_INODE_NR = inode_nr; - m.REQ_GRANT = gid; + m.REQ_GRANT = grant_id; /* Send/rec request */ - r= fs_sendrec(fs_e, &m); - - cpf_revoke(gid); + r = fs_sendrec(fs_e, &m); + cpf_revoke(grant_id); - if (r == OK && pos != 0) - { - sb.st_size -= pos; - r= sys_vircopy(SELF, D, (vir_bytes)&sb, who_e, D, (vir_bytes)buf, - sizeof(struct stat)); + if (r == OK && pos != 0) { + sb.st_size -= pos; + r = sys_vircopy(SELF, D, (vir_bytes) &sb, who_e, D, (vir_bytes) buf, + sizeof(struct stat)); } - - return r; + + return(r); } @@ -964,13 +933,13 @@ int pos; PUBLIC int req_sync(fs_e) endpoint_t fs_e; { - message m; + message m; - /* Fill in request message */ - m.m_type = REQ_SYNC; - - /* Send/rec request */ - return fs_sendrec(fs_e, &m); + /* Fill in request message */ + m.m_type = REQ_SYNC; + + /* Send/rec request */ + return fs_sendrec(fs_e, &m); } @@ -982,28 +951,27 @@ endpoint_t fs_e; ino_t inode_nr; char *lastc; { - cp_grant_id_t gid; - size_t len; - int r; - message m; - - len= strlen(lastc) + 1; - gid= cpf_grant_direct(fs_e, (vir_bytes)lastc, len, CPF_READ); - if (gid == -1) - panic(__FILE__, "req_unlink: cpf_grant_direct failed", NO_NUM); - - /* Fill in request message */ - m.m_type = REQ_UNLINK_S; - m.REQ_INODE_NR = inode_nr; - m.REQ_GRANT = gid; - m.REQ_PATH_LEN = len; - - /* Send/rec request */ - r = fs_sendrec(fs_e, &m); + cp_grant_id_t grant_id; + size_t len; + int r; + message m; + + len = strlen(lastc) + 1; + grant_id = cpf_grant_direct(fs_e, (vir_bytes) lastc, len, CPF_READ); + if(grant_id == -1) + panic(__FILE__, "req_unlink: cpf_grant_direct failed", NO_NUM); - cpf_revoke(gid); + /* Fill in request message */ + m.m_type = REQ_UNLINK; + m.REQ_INODE_NR = inode_nr; + m.REQ_GRANT = grant_id; + m.REQ_PATH_LEN = len; - return r; + /* Send/rec request */ + r = fs_sendrec(fs_e, &m); + cpf_revoke(grant_id); + + return(r); } @@ -1013,13 +981,13 @@ char *lastc; PUBLIC int req_unmount(fs_e) endpoint_t fs_e; { - message m; + message m; - /* Fill in request message */ - m.m_type = REQ_UNMOUNT; + /* Fill in request message */ + m.m_type = REQ_UNMOUNT; - /* Send/rec request */ - return fs_sendrec(fs_e, &m); + /* Send/rec request */ + return fs_sendrec(fs_e, &m); } @@ -1032,21 +1000,19 @@ ino_t inode_nr; time_t actime; time_t modtime; { - message m; - - /* Fill in request message */ - m.m_type = REQ_UTIME; - m.REQ_INODE_NR = inode_nr; - m.REQ_ACTIME = actime; - m.REQ_MODTIME = modtime; + message m; - /* Send/rec request */ - return fs_sendrec(fs_e, &m); + /* Fill in request message */ + m.m_type = REQ_UTIME; + m.REQ_INODE_NR = inode_nr; + m.REQ_ACTIME = actime; + m.REQ_MODTIME = modtime; + + /* Send/rec request */ + return fs_sendrec(fs_e, &m); } - - /*===========================================================================* * fs_sendrec * *===========================================================================*/ @@ -1078,34 +1044,30 @@ PRIVATE int fs_sendrec_f(char *file, int line, endpoint_t fs_e, message *reqm) * VFS will solve this problem for good. */ for (;;) { - /* Do the actual send, receive */ - if (OK != (r=sendrec(fs_e, reqm))) { - printf("VFS:fs_sendrec:%s:%d: error sending message. FS_e: %d req_nr: %d err: %d\n", - file, line, fs_e, reqm->m_type, r); - util_stacktrace(); - return r; - } - - /* If the type field is 0 (OK) or negative (E*), this is a reply. If it - * contains a positive nonzero value, this is a request. - */ - if (reqm->m_type <= 0) - break; /* Reply */ - - /* Legacy support: hacks for old nonzero nonnegative replies */ - if (origm.m_type == REQ_GETDENTS_O || origm.m_type == REQ_RDLINK_SO) - break; /* Reply */ + /* Do the actual send, receive */ + if (OK != (r = sendrec(fs_e, reqm))) { + printf("VFS:fs_sendrec:%s:%d: error sending message. " + "FS_e: %d req_nr: %d err: %d\n", file, line, fs_e, + reqm->m_type, r); + util_stacktrace(); + return(r); + } - if (reqm->m_type == -EENTERMOUNT || reqm->m_type == -ELEAVEMOUNT || - reqm->m_type == -ESYMLINK) { + /* If the type field is 0 (OK) or negative (E*), this is a reply. If it + * contains a positive nonzero value, this is a request. + */ + if (reqm->m_type <= 0) + break; /* Reply */ - reqm->m_type = -reqm->m_type; + if (reqm->m_type == -EENTERMOUNT || reqm->m_type == -ELEAVEMOUNT || + reqm->m_type == -ESYMLINK) { - break; /* Reply */ - } + reqm->m_type = -reqm->m_type; + break; /* Reply */ + } - /* Request */ - nested_fs_call(reqm); + /* Request */ + nested_fs_call(reqm); } #if 0 @@ -1174,7 +1136,6 @@ PRIVATE int fs_sendrec_f(char *file, int line, endpoint_t fs_e, message *reqm) #endif /* Return message type */ - return reqm->m_type; + return(reqm->m_type); } - diff --git a/servers/vfs/select.c b/servers/vfs/select.c index 193c2f350..5472b03b1 100644 --- a/servers/vfs/select.c +++ b/servers/vfs/select.c @@ -5,9 +5,6 @@ * select_callback: notify select system of possible fd operation * select_notified: low-level entry for device notifying select * select_unsuspend_by_endpt: cancel a blocking select on exiting driver - * - * Changes: - * 6 june 2005 Created (Ben Gras) */ #define DEBUG_SELECT 0 @@ -25,48 +22,46 @@ /* max. number of simultaneously pending select() calls */ #define MAXSELECTS 25 +#define FROM_PROC 0 +#define TO_PROC 1 PRIVATE struct selectentry { - struct fproc *requestor; /* slot is free iff this is NULL */ - int req_endpt; - fd_set readfds, writefds, errorfds; - fd_set ready_readfds, ready_writefds, ready_errorfds; - fd_set *vir_readfds, *vir_writefds, *vir_errorfds; - struct filp *filps[OPEN_MAX]; - int type[OPEN_MAX]; - int deferred; /* awaiting initial reply from driver */ - int deferred_fd; /* fd awaiting initial reply from driver */ - int nfds, nreadyfds; - int dontblock; - clock_t expiry; - timer_t timer; /* if expiry > 0 */ + struct fproc *requestor; /* slot is free iff this is NULL */ + int req_endpt; + fd_set readfds, writefds, errorfds; + fd_set ready_readfds, ready_writefds, ready_errorfds; + fd_set *vir_readfds, *vir_writefds, *vir_errorfds; + struct filp *filps[OPEN_MAX]; + int type[OPEN_MAX]; + int deferred; /* awaiting initial reply from driver */ + int deferred_fd; /* fd awaiting initial reply from driver */ + int nfds, nreadyfds; + char block; + clock_t expiry; + timer_t timer; /* if expiry > 0 */ } selecttab[MAXSELECTS]; -FORWARD _PROTOTYPE(int select_reevaluate, (struct filp *fp)); - -FORWARD _PROTOTYPE(int select_request_file, - (struct filp *f, int *ops, int block)); -FORWARD _PROTOTYPE(int select_match_file, (struct filp *f)); - -FORWARD _PROTOTYPE(int select_request_general, - (struct filp *f, int *ops, int block)); -FORWARD _PROTOTYPE(int select_request_asynch, - (struct filp *f, int *ops, int block)); -FORWARD _PROTOTYPE(int select_major_match, - (int match_major, struct filp *file)); - -FORWARD _PROTOTYPE(void select_cancel_all, (struct selectentry *e)); -FORWARD _PROTOTYPE(void select_wakeup, (struct selectentry *e, int r)); -FORWARD _PROTOTYPE(void select_return, (struct selectentry *, int)); -FORWARD _PROTOTYPE(void sel_restart_dev, (void)); -FORWARD _PROTOTYPE(void filp_status, (struct filp *fp, int status)); -FORWARD _PROTOTYPE(void restart_proc, (int slot)); - -/* The Open Group: - * "The pselect() and select() functions shall support - * regular files, terminal and pseudo-terminal devices, - * STREAMS-based files, FIFOs, pipes, and sockets." - */ +FORWARD _PROTOTYPE(int copy_fdsets, (struct selectentry *se, int nfds, + int direction) ); +FORWARD _PROTOTYPE(void filp_status, (struct filp *fp, int status) ); +FORWARD _PROTOTYPE(void restart_proc, (int slot) ); +FORWARD _PROTOTYPE(void ops2tab, (int ops, int fd, struct selectentry *e)); +FORWARD _PROTOTYPE(int select_reevaluate, (struct filp *fp) ); +FORWARD _PROTOTYPE(int select_request_file, (struct filp *f, int *ops, + int block) ); +FORWARD _PROTOTYPE(int select_match_file, (struct filp *f) ); +FORWARD _PROTOTYPE(int select_request_general, (struct filp *f, int *ops, + int block) ); +FORWARD _PROTOTYPE(int select_request_asynch, (struct filp *f, int *ops, + int block) ); +FORWARD _PROTOTYPE(int select_major_match, (int match_major, + struct filp *file) ); +FORWARD _PROTOTYPE(void select_cancel_all, (struct selectentry *e) ); +FORWARD _PROTOTYPE(void select_wakeup, (struct selectentry *e, int r) ); +FORWARD _PROTOTYPE(void select_return, (struct selectentry *, int) ); +FORWARD _PROTOTYPE(void sel_restart_dev, (void) ); +FORWARD _PROTOTYPE(int tab2ops, (int fd, struct selectentry *e) ); +FORWARD _PROTOTYPE(void wipe_select, (struct selectentry *s) ); PRIVATE struct fdtype { int (*select_request)(struct filp *, int *ops, int block); @@ -81,415 +76,355 @@ PRIVATE struct fdtype { }; #define SEL_FDS (sizeof(fdtypes) / sizeof(fdtypes[0])) -/* Open Group: - * "File descriptors associated with regular files shall always select true - * for ready to read, ready to write, and error conditions." - */ +/*===========================================================================* + * do_select * + *===========================================================================*/ +PUBLIC int do_select(void) +{ +/* Implement the select(nfds, readfds, writefds, errorfds, timeout) system + * call. First we copy the arguments and verify their sanity. Then we check + * whether there are file descriptors that satisfy the select call right of the + * bat. If so, or if there are no ready file descriptors but the process + * requested to return immediately, we return the result. Otherwise we set a + * timeout and wait for either the file descriptors to become ready or the + * timer to go off. If no timeout value was provided, we wait indefinitely. */ + + int r, nfds, do_timeout = 0, nonzero_timeout = 0, fd, s, fd_setsize; + struct timeval timeout; + struct selectentry *se; + + nfds = m_in.SEL_NFDS; + + /* Sane amount of file descriptors? */ + if (nfds < 0 || nfds > OPEN_MAX) return(EINVAL); + fd_setsize = _FDSETWORDS(nfds) * _FDSETBITSPERWORD/8; + + /* Find a slot to store this select request */ + for (s = 0; s < MAXSELECTS; s++) + if (selecttab[s].requestor == NULL) /* Unused slot */ + break; + if (s >= MAXSELECTS) return(ENOSPC); + + se = &selecttab[s]; + wipe_select(se); /* Clear results of previous usage.*/ + se->req_endpt = who_e; + se->vir_readfds = (fd_set *) m_in.SEL_READFDS; + se->vir_writefds = (fd_set *) m_in.SEL_WRITEFDS; + se->vir_errorfds = (fd_set *) m_in.SEL_ERRORFDS; + + /* Copy fdsets from the process */ + if ((r = copy_fdsets(se, nfds, FROM_PROC)) != OK) return(r); + + /* Did the process set a timeout value? If so, retrieve it. */ + if (m_in.SEL_TIMEOUT != NULL) { + do_timeout = 1; + r = sys_vircopy(who_e, D, (vir_bytes) m_in.SEL_TIMEOUT, SELF, D, + (vir_bytes) &timeout, sizeof(timeout)); + if (r != OK) return(r); + } + + /* No nonsense in the timeval. */ + if(do_timeout && (timeout.tv_sec < 0 || timeout.tv_usec < 0)) return(EINVAL); + + /* If there is no timeout, we block forever. Otherwise, we block up to the + * specified time interval. + */ + if(!do_timeout) /* No timeout value set */ + se->block = 1; + else if (do_timeout && (timeout.tv_sec > 0 || timeout.tv_usec > 0)) + se->block = 1; + else /* timeout set as (0,0) - this effects a poll */ + se->block = 0; + se->expiry = 0; /* no timer set (yet) */ + + /* Check all file descriptors in the set whether one is 'ready' now. */ + for (fd = 0; fd < nfds; fd++) { + int ops, t, type = -1, r; + struct filp *filp; + + if (!(ops = tab2ops(fd, se))) + continue; /* No operations set; nothing to do for this fd */ + + /* Get filp belonging to this fd */ + filp = se->filps[fd] = get_filp(fd); + if (filp == NIL_FILP) { + if (err_code == EBADF) { + select_cancel_all(se); + return(EBADF); + } + + /* File descriptor is 'ready' to return EIO */ + printf("VFS do_select: EIO after driver failure\n"); + ops2tab(SEL_RD|SEL_WR|SEL_ERR, fd, se); + continue; + } + + /* Figure out what type of file we're dealing with */ + for(t = 0; t < SEL_FDS; t++) { + if (fdtypes[t].select_match) { + if (fdtypes[t].select_match(filp)) { + type = t; + } + } else if (select_major_match(fdtypes[t].select_major, filp)) { + type = t; + } + } + + if (type == -1) return(EBADF); + se->type[fd] = type; + + /* Test filp for select operations if not already done so. e.g., files + * sharing a filp and both doing a select on that filp. */ + if ((se->filps[fd]->filp_select_ops & ops) != ops) { + int wantops; + + wantops = (se->filps[fd]->filp_select_ops |= ops); + r = fdtypes[type].select_request(filp, &wantops, se->block); + if (r != SEL_OK) { + if (r == SEL_DEFERRED) { + se->deferred = TRUE; + se->deferred_fd = 0; + continue; + } + + /* Error or bogus return code; cancel select. */ + select_cancel_all(se); + return(EINVAL); + } + + /* The select request above might have turned on/off some + * operations because they were 'ready' or not meaningful. + * Either way, we might have a result and we need to store them + * in the select table entry. */ + if (wantops & ops) ops2tab(wantops, fd, se); + } + + se->nfds = fd+1; + se->filps[fd]->filp_selectors++; + } + + if (se->nreadyfds > 0 || (!se->block && !se->deferred)) { + /* fd's were found that were ready to go right away, and/or + * we were instructed not to block at all. Must return + * immediately. + */ + r = copy_fdsets(se, se->nfds, TO_PROC); + select_cancel_all(se); + se->requestor = NULL; + + if (r != OK) return(r); + else return(se->nreadyfds); + } + + /* Convert timeval to ticks and set the timer. If it fails, undo + * all, return error. + */ + if (do_timeout) { + int ticks; + /* Open Group: + * "If the requested timeout interval requires a finer + * granularity than the implementation supports, the + * actual timeout interval shall be rounded up to the next + * supported value." + */ +#define USECPERSEC 1000000 + while(timeout.tv_usec >= USECPERSEC) { + /* this is to avoid overflow with *system_hz below */ + timeout.tv_usec -= USECPERSEC; + timeout.tv_sec++; + } + ticks = timeout.tv_sec * system_hz + + (timeout.tv_usec * system_hz + USECPERSEC-1) / USECPERSEC; + se->expiry = ticks; + fs_set_timer(&se->timer, ticks, select_timeout_check, s); + } + + /* if we're blocking, the table entry is now valid. */ + se->requestor = fp; + + /* process now blocked */ + suspend(FP_BLOCKED_ON_SELECT); + return(SUSPEND); +} + /*===========================================================================* * select_request_file * *===========================================================================*/ PRIVATE int select_request_file(struct filp *f, int *ops, int block) { - /* output *ops is input *ops */ - return SEL_OK; + /* output *ops is input *ops */ + return(SEL_OK); } + /*===========================================================================* * select_match_file * *===========================================================================*/ PRIVATE int select_match_file(struct filp *file) { - if (file && file->filp_vno && (file->filp_vno->v_mode & I_REGULAR)) - return 1; - return 0; + return(file && file->filp_vno && (file->filp_vno->v_mode & I_REGULAR)); } + /*===========================================================================* * select_request_general * *===========================================================================*/ PRIVATE int select_request_general(struct filp *f, int *ops, int block) { - int rops = *ops; - if (block) rops |= SEL_NOTIFY; - *ops = dev_io(VFS_DEV_SELECT, f->filp_vno->v_sdev, rops, NULL, + int rops = *ops; + if (block) rops |= SEL_NOTIFY; + *ops = dev_io(VFS_DEV_SELECT, f->filp_vno->v_sdev, rops, NULL, cvu64(0), 0, 0, FALSE); - if (*ops < 0) - return SEL_ERR; - return SEL_OK; + if (*ops < 0) + return(SEL_ERR); + + return(SEL_OK); } + /*===========================================================================* * select_request_asynch * *===========================================================================*/ PRIVATE int select_request_asynch(struct filp *f, int *ops, int block) { - int r, rops; - struct dmap *dp; + int r, rops; + struct dmap *dp; - rops = *ops; - f->filp_select_flags |= FSF_UPDATE; - if (block) - { - rops |= SEL_NOTIFY; - f->filp_select_flags |= FSF_BLOCK; - } - if (f->filp_select_flags & FSF_BUSY) - return SEL_DEFERRED; + rops = *ops; + f->filp_select_flags |= FSF_UPDATE; + if (block) { + rops |= SEL_NOTIFY; + f->filp_select_flags |= FSF_BLOCK; + } - dp = &dmap[((f->filp_vno->v_sdev) >> MAJOR) & BYTE]; - if (dp->dmap_sel_filp) - return SEL_DEFERRED; + if (f->filp_select_flags & FSF_BUSY) + return(SEL_DEFERRED); - f->filp_select_flags &= ~FSF_UPDATE; - r = dev_io(VFS_DEV_SELECT, f->filp_vno->v_sdev, rops, NULL, - cvu64(0), 0, 0, FALSE); - if (r < 0 && r != SUSPEND) - return SEL_ERR; + dp = &dmap[((f->filp_vno->v_sdev) >> MAJOR) & BYTE]; + if (dp->dmap_sel_filp) + return(SEL_DEFERRED); - if (r != SUSPEND) - { - panic(__FILE__, "select_request_asynch: expected SUSPEND got", - r); - } - f->filp_count++; - dp->dmap_sel_filp= f; - f->filp_select_flags |= FSF_BUSY; - return SEL_DEFERRED; + f->filp_select_flags &= ~FSF_UPDATE; + r = dev_io(VFS_DEV_SELECT, f->filp_vno->v_sdev, rops, NULL, + cvu64(0), 0, 0, FALSE); + if (r < 0 && r != SUSPEND) + return(SEL_ERR); + + if (r != SUSPEND) + panic(__FILE__, "select_request_asynch: expected SUSPEND got", r); + + f->filp_count++; + dp->dmap_sel_filp = f; + f->filp_select_flags |= FSF_BUSY; + + return(SEL_DEFERRED); } + /*===========================================================================* * select_major_match * *===========================================================================*/ PRIVATE int select_major_match(int match_major, struct filp *file) { - int major; - if (!(file && file->filp_vno && - (file->filp_vno->v_mode & I_TYPE) == I_CHAR_SPECIAL)) - return 0; - major = (file->filp_vno->v_sdev >> MAJOR) & BYTE; - if (major == match_major) - return 1; - return 0; + int major; + if (!(file && file->filp_vno && + (file->filp_vno->v_mode & I_TYPE) == I_CHAR_SPECIAL)) + return(0); + major = (file->filp_vno->v_sdev >> MAJOR) & BYTE; + if (major == match_major) return 1; + return 0; } + /*===========================================================================* * tab2ops * *===========================================================================*/ PRIVATE int tab2ops(int fd, struct selectentry *e) { - return (FD_ISSET(fd, &e->readfds) ? SEL_RD : 0) | - (FD_ISSET(fd, &e->writefds) ? SEL_WR : 0) | - (FD_ISSET(fd, &e->errorfds) ? SEL_ERR : 0); + int ops = 0; + if (FD_ISSET(fd, &e->readfds)) ops |= SEL_RD; + if (FD_ISSET(fd, &e->writefds)) ops |= SEL_WR; + if (FD_ISSET(fd, &e->errorfds)) ops |= SEL_ERR; + + return(ops); } + /*===========================================================================* * ops2tab * *===========================================================================*/ PRIVATE void ops2tab(int ops, int fd, struct selectentry *e) { - if ((ops & SEL_RD) && e->vir_readfds && FD_ISSET(fd, &e->readfds) - && !FD_ISSET(fd, &e->ready_readfds)) { - FD_SET(fd, &e->ready_readfds); - e->nreadyfds++; - } - if ((ops & SEL_WR) && e->vir_writefds && FD_ISSET(fd, &e->writefds) - && !FD_ISSET(fd, &e->ready_writefds)) { - FD_SET(fd, &e->ready_writefds); - e->nreadyfds++; - } - if ((ops & SEL_ERR) && e->vir_errorfds && FD_ISSET(fd, &e->errorfds) - && !FD_ISSET(fd, &e->ready_errorfds)) { - FD_SET(fd, &e->ready_errorfds); - e->nreadyfds++; - } - - return; + if ((ops & SEL_RD) && e->vir_readfds && FD_ISSET(fd, &e->readfds) && + !FD_ISSET(fd, &e->ready_readfds)) { + FD_SET(fd, &e->ready_readfds); + e->nreadyfds++; + } + + if ((ops & SEL_WR) && e->vir_writefds && FD_ISSET(fd, &e->writefds) && + !FD_ISSET(fd, &e->ready_writefds)) { + FD_SET(fd, &e->ready_writefds); + e->nreadyfds++; + } + + if ((ops & SEL_ERR) && e->vir_errorfds && FD_ISSET(fd, &e->errorfds) && + !FD_ISSET(fd, &e->ready_errorfds)) { + FD_SET(fd, &e->ready_errorfds); + e->nreadyfds++; + } } + /*===========================================================================* * copy_fdsets * *===========================================================================*/ -PRIVATE void copy_fdsets(struct selectentry *e) +PRIVATE int copy_fdsets(struct selectentry *se, int nfds, int direction) { - int fd_setsize; - if(e->nfds < 0 || e->nfds > OPEN_MAX) - panic(__FILE__, "select copy_fdsets: e->nfds wrong", e->nfds); - - /* Only copy back as many bits as the user expects. */ - fd_setsize = _FDSETWORDS(e->nfds)*_FDSETBITSPERWORD/8; - - if (e->vir_readfds) - sys_vircopy(SELF, D, (vir_bytes) &e->ready_readfds, - e->req_endpt, D, (vir_bytes) e->vir_readfds, fd_setsize); - if (e->vir_writefds) - sys_vircopy(SELF, D, (vir_bytes) &e->ready_writefds, - e->req_endpt, D, (vir_bytes) e->vir_writefds, fd_setsize); - if (e->vir_errorfds) - sys_vircopy(SELF, D, (vir_bytes) &e->ready_errorfds, - e->req_endpt, D, (vir_bytes) e->vir_errorfds, fd_setsize); - - - return; + int fd_setsize, r; + endpoint_t src_e, dst_e; + fd_set *src_fds, *dst_fds; + + if(nfds < 0 || nfds > OPEN_MAX) + panic(__FILE__, "select copy_fdsets: nfds wrong", nfds); + + /* Only copy back as many bits as the user expects. */ + fd_setsize = _FDSETWORDS(nfds) * _FDSETBITSPERWORD/8; + + /* Set source and destination endpoints */ + src_e = (direction == FROM_PROC) ? se->req_endpt : SELF; + dst_e = (direction == FROM_PROC) ? SELF : se->req_endpt; + + /* read set */ + src_fds = (direction == FROM_PROC) ? se->vir_readfds : &se->ready_readfds; + dst_fds = (direction == FROM_PROC) ? &se->readfds : se->vir_readfds; + if (se->vir_readfds) { + r = sys_vircopy(src_e, D, (vir_bytes) src_fds, dst_e, D, + (vir_bytes) dst_fds, fd_setsize); + if (r != OK) return(r); + } + + /* write set */ + src_fds = (direction == FROM_PROC) ? se->vir_writefds : &se->ready_writefds; + dst_fds = (direction == FROM_PROC) ? &se->writefds : se->vir_writefds; + if (se->vir_writefds) { + r = sys_vircopy(src_e, D, (vir_bytes) src_fds, dst_e, D, + (vir_bytes) dst_fds, fd_setsize); + if (r != OK) return(r); + } + + /* error set */ + src_fds = (direction == FROM_PROC) ? se->vir_errorfds : &se->ready_errorfds; + dst_fds = (direction == FROM_PROC) ? &se->errorfds : se->vir_errorfds; + if (se->vir_errorfds) { + r = sys_vircopy(src_e, D, (vir_bytes) src_fds, dst_e, D, + (vir_bytes) dst_fds, fd_setsize); + if (r != OK) return(r); + } + + return(OK); } -/*===========================================================================* - * do_select * - *===========================================================================*/ -PUBLIC int do_select(void) -{ - int r, nfds, is_timeout = 1, nonzero_timeout = 0, - fd, s, block = 0, fd_setsize; - struct timeval timeout; - nfds = m_in.SEL_NFDS; - - if (nfds < 0 || nfds > OPEN_MAX) - return EINVAL; - - for(s = 0; s < MAXSELECTS; s++) - if (!selecttab[s].requestor) - break; - - if (s >= MAXSELECTS) - return ENOSPC; - - selecttab[s].deferred= FALSE; - selecttab[s].req_endpt = who_e; - selecttab[s].nfds = 0; - selecttab[s].nreadyfds = 0; - memset(selecttab[s].filps, 0, sizeof(selecttab[s].filps)); - - /* defaults */ - FD_ZERO(&selecttab[s].readfds); - FD_ZERO(&selecttab[s].writefds); - FD_ZERO(&selecttab[s].errorfds); - FD_ZERO(&selecttab[s].ready_readfds); - FD_ZERO(&selecttab[s].ready_writefds); - FD_ZERO(&selecttab[s].ready_errorfds); - - selecttab[s].vir_readfds = (fd_set *) m_in.SEL_READFDS; - selecttab[s].vir_writefds = (fd_set *) m_in.SEL_WRITEFDS; - selecttab[s].vir_errorfds = (fd_set *) m_in.SEL_ERRORFDS; - - - /* Copy args. Our storage size is zeroed above. Only copy - * as many bits as user has supplied (nfds). - * Could be compiled with a different OPEN_MAX or FD_SETSIZE. - * If nfds is too large, we have already returned above. - */ - - fd_setsize = _FDSETWORDS(nfds)*_FDSETBITSPERWORD/8; - if (selecttab[s].vir_readfds - && (r=sys_vircopy(who_e, D, (vir_bytes) m_in.SEL_READFDS, - SELF, D, (vir_bytes) &selecttab[s].readfds, fd_setsize)) != OK) - return r; - - if (selecttab[s].vir_writefds - && (r=sys_vircopy(who_e, D, (vir_bytes) m_in.SEL_WRITEFDS, - SELF, D, (vir_bytes) &selecttab[s].writefds, fd_setsize)) != OK) - return r; - - if (selecttab[s].vir_errorfds - && (r=sys_vircopy(who_e, D, (vir_bytes) m_in.SEL_ERRORFDS, - SELF, D, (vir_bytes) &selecttab[s].errorfds, fd_setsize)) != OK) - return r; - - if (!m_in.SEL_TIMEOUT) - is_timeout = nonzero_timeout = 0; - else - if ((r=sys_vircopy(who_e, D, (vir_bytes) m_in.SEL_TIMEOUT, - SELF, D, (vir_bytes) &timeout, sizeof(timeout))) != OK) - return r; - - /* No nonsense in the timeval please. */ - if (is_timeout && (timeout.tv_sec < 0 || timeout.tv_usec < 0)) - return EINVAL; - - /* if is_timeout if 0, we block forever. otherwise, if nonzero_timeout - * is 0, we do a poll (don't block). otherwise, we block up to the - * specified time interval. - */ - if (is_timeout && (timeout.tv_sec > 0 || timeout.tv_usec > 0)) - nonzero_timeout = 1; - - if (nonzero_timeout || !is_timeout) - block = 1; - else - block = 0; /* timeout set as (0,0) - this effects a poll */ - - selecttab[s].dontblock= !block; - - /* no timeout set (yet) */ - selecttab[s].expiry = 0; - - for(fd = 0; fd < nfds; fd++) { - int orig_ops, ops, t, type = -1, r; - struct filp *filp; - - if (!(orig_ops = ops = tab2ops(fd, &selecttab[s]))) - continue; - filp = selecttab[s].filps[fd] = get_filp(fd); - if (filp == NULL) { - if (err_code == EBADF) { - select_cancel_all(&selecttab[s]); - return EBADF; - } - - /* File descriptor is 'ready' to return EIO */ - printf("vfs:do_select: EIO after driver failure\n"); - ops2tab(SEL_RD|SEL_WR|SEL_ERR, fd, &selecttab[s]); - continue; - } - - for(t = 0; t < SEL_FDS; t++) { - if (fdtypes[t].select_match) { - if (fdtypes[t].select_match(filp)) { -#if DEBUG_SELECT - printf("select: fd %d is type %d ", fd, t); -#endif - if (type != -1) - printf("select: double match\n"); - type = t; - } - } else if (select_major_match(fdtypes[t].select_major, filp)) { - type = t; - } - } - - /* Open Group: - * "The pselect() and select() functions shall support - * regular files, terminal and pseudo-terminal devices, - * STREAMS-based files, FIFOs, pipes, and sockets. The - * behavior of pselect() and select() on file descriptors - * that refer to other types of file is unspecified." - * - * If all types are implemented, then this is another - * type of file and we get to do whatever we want. - */ - if (type == -1) - { -#if DEBUG_SELECT - printf("do_select: bad type\n"); -#endif - return EBADF; - } - - selecttab[s].type[fd] = type; - - if ((selecttab[s].filps[fd]->filp_select_ops & ops) != ops) { - int wantops; - /* Request the select on this fd. */ -#if DEBUG_SELECT - printf("%p requesting ops %d -> ", - selecttab[s].filps[fd], - selecttab[s].filps[fd]->filp_select_ops); -#endif - wantops = (selecttab[s].filps[fd]->filp_select_ops |= ops); -#if DEBUG_SELECT - printf("%d\n", selecttab[s].filps[fd]->filp_select_ops); -#endif - r = fdtypes[type].select_request(filp, &wantops, - block); - if (r != SEL_OK) { - if (r == SEL_DEFERRED) - { - selecttab[s].deferred= TRUE; - selecttab[s].deferred_fd= 0; - continue; - } - /* error or bogus return code.. backpaddle */ - select_cancel_all(&selecttab[s]); - printf( - "select: select_request returned error\n"); - return EINVAL; - } - if (wantops) { - if (wantops & ops) { - /* operations that were just requested - * are ready to go right away - */ - ops2tab(wantops, fd, &selecttab[s]); - } - /* if there are any other select()s blocking - * on these operations of this fp, they can - * be awoken too - */ - select_callback(filp, ops); - } -#if DEBUG_SELECT - printf("select request ok; ops returned %d\n", wantops); -#endif - } else { -#if DEBUG_SELECT - printf("select already happening on that filp\n"); -#endif - } - - selecttab[s].nfds = fd+1; - selecttab[s].filps[fd]->filp_selectors++; - -#if DEBUG_SELECT - printf("[fd %d ops: %d] ", fd, ops); -#endif - } - - if (selecttab[s].nreadyfds > 0 || (!block && !selecttab[s].deferred)) { - /* fd's were found that were ready to go right away, and/or - * we were instructed not to block at all. Must return - * immediately. - */ - copy_fdsets(&selecttab[s]); - select_cancel_all(&selecttab[s]); - selecttab[s].requestor = NULL; - - /* Open Group: - * "Upon successful completion, the pselect() and select() - * functions shall return the total number of bits - * set in the bit masks." - */ -#if DEBUG_SELECT - printf("returning\n"); -#endif - - return selecttab[s].nreadyfds; - } -#if DEBUG_SELECT - printf("not returning (%d, %d)\n", selecttab[s].nreadyfds, block); -#endif - - /* Convert timeval to ticks and set the timer. If it fails, undo - * all, return error. - */ - if (is_timeout) { - int ticks; - /* Open Group: - * "If the requested timeout interval requires a finer - * granularity than the implementation supports, the - * actual timeout interval shall be rounded up to the next - * supported value." - */ -#define USECPERSEC 1000000 - while(timeout.tv_usec >= USECPERSEC) { - /* this is to avoid overflow with *system_hz below */ - timeout.tv_usec -= USECPERSEC; - timeout.tv_sec++; - } - ticks = timeout.tv_sec * system_hz + - (timeout.tv_usec * system_hz + USECPERSEC-1) / USECPERSEC; - selecttab[s].expiry = ticks; - fs_set_timer(&selecttab[s].timer, ticks, select_timeout_check, s); -#if DEBUG_SELECT - printf("%d: blocking %d ticks\n", s, ticks); -#endif - } - - /* if we're blocking, the table entry is now valid. */ - selecttab[s].requestor = fp; - - /* process now blocked */ - suspend(FP_BLOCKED_ON_SELECT); - return SUSPEND; -} /*===========================================================================* * select_cancel_all * @@ -529,14 +464,16 @@ PRIVATE void select_cancel_all(struct selectentry *e) return; } + /*===========================================================================* * select_wakeup * *===========================================================================*/ PRIVATE void select_wakeup(struct selectentry *e, int r) { - revive(e->req_endpt, r); + revive(e->req_endpt, r); } + /*===========================================================================* * select_reevaluate * *===========================================================================*/ @@ -550,8 +487,8 @@ PRIVATE int select_reevaluate(struct filp *fp) } for(s = 0; s < MAXSELECTS; s++) { - if (!selecttab[s].requestor) - continue; + if (selecttab[s].requestor != NULL) continue; + for(fd = 0; fd < selecttab[s].nfds; fd++) if (fp == selecttab[s].filps[fd]) { remain_ops |= tab2ops(fd, &selecttab[s]); @@ -571,17 +508,19 @@ PRIVATE int select_reevaluate(struct filp *fp) return remain_ops; } + /*===========================================================================* * select_return * *===========================================================================*/ -PRIVATE void select_return(struct selectentry *s, int r) +PRIVATE void select_return(struct selectentry *se, int r) { - select_cancel_all(s); - copy_fdsets(s); - select_wakeup(s, r ? r : s->nreadyfds); - s->requestor = NULL; + select_cancel_all(se); + copy_fdsets(se, se->nfds, TO_PROC); /* FIXME, return error status */ + select_wakeup(se, r ? r : se->nreadyfds); + se->requestor = NULL; } + /*===========================================================================* * select_callback * *===========================================================================*/ @@ -598,8 +537,8 @@ PUBLIC int select_callback(struct filp *fp, int ops) type = -1; for(s = 0; s < MAXSELECTS; s++) { int wakehim = 0; - if (!selecttab[s].requestor) - continue; + if (selecttab[s].requestor == NULL) continue; + for(fd = 0; fd < selecttab[s].nfds; fd++) { if (!selecttab[s].filps[fd]) continue; @@ -622,6 +561,7 @@ PUBLIC int select_callback(struct filp *fp, int ops) return 0; } + /*===========================================================================* * select_notified * *===========================================================================*/ @@ -650,8 +590,7 @@ PUBLIC int select_notified(int major, int minor, int selected_ops) for(s = 0; s < MAXSELECTS; s++) { int s_minor, ops; - if (!selecttab[s].requestor) - continue; + if (selecttab[s].requestor == NULL) continue; for(f = 0; f < selecttab[s].nfds; f++) { if (!selecttab[s].filps[f] || !select_major_match(major, selecttab[s].filps[f])) @@ -670,6 +609,7 @@ PUBLIC int select_notified(int major, int minor, int selected_ops) return OK; } + /*===========================================================================* * init_select * *===========================================================================*/ @@ -681,6 +621,7 @@ PUBLIC void init_select(void) fs_init_timer(&selecttab[s].timer); } + /*===========================================================================* * select_forget * *===========================================================================*/ @@ -692,11 +633,10 @@ PUBLIC void select_forget(int proc_e) int s; for(s = 0; s < MAXSELECTS; s++) { - if (selecttab[s].requestor && - selecttab[s].req_endpt == proc_e) { + if (selecttab[s].requestor != NULL && + selecttab[s].req_endpt == proc_e) { break; } - } if (s >= MAXSELECTS) { @@ -712,66 +652,69 @@ PUBLIC void select_forget(int proc_e) return; } + /*===========================================================================* * select_timeout_check * *===========================================================================*/ PUBLIC void select_timeout_check(timer_t *timer) { - int s; - - s = tmr_arg(timer)->ta_int; + int s; + struct selectentry *se; - if (s < 0 || s >= MAXSELECTS) { + s = tmr_arg(timer)->ta_int; + if (s < 0 || s >= MAXSELECTS) { #if DEBUG_SELECT - printf("select: bogus slot arg to watchdog %d\n", s); + printf("select: bogus slot arg to watchdog %d\n", s); #endif - return; - } + return; + } + se = &selecttab[s]; /* Point to select table entry */ - if (!selecttab[s].requestor) { + if (se->requestor == NULL) { #if DEBUG_SELECT - printf("select: no requestor in watchdog\n"); + printf("select: no requestor in watchdog\n"); #endif - return; - } + return; + } - if (selecttab[s].expiry <= 0) { + if (se->expiry <= 0) { #if DEBUG_SELECT - printf("select: strange expiry value in watchdog\n", s); + printf("select: strange expiry value in watchdog\n", s); #endif - return; - } + return; + } - selecttab[s].expiry = 0; - select_return(&selecttab[s], 0); + se->expiry = 0; + select_return(se, 0); - return; } + /*===========================================================================* * select_unsuspend_by_endpt * *===========================================================================*/ PUBLIC void select_unsuspend_by_endpt(endpoint_t proc_e) { - int fd, s; - - for(s = 0; s < MAXSELECTS; s++) { - if (!selecttab[s].requestor) - continue; - for(fd = 0; fd < selecttab[s].nfds; fd++) { - int maj; - if (!selecttab[s].filps[fd] || !selecttab[s].filps[fd]->filp_vno) - continue; - maj = (selecttab[s].filps[fd]->filp_vno->v_sdev >> MAJOR)&BYTE; - if(dmap_driver_match(proc_e, maj)) { + int fd, s, maj; + + for(s = 0; s < MAXSELECTS; s++) { + if (selecttab[s].requestor == NULL) continue; + + for(fd = 0; fd < selecttab[s].nfds; fd++) { + if (selecttab[s].filps[fd] == NIL_FILP || + selecttab[s].filps[fd]->filp_vno == NIL_VNODE) { + continue; + } + + maj = (selecttab[s].filps[fd]->filp_vno->v_sdev >> MAJOR)&BYTE; + if (dmap_driver_match(proc_e, maj)) select_return(&selecttab[s], EAGAIN); - } - } + } - - return; + } } + /*===========================================================================* * select_reply1 * *===========================================================================*/ @@ -892,7 +835,7 @@ PUBLIC void select_reply2() /* Find filedescriptors for this device */ for (s= 0; sdeferred= FALSE; } - if (se->nreadyfds > 0 || se->dontblock) - { - copy_fdsets(se); + if (se->nreadyfds > 0 || !se->block) { + copy_fdsets(se, se->nfds, TO_PROC); /* FIXME, return error */ select_wakeup(se, se->nreadyfds); - se->requestor= NULL; + se->requestor = NULL; } } + +/*===========================================================================* + * wipe_select * + *===========================================================================*/ +PRIVATE void wipe_select(struct selectentry *se) +{ + se->deferred = FALSE; + se->nfds = 0; + se->nreadyfds = 0; +/* memset(se->filps, 0, OPEN_MAX * sizeof(struct filp *)); */ + memset(se->filps, 0, sizeof(se->filps)); + + FD_ZERO(&se->readfds); + FD_ZERO(&se->writefds); + FD_ZERO(&se->errorfds); + FD_ZERO(&se->ready_readfds); + FD_ZERO(&se->ready_writefds); + FD_ZERO(&se->ready_errorfds); +} + diff --git a/servers/vfs/stadir.c b/servers/vfs/stadir.c index d894900af..448637ef6 100644 --- a/servers/vfs/stadir.c +++ b/servers/vfs/stadir.c @@ -4,13 +4,10 @@ * The entry points into this file are * do_chdir: perform the CHDIR system call * do_chroot: perform the CHROOT system call + * do_lstat: perform the LSTAT system call * do_stat: perform the STAT system call * do_fstat: perform the FSTAT system call * do_fstatfs: perform the FSTATFS system call - * do_lstat: perform the LSTAT system call - * - * Changes for VFS: - * Jul 2006 (Balazs Gerofi) */ #include "fs.h" @@ -22,7 +19,6 @@ #include "file.h" #include "fproc.h" #include "param.h" - #include #include "vnode.h" #include "vmnt.h" @@ -30,6 +26,7 @@ FORWARD _PROTOTYPE( int change, (struct vnode **iip, char *name_ptr, int len)); FORWARD _PROTOTYPE( int change_into, (struct vnode **iip, struct vnode *vp)); + /*===========================================================================* * do_fchdir * *===========================================================================*/ @@ -37,30 +34,13 @@ PUBLIC int do_fchdir() { /* Change directory on already-opened fd. */ struct filp *rfilp; - int r; - - if(!fp->fp_wd || !fp->fp_rd) { - printf("VFS: do_fchdir: %d: no rd/wd\n", - fp->fp_endpoint); - return ENOENT; - } /* Is the file descriptor valid? */ - if ( (rfilp = get_filp(m_in.fd)) == NIL_FILP) return(err_code); - - /* Is it a dir? */ - if ((rfilp->filp_vno->v_mode & I_TYPE) != I_DIRECTORY) - return ENOTDIR; - - /* Issue request and handle error */ - r = forbidden(rfilp->filp_vno, X_BIT, 0 /*!use_realuid*/); - if (r != OK) return r; - - rfilp->filp_vno->v_ref_count++; /* change_into expects a reference */ - + if ((rfilp = get_filp(m_in.fd)) == NIL_FILP) return(err_code); return change_into(&fp->fp_wd, rfilp->filp_vno); } + /*===========================================================================* * do_chdir * *===========================================================================*/ @@ -73,23 +53,11 @@ PUBLIC int do_chdir() int r; register struct fproc *rfp; - if(!fp->fp_wd || !fp->fp_rd) { - printf("VFS: do_chdir: %d: no rd/wd\n", - fp->fp_endpoint); - return ENOENT; - } - if (who_e == PM_PROC_NR) { int slot; - if(isokendpt(m_in.endpt1, &slot) != OK) - return EINVAL; + if(isokendpt(m_in.endpt1, &slot) != OK) return(EINVAL); rfp = &fproc[slot]; - if(!rfp->fp_wd || !rfp->fp_rd) { - printf("VFS: do_chdir: %d: no other rd/wd\n", fp->fp_endpoint); - return ENOENT; - } - put_vnode(fp->fp_rd); dup_vnode(fp->fp_rd = rfp->fp_rd); put_vnode(fp->fp_wd); @@ -109,10 +77,10 @@ PUBLIC int do_chdir() } /* Perform the chdir(name) system call. */ - r = change(&fp->fp_wd, m_in.name, m_in.name_length); - return(r); + return change(&fp->fp_wd, m_in.name, m_in.name_length); } + /*===========================================================================* * do_chroot * *===========================================================================*/ @@ -120,18 +88,8 @@ PUBLIC int do_chroot() { /* Perform the chroot(name) system call. */ - register int r; - if (!super_user) return(EPERM); /* only su may chroot() */ - - if(!fp->fp_wd || !fp->fp_rd) { - printf("VFS: do_chroot: %d: no rd/wd\n", - fp->fp_endpoint); - return ENOENT; - } - - r = change(&fp->fp_rd, m_in.name, m_in.name_length); - return(r); + return change(&fp->fp_rd, m_in.name, m_in.name_length); } @@ -147,25 +105,9 @@ int len; /* length of the directory name string */ struct vnode *vp; int r; + /* Try to open the directory */ if (fetch_name(name_ptr, len, M3) != OK) return(err_code); - - /* Request lookup */ - if ((r = lookup_vp(0 /*flags*/, 0 /*!use_realuid*/, &vp)) != OK) return r; - - /* Is it a dir? */ - if ((vp->v_mode & I_TYPE) != I_DIRECTORY) - { - put_vnode(vp); - return ENOTDIR; - } - - /* Access check */ - r = forbidden(vp, X_BIT, 0 /*!use_realuid*/); - if (r != OK) { - put_vnode(vp); - return r; - } - + if ((vp = eat_path(PATH_NOFLAGS)) == NIL_VNODE) return(err_code); return change_into(iip, vp); } @@ -177,10 +119,23 @@ PRIVATE int change_into(iip, vp) struct vnode **iip; /* pointer to the inode pointer for the dir */ struct vnode *vp; /* this is what the inode has to become */ { + int r; + + /* It must be a directory and also be searchable */ + if ((vp->v_mode & I_TYPE) != I_DIRECTORY) + r = ENOTDIR; + else + r = forbidden(vp, X_BIT); /* Check if dir is searchable*/ + + /* If error, return vnode */ + if (r != OK) { + put_vnode(vp); + return(r); + } + /* Everything is OK. Make the change. */ put_vnode(*iip); /* release the old directory */ *iip = vp; /* acquire the new one */ - return(OK); } @@ -195,19 +150,14 @@ PUBLIC int do_stat() struct vnode *vp; if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code); - - /* Request lookup */ - if ((r = lookup_vp(0 /*flags*/, 0 /*!use_realuid*/, &vp)) != OK) - return r; + if ((vp = eat_path(PATH_NOFLAGS)) == NIL_VNODE) return(err_code); + r = req_stat(vp->v_fs_e, vp->v_inode_nr, who_e, m_in.name2, 0); - /* Issue request */ - r= req_stat(vp->v_fs_e, vp->v_inode_nr, who_e, m_in.name2, 0); put_vnode(vp); return r; } - /*===========================================================================* * do_fstat * *===========================================================================*/ @@ -218,46 +168,38 @@ PUBLIC int do_fstat() int pipe_pos = 0; /* Is the file descriptor valid? */ - if ( (rfilp = get_filp(m_in.fd)) == NIL_FILP) { - return(err_code); - } + if ((rfilp = get_filp(m_in.fd)) == NIL_FILP) return(err_code); /* If we read from a pipe, send position too */ - pipe_pos= 0; if (rfilp->filp_vno->v_pipe == I_PIPE) { if (rfilp->filp_mode & R_BIT) - if (ex64hi(rfilp->filp_pos) != 0) - { + if (ex64hi(rfilp->filp_pos) != 0) { panic(__FILE__, "do_fstat: bad position in pipe", NO_NUM); } - pipe_pos = ex64lo(rfilp->filp_pos); + pipe_pos = ex64lo(rfilp->filp_pos); } - /* Issue request */ return req_stat(rfilp->filp_vno->v_fs_e, rfilp->filp_vno->v_inode_nr, - who_e, m_in.buffer, pipe_pos); + who_e, m_in.buffer, pipe_pos); } - /*===========================================================================* * do_fstatfs * *===========================================================================*/ PUBLIC int do_fstatfs() { - /* Perform the fstatfs(fd, buf) system call. */ - register struct filp *rfilp; +/* Perform the fstatfs(fd, buf) system call. */ + struct filp *rfilp; /* Is the file descriptor valid? */ - if ( (rfilp = get_filp(m_in.fd)) == NIL_FILP) return(err_code); + if( (rfilp = get_filp(m_in.fd)) == NIL_FILP) return(err_code); - /* Issue request */ return req_fstatfs(rfilp->filp_vno->v_fs_e, who_e, m_in.buffer); } - /*===========================================================================* * do_lstat * *===========================================================================*/ @@ -268,18 +210,11 @@ PUBLIC int do_lstat() int r; if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code); - - /* Request lookup */ - if ((r = lookup_vp(PATH_RET_SYMLINK, 0 /*!use_realuid*/, &vp)) != OK) - return r; - - /* Issue request */ - r= req_stat(vp->v_fs_e, vp->v_inode_nr, who_e, m_in.name2, 0); + if ((vp = eat_path(PATH_RET_SYMLINK)) == NIL_VNODE) return(err_code); + r = req_stat(vp->v_fs_e, vp->v_inode_nr, who_e, m_in.name2, 0); put_vnode(vp); - - return r; + return(r); } - diff --git a/servers/vfs/table.c b/servers/vfs/table.c index cd350252c..33afdac56 100644 --- a/servers/vfs/table.c +++ b/servers/vfs/table.c @@ -10,7 +10,6 @@ #include "file.h" #include "fproc.h" #include "lock.h" - #include "vnode.h" #include "vmnt.h" @@ -62,7 +61,7 @@ PUBLIC _PROTOTYPE (int (*call_vec[]), (void) ) = { no_sys, /* 43 = times */ no_sys, /* 44 = (prof) */ do_slink, /* 45 = symlink */ - no_sys, /* 46 = (setgid) */ + no_sys, /* 46 = (setgid)*/ no_sys, /* 47 = getgid */ no_sys, /* 48 = (signal)*/ do_rdlink, /* 49 = readlink*/ @@ -75,18 +74,18 @@ PUBLIC _PROTOTYPE (int (*call_vec[]), (void) ) = { no_sys, /* 56 = (mpx) */ do_fslogin, /* 57 = FS proc login */ no_sys, /* 58 = unused */ - no_sys, /* 59 = (execve) */ + no_sys, /* 59 = (execve)*/ do_umask, /* 60 = umask */ do_chroot, /* 61 = chroot */ - no_sys, /* 62 = (setsid) */ - no_sys, /* 63 = (getpgrp) */ - no_sys, /* 64 = (itimer) */ + no_sys, /* 62 = (setsid)*/ + no_sys, /* 63 = (getpgrp)*/ + no_sys, /* 64 = (itimer)*/ no_sys, /* 65 = unused */ no_sys, /* 66 = unused */ no_sys, /* 67 = unused */ no_sys, /* 68 = unused */ - no_sys, /* 69 = unused */ - no_sys, /* 70 = unused */ + no_sys, /* 69 = unused */ + no_sys, /* 70 = unused */ no_sys, /* 71 = (sigaction) */ no_sys, /* 72 = (sigsuspend) */ no_sys, /* 73 = (sigpending) */ diff --git a/servers/vfs/time.c b/servers/vfs/time.c index aa30a2861..3415ec689 100644 --- a/servers/vfs/time.c +++ b/servers/vfs/time.c @@ -2,7 +2,6 @@ * * The entry points into this file are * do_utime: perform the UTIME system call - * do_stime: PM informs FS about STIME system call */ #include "fs.h" @@ -12,7 +11,6 @@ #include "fproc.h" #include "param.h" #include "vnode.h" - #include #include "vmnt.h" @@ -29,48 +27,31 @@ PUBLIC int do_utime() struct vnode *vp; /* Adjust for case of 'timep' being NULL; - * utime_strlen then holds the actual size: strlen(name)+1. - */ + * utime_strlen then holds the actual size: strlen(name)+1 */ len = m_in.utime_length; - if (len == 0) len = m_in.utime_strlen; + if(len == 0) len = m_in.utime_strlen; + /* Temporarily open the file */ if (fetch_name(m_in.utime_file, len, M1) != OK) return(err_code); - - /* Request lookup */ - if ((r = lookup_vp(0 /*flags*/, 0 /*!use_realuid*/, &vp)) != OK) return r; - - /* Fill in request fields.*/ - if (m_in.utime_length == 0) { - actime = modtime = clock_time(); - } else { - actime = m_in.utime_actime; - modtime = m_in.utime_modtime; + if ((vp = eat_path(PATH_NOFLAGS)) == NIL_VNODE) return(err_code); + + /* Only the owner of a file or the super user can change its name. */ + r = OK; + if (vp->v_uid != fp->fp_effuid && fp->fp_effuid != SU_UID) r = EPERM; + if (m_in.utime_length == 0 && r != OK) r = forbidden(vp, W_BIT); + if (read_only(vp) != OK) r = EROFS; /* Not even su can touch if R/O */ + if (r == OK) { + /* Issue request */ + if(m_in.utime_length == 0) { + actime = modtime = clock_time(); + } else { + actime = m_in.utime_actime; + modtime = m_in.utime_modtime; + } + r = req_utime(vp->v_fs_e, vp->v_inode_nr, actime, modtime); } - uid= fp->fp_effuid; - - r= OK; - if (vp->v_uid != uid && uid != SU_UID) r = EPERM; - if (m_in.utime_length == 0 && r != OK) - { - /* With a null times pointer, updating the times (to the current time) - * is allow if the object is writable. - */ - r = forbidden(vp, W_BIT, 0 /*!use_realuid*/); - } - - if (r == OK) - r = read_only(vp); - - if (r != OK) - { - put_vnode(vp); - return r; - } - - /* Issue request */ - r= req_utime(vp->v_fs_e, vp->v_inode_nr, actime, modtime); put_vnode(vp); - return r; + return(r); } diff --git a/servers/vfs/timers.c b/servers/vfs/timers.c index 7c10ac32e..d1f94f0c0 100644 --- a/servers/vfs/timers.c +++ b/servers/vfs/timers.c @@ -2,7 +2,6 @@ */ #include "fs.h" - #include #include #include diff --git a/servers/vfs/utility.c b/servers/vfs/utility.c index 81b3651e2..1e23caf7f 100644 --- a/servers/vfs/utility.c +++ b/servers/vfs/utility.c @@ -37,23 +37,16 @@ int flag; /* M3 means path may be in message */ int r, count; if (len > PATH_MAX) { -#if 0 - printf("VFS: fetch_name: len (%d) > %d\n", len, PATH_MAX); - util_stacktrace(); -#endif err_code = ENAMETOOLONG; return(EGENERIC); } - if(len >= sizeof(user_fullpath)) { + if(len >= sizeof(user_fullpath)) panic(__FILE__, "fetch_name: len too much for user_fullpath", len); - } /* Check name length for validity. */ if (len <= 0) { err_code = EINVAL; - printf("vfs: fetch_name: len %d?\n", len); - util_stacktrace(); return(EGENERIC); } @@ -70,64 +63,62 @@ int flag; /* M3 means path may be in message */ FS_PROC_NR, (vir_bytes) user_fullpath, (phys_bytes) len); } - if(user_fullpath[len-1] != '\0') { - int i; - printf("vfs: fetch_name: name not null-terminated: "); - for(i = 0; i < len; i++) { - printf("%c", user_fullpath[i]); - } - printf("\n"); - user_fullpath[len-1] = '\0'; + if (user_fullpath[len - 1] != '\0') { + err_code = ENAMETOOLONG; + return(EGENERIC); } return(r); } + /*===========================================================================* * no_sys * *===========================================================================*/ PUBLIC int no_sys() { /* Somebody has used an illegal system call number */ - printf("VFSno_sys: call %d from %d\n", call_nr, who_e); + printf("VFS no_sys: call %d from %d (pid %d)\n", call_nr, who_e, who_p); return(ENOSYS); } + /*===========================================================================* * isokendpt_f * *===========================================================================*/ PUBLIC int isokendpt_f(char *file, int line, int endpoint, int *proc, int fatal) { - int failed = 0; - endpoint_t ke; - *proc = _ENDPOINT_P(endpoint); - if(endpoint == NONE) { - printf("vfs:%s: endpoint is NONE\n", file, line, endpoint); - failed = 1; - } else if(*proc < 0 || *proc >= NR_PROCS) { - printf("vfs:%s:%d: proc (%d) from endpoint (%d) out of range\n", - file, line, *proc, endpoint); - failed = 1; - } else if((ke=fproc[*proc].fp_endpoint) != endpoint) { + int failed = 0; + endpoint_t ke; + *proc = _ENDPOINT_P(endpoint); + if(endpoint == NONE) { + printf("vfs:%s: endpoint is NONE\n", file, line, endpoint); + failed = 1; + } else if(*proc < 0 || *proc >= NR_PROCS) { + printf("vfs:%s:%d: proc (%d) from endpoint (%d) out of range\n", + file, line, *proc, endpoint); + failed = 1; + } else if((ke=fproc[*proc].fp_endpoint) != endpoint) { if(ke == NONE) { - printf("vfs:%s:%d: endpoint (%d) points to NONE slot (%d)\n", + printf("vfs:%s:%d: endpoint (%d) points to NONE slot (%d)\n", file, line, endpoint, *proc); assert(fproc[*proc].fp_pid == PID_FREE); - } else { - printf("vfs:%s:%d: proc (%d) from endpoint (%d) doesn't match " - "known endpoint (%d)\n", - file, line, *proc, endpoint, fproc[*proc].fp_endpoint); + } else { + printf("vfs:%s:%d: proc (%d) from endpoint (%d) doesn't match " + "known endpoint (%d)\n", file, line, *proc, endpoint, + fproc[*proc].fp_endpoint); assert(fproc[*proc].fp_pid != PID_FREE); } - failed = 1; - } + failed = 1; + } - if(failed && fatal) - panic(__FILE__, "isokendpt_f failed", NO_NUM); + if(failed && fatal) + panic(__FILE__, "isokendpt_f failed", NO_NUM); - return failed ? EDEADSRCDST : OK; + return(failed ? EDEADSRCDST : OK); } + /*===========================================================================* * clock_time * *===========================================================================*/ @@ -142,7 +133,7 @@ PUBLIC time_t clock_time() clock_t uptime; time_t boottime; - r= getuptime2(&uptime, &boottime); + r = getuptime2(&uptime, &boottime); if (r != OK) panic(__FILE__,"clock_time err", r); diff --git a/servers/vfs/vmnt.c b/servers/vfs/vmnt.c index 9b92743b0..03cee6f7b 100644 --- a/servers/vfs/vmnt.c +++ b/servers/vfs/vmnt.c @@ -1,6 +1,5 @@ /* Virtual mount table related routines. * - * Jul 2006 (Balazs Gerofi) */ #include "fs.h" @@ -14,24 +13,23 @@ PUBLIC struct vmnt *get_free_vmnt(short *index) { struct vmnt *vp; *index = 0; - for (vp = &vmnt[0]; vp < &vmnt[NR_MNTS]; ++vp, ++(*index)) { - if (vp->m_dev == NO_DEV) return vp; - } + for (vp = &vmnt[0]; vp < &vmnt[NR_MNTS]; ++vp, ++(*index)) + if (vp->m_dev == NO_DEV) return(vp); - return NIL_VMNT; + return(NIL_VMNT); } + /*===========================================================================* * find_vmnt * *===========================================================================*/ PUBLIC struct vmnt *find_vmnt(int fs_e) { struct vmnt *vp; - for (vp = &vmnt[0]; vp < &vmnt[NR_MNTS]; ++vp) { - if (vp->m_fs_e == fs_e) return vp; - } + for (vp = &vmnt[0]; vp < &vmnt[NR_MNTS]; ++vp) + if (vp->m_fs_e == fs_e) return(vp); - return NIL_VMNT; + return(NIL_VMNT); } diff --git a/servers/vfs/vnode.c b/servers/vfs/vnode.c index 8c6da3706..5a7e4084a 100644 --- a/servers/vfs/vnode.c +++ b/servers/vfs/vnode.c @@ -1,4 +1,3 @@ - /* This file contains the routines related to vnodes. * The entry points are: * @@ -7,16 +6,13 @@ * find_vnode - find a vnode according to the FS endpoint and the inode num. * dup_vnode - duplicate vnode (i.e. increase counter) * put_vnode - drop vnode (i.e. decrease counter) - * - * Jul 2006 (Balazs Gerofi) */ + #include "fs.h" #include "vnode.h" #include "vmnt.h" - #include "fproc.h" #include "file.h" - #include /* Is vnode pointer reasonable? */ @@ -37,30 +33,28 @@ /*===========================================================================* * get_free_vnode * *===========================================================================*/ -PUBLIC struct vnode *get_free_vnode(file, line) -char *file; -int line; +PUBLIC struct vnode *get_free_vnode() { -/* Find a free vnode slot in the vnode table */ +/* Find a free vnode slot in the vnode table (it's not actually allocated) */ struct vnode *vp; - for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; ++vp) - if (vp->v_ref_count == 0) - { - vp->v_pipe= NO_PIPE; - vp->v_uid= -1; - vp->v_gid= -1; - vp->v_sdev= -1; - vp->v_file= file; - vp->v_line= line; - return vp; + for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; ++vp) { + if (vp->v_ref_count == 0) { + vp->v_pipe = NO_PIPE; + vp->v_uid = -1; + vp->v_gid = -1; + vp->v_sdev = NO_DEV; + vp->v_mapfs_e = 0; + vp->v_mapinode_nr = 0; + return(vp); } + } - err_code = ENFILE; - return NIL_VNODE; + return(NIL_VNODE); } + /*===========================================================================* * find_vnode * *===========================================================================*/ @@ -71,10 +65,10 @@ PUBLIC struct vnode *find_vnode(int fs_e, int numb) struct vnode *vp; for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; ++vp) - if (vp->v_ref_count > 0 && vp->v_inode_nr == numb - && vp->v_fs_e == fs_e) return vp; + if (vp->v_ref_count > 0 && vp->v_inode_nr == numb && vp->v_fs_e == fs_e) + return(vp); - return NIL_VNODE; + return(NIL_VNODE); } @@ -97,39 +91,52 @@ PUBLIC void dup_vnode(struct vnode *vp) PUBLIC void put_vnode(struct vnode *vp) { /* Decrease vnode's usage counter and decrease inode's usage counter in the - * corresponding FS process. + * corresponding FS process. Decreasing the fs_count each time we decrease the + * ref count would lead to poor performance. Instead, only decrease fs_count + * when the ref count hits zero. However, this could lead to fs_count to wrap. + * To prevent this, we drop the counter to 1 when the counter hits 256. + * We maintain fs_count as a sanity check to make sure VFS and the FS are in + * sync. */ ASSERTVP(vp); - if (vp->v_ref_count > 1) - { + if (vp->v_ref_count > 1) { /* Decrease counter */ vp->v_ref_count--; - if (vp->v_fs_count > 256) + if (vp->v_fs_count > 256) vnode_clean_refs(vp); + return; } - if (vp->v_ref_count <= 0) - { + /* A vnode that's not in use can't be put. */ + if (vp->v_ref_count <= 0) { printf("put_vnode: bad v_ref_count %d\n", vp->v_ref_count); panic(__FILE__, "put_vnode failed", NO_NUM); } - if (vp->v_fs_count <= 0) - { + + /* fs_count should indicate that the file is in use. */ + if (vp->v_fs_count <= 0) { printf("put_vnode: bad v_fs_count %d\n", vp->v_fs_count); panic(__FILE__, "put_vnode failed", NO_NUM); } - /* Send request */ - if (req_putnode(vp->v_fs_e, vp->v_inode_nr, vp->v_fs_count) != OK) - printf("VFSput_vnode Warning: inode doesn't exist\n"); + /* Tell FS we don't need this inode to be open anymore. */ + req_putnode(vp->v_fs_e, vp->v_inode_nr, vp->v_fs_count); - vp->v_fs_count= 0; - vp->v_ref_count= 0; + /* This inode could've been mapped. If so, tell PFS to close it as well. */ + if(vp->v_mapfs_e != 0 && vp->v_mapinode_nr != vp->v_inode_nr && + vp->v_mapfs_e != vp->v_fs_e) { + req_putnode(vp->v_mapfs_e, vp->v_mapinode_nr, vp->v_mapfs_count); + } + + vp->v_fs_count = 0; + vp->v_ref_count = 0; vp->v_pipe = NO_PIPE; vp->v_sdev = NO_DEV; - vp->v_index = 0; + vp->v_mapfs_e = 0; + vp->v_mapinode_nr = 0; + vp->v_fs_count = 0; } @@ -139,33 +146,15 @@ PUBLIC void put_vnode(struct vnode *vp) PUBLIC void vnode_clean_refs(struct vnode *vp) { /* Tell the underlying FS to drop all reference but one. */ - if (vp == NIL_VNODE) { - return; - } - - if (vp->v_fs_count <= 1) - return; /* Nothing to do */ - if (req_putnode(vp->v_fs_e, vp->v_inode_nr, vp->v_fs_count-1) != OK) - printf("vnode_clean_refs: req_putnode failed\n"); - vp->v_fs_count= 1; -} + if (vp == NIL_VNODE) return; + if (vp->v_fs_count <= 1) return; /* Nothing to do */ -#if 0 -/*===========================================================================* - * mark_vn * - *===========================================================================*/ -PUBLIC void mark_vn(vp, file, line) -struct vnode *vp; -char *file; -int line; -{ - if (!vp) - return; - vp->v_file= file; - vp->v_line= line; + /* Drop all references except one */ + req_putnode(vp->v_fs_e, vp->v_inode_nr, vp->v_fs_count - 1); + vp->v_fs_count = 1; } -#endif + #define REFVP(v) { vp = (v); CHECKVN(v); vp->v_ref_check++; } diff --git a/servers/vfs/vnode.h b/servers/vfs/vnode.h index 5755f9b61..110d231b0 100644 --- a/servers/vfs/vnode.h +++ b/servers/vfs/vnode.h @@ -2,30 +2,28 @@ EXTERN struct vnode { endpoint_t v_fs_e; /* FS process' endpoint number */ + endpoint_t v_mapfs_e; /* mapped FS process' endpoint number */ ino_t v_inode_nr; /* inode number on its (minor) device */ + ino_t v_mapinode_nr; /* mapped inode number of mapped FS. */ mode_t v_mode; /* file type, protection, etc. */ - uid_t v_uid; - gid_t v_gid; + uid_t v_uid; /* uid of inode. */ + gid_t v_gid; /* gid of inode. */ off_t v_size; /* current file size in bytes */ int v_ref_count; /* # times vnode used; 0 means slot is free */ int v_fs_count; /* # reference at the underlying FS */ + int v_mapfs_count; /* # reference at the underlying mapped FS */ +#if 0 int v_ref_check; /* for consistency checks */ +#endif char v_pipe; /* set to I_PIPE if pipe */ off_t v_pipe_rd_pos; off_t v_pipe_wr_pos; endpoint_t v_bfs_e; /* endpoint number for the FS proces in case of a block special file */ - dev_t v_dev; /* device number on which the corresponding inode resides */ - dev_t v_sdev; /* device number for special files */ - unsigned short v_index; /* inode's index in the FS inode table */ struct vmnt *v_vmnt; /* vmnt object of the partition */ - - /* For debugging */ - char *v_file; - int v_line; } vnode[NR_VNODES]; #define NIL_VNODE (struct vnode *) 0 /* indicates absence of vnode slot */ diff --git a/test/Makefile b/test/Makefile index 9972a7fca..a275ae6eb 100644 --- a/test/Makefile +++ b/test/Makefile @@ -13,7 +13,7 @@ OBJ= test1 test2 test3 test4 test5 test6 test7 test8 test9 \ test42 test44 test45 BIGOBJ= test20 test24 -ROOTOBJ= test11 test33 test43 +ROOTOBJ= test11 test33 test43 test46 GCCOBJ= test45-gcc all: $(OBJ) $(BIGOBJ) $(GCCOBJ) $(ROOTOBJ) @@ -93,4 +93,5 @@ test43: test43.c test44: test44.c test45: test45.c test45.h test45-gcc: test45.c test45.h +test46: test46.c diff --git a/test/run b/test/run index 6205c052b..1dc5ee68b 100755 --- a/test/run +++ b/test/run @@ -13,13 +13,13 @@ badones= # list of tests that failed # Print test welcome message clr -echo "Running POSIX compliance test suite. There are 48 tests in total." +echo "Running POSIX compliance test suite. There are 49 tests in total." echo " " # Run all the tests, keeping track of who failed. for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 \ 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 \ - 41 42 43 44 45 45-gcc sh1.sh sh2.sh + 41 42 43 44 45 45-gcc 46 sh1.sh sh2.sh do if [ -x ./test$i ] then diff --git a/test/t40b.c b/test/t40b.c index a23abaacb..472bf6d32 100644 --- a/test/t40b.c +++ b/test/t40b.c @@ -107,7 +107,7 @@ int main(int argc, char **argv) { if(end-start != TIME - TIME) { snprintf(errorbuf,sizeof(errorbuf),"time spent blocking is not %d, but %ld", TIME - TIME, (long int) (end-start)); - e(8, "time spent blocking is not %d, but %ld"); + e(8, errorbuf); } /* Wait for read to become ready on O_WRONLY. This should fail immediately. */ diff --git a/test/test2.c b/test/test2.c index a12077717..7c08a0f93 100644 --- a/test/test2.c +++ b/test/test2.c @@ -25,7 +25,6 @@ _PROTOTYPE(void test2d, (void)); _PROTOTYPE(void test2e, (void)); _PROTOTYPE(void test2f, (void)); _PROTOTYPE(void test2g, (void)); -_PROTOTYPE(void test2h, (void)); _PROTOTYPE(void sigpip, (int s)); _PROTOTYPE(void quit, (void)); _PROTOTYPE(void e, (int n)); @@ -55,7 +54,6 @@ char *argv[]; if (m & 0020) test2e(); if (m & 0040) test2f(); if (m & 0100) test2g(); - if (m & 0200) test2h(); } subtest = 100; if (cumsig != ITERATIONS) e(101); @@ -357,19 +355,6 @@ void test2g() if (tmsbuf.tms_cstime < 0) e(11); } -void test2h() -{ -/* Test getgroups(). */ - - gid_t g[10]; - - subtest = 8; - errno = -8000; - if (getgroups(10, g) != 0) e(1); - if (getgroups(1, g) != 0) e(2); - if (getgroups(0, g) != 0) e(3); -} - void sigpip(s) int s; /* for ANSI */ { diff --git a/tools/Makefile b/tools/Makefile index f81db6a0c..e41743c53 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -16,6 +16,7 @@ PROGRAMS= ../kernel/kernel \ ../servers/ds/ds \ ../servers/mfs/mfs \ ../servers/vm/vm \ + ../servers/pfs/pfs \ ../servers/init/init usage: -- 2.44.0