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 -/* 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 +#include +#include -#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 */ - -/* For REQ_GETDENTS */ -#define RES_GDE_POS_CHANGE m2_l1 -#define RES_GDE_CUM_IO m2_i1 - -/* For REQ_RDLINK */ -#define RES_RDL_LENGTH m6_l1 - -/* 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 NREQS 55 +/* 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). */ + +/* VFS/FS error messages */ #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). - */ +/* VFS/FS types */ + +/* 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 (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 + 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; + struct dir_record *dir = NULL; -/* 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 { */ 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; */ + 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; + 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); } + +/*===========================================================================* + * load_dir_record_from_disk * + *===========================================================================*/ +PUBLIC struct dir_record *load_dir_record_from_disk(address) +u32_t address; +{ /* This function load a particular dir record from a specific address * on the device */ -PUBLIC struct dir_record *load_dir_record_from_disk(address) - u32_t address; -{ + 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; + 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; + /* 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; + /* 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 */ + 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 */ - /* 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; + 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)); +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 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; - - /* 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_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 */ + + + if (r == EENTERMOUNT) { + fs_m_out.RES_OFFSET = offset; + release_dir_record(dir); } - 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 */ - -/* /\* Drop inode (path parse increased the counter) *\/ */ -/* release_dir_record(dir); */ - - if (r == EENTERMOUNT) - 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 * - *===========================================================================*/ -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 * - *===========================================================================*/ -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 * - *===========================================================================*/ -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 */ + 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; + 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; - } + /*If no file extension, then remove final '.'*/ + if (name[strlen(name) - 1] == '.') + name[strlen(name) - 1] = '\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 (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; + } - cur_pos += dir_tmp->length; - release_dir_record(dir_tmp); - } + /* 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); + } - 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 * + * read_chunk * *===========================================================================*/ -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 * - *===========================================================================*/ -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; + int access = 0, size; + int j; + iovec_t *v; + static iovec_t *new_iovec; - STATICINIT(new_iovec, NR_IOREQS); + STATICINIT(new_iovec, NR_IOREQS); + + /* Number of grants allocated in vector I/O. */ + *vec_grants = 0; - /* 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); + } - /* Driver can handle it - change request to a safe one. */ + break; + case MFS_DEV_GATHER: + case MFS_DEV_SCATTER: + /* Change to safe op. */ + *op = *op == MFS_DEV_GATHER ? DEV_GATHER_S : DEV_SCATTER_S; - *gid = GRANT_INVALID; + /* 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)++; + } - 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; + /* Set user's vector to the new one. */ + *buf = new_iovec; + break; + } - 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); - } + /* 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; + } - 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; - } - - /* 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; + /* 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) { + 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); } - if (!rip) - { + 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); + } 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); } - 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 > rip->i_count) - { - printf("put_inode: count too high: %d > %d\n", 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 * + * remove_dir * *===========================================================================*/ -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 * - *===========================================================================*/ -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,62 +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 * + * unlink_file * *===========================================================================*/ -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) +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 */ @@ -512,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(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(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 */ @@ -533,252 +270,9 @@ char file_name[NAME_MAX]; /* name of file to be removed */ /*===========================================================================* - * unlink_file_nocheck * + * fs_rename * *===========================================================================*/ -PRIVATE int unlink_file_nocheck(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_nocheck(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_nocheck(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); -} - - -/*===========================================================================* - * fs_rename_o * - *===========================================================================*/ -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; + 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(end > rip->i_size) /* freeing beyond end makes no sense */ + end = rip->i_size; + if(end <= start) /* end is uninclusive, so starti_size) - zeroblock_half(rip, end, FIRST_HALF); - } + zone_size = rip->i_sp->s_block_size << rip->i_sp->s_log_zone_size; + dev = rip->i_dev; /* device on which inode resides */ - /* 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 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); + } - rip->i_update |= CTIME | MTIME; - rip->i_dirt = DIRTY; + /* 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); - return OK; + 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; + 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); + 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; + endpoint_t src; - caller_uid = -1; /* To trap errors */ - caller_gid = -1; + /* 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; - } + /* 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); + /* This must be a regular VFS request. */ + assert(src == VFS_PROC_NR && !unmountdone); - 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; + } + ind = req_nr - VFS_BASE; - 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();*/ + } - 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); - fs_m_out.m_type = error; - reply(src, &fs_m_out); - - if (error == OK && rdahed_inode != NIL_INODE) { - read_ahead(); /* do block read ahead */ - } + 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("%s:%d fs_readsuper: safecopyfrom failed: %d\n", + __FILE__, __LINE__, 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("mfs:fs_readsuper: safecopyfrom failed: %d\n", 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); } - 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; - } - - 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,158 +85,39 @@ 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() -{ -/* 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. - */ - 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; - } - - 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() +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. @@ -252,23 +127,21 @@ PUBLIC int fs_mountpoint_s() 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 = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) + return(EINVAL); + + + 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; + + 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. */ + 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 ((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); + + /* 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); - 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. - */ - 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 */ - } - - /* Sync the disk, and invalidate cache. */ - (void) fs_sync(); /* force any cached blocks out of memory */ - /* 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,152 +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 * + * fs_create * *===========================================================================*/ -PUBLIC int fs_create_o() +PUBLIC int fs_create() { phys_bytes len; int r, b; @@ -166,156 +29,54 @@ PUBLIC int fs_create_o() /* 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 * - *===========================================================================*/ -PUBLIC int fs_create_s() -{ - 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 */ + /* 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; + return(OK); } /*===========================================================================* - * fs_mknod_o * + * fs_mknod * *===========================================================================*/ -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); -} - - -/*===========================================================================* - * fs_mknod_s * - *===========================================================================*/ -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,77 +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() -{ - 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_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 mkdir() failed\n", SELF_E); - 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() +PUBLIC int fs_mkdir() { int r1, r2; /* status codes */ ino_t dot, dotdot; /* inode numbers for . and .. */ @@ -428,28 +119,26 @@ PUBLIC int fs_mkdir_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); - if (err_code != OK) return err_code; + (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_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); + rip = new_node(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,9 +172,9 @@ printf("MFS(%d) get_inode for parent dir by mkdir() failed\n", SELF_E); /*===========================================================================* - * fs_slink_o * + * fs_slink * *===========================================================================*/ -PUBLIC int fs_slink_o() +PUBLIC int fs_slink() { phys_bytes len; struct inode *sip; /* inode containing symbolic link */ @@ -498,139 +186,60 @@ PUBLIC int fs_slink_o() 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 * - *===========================================================================*/ -PUBLIC int fs_slink_s() -{ - 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; - -#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); + * 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_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; - } - } + 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. */ - 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); - } + 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; - } + 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; + 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 * + * fs_lookup * *===========================================================================*/ -PUBLIC int lookup_o() +PUBLIC int fs_lookup() { - 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 * - *===========================================================================*/ -PUBLIC int fs_lookup_s() -{ - 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 0 - printf("mfs:fs_lookup_s: string '%s', ino %d, root %d\n", - user_path, dir_ino, root_ino); -#endif + 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; + } /* Lookup inode */ - rip= NULL; - r = parse_path_s(dir_ino, root_ino, flags, &rip, &offset, &symlinks); + 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 > 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; + 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; + + return(r); } - if (r != OK && r != EENTERMOUNT) - { - if (rip) panic(__FILE__, "fs_lookup_s: rip should be clear", - (unsigned)rip); - return r; - } + if (r != OK && r != EENTERMOUNT) 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; + 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; /* 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]; + * 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 */ + if(r == EENTERMOUNT) { + fs_m_out.RES_OFFSET = offset; + put_inode(rip); /* Only return a reference to the final object */ + } - return r; + return(r); } /*===========================================================================* - * parse_path_o * + * parse_path * *===========================================================================*/ -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]; - - /* 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 */ - } - - 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 (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); - } - } -} - - -/*===========================================================================* - * parse_path_s * - *===========================================================================*/ -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; - } - - cp= ncp; - continue; /* Just ignore the '..' at a process' - * root. - */ + if(strcmp(component, "..") == 0) { + /* 'rip' is now accessed as directory */ + if ((r = forbidden(rip, X_BIT)) != OK) { + put_inode(rip); + return(r); } + + 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; + cp = next_cp; /* Process subsequent component in next round */ } } + /*===========================================================================* * 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; - } - - put_block(bp, DIRECTORY_BLOCK); - put_inode(rip); - return r; -} - - -/*===========================================================================* - * ltraverse_s * - *===========================================================================*/ -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,333 +305,137 @@ 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; + slen = strlen(suffix); - tl = strlen(suffix); - if (tl > 0) - { + /* 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 */ -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. */ - /* 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) { - 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 'string' is not present in the directory, signal error. */ - if ( (r = search_dir(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) { - 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) { - - /* 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_s1 * - *===========================================================================*/ -PRIVATE int advance_s1(dirp, string, resp) +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 */ -struct inode **resp; /* resulting inode */ +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. */ - int r; ino_t numb; struct inode *rip; /* If 'string' is empty, return an error. */ - if (string[0] == '\0') return ENOENT; + if (string[0] == '\0') { + err_code = ENOENT; + return(NIL_INODE); + } /* Check for NIL_INODE. */ - if (dirp == NIL_INODE) panic(__FILE__, "advance_s: nil dirp", NO_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) { - return(r); + if ( (err_code = search_dir(dirp, string, &numb, LOOK_UP, chk_perm)) != OK) { + return(NIL_INODE); } /* The component has been found in the directory. Get inode. */ if ( (rip = get_inode(dirp->i_dev, (int) numb)) == NIL_INODE) { - return(err_code); + return(NIL_INODE); } - *resp= rip; - return OK; + /* 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] == '.') { + if (!rip->i_sp->s_is_root) { + /* Climbing up mountpoint */ + err_code = ELEAVEMOUNT; + } + } + } + } + + /* 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; + } + + 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,8 +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 */ + } else if(check_permissions) { + r = forbidden(ldir_ptr, bits); /* check access permissions */ + } } if (r != OK) return(r); @@ -1222,184 +630,3 @@ int flag; /* LOOK_UP, ENTER, DELETE or IS_EMPTY */ 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); - - /* 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; - } - } - - /* 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); -} - - -/*===========================================================================* - * 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,57 +43,28 @@ 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,166 +8,21 @@ #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) -{ - int r, usr, seg, rw_flag, chunk, block_size, block_spec; - int partial_cnt, regular, partial_pipe, nrbytes; - 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; - } - } - - 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_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;*/ - - 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); - } - - 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 */ - } - - 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) */ - } - } - } - - /* 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 (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) { - 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_readwrite_s * - *===========================================================================*/ -PUBLIC int fs_readwrite_s(void) +PUBLIC int fs_readwrite(void) { int r, rw_flag, chunk, block_size, block_spec; - int partial_cnt, regular, partial_pipe, nrbytes; + int partial_cnt, regular, nrbytes; cp_grant_id_t gid; off_t position, f_size, bytes_left; unsigned int off, cum_io; @@ -177,204 +30,110 @@ PUBLIC int fs_readwrite_s(void) 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; - } - } + /* 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_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;*/ + 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) { - /* Check in advance to see if file will grow too big. */ - if (position > rip->i_sp->s_max_size - nrbytes) - return(EFBIG); + /* 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); + /* 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; + off = (unsigned int) (position % block_size);/* offset in blk*/ + chunk = MIN(nrbytes, 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; - } + if (chunk < 0) chunk = block_size - off; - /* 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 (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 (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; /* 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 */ + 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; + fs_m_out.RES_NBYTES = cum_io; return(r); } /*===========================================================================* - * fs_breadwrite_o * + * fs_breadwrite * *===========================================================================*/ -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 */ - } - - 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; - - return(r); -} - - -/*===========================================================================* - * fs_breadwrite_s * - *===========================================================================*/ -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; + * 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 */ + 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 */ - /* 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); - 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 */ - /* 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 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; - /* 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); - /* 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__, + 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; - } + 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; + } - if (userbuf_off + tmpbuf_off + reclen > size) - { - /* The user has no space for one more record */ - done= TRUE; + 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; + } - /* 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; + 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); + 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; + 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; + 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; + 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); - } - - /* 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]; + 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; + /* Number of grants allocated in vector I/O. */ + *vec_grants = 0; - /* Driver can handle it - change request to a safe one. */ + /* Driver can handle it - change request to a safe one. */ + *gid = GRANT_INVALID; - *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; - 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; - 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); - } + /* 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); - break; - case VFS_DEV_GATHER: - case VFS_DEV_SCATTER: - /* Change to safe op. */ - *op = *op == VFS_DEV_GATHER ? - DEV_GATHER_S : DEV_SCATTER_S; + 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); - /* 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)++; - } + 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); + /* 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); - } + /* 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); + } - /* 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; - } + /* 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; + /* 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; + int j; - cpf_revoke(gid); - - 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); + } - return OK; + /* 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); } + /*===========================================================================* * 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 */ + 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? */ + 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 */ - } + /* 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); - /* can't fetch stack (e.g. bad virtual addr) */ - if (r != OK) - { + /* 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) { + /* Open executable */ + if ((vp = eat_path(PATH_NOFLAGS)) == NIL_VNODE) return(err_code); + + 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 ENOEXEC; - } - - /* Check access. */ - if ((r = forbidden(vp, X_BIT, 0 /*!use_realuid*/)) != 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; + 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; - } - } + /* 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; - } + 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) - { + 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; - } + 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; - } + /* 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; + 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); + /* 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); - put_vnode(vp); + if (allow_setuid) { + rfp->fp_effuid = new_uid; + rfp->fp_effgid = new_gid; + } - if (r != OK) - { - return r; - } + /* This child has now exec()ced. */ + rfp->fp_execced = 1; - clo_exec(rfp); + /* Check if this is a driver that can now be useful. */ + dmap_endpt_up(rfp->fp_endpoint); - 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(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; + 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'; + 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; + 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++; - } - } - } +/* Invalidate filp. fp_filp_inuse is not cleared, so filp can't be reused + until it is closed first. */ - return n; + 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; + struct vnode *vp, *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; - - 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); + 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); } - /* Request lookup */ - if ((r = lookup_lastdir(0 /*!use_realuid*/, &vp_d)) != OK) - { - put_vnode(vp_o); - 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; + 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); - r= forbidden(vp_od, W_BIT|X_BIT, 0 /*!use_realuid*/); - if (r != OK) - { - put_vnode(vp_od); - return r; + /* 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; + if(strlen(user_fullpath) >= sizeof(old_name)) { + put_vnode(old_dirp); + return(ENAMETOOLONG); } - memcpy(old_name, user_fullpath, len+1); - + strcpy(old_name, user_fullpath); + /* 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; - } - - /* Request lookup */ - r = lookup_lastdir(0 /*!use_realuid*/, &vp_nd); - if (r != OK) - { - put_vnode(vp_od); - return r; + 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"); + /* 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); - if (fetch_name(m_in.m2_p1, m_in.m2_i1, M1) != OK) return err_code; + /* Ask FS to truncate the file */ + if ((r = forbidden(vp, W_BIT)) == OK) + r = truncate_vnode(vp, m_in.flength); - /* Request lookup */ - if ((r = lookup_vp(0 /*flags*/, 0 /*!use_realuid*/, &vp)) != OK) return r; - - 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) 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 (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 ((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); } -#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; - } - - /* 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; + /* Copy back original mount request message */ + m_in = mount_m_in; - /* Set up last login FS */ - last_login_fs_e = who_e; + /* 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? */ + /* 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; + /* 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; - 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; - } - - /* 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; - 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 - /* 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; + label = dp->dmap_label; + if (strlen(label) == 0) + panic(__FILE__, "VFS mount_fs: no label for major", dev >> MAJOR); + + /* 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); - } + if(tfp->fp_rd) MAKEROOT(tfp->fp_rd); + if(tfp->fp_wd) MAKEROOT(tfp->fp_wd); + } - SANITYCHECK; - - 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) { + 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; + } - /* 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"); - } - } + 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"); + + } } - - SANITYCHECK; - + 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; + fil_ptr->filp_flags = oflags; - 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; - } + /* 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)); - /* 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; + /* 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; - 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; + /* 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; + } - /* 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; + /* 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 * + * new_node * *===========================================================================*/ -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 * - *===========================================================================*/ -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; + struct node_details res; + struct vnode *rest; - /* Check protections. */ - if ((r = forbidden(vp, bits, 0 /*!use_realuid*/)) != OK) - return r; + /* See if the path can be opened down to the last directory. */ + if ((dirp = last_dir()) == NIL_VNODE) return(NIL_VNODE); - /* 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); + /* 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; + /* 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); } - - 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; - } - + /* 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]; +/* 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. + */ - len= strlen(user_fullpath); - if (len == 0) - { - /* Empty path, always fail */ - return ENOENT; - } + 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); + + len = strlen(user_fullpath); + + /* 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'; - } + /* 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; - - /* Copy the directory entry back to user_fullpath */ - strcpy(user_fullpath, dir_entry); - - return OK; -} - - -/*===========================================================================* - * 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; - - if(!fp->fp_rd || !fp->fp_wd) { - printf("VFS: lookup_lastdir %d: no rd/wd\n", fp->fp_endpoint); - return ENOENT; + 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'; } - vp= (user_fullpath[0] == '/' ? fp->fp_rd : fp->fp_wd); - return lookup_lastdir_rel(vp, use_realuid, vpp); + /* Remove trailing slashes */ + while(cp > user_fullpath && cp[0] == '/') { + cp[0]= '\0'; + cp--; + } + + 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); - } - } - else { + if (!dir_vp) { + panic(__FILE__, + "VFS lookup: can't find mounted partition", + NO_NUM); + } + } 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 */ + 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; + } } - if (r == OK) - r = read_only(vp); - - if (r != OK) { - put_vnode(vp); - return r; - } - - /* 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) { + } 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_breadwrite(vp->v_bfs_e, usr, vp->v_sdev, position, - m_in.nbytes, m_in.buffer, rw_flag, &res_pos, &res_cum_io); + /* 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); - 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); - } + if (r >= 0) { + if (ex64hi(new_pos)) + panic(__FILE__, "read_write: bad new pos", NO_NUM); - - /* 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 - - /* 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); - - 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; + 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); - - /* 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; + int r; + cp_grant_id_t grant_id; + 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); + 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); - /* 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; + /* 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; - /* Send/rec request */ - r = fs_sendrec(fs_e, &m); + /* Send/rec request */ + r = fs_sendrec(fs_e, &m); + cpf_revoke(grant_id); + if (r != OK) return(r); - cpf_revoke(gid); + /* Fill in response structure */ + *new_posp = make64(m.RES_SEEK_POS_LO, m.RES_SEEK_POS_HI); + *cum_iop = m.RES_NBYTES; - 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; - - return OK; + return(OK); } @@ -88,23 +85,21 @@ ino_t inode_nr; mode_t rmode; mode_t *new_modep; { - message m; - int r; + 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; + /* Fill in request message */ + m.m_type = REQ_CHMOD; + m.REQ_INODE_NR = inode_nr; + m.REQ_MODE = rmode; - /* Send/rec request */ - r = fs_sendrec(fs_e, &m); + /* Send/rec request */ + r = fs_sendrec(fs_e, &m); + + /* Copy back actual mode. */ + *new_modep = m.RES_MODE; - /* 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; + 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; + /* 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); + /* Send/rec request */ + r = fs_sendrec(fs_e, &m); - /* Return new mode to caller. */ - *new_modep = m.RES_MODE; + /* Return new mode to caller. */ + *new_modep = m.RES_MODE; - return r; + 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; + 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); + 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; + /* 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); + /* Send/rec request */ + r = fs_sendrec(fs_e, &m); + cpf_revoke(grant_id); + if (r != OK) return(r); - 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; + /* 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; + 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; - - /* 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; + 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); - 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; + 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; + } - 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; - - r = fs_sendrec(fs_e, &m); - - *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; + message 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); + /* 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; + int r; + cp_grant_id_t grant_id; + 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); + 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); - /* 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; + /* 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; - /* Send/rec request */ - r = fs_sendrec(fs_e, &m); - - cpf_revoke(gid); - - 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; -#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 + 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); - 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; + len = strlen(user_fullpath) + 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; + 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; - /* Send/rec request */ - r = fs_sendrec(fs_e, &m); + 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; - cpf_revoke(grant_id); + /* 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]; - /* 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; - } + 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); - return r; + 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; + } + + m.REQ_FLAGS = flags; + + /* 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; + 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); - 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; - /* 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); - /* Send/rec request */ - r = fs_sendrec(fs_e, &m); - - cpf_revoke(grant_id); - - return r; + 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; + 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); - 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; + /* 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; + 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; + /* 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); + /* 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; + 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; + 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; + message m; + int r; - /* Fill in request message */ - m.m_type = REQ_NEW_DRIVER; - m.REQ_DEV = dev; - m.REQ_DRIVER_E = driver_e; + /* 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; - } + /* 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; + 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; + message m; + int r; + cp_grant_id_t grant_id; - 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); + 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); - /* Fill in request message */ - m.m_type = REQ_RDLINK_S; - m.REQ_INODE_NR = inode_nr; - m.REQ_GRANT = gid; - m.REQ_SLENGTH = len; + /* 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); - /* Send/rec request */ - r= fs_sendrec(fs_e, &m); + if(r == OK) r = m.RES_NBYTES; - if (r != ENOSYS && r != EINVAL) { - cpf_revoke(gid); - - if (r == OK) - r = m.RES_RDL_LENGTH; - - return r; - } - - /* 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; - - r= fs_sendrec(fs_e, &m); - - cpf_revoke(gid); - - 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; + 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); - 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; + 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); - /* 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; + 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; + } - /* 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; + 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; + int r; + cp_grant_id_t grant_id; + message m; - if (ex64hi(pos) != 0) - panic(__FILE__, "req_readwrite: pos too large", NO_NUM); + 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); + 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 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); + /* 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); - cpf_revoke(gid); - - if (r != OK) return r; - - /* Fill in response structure */ - *new_posp = cvul64(m.RES_FD_POS); - *cum_iop = m.RES_FD_CUM_IO; - - 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; + 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); + 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); - /* 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; + 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); - /* Send/rec request */ - r = fs_sendrec(fs_e, &m); + /* 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); - cpf_revoke(gid_old); - cpf_revoke(gid_new); - - return r; + 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; + 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); - 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; + m.REQ_INODE_NR = inode_nr; + m.REQ_GRANT = grant_id; + m.REQ_PATH_LEN = len; - /* 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; + /* Send/rec request */ + r = fs_sendrec(fs_e, &m); + cpf_revoke(grant_id); - /* Send/rec request */ - r = fs_sendrec(fs_e, &m); - - cpf_revoke(gid); - - 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; + 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); + 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); - } + 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; + /* 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); + /* Send/rec request */ + r = fs_sendrec(fs_e, &m); + cpf_revoke(gid_name); + cpf_revoke(gid_buf); - cpf_revoke(gid_name); - cpf_revoke(gid_buf); - - return r; + 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); + r = fs_sendrec(fs_e, &m); + cpf_revoke(grant_id); - cpf_revoke(gid); - - 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; + 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); - 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; + m.REQ_INODE_NR = inode_nr; + m.REQ_GRANT = grant_id; + m.REQ_PATH_LEN = len; - /* 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); - - cpf_revoke(gid); - - 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; + 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; - - /* 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; - } + /* 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 */ + /* 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 */ + if (reqm->m_type == -EENTERMOUNT || reqm->m_type == -ELEAVEMOUNT || + reqm->m_type == -ESYMLINK) { - if (reqm->m_type == -EENTERMOUNT || reqm->m_type == -ELEAVEMOUNT || - reqm->m_type == -ESYMLINK) { + reqm->m_type = -reqm->m_type; + 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++; - } + 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++; + } - return; + 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); + int fd_setsize, r; + endpoint_t src_e, dst_e; + fd_set *src_fds, *dst_fds; - /* Only copy back as many bits as the user expects. */ - fd_setsize = _FDSETWORDS(e->nfds)*_FDSETBITSPERWORD/8; + if(nfds < 0 || nfds > OPEN_MAX) + panic(__FILE__, "select copy_fdsets: nfds wrong", nfds); - 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); + /* 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; - return; + /* 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; + int s; + struct selectentry *se; - s = tmr_arg(timer)->ta_int; - - 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; - } - - if (!selecttab[s].requestor) { -#if DEBUG_SELECT - printf("select: no requestor in watchdog\n"); -#endif - return; - } - - if (selecttab[s].expiry <= 0) { -#if DEBUG_SELECT - printf("select: strange expiry value in watchdog\n", s); -#endif - return; - } - - selecttab[s].expiry = 0; - select_return(&selecttab[s], 0); - return; + } + se = &selecttab[s]; /* Point to select table entry */ + + if (se->requestor == NULL) { +#if DEBUG_SELECT + printf("select: no requestor in watchdog\n"); +#endif + return; + } + + if (se->expiry <= 0) { +#if DEBUG_SELECT + printf("select: strange expiry value in watchdog\n", s); +#endif + return; + } + + se->expiry = 0; + select_return(se, 0); + } + /*===========================================================================* * select_unsuspend_by_endpt * *===========================================================================*/ PUBLIC void select_unsuspend_by_endpt(endpoint_t proc_e) { - int fd, s; + int fd, s, maj; - 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)) { + 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; + if ((vp = eat_path(PATH_NOFLAGS)) == NIL_VNODE) return(err_code); - /* 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; + /* 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,34 +146,16 @@ 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 */ + + /* 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; } -#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; -} -#endif - #define REFVP(v) { vp = (v); CHECKVN(v); vp->v_ref_check++; } #if DO_SANITYCHECKS 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: