- Introduce support for sticky bit.

- Revise VFS-FS protocol and update VFS/MFS/ISOFS accordingly.
- Clean up MFS by removing old, dead code (backwards compatibility is broken by
  the new VFS-FS protocol, anyway) and rewrite other parts. Also, make sure all
  functions have proper banners and prototypes.
- VFS should always provide a (syntactically) valid path to the FS; no need for
  the FS to do sanity checks when leaving/entering mount points.
- Fix several bugs in MFS:
  - Several path lookup bugs in MFS.
  - A link can be too big for the path buffer.
  - A mountpoint can become inaccessible when the creation of a new inode
    fails, because the inode already exists and is a mountpoint.
- Introduce support for supplemental groups.
- Add test 46 to test supplemental group functionality (and removed obsolete
  suppl. tests from test 2).
- Clean up VFS (not everything is done yet).
- ISOFS now opens device read-only. This makes the -r flag in the mount command
  unnecessary (but will still report to be mounted read-write).
- Introduce PipeFS. PipeFS is a new FS that handles all anonymous and
  named pipes. However, named pipes still reside on the (M)FS, as they are part
  of the file system on disk. To make this work VFS now has a concept of
  'mapped' inodes, which causes read, write, truncate and stat requests to be
  redirected to the mapped FS, and all other requests to the original FS.
This commit is contained in:
Thomas Veerman 2009-12-20 20:27:14 +00:00
parent ac900e59ba
commit 958b25be50
94 changed files with 4649 additions and 8732 deletions

View file

@ -434,9 +434,7 @@ char *argv[];
chmod(tty_name, 0620); chmod(tty_name, 0620);
/* Change id. */ /* Change id. */
#if __minix_vmd
initgroups(pwd->pw_name, pwd->pw_gid); initgroups(pwd->pw_name, pwd->pw_gid);
#endif
setgid(pwd->pw_gid); setgid(pwd->pw_gid);
setuid(pwd->pw_uid); setuid(pwd->pw_uid);

View file

@ -31,11 +31,9 @@ char *argv[];
char *p; char *p;
int super; int super;
int loginshell; int loginshell;
#if __minix_vmd
gid_t groups[NGROUPS_MAX]; gid_t groups[NGROUPS_MAX];
int ngroups; int ngroups;
int g; int g;
#endif
smallenv = 0; smallenv = 0;
loginshell = 0; loginshell = 0;
@ -76,10 +74,8 @@ char *argv[];
} }
super = 0; super = 0;
if (getgid() == 0) super = 1; if (getgid() == 0) super = 1;
#if __minix_vmd
ngroups = getgroups(NGROUPS_MAX, groups); ngroups = getgroups(NGROUPS_MAX, groups);
for (g = 0; g < ngroups; g++) if (groups[g] == 0) super = 1; 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 (!super && strcmp(pwd->pw_passwd, crypt("", pwd->pw_passwd)) != 0) {
#if __minix_vmd #if __minix_vmd
@ -103,9 +99,7 @@ char *argv[];
#endif #endif
} }
#if __minix_vmd
initgroups(pwd->pw_name, pwd->pw_gid); initgroups(pwd->pw_name, pwd->pw_gid);
#endif
setgid(pwd->pw_gid); setgid(pwd->pw_gid);
setuid(pwd->pw_uid); setuid(pwd->pw_uid);
if (loginshell) { if (loginshell) {

View file

@ -61,7 +61,7 @@
#define _POSIX_MAX_CANON 255 /* size of the canonical input queue */ #define _POSIX_MAX_CANON 255 /* size of the canonical input queue */
#define _POSIX_MAX_INPUT 255 /* you can type 255 chars ahead */ #define _POSIX_MAX_INPUT 255 /* you can type 255 chars ahead */
#define _POSIX_NAME_MAX DIRSIZ /* max. file name length */ #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_OPEN_MAX 16 /* a process may have 16 files open */
#define _POSIX_PATH_MAX 255 /* a pathname may contain 255 chars */ #define _POSIX_PATH_MAX 255 /* a pathname may contain 255 chars */
#define _POSIX_PIPE_BUF 512 /* pipes writes of 512 bytes must be atomic */ #define _POSIX_PIPE_BUF 512 /* pipes writes of 512 bytes must be atomic */
@ -72,12 +72,13 @@
* traversed in the resolution of a pathname * traversed in the resolution of a pathname
* in the absence of a loop. * 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). */ /* 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. */ /* Some of these old names had better be defined when not POSIX. */
#define _NO_LIMIT 100 /* arbitrary number; limit not enforced */ #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 #if _EM_WSIZE > 2
#define ARG_MAX 262144 /* # bytes of args + environ for exec() */ #define ARG_MAX 262144 /* # bytes of args + environ for exec() */
#else #else
@ -98,6 +99,7 @@
#define STREAM_MAX 20 /* must be the same as FOPEN_MAX in stdio.h */ #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 TZNAME_MAX 3 /* maximum bytes in a time zone name is 3 */
#define SSIZE_MAX 32767 /* max defined byte count for read() */ #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 #define SYMLOOP_MAX 16 /* maximum number of symbolic links that can
* be reliably traversed in the resolution of * be reliably traversed in the resolution of
* a pathname in the absence of a loop. * a pathname in the absence of a loop.

View file

@ -54,6 +54,8 @@
#define SETSID 62 #define SETSID 62
#define GETPGRP 63 #define GETPGRP 63
#define ITIMER 64 #define ITIMER 64
#define GETGROUPS 65
#define SETGROUPS 66
/* Posix signal handling. */ /* Posix signal handling. */
#define SIGACTION 71 #define SIGACTION 71

View file

@ -71,7 +71,8 @@
#define DS_PROC_NR 6 /* data store server */ #define DS_PROC_NR 6 /* data store server */
#define MFS_PROC_NR 7 /* minix root filesystem */ #define MFS_PROC_NR 7 /* minix root filesystem */
#define VM_PROC_NR 8 /* memory server */ #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. */ /* Root system process and root user process. */
#define ROOT_SYS_PROC_NR RS_PROC_NR #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_FORK_NB (PM_RQ_BASE + 8) /* Non-blocking fork */
#define PM_UNPAUSE (PM_RQ_BASE + 9) /* Interrupt process call */ #define PM_UNPAUSE (PM_RQ_BASE + 9) /* Interrupt process call */
#define PM_REBOOT (PM_RQ_BASE + 10) /* System reboot */ #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 */ /* Replies from VFS to PM */
#define PM_SETUID_REPLY (PM_RS_BASE + 21) #define PM_SETUID_REPLY (PM_RS_BASE + 21)
@ -764,6 +766,7 @@
#define PM_FORK_NB_REPLY (PM_RS_BASE + 28) #define PM_FORK_NB_REPLY (PM_RS_BASE + 28)
#define PM_UNPAUSE_REPLY (PM_RS_BASE + 29) #define PM_UNPAUSE_REPLY (PM_RS_BASE + 29)
#define PM_REBOOT_REPLY (PM_RS_BASE + 30) #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 */ /* Standard parameters for all requests and replies, except PM_REBOOT */
# define PM_PROC m1_i1 /* process */ # define PM_PROC m1_i1 /* process */
@ -772,6 +775,11 @@
# define PM_EID m1_i2 /* effective user/group id */ # define PM_EID m1_i2 /* effective user/group id */
# define PM_RID m1_i3 /* real 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 */ /* Additional parameters for PM_EXEC */
# define PM_PATH m1_p1 /* executable */ # define PM_PATH m1_p1 /* executable */
# define PM_PATH_LEN m1_i2 /* length of path including # define PM_PATH_LEN m1_i2 /* length of path including

View file

@ -108,10 +108,11 @@
#define I_BLOCK_SPECIAL 0060000 /* block special file */ #define I_BLOCK_SPECIAL 0060000 /* block special file */
#define I_DIRECTORY 0040000 /* file is a directory */ #define I_DIRECTORY 0040000 /* file is a directory */
#define I_CHAR_SPECIAL 0020000 /* character special file */ #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_UID_BIT 0004000 /* set effective uid_t on exec */
#define I_SET_GID_BIT 0002000 /* set effective gid_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 RWX_MODES 0000777 /* mode bits for RWX only */
#define R_BIT 0000004 /* Rwx protection bit */ #define R_BIT 0000004 /* Rwx protection bit */
#define W_BIT 0000002 /* rWx protection bit */ #define W_BIT 0000002 /* rWx protection bit */

View file

@ -22,8 +22,8 @@ typedef struct {long m6l1, m6l2, m6l3; short m6s1, m6s2, m6s3; char m6c1, m6c2;
char *m6p1, *m6p2;} mess_6; char *m6p1, *m6p2;} mess_6;
typedef struct {int m7i1, m7i2, m7i3, m7i4; char *m7p1, *m7p2;} mess_7; 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 {int m8i1, m8i2; char *m8p1, *m8p2, *m8p3, *m8p4;} mess_8;
typedef struct {long m9l1, m9l2, m9l3, m9l4, m9l5; short m9s1, m9s2, m9s3; typedef struct {long m9l1, m9l2, m9l3, m9l4, m9l5;
char m9c1, m9c2; } mess_9; short m9s1, m9s2, m9s3, m9s4; } mess_9;
typedef struct { typedef struct {
endpoint_t m_source; /* who sent the message */ endpoint_t m_source; /* who sent the message */
@ -110,8 +110,7 @@ typedef struct {
#define m9_s1 m_u.m_m9.m9s1 #define m9_s1 m_u.m_m9.m9s1
#define m9_s2 m_u.m_m9.m9s2 #define m9_s2 m_u.m_m9.m9s2
#define m9_s3 m_u.m_m9.m9s3 #define m9_s3 m_u.m_m9.m9s3
#define m9_c1 m_u.m_m9.m9c1 #define m9_s4 m_u.m_m9.m9s4
#define m9_c2 m_u.m_m9.m9c2
/*==========================================================================* /*==========================================================================*
* Minix run-time system (IPC). * * Minix run-time system (IPC). *

View file

@ -1,200 +1,120 @@
#ifndef __MINIX_VFSIF_H
#define __MINIX_VFSIF_H
/* Fields of VFS/FS request messages */ #include <sys/types.h>
#define REQ_INODE_NR m6_l1 #include <limits.h>
#define REQ_CHROOT_NR m6_l2
#define REQ_DEVx m6_l2
#define REQ_GRANT2 m6_l2
#define REQ_UID m6_s1
#define REQ_GID m6_c1
#define REQ_MODE m6_s3
#define REQ_PATH m6_p1
#define REQ_PATH_LEN m6_s2
#define REQ_FLAGS m6_l3
#define REQ_DEV m6_l3
#define REQ_WHO_E m6_l3
#define REQ_GRANT m6_l3
#define REQ_USER_ADDR m6_p2
#define REQ_LENGTH m6_l3
#define REQ_SYMLOOP m6_c2
#define REQ_COUNT m6_l2
#define REQ_NEW_UID m6_s3 /* VFS/FS request fields */
#define REQ_NEW_GID m6_c2 #define REQ_ACTIME m9_l2
#define REQ_COUNT m9_l2
#define REQ_INODE_INDEX m6_l3 #define REQ_DEV m9_l5
#define REQ_DEV2 m9_l1
#define REQ_ACTIME m6_l2 #define REQ_DIR_INO m9_l3
#define REQ_MODTIME m6_l3 #define REQ_DRIVER_E m9_l2
#define REQ_FLAGS m9_s3
#define REQ_VMNT_IND m6_c2 #define REQ_GID m9_s1
#define REQ_SLINK_STORAGE m6_p1 #define REQ_GRANT m9_l2
#define REQ_BOOTTIME m6_l1 #define REQ_GRANT2 m9_l1
#define REQ_DRIVER_E m6_l2 #define REQ_GRANT3 m9_l3
#define REQ_READONLY m6_c1 #define REQ_INODE_NR m9_l1
#define REQ_ISROOT m6_c2 #define REQ_MEM_SIZE m9_l5
#define REQ_MODE m9_s3
#define REQ_REMOUNT m6_c2 #define REQ_MODTIME m9_l3
#define REQ_NBYTES m9_l5
#define REQ_LINKED_FILE m6_l1 #define REQ_PATH_LEN m9_s2
#define REQ_LINK_PARENT m6_l2 #define REQ_PATH_SIZE m9_l5
#define REQ_REN_GRANT_NEW m9_l1
#define REQ_OLD_DIR m6_l2 #define REQ_REN_GRANT_OLD m9_l2
#define REQ_NEW_DIR m6_l3 #define REQ_REN_LEN_NEW m9_s2
#define REQ_SLENGTH m6_s3 #define REQ_REN_LEN_OLD m9_s1
#define REQ_REN_NEW_DIR m9_l4
#define REQ_PIPE_POS m6_l1 #define REQ_REN_OLD_DIR m9_l3
#define REQ_ROOT_INO m9_l4
#define REQ_FD_INODE_NR m2_i1 #define REQ_SEEK_POS_HI m9_l3
#define REQ_FD_WHO_E m2_i2 #define REQ_SEEK_POS_LO m9_l4
#define REQ_FD_GID m2_i2 #define REQ_TRC_END_HI m9_l4
#define REQ_FD_POS m2_i3 #define REQ_TRC_END_LO m9_l5
#define REQ_FD_NBYTES m2_l1 #define REQ_TRC_START_HI m9_l2
#define REQ_FD_SEG m2_l2 #define REQ_TRC_START_LO m9_l3
#define REQ_FD_INODE_INDEX m2_s1 #define REQ_UCRED_SIZE m9_s4
#define REQ_UID m9_s4
#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 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 EENTERMOUNT (-301)
#define ELEAVEMOUNT (-302) #define ELEAVEMOUNT (-302)
#define ESYMLINK (-303) #define ESYMLINK (-303)
/* REQ_L_FLAGS */ /* VFS/FS types */
#define PATH_RET_SYMLINK 1 /* Return a symlink object (i.e.
* do not continue with the contents /* User credential structure */
* of the symlink if it is the last typedef struct {
* component in a path). 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

View file

@ -5,5 +5,6 @@ sys/param.h
*/ */
#define MAXHOSTNAMELEN 256 /* max hostname size */ #define MAXHOSTNAMELEN 256 /* max hostname size */
#define NGROUPS 8 /* max number of supplementary groups */
#endif /* __SYS_PARAM_H__ */ #endif /* __SYS_PARAM_H__ */

View file

@ -34,8 +34,7 @@ struct stat {
#define S_IFIFO 0010000 /* this is a FIFO */ #define S_IFIFO 0010000 /* this is a FIFO */
#define S_ISUID 0004000 /* set user id on execution */ #define S_ISUID 0004000 /* set user id on execution */
#define S_ISGID 0002000 /* set group id on execution */ #define S_ISGID 0002000 /* set group id on execution */
/* next is reserved for future use */ #define S_ISVTX 0001000 /* save swapped text even after use */
#define S_ISVTX 01000 /* save swapped text even after use */
/* POSIX masks for st_mode. */ /* POSIX masks for st_mode. */
#define S_IRWXU 00700 /* owner: rwx------ */ #define S_IRWXU 00700 /* owner: rwx------ */

View file

@ -118,6 +118,7 @@ _PROTOTYPE( gid_t getegid, (void) );
_PROTOTYPE( uid_t geteuid, (void) ); _PROTOTYPE( uid_t geteuid, (void) );
_PROTOTYPE( gid_t getgid, (void) ); _PROTOTYPE( gid_t getgid, (void) );
_PROTOTYPE( int getgroups, (int _gidsetsize, gid_t _grouplist[]) ); _PROTOTYPE( int getgroups, (int _gidsetsize, gid_t _grouplist[]) );
_PROTOTYPE( int setgroups, (int _ngroups, gid_t const *grps) );
_PROTOTYPE( char *getlogin, (void) ); _PROTOTYPE( char *getlogin, (void) );
_PROTOTYPE( pid_t getpgrp, (void) ); _PROTOTYPE( pid_t getpgrp, (void) );
_PROTOTYPE( pid_t getpid, (void) ); _PROTOTYPE( pid_t getpid, (void) );

View file

@ -74,6 +74,7 @@ PUBLIC struct boot_image image[] = {
{DS_PROC_NR, 0, BVM_F, 4, 4, 0, "ds" }, {DS_PROC_NR, 0, BVM_F, 4, 4, 0, "ds" },
{MFS_PROC_NR, 0, BVM_F, 32, 5, 0, "mfs" }, {MFS_PROC_NR, 0, BVM_F, 32, 5, 0, "mfs" },
{VM_PROC_NR, 0, 0, 32, 2, 0, "vm" }, {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" }, {INIT_PROC_NR, 0, BVM_F, 8, USER_Q, 0, "init" },
}; };

View file

@ -59,6 +59,7 @@ libc_FILES=" \
getw.c \ getw.c \
hypot.c \ hypot.c \
index.c \ index.c \
initgroups.c \
itoa.c \ itoa.c \
loadname.c \ loadname.c \
lock.c \ lock.c \

View file

@ -2,52 +2,17 @@
setgroups.c setgroups.c
*/ */
#include <errno.h> #include <lib.h>
#include <unistd.h> #include <unistd.h>
#include <string.h>
#include <grp.h>
int setgroups(int ngroups, const gid_t *gidset) int setgroups(int ngroups, const gid_t *gidset)
{ {
if(ngroups > 1) { message m;
/* Supplementary groups not implemented */
errno= EINVAL;
return -1;
}
if(ngroups == 1) m.m1_p1 = gidset;
return setgid(gidset[0]); 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;
}

View file

@ -8,7 +8,7 @@ _mnx_Mode_t mode;
{ {
message m; message m;
m.m3_i1 = fd; m.m1_i1 = fd;
m.m3_i2 = mode; m.m1_i2 = mode;
return(_syscall(FS, FCHMOD, &m)); return(_syscall(FS, FCHMOD, &m));
} }

View file

@ -1,18 +1,17 @@
/* getgroups.c POSIX 4.2.3 /*
* int getgroups(gidsetsize, grouplist); getgroups.c
* */
* This call relates to suplementary group ids, which are not
* supported in MINIX.
*/
#include <lib.h> #include <lib.h>
#define getgroups _getgroups #define getgroups _getgroups
#include <unistd.h> #include <unistd.h>
#include <time.h>
PUBLIC int getgroups(gidsetsize, grouplist) PUBLIC int getgroups(int ngroups, gid_t *arr)
int gidsetsize;
gid_t grouplist[];
{ {
return(0); message m;
m.m1_i1 = ngroups;
m.m1_p1 = arr;
return(_syscall(MM, GETGROUPS, &m));
} }

View file

@ -96,6 +96,7 @@ libc_FILES=" \
select.s \ select.s \
seekdir.s \ seekdir.s \
setgid.s \ setgid.s \
setgroups.s \
setitimer.s \ setitimer.s \
setsid.s \ setsid.s \
setuid.s \ setuid.s \

View file

@ -18,6 +18,7 @@ all install depend clean:
cd ./pm && $(MAKE) $@ cd ./pm && $(MAKE) $@
cd ./vfs && $(MAKE) $@ cd ./vfs && $(MAKE) $@
cd ./mfs && $(MAKE) $@ cd ./mfs && $(MAKE) $@
cd ./pfs && $(MAKE) $@
cd ./iso9660fs && $(MAKE) $@ cd ./iso9660fs && $(MAKE) $@
cd ./rs && $(MAKE) $@ cd ./rs && $(MAKE) $@
cd ./ds && $(MAKE) $@ cd ./ds && $(MAKE) $@
@ -30,6 +31,7 @@ all install depend clean:
image: image:
cd ./pm && $(MAKE) EXTRA_OPTS=$(EXTRA_OPTS) build cd ./pm && $(MAKE) EXTRA_OPTS=$(EXTRA_OPTS) build
cd ./vfs && $(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 ./mfs && $(MAKE) EXTRA_OPTS=$(EXTRA_OPTS) build
cd ./rs && $(MAKE) EXTRA_OPTS=$(EXTRA_OPTS) build cd ./rs && $(MAKE) EXTRA_OPTS=$(EXTRA_OPTS) build
cd ./ds && $(MAKE) EXTRA_OPTS=$(EXTRA_OPTS) build cd ./ds && $(MAKE) EXTRA_OPTS=$(EXTRA_OPTS) build

View file

@ -15,8 +15,7 @@ LDFLAGS = -i
LIBS = -lsys -ltimers LIBS = -lsys -ltimers
OBJ = main.o table.o mount.o super.o inode.o device.o \ 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 \ utility.o misc.o path.o read.o stadir.o cache.o
protect.o
# build local binary # build local binary
all build: $(SERVER) all build: $(SERVER)

View file

@ -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 PUBLIC struct buf *bp_to_pickup = buf; /* This is a pointer to the next node in the
* buffer cache to pick up*/ * buffer cache to pick up*/
/*===========================================================================* /*===========================================================================*
* get_block * * get_block *
*===========================================================================*/ *===========================================================================*/
@ -103,7 +104,7 @@ register struct buf *bp; /* buffer pointer */
if (r != block_size) { if (r != block_size) {
if (r >= 0) r = END_OF_FILE; if (r >= 0) r = END_OF_FILE;
if (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, SELF_E, (fs_dev>>MAJOR)&BYTE, (fs_dev>>MINOR)&BYTE,
bp->b_blocknr); bp->b_blocknr);

View file

@ -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 */ #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. /* #define NR_ID_INODES 1024 */ /* The ISO9660 doesn't save the inode numbers.
* There is a table that assign to every inode * There is a table that assign to every inode
* a particular id. This number defines the * a particular id. This number defines the
* maximum number of ids the finesystem can * maximum number of ids the filesystem can
* handle */ * handle */
#define NO_ADDRESS -1 /* Error constants */ #define NO_ADDRESS -1 /* Error constants */
@ -64,3 +63,7 @@
#define END_OF_FILE (-104) /* eof detected */ #define END_OF_FILE (-104) /* eof detected */
#define offsetof(type, field) ((size_t)(&((type *)0)->field)) #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 */

View file

@ -1,5 +1,3 @@
/* This file handles the direct communication to the device */
#include "inc.h" #include "inc.h"
#include <minix/vfsif.h> #include <minix/vfsif.h>
@ -9,13 +7,13 @@ FORWARD _PROTOTYPE( int safe_io_conversion, (endpoint_t, cp_grant_id_t *,
int *, cp_grant_id_t *, int, int *, cp_grant_id_t *, int,
endpoint_t *, void **, int *, endpoint_t *, void **, int *,
vir_bytes)); vir_bytes));
FORWARD _PROTOTYPE( void safe_io_cleanup, (cp_grant_id_t, cp_grant_id_t *, FORWARD _PROTOTYPE( void safe_io_cleanup, (cp_grant_id_t, cp_grant_id_t *,
int)); int));
FORWARD _PROTOTYPE( int gen_opcl, (endpoint_t driver_e, int op, FORWARD _PROTOTYPE( int gen_opcl, (endpoint_t driver_e, int op,
Dev_t dev, int proc_e, int flags)); Dev_t dev, int proc_e, int flags));
FORWARD _PROTOTYPE( int gen_io, (int task_nr, message *mess_ptr)); FORWARD _PROTOTYPE( int gen_io, (int task_nr, message *mess_ptr));
/*===========================================================================* /*===========================================================================*
* fs_new_driver * * fs_new_driver *
*===========================================================================*/ *===========================================================================*/
@ -24,7 +22,7 @@ PUBLIC int fs_new_driver(void)
/* New driver endpoint for this device */ /* New driver endpoint for this device */
driver_endpoints[(fs_m_in.REQ_DEV >> MAJOR) & BYTE].driver_e = driver_endpoints[(fs_m_in.REQ_DEV >> MAJOR) & BYTE].driver_e =
fs_m_in.REQ_DRIVER_E; fs_m_in.REQ_DRIVER_E;
return OK; return(OK);
} }
@ -118,6 +116,7 @@ vir_bytes bytes;
return 0; return 0;
} }
/*===========================================================================* /*===========================================================================*
* safe_io_cleanup * * safe_io_cleanup *
*===========================================================================*/ *===========================================================================*/
@ -127,16 +126,17 @@ cp_grant_id_t *gids;
int gids_size; int gids_size;
{ {
/* Free resources (specifically, grants) allocated by safe_io_conversion(). */ /* 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++) for(j = 0; j < gids_size; j++)
cpf_revoke(gids[j]); cpf_revoke(gids[j]);
return; return;
} }
/*===========================================================================* /*===========================================================================*
* dev_open * * dev_open *
*===========================================================================*/ *===========================================================================*/
@ -159,6 +159,7 @@ int flags; /* mode bits and flags */
return(r); return(r);
} }
/*===========================================================================* /*===========================================================================*
* block_dev_io * * block_dev_io *
*===========================================================================*/ *===========================================================================*/
@ -187,14 +188,11 @@ int flags; /* special flags, like O_NONBLOCK */
driver_e = driver_endpoints[(dev >> MAJOR) & BYTE].driver_e; driver_e = driver_endpoints[(dev >> MAJOR) & BYTE].driver_e;
/* See if driver is roughly valid. */ /* See if driver is roughly valid. */
if (driver_e == NONE) { if (driver_e == NONE) return(EDSTDIED);
printf("ISO9660FS(%d) block_dev_io: no driver for dev %x\n", SELF_E, dev);
return EDSTDIED;
}
/* The io vector copying relies on this I/O being for FS itself. */ /* The io vector copying relies on this I/O being for FS itself. */
if(proc_e != SELF_E) { 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); 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 != OK) {
if (r == EDEADSRCDST || r == EDSTDIED || r == ESRCDIED) { 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; driver_endpoints[(dev >> MAJOR) & BYTE].driver_e = NONE;
return r; return(r);
/*dmap_unmap_by_endpt(task_nr); <- in the VFS proc... */
} }
else if (r == ELOCKED) { else if (r == ELOCKED) {
printf("ISO9660FS(%d) ELOCKED talking to %d\n", SELF_E, driver_e); return(r);
return r;
} }
else else
panic(__FILE__,"call_task: can't send/receive", r); panic(__FILE__,"call_task: can't send/receive", r);
} else { } else {
/* Did the process we did the sendrec() for get a result? */ /* Did the process we did the sendrec() for get a result? */
if (m.REP_ENDPT != proc_e) { 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; r = EIO;
} }
} }
/* Task has completed. See if call completed. */ /* Task has completed. See if call completed. */
if (m.REP_STATUS == SUSPEND) { 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) { if(buf != buf_used && r == OK) {
@ -263,6 +259,7 @@ int flags; /* special flags, like O_NONBLOCK */
return(m.REP_STATUS); return(m.REP_STATUS);
} }
/*===========================================================================* /*===========================================================================*
* gen_opcl * * gen_opcl *
*===========================================================================*/ *===========================================================================*/
@ -327,12 +324,13 @@ message *mess_ptr; /* pointer to message for task */
mess_ptr->m_type, mess_ptr->m_type,
proc_e, proc_e,
mess_ptr->REP_ENDPT); mess_ptr->REP_ENDPT);
return EIO; return(EIO);
} }
return OK; return(OK);
} }
/*===========================================================================* /*===========================================================================*
* dev_close * * dev_close *
*===========================================================================*/ *===========================================================================*/
@ -342,3 +340,4 @@ dev_t dev; /* device to close */
{ {
(void) gen_opcl(driver_e, DEV_CLOSE, dev, 0, 0); (void) gen_opcl(driver_e, DEV_CLOSE, dev, 0, 0);
} }

View file

@ -6,125 +6,87 @@
#include "buf.h" #include "buf.h"
#include <minix/vfsif.h> #include <minix/vfsif.h>
/*===========================================================================*
* 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 * * fs_putnode *
*===========================================================================*/ *===========================================================================*/
PUBLIC int 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; 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); 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); release_dir_record(dir);
if (dir == (void *)0) { count = fs_m_in.REQ_COUNT;
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 */
if (count <= 0) { if (count <= 0) return(EINVAL);
printf("put_inode: bad value for count: %d\n", count);
panic(__FILE__, "fs_putnode failed", NO_NUM);
return EINVAL;
}
if (count > dir->d_count) { if (count > dir->d_count) {
printf("put_inode: count too high: %d > %d\n", 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);
return EINVAL;
} }
if (dir->d_count > 1) if (dir->d_count > 1)
dir->d_count = dir->d_count - count + 1; /* If the dir record should be released this dir->d_count = dir->d_count - count + 1;/*Keep at least one reference*/
operation will bring the counter to 1.
The next function will further decreases it
releasing it completely. */
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) 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) if (dir == NULL)
return EINVAL; return(EINVAL);
if (--dir->d_count == 0) { if (--dir->d_count == 0) {
if (dir->ext_attr != NULL) if (dir->ext_attr != NULL)
dir->ext_attr->count = 0; dir->ext_attr->count = 0;
dir->ext_attr = NULL; dir->ext_attr = NULL;
dir->d_mountpoint = FALSE; dir->d_mountpoint = FALSE;
/* This if checks we remove the good dir record and not another one
* associated to the same id.*/
/* if (dir->id != NULL && dir->id->h_dir_record == dir) */
/* dir->id->h_dir_record = NULL; */
dir->d_prior = NULL; dir->d_prior = NULL;
if (dir->d_next != NULL) if (dir->d_next != NULL)
release_dir_record(dir); release_dir_record(dir);
dir->d_next = NULL; 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) PUBLIC struct dir_record *get_free_dir_record(void)
{ {
/* Get a free dir record */
struct dir_record *dir; struct dir_record *dir;
for(dir = dir_records;dir<&dir_records[NR_ATTR_RECS]; dir++) { for(dir = dir_records; dir < &dir_records[NR_ATTR_RECS]; dir++) {
if (dir->d_count == 0) { /* The record is free */ if (dir->d_count == 0) { /* The record is free */
dir->d_count = 1; /* Set count to 1 */ dir->d_count = 1; /* Set count to 1 */
dir->ext_attr = NULL; dir->ext_attr = NULL;
return dir; 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) 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; struct dir_record *dir = NULL;
u32_t address; 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 */ /* Search through the cache if the inode is still present */
for(i = 0; i < NR_DIR_RECORDS && dir == NULL; ++i) { 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) { if (dir_records[i].d_ino_nr == id_dir_record
dir = dir_records + i; && dir_records[i].d_count > 0) {
dir->d_count++; dir = dir_records + i;
} dir->d_count++;
}
} }
if (dir == NULL) { if (dir == NULL) {
address = (u32_t)id_dir_record; address = (u32_t)id_dir_record;
dir = load_dir_record_from_disk(address); dir = load_dir_record_from_disk(address);
} }
if (dir == NULL) if (dir == NULL) return(NULL);
return NULL;
else return(dir);
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) { PUBLIC struct ext_attr_rec *get_free_ext_attr(void) {
/* Get a free extended attribute structure */
struct ext_attr_rec *dir; struct ext_attr_rec *dir;
for(dir = ext_attr_recs;dir<&ext_attr_recs[NR_ATTR_RECS]; dir++) { for(dir = ext_attr_recs; dir < &ext_attr_recs[NR_ATTR_RECS]; dir++) {
if (dir->count == 0) { /* The record is free */ if (dir->count == 0) { /* The record is free */
dir->count = 1; dir->count = 1;
return dir; 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) 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 /* 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->own_id,buffer,sizeof(u32_t));
memcpy(&ext->group_id,buffer + 4,sizeof(u32_t)); memcpy(&ext->group_id,buffer + 4,sizeof(u32_t));
memcpy(&ext->permissions,buffer + 8,sizeof(u16_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->ext_attr_rec_ver,buffer + 180,sizeof(u8_t));
memcpy(&ext->len_esc_seq,buffer + 181,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 */ /* 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; /* If the flag assign id is active it will return the id associated;
* otherwise it will return OK. */ * otherwise it will return OK. */
PUBLIC int create_dir_record(dir,buffer,address)
struct dir_record *dir;
char *buffer;
u32_t address;
{
short size; short size;
size = buffer[0]; 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 /* The data structure dir record is filled with the stream of data
* that is read. */ * that is read. */
@ -219,11 +193,11 @@ PUBLIC int create_dir_record(dir,buffer,address)
/* set memory attrs */ /* set memory attrs */
if ((dir->file_flags & D_TYPE) == D_DIRECTORY) if ((dir->file_flags & D_TYPE) == D_DIRECTORY)
dir->d_mode = I_DIRECTORY; dir->d_mode = I_DIRECTORY;
else 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 | X_BIT;
dir->d_mode |= R_BIT << 3 | X_BIT << 3; dir->d_mode |= R_BIT << 3 | X_BIT << 3;
dir->d_mode |= R_BIT << 6 | X_BIT << 6; 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 */ /* Set physical address of the dir record */
dir->d_phy_addr = address; 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 */ * the cast is safe */
/* if (assign_id == ASSIGN_ID) { */ return(OK);
/* assign_id_to_dir_record(dir); */
/* return ID_DIR_RECORD(dir->id); */
/* } else */
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 /* This function load a particular dir record from a specific address
* on the device */ * on the device */
PUBLIC struct dir_record *load_dir_record_from_disk(address)
u32_t address;
{
int block_nr, offset, block_size, new_pos; int block_nr, offset, block_size, new_pos;
struct buf *bp; struct buf *bp;
struct dir_record *dir, *dir_next, *dir_parent, *dir_tmp; 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 */ bp = get_block(block_nr); /* Read the block from the device */
if (bp == NIL_BUF) if (bp == NIL_BUF)
return NULL; return(NULL);
dir = get_free_dir_record(); /* Get a free record */ dir = get_free_dir_record(); /* Get a free record */
if (dir == NULL) 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); 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; new_pos = offset + dir->length;
dir_parent = dir; dir_parent = dir;
new_address = address + dir->length; new_address = address + dir->length;
while (new_pos < block_size) { while (new_pos < block_size) {
dir_next = get_free_dir_record(); dir_next = get_free_dir_record();
create_dir_record(dir_next, bp->b_data + new_pos, new_address); 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); if (dir_next->length > 0) {
name[dir_next->length_file_id] = '\0'; strncpy(name,dir_next->file_id,dir_next->length_file_id);
strncpy(old_name,dir_parent->file_id,dir_parent->length_file_id); name[dir_next->length_file_id] = '\0';
old_name[dir_parent->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) { if (strcmp(name, old_name) == 0) {
dir_parent->d_next = dir_next; dir_parent->d_next = dir_next;
dir_next->d_prior = dir_parent; dir_next->d_prior = dir_parent;
/* Link the dir records */ /* Link the dir records */
dir_tmp = dir_next; dir_tmp = dir_next;
size = dir_tmp->data_length_l; size = dir_tmp->data_length_l;
/* Update the file size */ /* Update the file size */
while (dir_tmp->d_prior != NULL) { while (dir_tmp->d_prior != NULL) {
dir_tmp = dir_tmp->d_prior; dir_tmp = dir_tmp->d_prior;
size += dir_tmp->data_length_l; size += dir_tmp->data_length_l;
dir_tmp->d_file_size = size; 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. */ put_block(bp); /* Release the block read. */
return dir; return(dir);
} }

View file

@ -25,44 +25,43 @@ PUBLIC int main(void) {
fs_m_in.m_type = FS_READY; fs_m_in.m_type = FS_READY;
if (send(FS_PROC_NR, &fs_m_in) != OK) { 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; return -1;
} }
for (;;) { for (;;) {
/* Wait for request message. */ /* Wait for request message. */
get_work(&fs_m_in); get_work(&fs_m_in);
error = OK; error = OK;
caller_uid = -1; /* To trap errors */ caller_uid = -1; /* To trap errors */
caller_gid = -1; 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 if (who_e != FS_PROC_NR) { /* If the message is not for us just
* continue */ * continue */
continue; continue;
} }
req_nr = fs_m_in.m_type; req_nr = fs_m_in.m_type;
if (req_nr < VFS_BASE) { if (req_nr < VFS_BASE) {
fs_m_in.m_type += VFS_BASE; fs_m_in.m_type += VFS_BASE;
req_nr = fs_m_in.m_type; req_nr = fs_m_in.m_type;
} }
ind= req_nr-VFS_BASE; ind = req_nr-VFS_BASE;
if (ind < 0 || ind >= NREQS) { if (ind < 0 || ind >= NREQS) {
error = EINVAL; error = EINVAL;
} } else
else error = (*fs_call_vec[ind])(); /* Process the request calling
error = (*fs_call_vec[ind])(); /* Process the request calling * the appropriate function. */
* the appropriate function. */
fs_m_out.m_type = error; fs_m_out.m_type = error;
reply(who_e, &fs_m_out); /* returns the response to VFS */ 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 */ int s; /* receive status */
if (OK != (s = receive(ANY, m_in))) /* wait for message */ 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 */ message *m_out; /* report result */
{ {
if (OK != send(who, m_out)) /* send the message */ 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);
} }

View file

@ -1,14 +1,14 @@
/* Some misc functions */
#include "inc.h" #include "inc.h"
#include <fcntl.h> #include <fcntl.h>
#include <minix/vfsif.h> #include <minix/vfsif.h>
/*===========================================================================* /*===========================================================================*
* fs_sync * * fs_sync *
*===========================================================================*/ *===========================================================================*/
PUBLIC int fs_sync() /* Calling of syncing the filesystem. No action PUBLIC int fs_sync()
* is taken */
{ {
/* Always mounted read only, so nothing to sync */
return(OK); /* sync() can't fail */ return(OK); /* sync() can't fail */
} }

View file

@ -3,112 +3,76 @@
#include <minix/com.h> #include <minix/com.h>
#include <minix/vfsif.h> #include <minix/vfsif.h>
#include <minix/ds.h> #include <minix/ds.h>
#include "const.h" #include "const.h"
#include "glo.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 * * fs_readsuper *
*===========================================================================*/ *===========================================================================*/
PUBLIC int 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; cp_grant_id_t label_gid;
size_t label_len; size_t label_len;
int r = OK; int r = OK;
unsigned long tasknr; unsigned long tasknr;
endpoint_t driver_e; 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; if (label_len > sizeof(fs_dev_label))
label_len= fs_m_in.REQ_PATH_LEN; return(EINVAL);
if (label_len > sizeof(fs_dev_label)) { r = sys_safecopyfrom(fs_m_in.m_source, label_gid, 0, (vir_bytes)fs_dev_label,
printf("iso9660fs:fs_readsuper: label too long\n"); label_len, D);
return EINVAL;
}
r= sys_safecopyfrom(fs_m_in.m_source, label_gid, 0, (vir_bytes)fs_dev_label,
label_len, D);
if (r != OK) { if (r != OK) {
printf("iso9660fs: fs_readsuper: safecopyfrom failed: %d\n", r); printf("ISOFS %s:%d safecopyfrom failed: %d\n", __FILE__, __LINE__, r);
return EINVAL; return(EINVAL);
} }
r= ds_retrieve_u32(fs_dev_label, &tasknr); r = ds_retrieve_u32(fs_dev_label, &tasknr);
if (r != OK) { if (r != OK) {
printf("mfs:fs_readsuper: ds_retrieve_u32 failed for '%s': %d\n", printf("ISOFS %s:%d ds_retrieve_u32 failed for '%s': %d\n",
fs_dev_label, r); __FILE__, __LINE__, fs_dev_label, r);
return EINVAL; return(EINVAL);
} }
driver_e= tasknr; driver_e = tasknr;
/* Map the driver endpoint for this major */ /* Map the driver endpoint for this major */
driver_endpoints[(fs_dev >> MAJOR) & BYTE].driver_e = driver_e; 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, 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); return(EINVAL);
} }
r = read_vds(&v_pri, fs_dev); /* This function reads the super block on the /* Read the superblock */
* device and save it in v_pri */ r = read_vds(&v_pri, fs_dev);
if (r != OK) if (r != OK)
return(r); return(r);
/* Return some root inode properties */ /* Return some root inode properties */
fs_m_out.RES_INODE_NR = ID_DIR_RECORD(v_pri.dir_rec_root); 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_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_FILE_SIZE_LO = v_pri.dir_rec_root->d_file_size;
fs_m_out.RES_UID = 0; /* root */ fs_m_out.RES_UID = SYS_UID; /* Always root */
fs_m_out.RES_GID = 0; /* operator */ fs_m_out.RES_GID = SYS_GID; /* operator */
/* and some partition properties */ return(r);
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_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 /* This function looks up the mount point, it checks the condition whether
* the partition can be mounted on the inode or not. * the partition can be mounted on the inode or not.
*/ */
@ -118,34 +82,31 @@ PUBLIC int fs_mountpoint_s() {
mode_t bits; mode_t bits;
/* Temporarily open the file. */ /* Temporarily open the file. */
if ((rip = get_dir_record(fs_m_in.REQ_INODE_NR)) == NULL) { 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);
return(EINVAL);
}
if (rip->d_mountpoint) if (rip->d_mountpoint)
r= EBUSY; r = EBUSY;
/* If the inode is not a dir returns error */ /* If the inode is not a dir returns error */
if ((rip->d_mode & I_TYPE) != I_DIRECTORY) if ((rip->d_mode & I_TYPE) != I_DIRECTORY)
r = ENOTDIR; r = ENOTDIR;
release_dir_record(rip); release_dir_record(rip);
if (r == OK) if (r == OK)
rip->d_mountpoint = TRUE; rip->d_mountpoint = TRUE;
return r; return(r);
} }
/* Unmount the filesystem */
/*===========================================================================* /*===========================================================================*
* fs_unmount * * fs_unmount *
*===========================================================================*/ *===========================================================================*/
PUBLIC int fs_unmount(void) { PUBLIC int fs_unmount(void) {
release_v_pri(&v_pri); /* Release the super block */ release_v_pri(&v_pri); /* Release the super block */
dev_close(driver_endpoints[(fs_dev >> MAJOR) & BYTE].driver_e, fs_dev); dev_close(driver_endpoints[(fs_dev >> MAJOR) & BYTE].driver_e, fs_dev);
return(OK);
return OK;
} }

View file

@ -5,159 +5,75 @@
#include "buf.h" #include "buf.h"
FORWARD _PROTOTYPE(char *get_name, (char *old_name, char string [NAME_MAX])); FORWARD _PROTOTYPE( char *get_name, (char *name, char string[NAME_MAX+1]) );
FORWARD _PROTOTYPE( char *get_name_s, (char *name, char string[NAME_MAX+1]) ); FORWARD _PROTOTYPE( int parse_path, (ino_t dir_ino, ino_t root_ino, int flags,
FORWARD _PROTOTYPE( int parse_path_s, (ino_t dir_ino, ino_t root_ino, struct dir_record **res_inop,
int flags, struct dir_record **res_inop, size_t *offsetp) );
size_t *offsetp));
FORWARD _PROTOTYPE( int advance_s, (struct dir_record *dirp,
char string[NAME_MAX], struct dir_record **resp));
/* Lookup is a function used to ``look up" a particular path. It is called
* very often. */
/*===========================================================================*
* lookup *
*===========================================================================*/
PUBLIC int lookup()
{
char string[PATH_MAX];
int s_error, flags;
int len;
struct dir_record *dir;
string[0] = '\0';
/* Check length. */
len = fs_m_in.REQ_PATH_LEN;
if(len > sizeof(user_path)) return E2BIG; /* too big for buffer */
if(len < 1) return EINVAL; /* too small for \0 */
/* Copy the pathname and set up caller's user and group id */
err_code = sys_datacopy(FS_PROC_NR, (vir_bytes) fs_m_in.REQ_PATH, SELF,
(vir_bytes) user_path, (phys_bytes) len);
if (err_code != OK) {
printf("i9660fs:%s:%d: sys_datacopy failed: %d\n", __FILE__, __LINE__, err_code);
return err_code;
}
/* Verify this is a null-terminated path. */
if(user_path[len-1] != '\0') {
printf("i9660fs:lookup: didn't get null-terminated string.\n");
return EINVAL;
}
caller_uid = fs_m_in.REQ_UID;
caller_gid = fs_m_in.REQ_GID;
flags = fs_m_in.REQ_FLAGS;
/* Clear RES_OFFSET for ENOENT */
fs_m_out.RES_OFFSET= 0;
/* 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; cp_grant_id_t grant;
int r, r1, len, flags; int r, r1, len, flags;
size_t offset, size; size_t offset, size;
ino_t dir_ino, root_ino; ino_t dir_ino, root_ino;
struct dir_record *dir; struct dir_record *dir;
grant= fs_m_in.REQ_L_GRANT; grant = fs_m_in.REQ_GRANT;
size= fs_m_in.REQ_L_PATH_SIZE; /* Size of the buffer */ size = fs_m_in.REQ_PATH_SIZE; /* Size of the buffer */
len = fs_m_in.REQ_L_PATH_LEN; /* including terminating nul */ len = fs_m_in.REQ_PATH_LEN; /* including terminating nul */
offset= fs_m_in.REQ_L_PATH_OFF; /* offset in buffer */ dir_ino = fs_m_in.REQ_DIR_INO;
dir_ino= fs_m_in.REQ_L_DIR_INO; root_ino = fs_m_in.REQ_ROOT_INO;
root_ino= fs_m_in.REQ_L_ROOT_INO; flags = fs_m_in.REQ_FLAGS;
flags = fs_m_in.REQ_L_FLAGS; caller_uid = fs_m_in.REQ_UID;
caller_uid = fs_m_in.REQ_L_UID; caller_gid = fs_m_in.REQ_GID;
caller_gid = fs_m_in.REQ_L_GID;
/* Check length. */ /* Check length. */
if(len > sizeof(user_path)) return E2BIG; /* too big for buffer */ if(len > sizeof(user_path)) return(E2BIG); /* too big for buffer */
if(len < 1)return EINVAL; /* too small */ if(len < 1) return(EINVAL); /* too small */
/* Copy the pathname and set up caller's user and group id */ /* 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, 0, (vir_bytes) user_path,
(vir_bytes) user_path, (phys_bytes) len, D); (phys_bytes) len, D);
if (r != OK) { if (r != OK) {
printf("iso9660fs:fs_lookup_s: sys_safecopyfrom failed: %d\n", r); printf("ISOFS %s:%d sys_safecopyfrom failed: %d\n",
return r; __FILE__, __LINE__, r);
return(r);
} }
/* Verify this is a null-terminated path. */ /* Verify this is a null-terminated path. */
if(user_path[len-1] != '\0') { if(user_path[len-1] != '\0') return(EINVAL);
printf("iso9660fs:fs_lookup_s: didn't get null-terminated string.\n");
return EINVAL;
}
/* Lookup inode */ /* Lookup inode */
dir = NULL; 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) { if (r == ELEAVEMOUNT) {
/* Report offset and the error */ /* Report offset and the error */
fs_m_out.RES_OFFSET = offset; fs_m_out.RES_OFFSET = offset;
fs_m_out.RES_SYMLOOP = 0; fs_m_out.RES_SYMLOOP = 0;
if (dir) panic(__FILE__, "fs_lookup_s: dir should be clear", return(r);
(unsigned)dir);
return r;
} }
if (r != OK && r != EENTERMOUNT) { if (r != OK && r != EENTERMOUNT) return(r);
if (dir)
panic(__FILE__, "fs_lookup_s: dir should be clear", fs_m_out.RES_INODE_NR = ID_DIR_RECORD(dir);
(unsigned)dir); fs_m_out.RES_MODE = dir->d_mode;
return r; 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; 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 = 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;
} }
/* The search dir actually performs the operation of searching for the /* 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; 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 * * parse_path *
*===========================================================================*/ *===========================================================================*/
PUBLIC struct dir_record *parse_path(path, string, action) PRIVATE int parse_path(dir_ino, root_ino, flags, res_inop, offsetp)
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)
ino_t dir_ino; ino_t dir_ino;
ino_t root_ino; ino_t root_ino;
int flags; int flags;
@ -400,10 +200,8 @@ size_t *offsetp;
/* Find starting inode inode according to the request message */ /* Find starting inode inode according to the request message */
if ((start_dir = get_dir_record(dir_ino)) == NULL) { if ((start_dir = get_dir_record(dir_ino)) == NULL) {
printf("I9660FS: couldn't find starting inode req_nr: %d %s\n", req_nr, printf("ISOFS: couldn't find starting inode %d\n", dir_ino);
user_path); return(ENOENT);
printf("%s, %d\n", __FILE__, __LINE__);
return ENOENT;
} }
cp = user_path; cp = user_path;
@ -433,10 +231,10 @@ size_t *offsetp;
ncp = cp; ncp = cp;
} }
else else
ncp = get_name_s(cp, string); ncp = get_name(cp, string);
} else } else
/* Just get the first component */ /* 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 /* Special code for '..'. A process is not allowed to leave a chrooted
* environment. A lookup of '..' at the root of a mounted filesystem * environment. A lookup of '..' at the root of a mounted filesystem
@ -471,7 +269,7 @@ size_t *offsetp;
/* There is more path. Keep parsing. */ /* There is more path. Keep parsing. */
old_dir = start_dir; old_dir = start_dir;
r = advance_s(old_dir, string, &start_dir); r = advance(old_dir, string, &start_dir);
if (r != OK) { if (r != OK) {
release_dir_record(old_dir); 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 * * advance *
*===========================================================================*/ *===========================================================================*/
PUBLIC struct dir_record *advance(pdirp, string) PUBLIC int advance(dirp, string, resp)
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)
struct dir_record *dirp; /* inode for directory to be searched */ struct dir_record *dirp; /* inode for directory to be searched */
char string[NAME_MAX]; /* component name to look for */ char string[NAME_MAX]; /* component name to look for */
struct dir_record **resp; /* resulting inode */ struct dir_record **resp; /* resulting inode */
@ -570,55 +324,11 @@ struct dir_record **resp; /* resulting inode */
return OK; return OK;
} }
/*===========================================================================* /*===========================================================================*
* get_name * * get_name *
*===========================================================================*/ *===========================================================================*/
PRIVATE char *get_name(old_name, string) PRIVATE char *get_name(path_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)
char *path_name; /* path name to parse */ char *path_name; /* path name to parse */
char string[NAME_MAX+1]; /* component extracted from 'old_name' */ 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). * component to 'string' (truncated if necessary, always nul terminated).
* A pointer to the string after the first component of the name as yet * A pointer to the string after the first component of the name as yet
* unparsed is returned. Roughly speaking, * 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, * This routine follows the standard convention that /usr/ast, /usr//ast,
* //usr///ast and /usr/ast/ are all equivalent. * //usr///ast and /usr/ast/ are all equivalent.

View file

@ -20,7 +20,7 @@ PUBLIC int fs_access()
/* Temporarily open the file. */ /* Temporarily open the file. */
if ( (rip = get_dir_record(fs_m_in.REQ_INODE_NR)) == NULL) { 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); return(EINVAL);
} }

View file

@ -4,80 +4,73 @@ struct dir_record;
struct ext_attr_rec; struct ext_attr_rec;
struct iso9660_vd_pri; 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 */ /* main.c */
_PROTOTYPE( int main, (void) ); _PROTOTYPE( int main, (void) );
_PROTOTYPE( void reply, (int who, message *m_out) ); _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 */ /* device.c */
_PROTOTYPE( int block_dev_io, (int op, Dev_t dev, int proc, void *buf, _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, _PROTOTYPE( int dev_open, (endpoint_t driver_e, Dev_t dev, int proc,
int flags)); int flags) );
_PROTOTYPE( void dev_close, (endpoint_t driver_e, Dev_t dev)); _PROTOTYPE( void dev_close, (endpoint_t driver_e, Dev_t dev) );
_PROTOTYPE( int fs_new_driver, (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));
/* inode.c */ /* inode.c */
_PROTOTYPE(int release_dir_record,(struct dir_record *dir)); _PROTOTYPE( int create_dir_record,(struct dir_record *dir, char *buffer,
_PROTOTYPE(struct dir_record *get_free_dir_record,(void)); u32_t address) );
_PROTOTYPE(struct dir_record *get_dir_record,(ino_t id_dir)); _PROTOTYPE( int create_ext_attr,(struct ext_attr_rec *ext, char *buffer));
_PROTOTYPE(struct ext_attr_rec *get_free_ext_attr,(void)); _PROTOTYPE( int fs_getnode, (void) );
_PROTOTYPE(int create_ext_attr,(struct ext_attr_rec *ext, _PROTOTYPE( int fs_putnode, (void) );
char *buffer)); _PROTOTYPE( struct dir_record *get_dir_record, (ino_t id_dir) );
_PROTOTYPE(int create_dir_record,(struct dir_record *dir, char *buffer, _PROTOTYPE( struct dir_record *get_free_dir_record, (void) );
u32_t address)); _PROTOTYPE( struct ext_attr_rec *get_free_ext_attr, (void) );
_PROTOTYPE(struct dir_record *load_dir_record_from_disk,(u32_t address)); _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 */ /* path.c */
int fs_lookup_s(void); _PROTOTYPE( int fs_lookup, (void) );
_PROTOTYPE(struct dir_record *advance,(struct dir_record **dirp, _PROTOTYPE( int advance, (struct dir_record *dirp, char string[NAME_MAX],
char string[NAME_MAX])); struct dir_record **resp) );
_PROTOTYPE( int search_dir, (struct dir_record *ldir_ptr, _PROTOTYPE( int search_dir, (struct dir_record *ldir_ptr,
char string [NAME_MAX], ino_t *numb)); char string [NAME_MAX], ino_t *numb) );
_PROTOTYPE( struct dir_record *parse_path, (char *path,
char string[NAME_MAX], /* protect.c */
int action)); _PROTOTYPE( int fs_access, (void) );
/* read.c */ /* read.c */
int fs_read_s(void); _PROTOTYPE( int fs_read, (void) );
int fs_read(void); _PROTOTYPE( int fs_bread, (void) );
int fs_bread(void); _PROTOTYPE( int fs_getdents, (void) );
int fs_bread_s(void); _PROTOTYPE( int read_chunk, (struct dir_record *rip, u64_t position,
_PROTOTYPE(int read_chunk,(struct dir_record *dir, u64_t position, unsigned off, int chunk, unsigned left,
unsigned off, int chunk, char *buff, int seg, cp_grant_id_t gid, unsigned buf_off,
int usr, int block_size, int *completed)); 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 */ /* utility.c */
_PROTOTYPE(int no_sys, (void)); _PROTOTYPE(int no_sys, (void));
_PROTOTYPE(void panic, (char *who, char *mess, int num)); _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);

View file

@ -1,21 +1,16 @@
/* Functions to reads_file */
#include "inc.h" #include "inc.h"
#include <minix/com.h> #include <minix/com.h>
#include <minix/vfsif.h> #include <minix/vfsif.h>
#include <fcntl.h> #include <fcntl.h>
#include "buf.h" #include "buf.h"
FORWARD _PROTOTYPE( int read_chunk_s, (struct dir_record *rip, off_t position, PRIVATE char getdents_buf[GETDENTS_BUFSIZ];
unsigned off, int chunk, unsigned left,cp_grant_id_t gid,
unsigned buf_off, int block_size, int *completed));
/*===========================================================================* /*===========================================================================*
* fs_read_s * * fs_read *
*===========================================================================*/ *===========================================================================*/
PUBLIC int fs_read_s(void) { PUBLIC int fs_read(void) {
int r, chunk, block_size; int r, chunk, block_size;
int nrbytes; int nrbytes;
cp_grant_id_t gid; cp_grant_id_t gid;
@ -27,14 +22,13 @@ PUBLIC int fs_read_s(void) {
r = OK; r = OK;
/* Try to get inode according to its index */ /* Try to get inode according to its index */
dir = get_dir_record(fs_m_in.REQ_FD_INODE_NR); dir = get_dir_record(fs_m_in.REQ_INODE_NR);
if (dir == NULL) return EINVAL; /* No inode found */ if (dir == NULL) return(EINVAL); /* no inode found */
position = fs_m_in.REQ_SEEK_POS_LO;
position = fs_m_in.REQ_FD_POS; /* start reading from this position */ nrbytes = (unsigned) fs_m_in.REQ_NBYTES; /* number of bytes to read */
nrbytes = (unsigned) fs_m_in.REQ_FD_NBYTES; /* number of bytes to read */
block_size = v_pri.logical_block_size_l; 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; f_size = dir->d_file_size;
rdwt_err = OK; /* set to EIO if disk error occurs */ rdwt_err = OK; /* set to EIO if disk error occurs */
@ -42,135 +36,64 @@ PUBLIC int fs_read_s(void) {
cum_io = 0; cum_io = 0;
/* Split the transfer into chunks that don't span two blocks. */ /* Split the transfer into chunks that don't span two blocks. */
while (nrbytes != 0) { while (nrbytes != 0) {
off = (unsigned int) (position % block_size);/* offset in blk*/ off = (unsigned int) (position % block_size);
chunk = MIN(nrbytes, block_size - off); chunk = MIN(nrbytes, block_size - off);
if (chunk < 0) chunk = block_size - off; if (chunk < 0) chunk = block_size - off;
bytes_left = f_size - position; bytes_left = f_size - position;
if (position >= f_size) break; /* we are beyond EOF */ if (position >= f_size) break; /* we are beyond EOF */
if (chunk > bytes_left) chunk = (int) bytes_left; if (chunk > bytes_left) chunk = (int) bytes_left;
/* Read or write 'chunk' bytes. */ /* Read or write 'chunk' bytes. */
r = read_chunk_s(dir, position, off, chunk, (unsigned) nrbytes, r = read_chunk(dir, cvul64(position), off, chunk, (unsigned) nrbytes,
gid, cum_io, block_size, &completed); gid, cum_io, block_size, &completed);
if (r != OK) break; /* EOF reached */ if (r != OK) break; /* EOF reached */
if (rdwt_err < 0) break; if (rdwt_err < 0) break;
/* Update counters and pointers. */ /* Update counters and pointers. */
nrbytes -= chunk; /* bytes yet to be read */ nrbytes -= chunk; /* bytes yet to be read */
cum_io += chunk; /* bytes read so far */ cum_io += chunk; /* bytes read so far */
position += chunk; /* position within the file */ position += chunk; /* position within the file */
} }
fs_m_out.RES_FD_POS = position; /* It might change later and the VFS has fs_m_out.RES_SEEK_POS_LO = position;
to know this value */
if (rdwt_err != OK) r = rdwt_err; /* check for disk error */ if (rdwt_err != OK) r = rdwt_err; /* check for disk error */
if (rdwt_err == END_OF_FILE) r = OK; 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_NBYTES = cum_io; /*dir->d_file_size;*/
fs_m_out.RES_FD_SIZE = dir->d_file_size;
release_dir_record(dir); release_dir_record(dir);
return(r); 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 * * fs_bread *
*===========================================================================*/ *===========================================================================*/
PUBLIC int fs_bread(void) 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; int nrbytes;
u64_t position; u64_t position;
unsigned int off, cum_io; unsigned int off, cum_io;
mode_t mode_word; mode_t mode_word;
int completed, r2 = OK; 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; r = OK;
/* Get the values from the request message */ rw_flag = (fs_m_in.m_type == REQ_BREAD ? READING : WRITING);
rw_flag = (fs_m_in.m_type == REQ_BREAD_S ? READING : WRITING); gid = fs_m_in.REQ_GRANT;
usr = fs_m_in.REQ_XFD_WHO_E; position = make64(fs_m_in.REQ_SEEK_POS_LO, fs_m_in.REQ_SEEK_POS_HI);
position = make64(fs_m_in.REQ_XFD_POS_LO, fs_m_in.REQ_XFD_POS_HI); nrbytes = (unsigned) fs_m_in.REQ_NBYTES;
nrbytes = (unsigned) fs_m_in.REQ_XFD_NBYTES;
user_addr = fs_m_in.REQ_XFD_USER_ADDR;
seg = fs_m_in.REQ_FD_SEG;
block_size = v_pri.logical_block_size_l; 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 */ rdwt_err = OK; /* set to EIO if disk error occurs */
cum_io = 0; cum_io = 0;
@ -180,38 +103,32 @@ PUBLIC int fs_bread(void)
chunk = MIN(nrbytes, block_size - off); chunk = MIN(nrbytes, block_size - off);
if (chunk < 0) chunk = block_size - off; if (chunk < 0) chunk = block_size - off;
/* Read or write 'chunk' bytes. */ /* Read 'chunk' bytes. */
r = read_chunk(NULL, position, off, chunk, r = read_chunk(dir, position, off, chunk, (unsigned) nrbytes,
user_addr, seg, usr, block_size, &completed); gid, cum_io, block_size, &completed);
if (r != OK) break; /* EOF reached */ if (r != OK) break; /* EOF reached */
if (rdwt_err < 0) break; if (rdwt_err < 0) break;
/* Update counters and pointers. */ /* Update counters and pointers. */
user_addr += chunk; /* user buffer address */
nrbytes -= chunk; /* bytes yet to be read */ nrbytes -= chunk; /* bytes yet to be read */
cum_io += chunk; /* bytes read so far */ cum_io += chunk; /* bytes read so far */
position= add64ul(position, chunk); /* position within the file */ position= add64ul(position, chunk); /* position within the file */
} }
fs_m_out.RES_XFD_POS_LO = ex64lo(position); fs_m_out.RES_SEEK_POS_LO = ex64lo(position);
fs_m_out.RES_XFD_POS_HI = ex64hi(position); fs_m_out.RES_SEEK_POS_HI = ex64hi(position);
if (rdwt_err != OK) r = rdwt_err; /* check for disk error */ if (rdwt_err != OK) r = rdwt_err; /* check for disk error */
if (rdwt_err == END_OF_FILE) r = OK; 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); 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 * * fs_getdents *
*===========================================================================*/ *===========================================================================*/
@ -234,10 +151,10 @@ PUBLIC int fs_getdents(void) {
memset(name_old,'\0',NAME_MAX); memset(name_old,'\0',NAME_MAX);
/* Get input parameters */ /* Get input parameters */
ino= fs_m_in.REQ_GDE_INODE; ino = fs_m_in.REQ_INODE_NR;
gid= fs_m_in.REQ_GDE_GRANT; gid = fs_m_in.REQ_GRANT;
size_to_read = fs_m_in.REQ_GDE_SIZE; size_to_read = fs_m_in.REQ_MEM_SIZE;
pos= fs_m_in.REQ_GDE_POS; pos = fs_m_in.REQ_SEEK_POS_LO;
block_size = v_pri.logical_block_size_l; block_size = v_pri.logical_block_size_l;
cur_pos = pos; /* The current position */ cur_pos = pos; /* The current position */
@ -245,187 +162,128 @@ PUBLIC int fs_getdents(void) {
userbuf_off = 0; userbuf_off = 0;
memset(getdents_buf, '\0', GETDENTS_BUFSIZ); /* Avoid leaking any data */ memset(getdents_buf, '\0', GETDENTS_BUFSIZ); /* Avoid leaking any data */
if ((dir = get_dir_record(ino)) == NULL) { if ((dir = get_dir_record(ino)) == NULL) return(EINVAL);
printf("I9660FS(%d) get_dir_record by fs_getdents() failed\n", SELF_E);
return(EINVAL);
}
block = dir->loc_extent_l; /* First block of the directory */ block = dir->loc_extent_l; /* First block of the directory */
block += pos / block_size; /* Shift to the block where start to read */ block += pos / block_size; /* Shift to the block where start to read */
done = FALSE; done = FALSE;
while (cur_pos<dir->d_file_size) { while (cur_pos<dir->d_file_size) {
bp = get_block(block); /* Get physical block */ bp = get_block(block); /* Get physical block */
if (bp == NIL_BUF) { if (bp == NIL_BUF) {
release_dir_record(dir); release_dir_record(dir);
return EINVAL; 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_pos<block_size) { while (block_pos < block_size) {
dir_tmp = get_free_dir_record(); dir_tmp = get_free_dir_record();
create_dir_record(dir_tmp,bp->b_data + block_pos, create_dir_record(dir_tmp,bp->b_data + block_pos,
block*block_size + block_pos); block*block_size + block_pos);
if (dir_tmp->length == 0) { /* EOF. I exit and return 0s */ if (dir_tmp->length == 0) { /* EOF. I exit and return 0s */
block_pos = block_size; block_pos = block_size;
done = TRUE; done = TRUE;
release_dir_record(dir_tmp); release_dir_record(dir_tmp);
} else { /* The dir record is valid. Copy data... */ } else { /* The dir record is valid. Copy data... */
if (dir_tmp->file_id[0] == 0) strcpy(name,"."); if (dir_tmp->file_id[0] == 0) strcpy(name,".");
else if (dir_tmp->file_id[0] == 1) strcpy(name,".."); else if (dir_tmp->file_id[0] == 1) strcpy(name,"..");
else { else {
/* These next functions will extract the name from the field /* Extract the name from the field file_id */
* file_id */ strncpy(name, dir_tmp->file_id,
strncpy(name,dir_tmp->file_id,dir_tmp->length_file_id); dir_tmp->length_file_id);
name[dir_tmp->length_file_id] = 0; 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;
/* If there is no extension I remove the last '.' */ /* Tidy up file name */
if (name[strlen(name) - 1] == '.') cp = memchr(name, ';', NAME_MAX);
name[strlen(name) - 1] = '\0'; if (cp != NULL) name[cp - name] = 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);
userbuf_off += tmpbuf_offset; /*If no file extension, then remove final '.'*/
tmpbuf_offset= 0; if (name[strlen(name) - 1] == '.')
} name[strlen(name) - 1] = '\0';
}
/* The standard data structure is created using the data in the if (strcmp(name_old, name) == 0) {
* buffer. */ cur_pos += dir_tmp->length;
dirp = (struct dirent *)&getdents_buf[tmpbuf_offset]; release_dir_record(dir_tmp);
dirp->d_ino = (ino_t)(bp->b_data + block_pos); continue;
dirp->d_off= cur_pos; }
dirp->d_reclen= reclen;
memcpy(dirp->d_name, name, len); strcpy(name_old,name);
dirp->d_name[len]= '\0';
tmpbuf_offset += reclen; /* 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; /* The standard data structure is created using the
release_dir_record(dir_tmp); * 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 */ put_block(bp); /* release the block */
if (done == TRUE) break; if (done == TRUE) break;
cur_pos += block_size - cur_pos; cur_pos += block_size - cur_pos;
block++; /* read the next one */
block++; /* read the next one */
} }
if (tmpbuf_offset != 0) { if (tmpbuf_offset != 0) {
r= sys_safecopyto(FS_PROC_NR, gid, userbuf_off, r = sys_safecopyto(FS_PROC_NR, gid, userbuf_off,
(vir_bytes)getdents_buf, tmpbuf_offset, D); (vir_bytes) getdents_buf, tmpbuf_offset, D);
if (r != OK) if (r != OK)
panic(__FILE__, "fs_getdents: sys_safecopyto failed\n", r); panic(__FILE__, "fs_getdents: sys_safecopyto failed\n", r);
userbuf_off += tmpbuf_offset; userbuf_off += tmpbuf_offset;
} }
r= ENOSYS; fs_m_out.RES_NBYTES = userbuf_off;
fs_m_out.RES_GDE_POS_CHANGE= 0; /* No change in case of an error */ fs_m_out.RES_SEEK_POS_LO = cur_pos;
/* 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;
release_dir_record(dir); /* release the inode */ release_dir_record(dir); /* release the inode */
r= OK; return(OK);
return(r);
} }
/*===========================================================================* /*===========================================================================*
* fs_getdents_s * * read_chunk *
*===========================================================================*/ *===========================================================================*/
PUBLIC int fs_getdents_o(void) PUBLIC int read_chunk(dir, position, off, chunk, left, gid, buf_off, block_size, completed)
{
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)
register struct dir_record *dir;/* pointer to inode for file to be rd/wr */ 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 */ unsigned off; /* off within the current block */
int chunk; /* number of bytes to read or write */ int chunk; /* number of bytes to read or write */
unsigned left; /* max number of bytes wanted after position */ 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 block_size; /* block size of FS operating on */
int *completed; /* number of bytes copied */ int *completed; /* number of bytes copied */
{ {
/* Read or write (part of) a block. */
register struct buf *bp; register struct buf *bp;
register int r = OK; register int r = OK;
@ -445,21 +302,23 @@ int *completed; /* number of bytes copied */
*completed = 0; *completed = 0;
if ((position <= dir->d_file_size) && (position > dir->data_length_l)) { if ((ex64lo(position) <= dir->d_file_size) &&
while ((dir->d_next != NULL) && (position > dir->data_length_l)) { (ex64lo(position) > dir->data_length_l)) {
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; dir = dir->d_next;
} }
} }
if (dir->inter_gap_size != 0) { 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; file_unit = rel_block / dir->data_length_l;
offset = rel_block % dir->file_unit_size; 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 { } else {
b = dir->loc_extent_l + position / block_size; /* Physical position b = dir->loc_extent_l + div64u(position, block_size); /* Physical position
* to read. */ * to read. */
} }
bp = get_block(b); bp = get_block(b);
@ -476,3 +335,4 @@ int *completed; /* number of bytes copied */
return(r); return(r);
} }

View file

@ -9,12 +9,9 @@
FORWARD _PROTOTYPE(int stat_dir_record, (struct dir_record *dir, int pipe_pos, 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 * * stat_dir_record *
*===========================================================================*/ *===========================================================================*/
@ -24,6 +21,10 @@ int pipe_pos; /* position in a pipe, supplied by fstat() */
int who_e; /* Caller endpoint */ int who_e; /* Caller endpoint */
cp_grant_id_t gid; /* grant for the stat buf */ 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. */ /* Common code for stat and fstat system calls. */
struct stat statbuf; struct stat statbuf;
@ -50,7 +51,7 @@ cp_grant_id_t gid; /* grant for the stat buf */
ltime.tm_isdst = 0; ltime.tm_isdst = 0;
if (dir->rec_date[6] != 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(&ltime); time1 = mktime(&ltime);
@ -60,13 +61,12 @@ cp_grant_id_t gid; /* grant for the stat buf */
/* Copy the struct to user space. */ /* Copy the struct to user space. */
r = sys_safecopyto(who_e, gid, 0, (vir_bytes) &statbuf, r = sys_safecopyto(who_e, gid, 0, (vir_bytes) &statbuf,
(phys_bytes) sizeof(statbuf), D); (phys_bytes) sizeof(statbuf), D);
return(r); return(r);
} }
/* This function is a wrapper to the function above. It is called with the
* request. */
/*===========================================================================* /*===========================================================================*
* fs_stat * * fs_stat *
*===========================================================================*/ *===========================================================================*/
@ -77,14 +77,14 @@ PUBLIC int fs_stat()
r = EINVAL; r = EINVAL;
if ((dir = get_dir_record(fs_m_in.REQ_INODE_NR)) != NULL) { 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); r = stat_dir_record(dir, 0, fs_m_in.m_source, fs_m_in.REQ_GRANT);
release_dir_record(dir); release_dir_record(dir);
} else }
printf("I9660FS(%d) fs_stat() failed\n", SELF_E);
return r; return(r);
} }
/*===========================================================================* /*===========================================================================*
* fs_fstatfs * * fs_fstatfs *
*===========================================================================*/ *===========================================================================*/
@ -97,7 +97,7 @@ PUBLIC int fs_fstatfs()
/* Copy the struct to user space. */ /* Copy the struct to user space. */
r = sys_safecopyto(fs_m_in.m_source, fs_m_in.REQ_GRANT, 0, 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); return(r);
} }

View file

@ -9,58 +9,35 @@
PUBLIC _PROTOTYPE (int (*fs_call_vec[]), (void) ) = { PUBLIC _PROTOTYPE (int (*fs_call_vec[]), (void) ) = {
no_sys, /* 0: not used */ no_sys, /* 0: not used */
fs_getnode, /* 1 */ no_sys, /* 1 */
fs_putnode, /* 2 */ fs_putnode, /* 2 */
no_sys, /* 3: not used */ 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, /* 8: not used */
no_sys, /* 9: not used */ no_sys, /* 9: not used */
no_sys, /* 10: 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 */ no_sys, /* 14: not used */
fs_stat, /* 15 */ 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, /* 19: not used */
no_sys, /* 20: not used */
fs_fstatfs, /* 21 */ fs_fstatfs, /* 21 */
fs_bread_s, /* 22 */ fs_bread, /* 22 */
no_sys, /* 23: not used */ no_sys, /* 23: not used */
no_sys, /* 24: 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, /* 29: not used */
no_sys, /* 30: not used */
fs_readsuper, /* 31 */
fs_unmount, /* 32 */ fs_unmount, /* 32 */
no_sys, /* 33: not used */
fs_sync, /* 34 */ fs_sync, /* 34 */
lookup, /* 35 */
no_sys, /* 36: not used */
fs_new_driver, /* 37 */ fs_new_driver, /* 37 */
fs_bread, /* 38 */
no_sys, /* 39 */
fs_getdents_o, /* 40 */
no_sys, /* 41: not_used */ no_sys, /* 41: not_used */
fs_read_s, /* 42 */ fs_read, /* 42 */
no_sys, /* 43: not used */ no_sys, /* 43: not used */
no_sys, /* 44: not used */ no_sys, /* 44: not used */
no_sys, /* 45: not used */ no_sys, /* 45: not used */
no_sys, /* 46: not used */ no_sys, /* 46: not used */
no_sys, /* 47: not used */ no_sys, /* 47: not used */
no_sys, /* 48: not used */ no_sys, /* 48: not used */
fs_lookup_s, /* 49 */ fs_lookup, /* 49 */
fs_mountpoint_s, /* 50 */ fs_mountpoint, /* 50 */
fs_readsuper_s, /* 51 */ fs_readsuper, /* 51 */
no_sys, /* 52: not used */ no_sys, /* 52: not used */
no_sys, /* 53 */ no_sys, /* 53: not used */
fs_getdents, /* 54 */ fs_getdents, /* 54 */
}; };

View file

@ -1,4 +1,4 @@
# Makefile for File System (FS) # Makefile for Minix File System (MFS)
SERVER = mfs SERVER = mfs
DEST=/sbin/$(SERVER) DEST=/sbin/$(SERVER)
NR_BUFS=1024 NR_BUFS=1024
@ -14,10 +14,10 @@ h = $i/minix
CC = exec cc CC = exec cc
CFLAGS = -I$i $(EXTRA_OPTS) $(CPROFILE) -DNR_BUFS=$(NR_BUFS) CFLAGS = -I$i $(EXTRA_OPTS) $(CPROFILE) -DNR_BUFS=$(NR_BUFS)
LDFLAGS = -i LDFLAGS = -i
LIBS = -lsys -ltimers LIBS = -lsys
OBJ = cache.o device.o link.o \ 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 \ stadir.o table.o time.o utility.o \
write.o inode.o main.o path.o super.o write.o inode.o main.o path.o super.o

View file

@ -303,14 +303,6 @@ int rw_flag; /* READING or WRITING */
/* Report read errors to interested parties. */ /* Report read errors to interested parties. */
if (rw_flag == READING) rdwt_err = r; 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; bp->b_dirt = CLEAN;

View file

@ -5,6 +5,7 @@
#define V2_NR_TZONES 10 /* total # zone numbers in a V2 inode */ #define V2_NR_TZONES 10 /* total # zone numbers in a V2 inode */
#define NR_INODES 256 /* # slots in "in core" inode table */ #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_LOG2 7 /* 2 based logarithm of the inode hash size */
#define INODE_HASH_SIZE ((unsigned long)1<<INODE_HASH_LOG2) #define INODE_HASH_SIZE ((unsigned long)1<<INODE_HASH_LOG2)
@ -47,6 +48,9 @@
/* write_map() args */ /* write_map() args */
#define WMAP_FREE (1 << 0) #define WMAP_FREE (1 << 0)
#define IGN_PERM 0
#define CHK_PERM 1
#define PATH_TRANSPARENT 000 /* parse_path stops at final object */ #define PATH_TRANSPARENT 000 /* parse_path stops at final object */
#define PATH_PENULTIMATE 001 /* parse_path stops at last but one name */ #define PATH_PENULTIMATE 001 /* parse_path stops at last but one name */
#define PATH_OPAQUE 002 /* parse_path stops at final name */ #define PATH_OPAQUE 002 /* parse_path stops at final name */
@ -76,7 +80,6 @@
#define DIR_ENTRY_SIZE usizeof (struct direct) /* # bytes/dir entry */ #define DIR_ENTRY_SIZE usizeof (struct direct) /* # bytes/dir entry */
#define NR_DIR_ENTRIES(b) ((b)/DIR_ENTRY_SIZE) /* # dir entries/blk */ #define NR_DIR_ENTRIES(b) ((b)/DIR_ENTRY_SIZE) /* # dir entries/blk */
#define SUPER_SIZE usizeof (struct super_block) /* super_block size */ #define SUPER_SIZE usizeof (struct super_block) /* super_block size */
#define PIPE_SIZE(b) (V1_NR_DZONES*(b)) /* pipe size in bytes */
#define FS_BITMAP_CHUNKS(b) ((b)/usizeof (bitchunk_t))/* # map chunks/blk */ #define FS_BITMAP_CHUNKS(b) ((b)/usizeof (bitchunk_t))/* # map chunks/blk */
#define FS_BITCHUNK_BITS (usizeof(bitchunk_t) * CHAR_BIT) #define FS_BITCHUNK_BITS (usizeof(bitchunk_t) * CHAR_BIT)

View file

@ -1,4 +1,3 @@
#include "fs.h" #include "fs.h"
#include <fcntl.h> #include <fcntl.h>
#include <assert.h> #include <assert.h>
@ -27,31 +26,6 @@ FORWARD _PROTOTYPE( int gen_opcl, (endpoint_t driver_e, int op,
Dev_t dev, int proc_e, int flags) ); Dev_t dev, int proc_e, int flags) );
FORWARD _PROTOTYPE( int gen_io, (int task_nr, message *mess_ptr) ); 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 * * fs_new_driver *
@ -60,8 +34,8 @@ PUBLIC int fs_new_driver(void)
{ {
/* New driver endpoint for this device */ /* New driver endpoint for this device */
driver_endpoints[(fs_m_in.REQ_DEV >> MAJOR) & BYTE].driver_e = driver_endpoints[(fs_m_in.REQ_DEV >> MAJOR) & BYTE].driver_e =
fs_m_in.REQ_DRIVER_E; fs_m_in.REQ_DRIVER_E;
return OK; return(OK);
} }
@ -80,81 +54,77 @@ void **buf;
int *vec_grants; int *vec_grants;
vir_bytes bytes; vir_bytes bytes;
{ {
int access = 0, size; int access = 0, size;
int j; int j;
iovec_t *v; iovec_t *v;
static iovec_t *new_iovec; 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. */ /* Driver can handle it - change request to a safe one. */
*vec_grants = 0;
*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) { /* Set user's vector to the new one. */
case MFS_DEV_READ: *buf = new_iovec;
case MFS_DEV_WRITE: break;
/* Change to safe op. */ }
*op = *op == MFS_DEV_READ ? DEV_READ_S : DEV_WRITE_S;
if((*gid=cpf_grant_direct(driver, (vir_bytes) *buf, /* If we have converted to a safe operation, I/O
bytes, *op == DEV_READ_S ? CPF_WRITE : * endpoint becomes FS if it wasn't already.
CPF_READ)) < 0) { */
panic(__FILE__, if(GRANT_VALID(*gid)) {
"cpf_grant_magic of buffer failed\n", NO_NUM); *io_ept = SELF_E;
} return 1;
}
break; /* Not converted to a safe operation (because there is no
case MFS_DEV_GATHER: * copying involved in this operation).
case MFS_DEV_SCATTER: */
/* Change to safe op. */ return 0;
*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;
} }
/*===========================================================================* /*===========================================================================*
@ -166,14 +136,14 @@ cp_grant_id_t *gids;
int gids_size; int gids_size;
{ {
/* Free resources (specifically, grants) allocated by safe_io_conversion(). */ /* 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++) for(j = 0; j < gids_size; j++)
cpf_revoke(gids[j]); cpf_revoke(gids[j]);
return; return;
} }
/*===========================================================================* /*===========================================================================*
@ -208,7 +178,7 @@ int flags; /* special flags, like O_NONBLOCK */
/* See if driver is roughly valid. */ /* See if driver is roughly valid. */
if (driver_e == NONE) { if (driver_e == NONE) {
printf("MFS(%d) block_dev_io: no driver for dev %x\n", SELF_E, dev); 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. */ /* 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, mess_ptr->m_type,
proc_e, proc_e,
mess_ptr->REP_ENDPT); mess_ptr->REP_ENDPT);
return EIO; return(EIO);
} }
return OK; return(OK);
} }

View file

@ -4,6 +4,8 @@
#define EXTERN #define EXTERN
#endif #endif
#include <minix/vfsif.h>
EXTERN off_t rdahedpos; /* position to read ahead */ EXTERN off_t rdahedpos; /* position to read ahead */
EXTERN struct inode *rdahed_inode; /* pointer to inode 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_in;
EXTERN message fs_m_out; EXTERN message fs_m_out;
EXTERN int FS_STATE; EXTERN int FS_STATE;
EXTERN vfs_ucred_t credentials;
EXTERN uid_t caller_uid; EXTERN uid_t caller_uid;
EXTERN gid_t caller_gid; EXTERN gid_t caller_gid;

View file

@ -11,25 +11,23 @@
* free_inode: mark an inode as available for a new file * free_inode: mark an inode as available for a new file
* update_times: update atime, ctime, and mtime * update_times: update atime, ctime, and mtime
* rw_inode: read a disk block and extract an inode, or corresp. write * 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 * 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 "fs.h"
#include "buf.h" #include "buf.h"
#include "inode.h" #include "inode.h"
#include "super.h" #include "super.h"
#include <minix/vfsif.h> #include <minix/vfsif.h>
FORWARD _PROTOTYPE( void old_icopy, (struct inode *rip, d1_inode *dip, FORWARD _PROTOTYPE( int addhash_inode, (struct inode *node) );
int direction, int norm));
FORWARD _PROTOTYPE( void new_icopy, (struct inode *rip, d2_inode *dip, FORWARD _PROTOTYPE( void new_icopy, (struct inode *rip, d2_inode *dip,
int direction, int norm)); 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() 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; struct inode *rip;
int count; int count;
/* Sanity check for the direct index */ rip = find_inode(fs_dev, fs_m_in.REQ_INODE_NR);
if (fs_m_in.REQ_INODE_INDEX >= 0 &&
fs_m_in.REQ_INODE_INDEX < NR_INODES && if(!rip) {
inode[fs_m_in.REQ_INODE_INDEX].i_num == fs_m_in.REQ_INODE_NR) { printf("%s:%d put_inode: inode #%d dev: %d not found\n", __FILE__,
rip = &inode[fs_m_in.REQ_INODE_INDEX]; __LINE__, fs_m_in.REQ_INODE_NR, fs_dev);
if(!rip) { panic(__FILE__, "fs_putnode failed", NO_NUM);
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);
}
} }
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); panic(__FILE__, "fs_putnode failed", NO_NUM);
} }
count= fs_m_in.REQ_COUNT; /* Decrease reference counter, but keep one reference; it will be consumed by
if (count <= 0) * put_inode(). */
{
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;
}
rip->i_count -= count - 1; rip->i_count -= count - 1;
put_inode(rip); put_inode(rip);
return OK; 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;
} }
@ -149,9 +103,10 @@ PRIVATE int addhash_inode(struct inode *node)
/* insert into hash table */ /* insert into hash table */
LIST_INSERT_HEAD(&hash_inodes[hashi], node, i_hash); LIST_INSERT_HEAD(&hash_inodes[hashi], node, i_hash);
return OK; return(OK);
} }
/*===========================================================================* /*===========================================================================*
* unhash_inode * * unhash_inode *
*===========================================================================*/ *===========================================================================*/
@ -159,9 +114,10 @@ PRIVATE int unhash_inode(struct inode *node)
{ {
/* remove from hash table */ /* remove from hash table */
LIST_REMOVE(node, i_hash); LIST_REMOVE(node, i_hash);
return OK; return(OK);
} }
/*===========================================================================* /*===========================================================================*
* get_inode * * get_inode *
*===========================================================================*/ *===========================================================================*/
@ -186,7 +142,7 @@ int numb; /* inode number (ANSI: may not be unshort) */
TAILQ_REMOVE(&unused_inodes, rip, i_unused); TAILQ_REMOVE(&unused_inodes, rip, i_unused);
} }
++rip->i_count; ++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 */ /* Inode is not on the hash, get a free one */
if (TAILQ_EMPTY(&unused_inodes)) { if (TAILQ_EMPTY(&unused_inodes)) {
err_code = ENFILE; err_code = ENFILE;
return NIL_INODE; return(NIL_INODE);
} }
rip = TAILQ_FIRST(&unused_inodes); 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 */ 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_update = 0; /* all the times are initially up-to-date */
rip->i_zsearch = NO_ZONE; /* no zones searched for yet */ 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; rip->i_mountpoint= FALSE;
/* Add to hash */ /* Add to hash */
@ -225,6 +177,7 @@ int numb; /* inode number (ANSI: may not be unshort) */
return(rip); return(rip);
} }
/*===========================================================================* /*===========================================================================*
* find_inode * * find_inode *
*===========================================================================*/ *===========================================================================*/
@ -242,11 +195,11 @@ int numb; /* inode number (ANSI: may not be unshort) */
/* Search inode in the hash table */ /* Search inode in the hash table */
LIST_FOREACH(rip, &hash_inodes[hashi], i_hash) { LIST_FOREACH(rip, &hash_inodes[hashi], i_hash) {
if (rip->i_count > 0 && rip->i_num == numb && rip->i_dev == dev) { 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; rip->i_dirt = DIRTY;
free_inode(rip->i_dev, rip->i_num); free_inode(rip->i_dev, rip->i_num);
} }
else {
if (rip->i_pipe == I_PIPE) truncate_inode(rip, 0);
}
rip->i_mountpoint = FALSE; rip->i_mountpoint = FALSE;
if (rip->i_dirt == DIRTY) rw_inode(rip, WRITING); 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); unhash_inode(rip);
rip->i_num = 0; rip->i_num = 0;
TAILQ_INSERT_HEAD(&unused_inodes, rip, i_unused); TAILQ_INSERT_HEAD(&unused_inodes, rip, i_unused);
} } else {
else {
/* unused, put at the back of the LRU (cache it) */ /* unused, put at the back of the LRU (cache it) */
TAILQ_INSERT_TAIL(&unused_inodes, rip, i_unused); 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); return(rip);
} }
/*===========================================================================* /*===========================================================================*
* wipe_inode * * wipe_inode *
*===========================================================================*/ *===========================================================================*/
@ -389,6 +340,7 @@ ino_t inumb; /* number of inode to be freed */
if (b < sp->s_isearch) sp->s_isearch = b; if (b < sp->s_isearch) sp->s_isearch = b;
} }
/*===========================================================================* /*===========================================================================*
* update_times * * update_times *
*===========================================================================*/ *===========================================================================*/
@ -458,6 +410,7 @@ int rw_flag; /* READING or WRITING */
rip->i_dirt = CLEAN; rip->i_dirt = CLEAN;
} }
/*===========================================================================* /*===========================================================================*
* old_icopy * * 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 */ register d1_inode *dip; /* pointer to the d1_inode inode struct */
int direction; /* READING (from disk) or WRITING (to disk) */ int direction; /* READING (from disk) or WRITING (to disk) */
int norm; /* TRUE = do not swap bytes; FALSE = swap */ 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 /* 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 * 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 * * 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 */ register d2_inode *dip; /* pointer to the d2_inode struct */
int direction; /* READING (from disk) or WRITING (to disk) */ int direction; /* READING (from disk) or WRITING (to disk) */
int norm; /* TRUE = do not swap bytes; FALSE = swap */ int norm; /* TRUE = do not swap bytes; FALSE = swap */
{ {
/* Same as old_icopy, but to/from V2 disk layout. */ /* 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 * * dup_inode *
*===========================================================================*/ *===========================================================================*/
@ -559,3 +512,4 @@ struct inode *ip; /* The inode to be duplicated. */
ip->i_count++; ip->i_count++;
} }

View file

@ -32,7 +32,6 @@ EXTERN struct inode {
int i_nindirs; /* # indirect zones per indirect block */ int i_nindirs; /* # indirect zones per indirect block */
struct super_block *i_sp; /* pointer to super block for inode's device */ struct super_block *i_sp; /* pointer to super block for inode's device */
char i_dirt; /* CLEAN or DIRTY */ 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 */ bit_t i_zsearch; /* where to start search for new zones */
char i_mountpoint; /* true if mounted on */ 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 */ #define NIL_INODE (struct inode *) 0 /* indicates absence of inode slot */
/* Field values. Note that CLEAN and DIRTY are defined in "const.h" */ /* 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 NO_SEEK 0 /* i_seek = NO_SEEK if last op was not SEEK */
#define ISEEK 1 /* i_seek = ISEEK if last op was SEEK */ #define ISEEK 1 /* i_seek = ISEEK if last op was SEEK */

File diff suppressed because it is too large Load diff

View file

@ -1,9 +1,7 @@
#include "inc.h" #include "inc.h"
#include <assert.h> #include <assert.h>
#include <minix/dmap.h> #include <minix/dmap.h>
#include <minix/endpoint.h> #include <minix/endpoint.h>
#include <minix/vfsif.h> #include <minix/vfsif.h>
#include "fs.h" #include "fs.h"
#include "buf.h" #include "buf.h"
@ -14,9 +12,9 @@
/* Declare some local functions. */ /* Declare some local functions. */
FORWARD _PROTOTYPE(void init_server, (void) ); FORWARD _PROTOTYPE(void init_server, (void) );
FORWARD _PROTOTYPE(void get_work, (message *m_in) ); FORWARD _PROTOTYPE(void get_work, (message *m_in) );
FORWARD _PROTOTYPE(void cch_check, (void) ); FORWARD _PROTOTYPE(void cch_check, (void) );
/*===========================================================================* /*===========================================================================*
* main * * main *
*===========================================================================*/ *===========================================================================*/
@ -35,114 +33,113 @@ PUBLIC int main(int argc, char *argv[])
fs_m_in.m_type = FS_READY; fs_m_in.m_type = FS_READY;
if (send(FS_PROC_NR, &fs_m_in) != OK) { if (send(FS_PROC_NR, &fs_m_in) != OK) {
printf("MFS(%d): Error sending login to VFS\n", SELF_E); printf("MFS(%d): Error sending login to VFS\n", SELF_E);
return -1; return(-1);
} }
while(!unmountdone || !exitsignaled) { while(!unmountdone || !exitsignaled) {
endpoint_t src; endpoint_t src;
/* Wait for request message. */
get_work(&fs_m_in);
src = fs_m_in.m_source;
error = OK;
caller_uid = -1; /* To trap errors */ /* Wait for request message. */
caller_gid = -1; get_work(&fs_m_in);
src = fs_m_in.m_source;
error = OK;
caller_uid = -1; /* To trap errors */
caller_gid = -1;
/* Exit request? */ /* Exit request? */
if(src == PM_PROC_NR) { if(src == PM_PROC_NR) {
exitsignaled = 1; exitsignaled = 1;
fs_sync(); fs_sync();
continue; continue;
} }
/* This must be a regular VFS request. */ /* This must be a regular VFS request. */
assert(src == VFS_PROC_NR && !unmountdone); 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) if (ind < 0 || ind >= NREQS) {
{ printf("mfs: bad request %d\n", req_nr);
fs_m_in.m_type += VFS_BASE; printf("ind = %d\n", ind);
req_nr = fs_m_in.m_type; error = EINVAL;
} } else {
ind= req_nr-VFS_BASE; error = (*fs_call_vec[ind])();
/*cch_check();*/
}
if (ind < 0 || ind >= NREQS) { fs_m_out.m_type = error;
printf("mfs: bad request %d\n", req_nr); reply(src, &fs_m_out);
printf("ind = %d\n", ind);
error = EINVAL;
}
else {
error = (*fs_call_vec[ind])();
/*cch_check();*/
}
fs_m_out.m_type = error; if (error == OK && rdahed_inode != NIL_INODE)
reply(src, &fs_m_out); read_ahead(); /* do block read ahead */
if (error == OK && rdahed_inode != NIL_INODE) {
read_ahead(); /* do block read ahead */
}
} }
} }
/*===========================================================================* /*===========================================================================*
* init_server * * init_server *
*===========================================================================*/ *===========================================================================*/
PRIVATE void init_server(void) PRIVATE void init_server(void)
{ {
int i; int i;
/* Init inode table */ /* Init inode table */
for (i = 0; i < NR_INODES; ++i) { for (i = 0; i < NR_INODES; ++i) {
inode[i].i_count = 0; inode[i].i_count = 0;
cch[i] = 0; cch[i] = 0;
} }
init_inode_cache(); init_inode_cache();
/* Init driver mapping */ /* Init driver mapping */
for (i = 0; i < NR_DEVICES; ++i) for (i = 0; i < NR_DEVICES; ++i)
driver_endpoints[i].driver_e = NONE; driver_endpoints[i].driver_e = NONE;
SELF_E = getprocnr(); SELF_E = getprocnr();
buf_pool(); buf_pool();
fs_block_size = _MIN_BLOCK_SIZE; fs_block_size = _MIN_BLOCK_SIZE;
} }
/*===========================================================================* /*===========================================================================*
* get_work * * get_work *
*===========================================================================*/ *===========================================================================*/
PRIVATE void get_work(m_in) PRIVATE void get_work(m_in)
message *m_in; /* pointer to message */ message *m_in; /* pointer to message */
{ {
int srcok = 0; int r, srcok = 0;
endpoint_t src; endpoint_t src;
do {
int s; /* receive status */ do {
if (OK != (s = receive(ANY, m_in))) /* wait for message */ if ((r = receive(ANY, m_in)) != OK) /* wait for message */
panic("MFS","receive failed", s); panic("MFS","receive failed", r);
src = fs_m_in.m_source; src = fs_m_in.m_source;
if (src != FS_PROC_NR) { if (src != FS_PROC_NR) {
if(src == PM_PROC_NR) { if(src == PM_PROC_NR) {
if(is_notify(fs_m_in.m_type)) if(is_notify(fs_m_in.m_type))
srcok = 1; /* Normal exit request. */ srcok = 1; /* Normal exit request. */
else else
printf("MFS: unexpected message from PM\n"); printf("MFS: unexpected message from PM\n");
} else } else
printf("MFS: unexpected source %d\n", src); printf("MFS: unexpected source %d\n", src);
} else if(src == FS_PROC_NR) { } else if(src == FS_PROC_NR) {
if(unmountdone) { if(unmountdone)
printf("MFS: unmounted: unexpected message from FS\n"); printf("MFS: unmounted: unexpected message from FS\n");
} else { else
/* Normal FS request. */ srcok = 1; /* Normal FS request. */
srcok = 1;
}
} else } else
printf("MFS: unexpected source %d\n", src); printf("MFS: unexpected source %d\n", src);
} while(!srcok); } while(!srcok);
assert((src == FS_PROC_NR && !unmountdone) || assert((src == FS_PROC_NR && !unmountdone) ||
(src == PM_PROC_NR && is_notify(fs_m_in.m_type))); (src == PM_PROC_NR && is_notify(fs_m_in.m_type)));
@ -156,10 +153,14 @@ PUBLIC void reply(who, m_out)
int who; int who;
message *m_out; /* report result */ message *m_out; /* report result */
{ {
if (OK != send(who, m_out)) /* send the message */ if (OK != send(who, m_out)) /* send the message */
printf("MFS(%d) was unable to send reply\n", SELF_E); printf("MFS(%d) was unable to send reply\n", SELF_E);
} }
/*===========================================================================*
* cch_check *
*===========================================================================*/
PRIVATE void cch_check(void) PRIVATE void cch_check(void)
{ {
int i; int i;
@ -168,10 +169,9 @@ PRIVATE void cch_check(void)
if (inode[i].i_count != cch[i] && if (inode[i].i_count != cch[i] &&
req_nr != REQ_GETNODE && req_nr != REQ_GETNODE &&
req_nr != REQ_PUTNODE && req_nr != REQ_PUTNODE &&
req_nr != REQ_CLONE_OPCL && req_nr != REQ_READSUPER_S && req_nr != REQ_READSUPER &&
req_nr != REQ_MOUNTPOINT_S && req_nr != REQ_UNMOUNT && req_nr != REQ_MOUNTPOINT && req_nr != REQ_UNMOUNT &&
req_nr != REQ_PIPE && req_nr != REQ_SYNC && req_nr != REQ_SYNC && req_nr != REQ_LOOKUP)
req_nr != REQ_LOOKUP_S)
printf("MFS(%d) inode(%d) cc: %d req_nr: %d\n", 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); 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",
} }
} }

View file

@ -1,8 +1,6 @@
#include "fs.h" #include "fs.h"
#include <fcntl.h> #include <fcntl.h>
#include <minix/vfsif.h> #include <minix/vfsif.h>
#include "buf.h" #include "buf.h"
#include "inode.h" #include "inode.h"
@ -17,17 +15,17 @@ PUBLIC int fs_sync()
* blocks must be flushed last, since rw_inode() leaves its results in * blocks must be flushed last, since rw_inode() leaves its results in
* the block cache. * the block cache.
*/ */
register struct inode *rip; struct inode *rip;
register struct buf *bp; struct buf *bp;
/* Write all the dirty inodes to the disk. */ /* Write all the dirty inodes to the disk. */
for (rip = &inode[0]; rip < &inode[NR_INODES]; rip++) for(rip = &inode[0]; rip < &inode[NR_INODES]; rip++)
if (rip->i_count > 0 && rip->i_dirt == DIRTY) rw_inode(rip, WRITING); 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. */ /* Write all the dirty blocks to the disk, one drive at a time. */
for (bp = &buf[0]; bp < &buf[NR_BUFS]; bp++) for(bp = &buf[0]; bp < &buf[NR_BUFS]; bp++)
if (bp->b_dev != NO_DEV && bp->b_dirt == DIRTY) if(bp->b_dev != NO_DEV && bp->b_dirt == DIRTY)
flushall(bp->b_dev); flushall(bp->b_dev);
return(OK); /* sync() can't fail */ return(OK); /* sync() can't fail */
} }
@ -43,15 +41,12 @@ PUBLIC int fs_flush()
*/ */
dev_t dev; dev_t dev;
dev= fs_m_in.REQ_DEV; dev = fs_m_in.REQ_DEV;
if (dev == fs_dev) if(dev == fs_dev) return(EBUSY);
{
return EBUSY;
}
flushall(dev); flushall(dev);
invalidate(dev); invalidate(dev);
return(OK); return(OK);
} }

View file

@ -1,5 +1,3 @@
#include "fs.h" #include "fs.h"
#include <fcntl.h> #include <fcntl.h>
#include <string.h> #include <string.h>
@ -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 /* 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 * 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; int r = OK;
unsigned long tasknr; unsigned long tasknr;
endpoint_t driver_e; 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_gid= fs_m_in.REQ_GRANT2; label_len = fs_m_in.REQ_PATH_LEN;
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)) if (label_len > sizeof(fs_dev_label))
{ return(EINVAL);
printf("mfs: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);
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, r = ds_retrieve_u32(fs_dev_label, &tasknr);
label_len, D); if (r != OK) {
if (r != OK) printf("%s:%d fs_readsuper: ds_retrieve_u32 failed for '%s': %d\n",
{ fs_dev_label, __FILE__, __LINE__, r);
printf("mfs:fs_readsuper: safecopyfrom failed: %d\n", r); return(EINVAL);
return EINVAL;
} }
r= ds_retrieve_u32(fs_dev_label, &tasknr); driver_e = 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;
/* Map the driver endpoint for this major */ /* Map the driver endpoint for this major */
driver_endpoints[(fs_dev >> MAJOR) & BYTE].driver_e = driver_e; driver_endpoints[(fs_dev >> MAJOR) & BYTE].driver_e = driver_e;
use_getuptime2= TRUE; /* Should be removed with old use_getuptime2 = TRUE; /* Should be removed with old getuptime call. */
* getuptime call.
*/
vfs_slink_storage = (char *)0xdeadbeef; /* Should be removed together vfs_slink_storage = (char *)0xdeadbeef; /* Should be removed together
* with old lookup code. * with old lookup code.
*/; */;
/* Open the device the file system lives on. */ /* Open the device the file system lives on. */
if (dev_open(driver_e, fs_dev, driver_e, 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); return(EINVAL);
} }
@ -91,158 +85,39 @@ PUBLIC int fs_readsuper_s()
set_blocksize(superblock.s_block_size); set_blocksize(superblock.s_block_size);
/* Get the root inode of the mounted file system. */ /* Get the root inode of the mounted file system. */
if ( (root_ip = get_inode(fs_dev, ROOT_INODE)) == NIL_INODE) { if( (root_ip = get_inode(fs_dev, ROOT_INODE)) == NIL_INODE) {
printf("MFS: couldn't get root inode?!\n"); printf("MFS: couldn't get root inode\n");
superblock.s_dev = NO_DEV; superblock.s_dev = NO_DEV;
dev_close(driver_e, fs_dev); dev_close(driver_e, fs_dev);
return EINVAL; return(EINVAL);
} }
if (root_ip != NIL_INODE && root_ip->i_mode == 0) { if(root_ip != NIL_INODE && root_ip->i_mode == 0) {
printf("MFS: zero mode for root inode?!\n"); printf("%s:%d zero mode for root inode?\n", __FILE__, __LINE__);
put_inode(root_ip); put_inode(root_ip);
superblock.s_dev = NO_DEV; superblock.s_dev = NO_DEV;
dev_close(driver_e, fs_dev); dev_close(driver_e, fs_dev);
return EINVAL; return(EINVAL);
} }
superblock.s_rd_only = fs_m_in.REQ_READONLY; superblock.s_rd_only = readonly;
superblock.s_is_root = fs_m_in.REQ_ISROOT; superblock.s_is_root = isroot;
/* Root inode properties */ /* Root inode properties */
fs_m_out.RES_INODE_NR = root_ip->i_num; fs_m_out.RES_INODE_NR = root_ip->i_num;
fs_m_out.RES_MODE = root_ip->i_mode; 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_UID = root_ip->i_uid;
fs_m_out.RES_GID = root_ip->i_gid; fs_m_out.RES_GID = root_ip->i_gid;
return r; return(r);
} }
/*===========================================================================* /*===========================================================================*
* fs_readsuper_o * * fs_mountpoint *
*===========================================================================*/ *===========================================================================*/
PUBLIC int fs_readsuper_o() PUBLIC int fs_mountpoint()
{
/* 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()
{ {
/* This function looks up the mount point, it checks the condition whether /* This function looks up the mount point, it checks the condition whether
* the partition can be mounted on the inode or not. * the partition can be mounted on the inode or not.
@ -252,23 +127,21 @@ PUBLIC int fs_mountpoint_s()
mode_t bits; mode_t bits;
/* Temporarily open the file. */ /* Temporarily open the file. */
if ( (rip = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) { 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);
return(EINVAL);
}
if(rip->i_mountpoint) r = EBUSY;
if (rip->i_mountpoint)
r= EBUSY;
/* It may not be special. */ /* It may not be special. */
bits = rip->i_mode & I_TYPE; bits = rip->i_mode & I_TYPE;
if (bits == I_BLOCK_SPECIAL || bits == I_CHAR_SPECIAL) r = ENOTDIR; if (bits == I_BLOCK_SPECIAL || bits == I_CHAR_SPECIAL) r = ENOTDIR;
put_inode(rip); put_inode(rip);
if (r == OK) if(r == OK) rip->i_mountpoint = TRUE;
rip->i_mountpoint = TRUE;
return r; return(r);
} }
@ -280,38 +153,35 @@ PUBLIC int fs_unmount()
/* Unmount a file system by device number. */ /* Unmount a file system by device number. */
struct super_block *sp1; struct super_block *sp1;
int count; 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. */ /* Close the device the file system lives on. */
dev_close(driver_endpoints[(fs_dev >> MAJOR) & BYTE].driver_e, fs_dev); 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. */ /* Finish off the unmount. */
superblock.s_dev = NO_DEV; superblock.s_dev = NO_DEV;
unmountdone = TRUE; unmountdone = TRUE;
return OK; return(OK);
} }

View file

@ -1,5 +1,3 @@
#include "fs.h" #include "fs.h"
#include <sys/stat.h> #include <sys/stat.h>
#include <fcntl.h> #include <fcntl.h>
@ -10,152 +8,17 @@
#include "buf.h" #include "buf.h"
#include "inode.h" #include "inode.h"
#include "super.h" #include "super.h"
#include <minix/vfsif.h> #include <minix/vfsif.h>
PRIVATE char mode_map[] = {R_BIT, W_BIT, R_BIT|W_BIT, 0}; 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)); 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; phys_bytes len;
int r, b; int r, b;
@ -166,156 +29,54 @@ PUBLIC int fs_create_o()
/* Read request message */ /* Read request message */
omode = fs_m_in.REQ_MODE; omode = fs_m_in.REQ_MODE;
caller_uid = fs_m_in.REQ_UID; caller_uid = fs_m_in.REQ_UID;
caller_gid = fs_m_in.REQ_GID; caller_gid = fs_m_in.REQ_GID;
/* Try to make the file. */ /* 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_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 */
len = MFS_MIN(fs_m_in.REQ_PATH_LEN, sizeof(lastc)); len = MFS_MIN(fs_m_in.REQ_PATH_LEN, sizeof(lastc));
err_code = sys_safecopyfrom(FS_PROC_NR, fs_m_in.REQ_GRANT, 0, 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; if (err_code != OK) return err_code;
MFS_NUL(lastc, len, sizeof(lastc)); MFS_NUL(lastc, len, sizeof(lastc));
/* Get last directory inode */ /* 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) { 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);
return ENOENT;
}
/* Create a new inode by calling new_node(). */ /* 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; r = err_code;
/* If error, release inode. */ /* If an error occurred, release inode. */
if (r != OK) { if (r != OK) {
put_inode(ldirp); put_inode(ldirp);
put_inode(rip); put_inode(rip);
return(r); return(r);
} }
/* Reply message */ /* Reply message */
fs_m_out.m_source = rip->i_dev; /* filled with FS endpoint by the system */ 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_INODE_NR = rip->i_num;
fs_m_out.RES_MODE = rip->i_mode; fs_m_out.RES_MODE = rip->i_mode;
fs_m_out.RES_FILE_SIZE = rip->i_size; fs_m_out.RES_FILE_SIZE_LO = rip->i_size;
fs_m_out.RES_INODE_INDEX = (rip - &inode[0]) / sizeof(struct inode);
/* This values are needed for the execution */ /* This values are needed for the execution */
fs_m_out.RES_UID = rip->i_uid; fs_m_out.RES_UID = rip->i_uid;
fs_m_out.RES_GID = rip->i_gid; 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 */ /* Drop parent dir */
put_inode(ldirp); put_inode(ldirp);
return OK; return(OK);
} }
/*===========================================================================* /*===========================================================================*
* fs_mknod_o * * fs_mknod *
*===========================================================================*/ *===========================================================================*/
PUBLIC int fs_mknod_o() PUBLIC int fs_mknod()
{
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()
{ {
struct inode *ip, *ldirp; struct inode *ip, *ldirp;
char lastc[NAME_MAX]; 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 */ /* Copy the last component and set up caller's user and group id */
len = MFS_MIN(fs_m_in.REQ_PATH_LEN, sizeof(lastc)); len = MFS_MIN(fs_m_in.REQ_PATH_LEN, sizeof(lastc));
err_code = sys_safecopyfrom(FS_PROC_NR, fs_m_in.REQ_GRANT, 0, 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; if (err_code != OK) return err_code;
MFS_NUL(lastc, len, sizeof(lastc)); MFS_NUL(lastc, len, sizeof(lastc));
caller_uid = fs_m_in.REQ_UID; caller_uid = fs_m_in.REQ_UID;
caller_gid = fs_m_in.REQ_GID; caller_gid = fs_m_in.REQ_GID;
/* Get last directory inode */ /* Get last directory inode */
if ((ldirp = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_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);
return ENOENT;
}
/* Try to create the new node */ /* 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(ip);
put_inode(ldirp); 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() PUBLIC int fs_mkdir()
{
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()
{ {
int r1, r2; /* status codes */ int r1, r2; /* status codes */
ino_t dot, dotdot; /* inode numbers for . and .. */ 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 */ /* Copy the last component and set up caller's user and group id */
len = MFS_MIN(fs_m_in.REQ_PATH_LEN, sizeof(lastc)); len = MFS_MIN(fs_m_in.REQ_PATH_LEN, sizeof(lastc));
err_code = sys_safecopyfrom(FS_PROC_NR, fs_m_in.REQ_GRANT, 0, 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; if(err_code != OK) return(err_code);
MFS_NUL(lastc, len, sizeof(lastc)); MFS_NUL(lastc, len, sizeof(lastc));
caller_uid = fs_m_in.REQ_UID; caller_uid = fs_m_in.REQ_UID;
caller_gid = fs_m_in.REQ_GID; caller_gid = fs_m_in.REQ_GID;
/* Get last directory inode */ /* Get last directory inode */
if ((ldirp = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_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);
return ENOENT;
}
/* Next make the inode. If that fails, return error code. */ /* Next make the inode. If that fails, return error code. */
rip = new_node_s(ldirp, lastc, fs_m_in.REQ_MODE, (zone_t) 0); rip = new_node(ldirp, lastc, fs_m_in.REQ_MODE, (zone_t) 0);
if (rip == NIL_INODE || err_code == EEXIST) { if(rip == NIL_INODE || err_code == EEXIST) {
put_inode(rip); /* can't make dir: it already exists */ put_inode(rip); /* can't make dir: it already exists */
put_inode(ldirp); put_inode(ldirp);
return(err_code); return(err_code);
} }
/* Get the inode numbers for . and .. to enter in the directory. */ /* Get the inode numbers for . and .. to enter in the directory. */
dotdot = ldirp->i_num; /* parent's inode number */ dotdot = ldirp->i_num; /* parent's inode number */
dot = rip->i_num; /* inode number of the new dir itself */ 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. */ /* 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. */ /* Use dot1 and dot2, so the mode of the directory isn't important. */
rip->i_mode = fs_m_in.REQ_MODE; /* set mode */ rip->i_mode = fs_m_in.REQ_MODE; /* set mode */
r1 = search_dir_nocheck(rip, dot1, &dot, ENTER); /* enter . in the new dir */ r1 = search_dir(rip, dot1, &dot, ENTER, IGN_PERM);/* enter . in the new dir*/
r2 = search_dir_nocheck(rip, dot2, &dotdot, ENTER); /* enter .. in the new r2 = search_dir(rip, dot2, &dotdot, ENTER, IGN_PERM); /* enter .. in the new
dir */ dir */
/* If both . and .. were successfully entered, increment the link counts. */ /* If both . and .. were successfully entered, increment the link counts. */
if (r1 == OK && r2 == OK) { if (r1 == OK && r2 == OK) {
/* Normal case. It was possible to enter . and .. in the new dir. */ /* Normal case. It was possible to enter . and .. in the new dir. */
rip->i_nlinks++; /* this accounts for . */ rip->i_nlinks++; /* this accounts for . */
ldirp->i_nlinks++; /* this accounts for .. */ ldirp->i_nlinks++; /* this accounts for .. */
ldirp->i_dirt = DIRTY; /* mark parent's inode as dirty */ ldirp->i_dirt = DIRTY; /* mark parent's inode as dirty */
} else { } else {
/* It was not possible to enter . or .. probably disk was full - /* It was not possible to enter . or .. probably disk was full -
* links counts haven't been touched. * links counts haven't been touched. */
*/ if(search_dir(ldirp, lastc, (ino_t *) 0, DELETE, IGN_PERM) != OK)
if(search_dir_nocheck(ldirp, lastc, (ino_t *) 0, DELETE) != OK) panic(__FILE__, "Dir disappeared ", rip->i_num);
panic(__FILE__, "Dir disappeared ", rip->i_num); rip->i_nlinks--; /* undo the increment done in new_node() */
rip->i_nlinks--; /* undo the increment done in new_node() */
} }
rip->i_dirt = DIRTY; /* either way, i_nlinks has changed */ 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; phys_bytes len;
struct inode *sip; /* inode containing symbolic link */ struct inode *sip; /* inode containing symbolic link */
@ -498,139 +186,60 @@ PUBLIC int fs_slink_o()
caller_uid = fs_m_in.REQ_UID; caller_uid = fs_m_in.REQ_UID;
caller_gid = fs_m_in.REQ_GID; 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 */ /* Copy the link name's last component */
len = MFS_MIN(fs_m_in.REQ_PATH_LEN, sizeof(string)); len = MFS_MIN(fs_m_in.REQ_PATH_LEN, sizeof(string));
r = sys_safecopyfrom(FS_PROC_NR, fs_m_in.REQ_GRANT, 0, 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; if (r != OK) return(r);
MFS_NUL(string, len, sizeof(string)); MFS_NUL(string, len, sizeof(string));
/* Temporarily open the dir. */ /* Temporarily open the dir. */
if ( (ldirp = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) { if( (ldirp = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE)
return(EINVAL); return(EINVAL);
}
/* Create the inode for the symlink. */ /* Create the inode for the symlink. */
sip = new_node_s(ldirp, string, (mode_t) (I_SYMBOLIC_LINK | RWX_MODES), sip = new_node(ldirp, string, (mode_t) (I_SYMBOLIC_LINK | RWX_MODES),
(zone_t) 0); (zone_t) 0);
/* Allocate a disk block for the contents of the symlink. /* Allocate a disk block for the contents of the symlink.
* Copy contents of symlink (the name pointed to) into first disk block. * Copy contents of symlink (the name pointed to) into first disk block. */
*/ if( (r = err_code) == OK) {
if ((r = err_code) == OK) { r = (bp = new_block(sip, (off_t) 0)) == NIL_BUF ? err_code :
r = (bp = new_block(sip, (off_t) 0)) == NIL_BUF ? err_code : sys_safecopyfrom(FS_PROC_NR, fs_m_in.REQ_GRANT3, 0,
sys_safecopyfrom(FS_PROC_NR, fs_m_in.REQ_GRANT2, 0, (vir_bytes) bp->b_data,
(vir_bytes) bp->b_data, (vir_bytes) fs_m_in.REQ_SLENGTH, D); (vir_bytes) fs_m_in.REQ_MEM_SIZE, D);
if(r == OK) { if(r == OK) {
bp->b_data[_MIN_BLOCK_SIZE-1] = '\0'; bp->b_data[_MIN_BLOCK_SIZE-1] = '\0';
sip->i_size = strlen(bp->b_data); sip->i_size = strlen(bp->b_data);
if(sip->i_size != fs_m_in.REQ_SLENGTH) { if(sip->i_size != fs_m_in.REQ_MEM_SIZE) {
/* This can happen if the user provides a buffer /* This can happen if the user provides a buffer
* with a \0 in it. This can cause a lot of trouble * with a \0 in it. This can cause a lot of trouble
* when the symlink is used later. We could just use * when the symlink is used later. We could just use
* the strlen() value, but we want to let the user * the strlen() value, but we want to let the user
* know he did something wrong. ENAMETOOLONG doesn't * know he did something wrong. ENAMETOOLONG doesn't
* exactly describe the error, but there is no * exactly describe the error, but there is no
* ENAMETOOWRONG. * ENAMETOOWRONG.
*/ */
r = ENAMETOOLONG; 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 (r != OK) { if(search_dir(ldirp, string, (ino_t *) 0, DELETE,
sip->i_nlinks = 0; IGN_PERM) != OK)
if (search_dir_nocheck(ldirp, string, (ino_t *) 0, DELETE) != OK)
panic(__FILE__, "Symbolic link vanished", NO_NUM); panic(__FILE__, "Symbolic link vanished", NO_NUM);
} }
} }
/* put_inode() accepts NIL_INODE as a noop, so the below are safe. */ /* put_inode() accepts NIL_INODE as a noop, so the below are safe. */
put_inode(sip); put_inode(sip);
put_inode(ldirp); put_inode(ldirp);
return(r); return(r);
} }
@ -646,23 +255,17 @@ PUBLIC int fs_newnode()
caller_uid = fs_m_in.REQ_UID; caller_uid = fs_m_in.REQ_UID;
caller_gid = fs_m_in.REQ_GID; caller_gid = fs_m_in.REQ_GID;
bits = fs_m_in.REQ_MODE;
bits= fs_m_in.REQ_MODE;
/* Try to allocate the inode */ /* Try to allocate the inode */
if ( (rip = alloc_inode(fs_dev, bits) ) == NIL_INODE) { if( (rip = alloc_inode(fs_dev, bits) ) == NIL_INODE)
return err_code; return err_code;
}
switch (bits & S_IFMT) switch (bits & S_IFMT) {
{ case S_IFBLK:
case S_IFBLK: case S_IFCHR:
case S_IFCHR: rip->i_zone[0] = fs_m_in.REQ_DEV; /* major/minor dev numbers*/
rip->i_zone[0] = fs_m_in.REQ_DEVx; /* major/minor device numbers */ break;
break;
case S_IFIFO:
rip->i_pipe = I_PIPE;
break;
} }
rw_inode(rip, WRITING); /* mark inode as allocated */ rw_inode(rip, WRITING); /* mark inode as allocated */
@ -671,21 +274,19 @@ PUBLIC int fs_newnode()
/* Fill in the fields of the response message */ /* Fill in the fields of the response message */
fs_m_out.RES_INODE_NR = rip->i_num; fs_m_out.RES_INODE_NR = rip->i_num;
fs_m_out.RES_MODE = rip->i_mode; fs_m_out.RES_MODE = rip->i_mode;
fs_m_out.RES_INODE_INDEX = (rip - &inode[0]); fs_m_out.RES_FILE_SIZE_LO = rip->i_size;
fs_m_out.RES_FILE_SIZE = rip->i_size;
fs_m_out.RES_UID = rip->i_uid; fs_m_out.RES_UID = rip->i_uid;
fs_m_out.RES_GID = rip->i_gid; fs_m_out.RES_GID = rip->i_gid;
fs_m_out.RES_DEV = (dev_t) rip->i_zone[0]; 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) char *string, mode_t bits, zone_t z0)
{ {
/* New_node() is called by fs_open(), fs_mknod(), and fs_mkdir(). /* 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; register int r;
/* Get final component of the path. */ /* Get final component of the path. */
rip = advance_o(&ldirp, string); rip = advance(ldirp, string, IGN_PERM);
if (S_ISDIR(bits) && if (S_ISDIR(bits) &&
(ldirp)->i_nlinks >= ((ldirp)->i_sp->s_version == V1 ? (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 */ rw_inode(rip, WRITING); /* force inode to disk now */
/* New inode acquired. Try to make directory entry. */ /* 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_nlinks--; /* pity, have to free disk inode */
rip->i_dirt = DIRTY; /* dirty inodes are written out */ rip->i_dirt = DIRTY; /* dirty inodes are written out */
put_inode(rip); /* this call frees the inode */ put_inode(rip); /* this call frees the inode */
@ -738,81 +339,11 @@ PRIVATE struct inode *new_node_o(struct inode *ldirp,
return(NIL_INODE); return(NIL_INODE);
} }
} else { } else if (err_code == EENTERMOUNT || err_code == ELEAVEMOUNT) {
r = EEXIST;
} else {
/* Either last component exists, or there is some problem. */ /* Either last component exists, or there is some problem. */
if (rip != NIL_INODE || err_code == EENTERMOUNT || if (rip != NIL_INODE)
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)
r = EEXIST; r = EEXIST;
else else
r = err_code; r = err_code;
@ -831,14 +362,12 @@ PUBLIC int fs_inhibread()
{ {
struct inode *rip; struct inode *rip;
if ((rip = find_inode(fs_dev, fs_m_in.REQ_INODE_NR))== NIL_INODE){ 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);
return EINVAL;
}
/* inhibit read ahead */ /* inhibit read ahead */
rip->i_seek = ISEEK; rip->i_seek = ISEEK;
return OK; return(OK);
} }

File diff suppressed because it is too large Load diff

View file

@ -1,54 +0,0 @@
#include "fs.h"
#include <fcntl.h>
#include <signal.h>
#include <minix/callnr.h>
#include <minix/endpoint.h>
#include <minix/com.h>
#include <sys/select.h>
#include <sys/time.h>
#include "inode.h"
#include "super.h"
#include <minix/vfsif.h>
/*===========================================================================*
* 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;
}

View file

@ -1,14 +1,13 @@
#include "fs.h" #include "fs.h"
#include <unistd.h> #include <unistd.h>
#include <minix/callnr.h> #include <minix/callnr.h>
#include "buf.h" #include "buf.h"
#include "inode.h" #include "inode.h"
#include "super.h" #include "super.h"
#include <minix/vfsif.h> #include <minix/vfsif.h>
FORWARD _PROTOTYPE( in_group, (gid_t grp) );
/*===========================================================================* /*===========================================================================*
* fs_chmod * * fs_chmod *
@ -21,10 +20,8 @@ PUBLIC int fs_chmod()
register int r; register int r;
/* Temporarily open the file. */ /* Temporarily open the file. */
if ( (rip = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) { 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);
return(EINVAL);
}
/* Now make the change. Clear setgid bit if file is not in caller's grp */ /* 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); 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 struct inode *rip;
register int r; register int r;
/* Temporarily open the file. */ /* Temporarily open the file. */
caller_uid = fs_m_in.REQ_UID; if( (rip = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE)
caller_gid = fs_m_in.REQ_GID; return(EINVAL);
/* 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);
}
/* Not permitted to change the owner of a file on a read-only file sys. */ /* Not permitted to change the owner of a file on a read-only file sys. */
r = read_only(rip); r = read_only(rip);
if (r == OK) { if (r == OK) {
rip->i_uid = fs_m_in.REQ_NEW_UID; rip->i_uid = fs_m_in.REQ_UID;
rip->i_gid = fs_m_in.REQ_NEW_GID; rip->i_gid = fs_m_in.REQ_GID;
rip->i_mode &= ~(I_SET_UID_BIT | I_SET_GID_BIT); rip->i_mode &= ~(I_SET_UID_BIT | I_SET_GID_BIT);
rip->i_update |= CTIME; rip->i_update |= CTIME;
rip->i_dirt = DIRTY; rip->i_dirt = DIRTY;
} }
/* Update caller on current mode, as it may have changed. */ /* Update caller on current mode, as it may have changed. */
fs_m_out.RES_MODE = rip->i_mode; fs_m_out.RES_MODE = rip->i_mode;
put_inode(rip); put_inode(rip);
return(r); 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 * * forbidden *
@ -112,22 +80,7 @@ PUBLIC int forbidden(register struct inode *rip, mode_t access_desired)
register struct inode *old_rip = rip; register struct inode *old_rip = rip;
register struct super_block *sp; register struct super_block *sp;
register mode_t bits, perm_bits; register mode_t bits, perm_bits;
int r, shift, type; int r, shift;
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;
}
*/
/* Isolate the relevant rwx bits from the mode. */ /* Isolate the relevant rwx bits from the mode. */
bits = rip->i_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; perm_bits = R_BIT | W_BIT;
} else { } else {
if (caller_uid == rip->i_uid) shift = 6; /* owner */ 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 */ else shift = 0; /* other */
perm_bits = (bits >> shift) & (R_BIT | W_BIT | X_BIT); 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 /* Check to see if someone is trying to write on a file system that is
* mounted read-only. * mounted read-only.
*/ */
type = rip->i_mode & I_TYPE;
if (r == OK) if (r == OK)
if (access_desired & W_BIT) if (access_desired & W_BIT)
r = read_only(rip); 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); if (rip != old_rip) put_inode(rip);
return(r); 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 * * 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); return(sp->s_rd_only ? EROFS : OK);
} }

View file

@ -1,7 +1,5 @@
/* Function prototypes. */ /* Function prototypes. */
#include "timers.h"
/* Structs used in prototypes must be declared as such first. */ /* Structs used in prototypes must be declared as such first. */
struct buf; struct buf;
struct filp; struct filp;
@ -9,32 +7,9 @@ struct inode;
struct super_block; 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 */ /* cache.c */
_PROTOTYPE( zone_t alloc_zone, (Dev_t dev, zone_t z) ); _PROTOTYPE( zone_t alloc_zone, (Dev_t dev, zone_t z) );
_PROTOTYPE( void buf_pool, (void) );
_PROTOTYPE( void flushall, (Dev_t dev) ); _PROTOTYPE( void flushall, (Dev_t dev) );
_PROTOTYPE( void free_zone, (Dev_t dev, zone_t numb) ); _PROTOTYPE( void free_zone, (Dev_t dev, zone_t numb) );
_PROTOTYPE( struct buf *get_block, (Dev_t dev, block_t block,int only_search)); _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 set_blocksize, (int blocksize) );
_PROTOTYPE( void rw_scattered, (Dev_t dev, _PROTOTYPE( void rw_scattered, (Dev_t dev,
struct buf **bufq, int bufqsize, int rw_flag) ); struct buf **bufq, int bufqsize, int rw_flag) );
_PROTOTYPE( void buf_pool, (void) );
/* device.c */ /* device.c */
_PROTOTYPE( int block_dev_io, (int op, Dev_t dev, int proc, void *buf, _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, _PROTOTYPE( int dev_open, (endpoint_t driver_e, Dev_t dev, int proc,
int flags) ); int flags) );
_PROTOTYPE( void dev_close, (endpoint_t driver_e, Dev_t dev) ); _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 */ /* inode.c */
_PROTOTYPE( struct inode *find_inode, (Dev_t dev, int numb) );
_PROTOTYPE( struct inode *alloc_inode, (dev_t dev, mode_t bits) ); _PROTOTYPE( struct inode *alloc_inode, (dev_t dev, mode_t bits) );
_PROTOTYPE( void dup_inode, (struct inode *ip) ); _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( 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( struct inode *get_inode, (Dev_t dev, int numb) );
_PROTOTYPE( void put_inode, (struct inode *rip) ); _PROTOTYPE( void put_inode, (struct inode *rip) );
_PROTOTYPE( void update_times, (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) ); _PROTOTYPE( void wipe_inode, (struct inode *rip) );
/* link.c */ /* 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 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 */ /* main.c */
_PROTOTYPE( void reply, (int who, message *m_out) ); _PROTOTYPE( void reply, (int who, message *m_out) );
/* misc.c */
_PROTOTYPE( int fs_flush, (void) );
_PROTOTYPE( int fs_sync, (void) );
/* mount.c */ /* mount.c */
int fs_mountpoint_o(void); _PROTOTYPE( int fs_mountpoint, (void) );
int fs_mountpoint_s(void); _PROTOTYPE( int fs_readsuper, (void) );
int fs_readsuper_o(void); _PROTOTYPE( int fs_unmount, (void) );
int fs_readsuper_s(void);
_PROTOTYPE( int unmount, (Dev_t dev) );
/* open.c */ /* open.c */
int fs_create_o(void); _PROTOTYPE( int fs_create, (void) );
int fs_create_s(void); _PROTOTYPE( int fs_inhibread, (void) );
int fs_mkdir_o(void); _PROTOTYPE( int fs_mkdir, (void) );
int fs_mkdir_s(void); _PROTOTYPE( int fs_mknod, (void) );
int fs_mknod_o(void); _PROTOTYPE( int fs_newnode, (void) );
int fs_mknod_s(void); _PROTOTYPE( int fs_slink, (void) );
int fs_slink_o(void);
int fs_slink_s(void);
int fs_newnode(void);
/* path.c */ /* path.c */
int lookup_o(void); _PROTOTYPE( int fs_lookup, (void) );
int fs_lookup_s(void); _PROTOTYPE( struct inode *advance, (struct inode *dirp,
_PROTOTYPE( struct inode *advance_o,(struct inode **dirp, char string[NAME_MAX], int chk_perm) );
char string[NAME_MAX]) ); _PROTOTYPE( int search_dir, (struct inode *ldir_ptr,
_PROTOTYPE( struct inode *advance_nocheck,(struct inode **dirp, char string [NAME_MAX], ino_t *numb, int flag,
char string[NAME_MAX]) ); int check_permissions) );
_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) );
/* protect.c */ /* 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 forbidden, (struct inode *rip, mode_t access_desired) );
_PROTOTYPE( int read_only, (struct inode *ip) ); _PROTOTYPE( int read_only, (struct inode *ip) );
/* read.c */ /* read.c */
int fs_breadwrite_o(void); _PROTOTYPE( int fs_breadwrite, (void) );
int fs_breadwrite_s(void); _PROTOTYPE( int fs_readwrite, (void) );
int fs_readwrite_o(void);
int fs_readwrite_s(void);
_PROTOTYPE( struct buf *rahead, (struct inode *rip, block_t baseblock, _PROTOTYPE( struct buf *rahead, (struct inode *rip, block_t baseblock,
u64_t position, unsigned bytes_ahead) ); u64_t position, unsigned bytes_ahead) );
_PROTOTYPE( void read_ahead, (void) ); _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( int read_write, (int rw_flag) );
_PROTOTYPE( zone_t rd_indir, (struct buf *bp, int index) ); _PROTOTYPE( zone_t rd_indir, (struct buf *bp, int index) );
/* stadir.c */
_PROTOTYPE( int fs_fstatfs, (void) );
_PROTOTYPE( int fs_stat, (void) );
/* super.c */ /* super.c */
_PROTOTYPE( bit_t alloc_bit, (struct super_block *sp, int map, bit_t origin)); _PROTOTYPE( bit_t alloc_bit, (struct super_block *sp, int map, bit_t origin));
_PROTOTYPE( void free_bit, (struct super_block *sp, int map, _PROTOTYPE( void free_bit, (struct super_block *sp, int map,
bit_t bit_returned) ); bit_t bit_returned) );
_PROTOTYPE( int get_block_size, (dev_t dev) );
_PROTOTYPE( struct super_block *get_super, (Dev_t dev) ); _PROTOTYPE( struct super_block *get_super, (Dev_t dev) );
_PROTOTYPE( int mounted, (struct inode *rip) ); _PROTOTYPE( int mounted, (struct inode *rip) );
_PROTOTYPE( int read_super, (struct super_block *sp) ); _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 */ /* utility.c */
_PROTOTYPE( time_t clock_time, (void) ); _PROTOTYPE( time_t clock_time, (void) );
_PROTOTYPE( unsigned conv2, (int norm, int w) ); _PROTOTYPE( unsigned conv2, (int norm, int w) );
_PROTOTYPE( long conv4, (int norm, long x) ); _PROTOTYPE( long conv4, (int norm, long x) );
_PROTOTYPE( int no_sys, (void) ); _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( 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( 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__) #define SANITYCHECK sanitycheck(__FILE__, __LINE__)
/* write.c */ /* write.c */
_PROTOTYPE( void clear_zone, (struct inode *rip, off_t pos, int flag) ); _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( struct buf *new_block, (struct inode *rip, off_t position) );
_PROTOTYPE( void zero_block, (struct buf *bp) ); _PROTOTYPE( void zero_block, (struct buf *bp) );
_PROTOTYPE( int write_map, (struct inode *, off_t, zone_t, int) ); _PROTOTYPE( int write_map, (struct inode *, off_t, zone_t, int) );

View file

@ -1,5 +1,3 @@
#include "fs.h" #include "fs.h"
#include <fcntl.h> #include <fcntl.h>
#include <stddef.h> #include <stddef.h>
@ -10,166 +8,21 @@
#include "buf.h" #include "buf.h"
#include "inode.h" #include "inode.h"
#include "super.h" #include "super.h"
#include <minix/vfsif.h> #include <minix/vfsif.h>
FORWARD _PROTOTYPE( int rw_chunk, (struct inode *rip, u64_t position, 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, unsigned off, int chunk, unsigned left, int rw_flag,
cp_grant_id_t gid, unsigned buf_off, int block_size, int *completed)); cp_grant_id_t gid, unsigned buf_off, int block_size, int *completed));
PRIVATE char getdents_buf[GETDENTS_BUFSIZ];
/*===========================================================================* /*===========================================================================*
* fs_readwrite_o * * fs_readwrite *
*===========================================================================*/ *===========================================================================*/
PUBLIC int fs_readwrite_o(void) PUBLIC int fs_readwrite(void)
{
int r, usr, seg, rw_flag, chunk, block_size, block_spec;
int partial_cnt, regular, partial_pipe, nrbytes;
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)
{ {
int r, rw_flag, chunk, block_size, block_spec; 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; cp_grant_id_t gid;
off_t position, f_size, bytes_left; off_t position, f_size, bytes_left;
unsigned int off, cum_io; unsigned int off, cum_io;
@ -177,204 +30,110 @@ PUBLIC int fs_readwrite_s(void)
int completed, r2 = OK; int completed, r2 = OK;
struct inode *rip; struct inode *rip;
partial_pipe = 0;
r = OK; r = OK;
/* Try to get inode according to its index */ /* Find the inode referred */
if (fs_m_in.REQ_FD_INODE_INDEX >= 0 && if ((rip = find_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE)
fs_m_in.REQ_FD_INODE_INDEX < NR_INODES && return(EINVAL);
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; mode_word = rip->i_mode & I_TYPE;
regular = (mode_word == I_REGULAR || mode_word == I_NAMED_PIPE); regular = (mode_word == I_REGULAR || mode_word == I_NAMED_PIPE);
block_spec = (mode_word == I_BLOCK_SPECIAL ? 1 : 0); block_spec = (mode_word == I_BLOCK_SPECIAL ? 1 : 0);
/* Determine blocksize */ /* Determine blocksize */
block_size = (block_spec ? get_block_size(rip->i_zone[0]) block_size = (block_spec ?
: rip->i_sp->s_block_size); get_block_size(rip->i_zone[0]) : rip->i_sp->s_block_size);
f_size = (block_spec ? ULONG_MAX : rip->i_size); f_size = (block_spec ? ULONG_MAX : rip->i_size);
/* Get the values from the request message */ /* Get the values from the request message */
rw_flag = (fs_m_in.m_type == REQ_READ_S ? READING : WRITING); rw_flag = (fs_m_in.m_type == REQ_READ ? READING : WRITING);
gid = fs_m_in.REQ_FD_GID; gid = fs_m_in.REQ_GRANT;
position = fs_m_in.REQ_FD_POS; position = fs_m_in.REQ_SEEK_POS_LO;
nrbytes = (unsigned) fs_m_in.REQ_FD_NBYTES; nrbytes = (unsigned) fs_m_in.REQ_NBYTES;
/*partial_cnt = fs_m_in.REQ_FD_PARTIAL;*/
/*if (partial_cnt > 0) partial_pipe = 1;*/
rdwt_err = OK; /* set to EIO if disk error occurs */ rdwt_err = OK; /* set to EIO if disk error occurs */
if (rw_flag == WRITING && block_spec == 0) { if (rw_flag == WRITING && block_spec == 0) {
/* Check in advance to see if file will grow too big. */ /* Check in advance to see if file will grow too big. */
if (position > rip->i_sp->s_max_size - nrbytes) if (position > rip->i_sp->s_max_size - nrbytes)
return(EFBIG); return(EFBIG);
/* Clear the zone containing present EOF if hole about /* Clear the zone containing present EOF if hole about
* to be created. This is necessary because all unwritten * to be created. This is necessary because all unwritten
* blocks prior to the EOF must read as zeros. * blocks prior to the EOF must read as zeros. */
*/ if(position > f_size) clear_zone(rip, f_size, 0);
if (position > f_size) clear_zone(rip, f_size, 0);
} }
cum_io = 0; cum_io = 0;
/* Split the transfer into chunks that don't span two blocks. */ /* Split the transfer into chunks that don't span two blocks. */
while (nrbytes != 0) { while (nrbytes != 0) {
off = (unsigned int) (position % block_size);/* offset in blk*/ off = (unsigned int) (position % block_size);/* offset in blk*/
chunk = MIN(nrbytes, block_size - off);
chunk = MIN(nrbytes, block_size - off);
if (chunk < 0) chunk = block_size - off;
if (rw_flag == READING) { 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;
}
/* Read or write 'chunk' bytes. */ if (rw_flag == READING) {
r = rw_chunk_s(rip, cvul64(position), off, chunk, (unsigned) nrbytes, bytes_left = f_size - position;
rw_flag, gid, cum_io, block_size, &completed); 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 (r != OK) break; /* EOF reached */
if (rdwt_err < 0) break; if (rdwt_err < 0) break;
/* Update counters and pointers. */ /* Update counters and pointers. */
nrbytes -= chunk; /* bytes yet to be read */ nrbytes -= chunk; /* bytes yet to be read */
cum_io += chunk; /* bytes read so far */ cum_io += chunk; /* bytes read so far */
position += chunk; /* position within the file */ position += chunk; /* position within the file */
} }
fs_m_out.RES_FD_POS = position; /* It might change later and the VFS has fs_m_out.RES_SEEK_POS_LO = position; /* It might change later and the VFS
to know this value */ has to know this value */
/* On write, update file size and access time. */ /* On write, update file size and access time. */
if (rw_flag == WRITING) { if (rw_flag == WRITING) {
if (regular || mode_word == I_DIRECTORY) { if (regular || mode_word == I_DIRECTORY) {
if (position > f_size) rip->i_size = position; 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. */ /* 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 if(rw_flag == READING && rip->i_seek == NO_SEEK &&
&& (regular || mode_word == I_DIRECTORY)) { position % block_size == 0 && (regular || mode_word == I_DIRECTORY)) {
rdahed_inode = rip; rdahed_inode = rip;
rdahedpos = position; rdahedpos = position;
} }
rip->i_seek = NO_SEEK; rip->i_seek = NO_SEEK;
if (rdwt_err != OK) r = rdwt_err; /* check for disk error */ if (rdwt_err != OK) r = rdwt_err; /* check for disk error */
if (rdwt_err == END_OF_FILE) r = OK; if (rdwt_err == END_OF_FILE) r = OK;
/* if user-space copying failed, read/write failed. */ /* if user-space copying failed, read/write failed. */
if (r == OK && r2 != OK) { if (r == OK && r2 != OK)
r = r2; r = r2;
}
if (r == OK) { if (r == OK) {
if (rw_flag == READING) rip->i_update |= ATIME; if (rw_flag == READING) rip->i_update |= ATIME;
if (rw_flag == WRITING) rip->i_update |= CTIME | MTIME; if (rw_flag == WRITING) rip->i_update |= CTIME | MTIME;
rip->i_dirt = DIRTY; /* inode is thus now dirty */ rip->i_dirt = DIRTY; /* inode is thus now dirty */
} }
fs_m_out.RES_FD_CUM_IO = cum_io; fs_m_out.RES_NBYTES = cum_io;
fs_m_out.RES_FD_SIZE = rip->i_size;
return(r); return(r);
} }
/*===========================================================================* /*===========================================================================*
* fs_breadwrite_o * * fs_breadwrite *
*===========================================================================*/ *===========================================================================*/
PUBLIC int fs_breadwrite_o(void) PUBLIC int fs_breadwrite(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)
{ {
int r, rw_flag, chunk, block_size; int r, rw_flag, chunk, block_size;
cp_grant_id_t gid; cp_grant_id_t gid;
@ -390,14 +149,14 @@ PUBLIC int fs_breadwrite_s(void)
r = OK; r = OK;
/* Get the values from the request message */ /* Get the values from the request message */
rw_flag = (fs_m_in.m_type == REQ_BREAD_S ? READING : WRITING); rw_flag = (fs_m_in.m_type == REQ_BREAD ? READING : WRITING);
gid = fs_m_in.REQ_XFD_GID; gid = fs_m_in.REQ_GRANT;
position = make64(fs_m_in.REQ_XFD_POS_LO, fs_m_in.REQ_XFD_POS_HI); position = make64(fs_m_in.REQ_SEEK_POS_LO, fs_m_in.REQ_SEEK_POS_HI);
nrbytes = (unsigned) fs_m_in.REQ_XFD_NBYTES; 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_mode = I_BLOCK_SPECIAL;
rip.i_size = 0; rip.i_size = 0;
@ -406,31 +165,31 @@ PUBLIC int fs_breadwrite_s(void)
cum_io = 0; cum_io = 0;
/* Split the transfer into chunks that don't span two blocks. */ /* Split the transfer into chunks that don't span two blocks. */
while (nrbytes != 0) { 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); chunk = MIN(nrbytes, block_size - off);
if (chunk < 0) chunk = block_size - off; if (chunk < 0) chunk = block_size - off;
/* Read or write 'chunk' bytes. */ /* Read or write 'chunk' bytes. */
r = rw_chunk_s(&rip, position, off, chunk, (unsigned) nrbytes, r = rw_chunk(&rip, position, off, chunk, (unsigned) nrbytes,
rw_flag, gid, cum_io, block_size, &completed); rw_flag, gid, cum_io, block_size, &completed);
if (r != OK) break; /* EOF reached */ if (r != OK) break; /* EOF reached */
if (rdwt_err < 0) break; if (rdwt_err < 0) break;
/* Update counters and pointers. */ /* Update counters and pointers. */
nrbytes -= chunk; /* bytes yet to be read */ nrbytes -= chunk; /* bytes yet to be read */
cum_io += chunk; /* bytes read so far */ cum_io += chunk; /* bytes read so far */
position= add64ul(position, chunk); /* position within the file */ position= add64ul(position, chunk); /* position within the file */
} }
fs_m_out.RES_XFD_POS_LO = ex64lo(position); fs_m_out.RES_SEEK_POS_LO = ex64lo(position);
fs_m_out.RES_XFD_POS_HI = ex64hi(position); fs_m_out.RES_SEEK_POS_HI = ex64hi(position);
if (rdwt_err != OK) r = rdwt_err; /* check for disk error */ if (rdwt_err != OK) r = rdwt_err; /* check for disk error */
if (rdwt_err == END_OF_FILE) r = OK; 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); return(r);
} }
@ -439,104 +198,7 @@ PUBLIC int fs_breadwrite_s(void)
/*===========================================================================* /*===========================================================================*
* rw_chunk * * rw_chunk *
*===========================================================================*/ *===========================================================================*/
PRIVATE int rw_chunk(rip, position, off, chunk, left, rw_flag, buff, PRIVATE int rw_chunk(rip, position, off, chunk, left, rw_flag, gid,
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,
buf_off, block_size, completed) buf_off, block_size, completed)
register struct inode *rip; /* pointer to inode for file to be rd/wr */ register struct inode *rip; /* pointer to inode for file to be rd/wr */
u64_t position; /* position within file to read or write */ u64_t position; /* position within file to read or write */
@ -564,8 +226,7 @@ int *completed; /* number of bytes copied */
if (block_spec) { if (block_spec) {
b = div64u(position, block_size); b = div64u(position, block_size);
dev = (dev_t) rip->i_zone[0]; dev = (dev_t) rip->i_zone[0];
} } else {
else {
if (ex64hi(position) != 0) if (ex64hi(position) != 0)
panic(__FILE__, "rw_chunk: position too high", NO_NUM); panic(__FILE__, "rw_chunk: position too high", NO_NUM);
b = read_map(rip, ex64lo(position)); 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.*/ /* Reading from a nonexistent block. Must read as all zeros.*/
bp = get_block(NO_DEV, NO_BLOCK, NORMAL); /* get a buffer */ bp = get_block(NO_DEV, NO_BLOCK, NORMAL); /* get a buffer */
zero_block(bp); zero_block(bp);
} } else {
else {
/* Writing to a nonexistent block. Create and enter in inode.*/ /* Writing to a nonexistent block. Create and enter in inode.*/
if ((bp= new_block(rip, ex64lo(position))) == NIL_BUF) if ((bp= new_block(rip, ex64lo(position))) == NIL_BUF)
return(err_code); return(err_code);
} }
} } else if (rw_flag == READING) {
else if (rw_flag == READING) {
/* Read and read ahead if convenient. */ /* Read and read ahead if convenient. */
bp = rahead(rip, b, position, left); bp = rahead(rip, b, position, left);
} } else {
else {
/* Normally an existing block to be partially overwritten is first read /* 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 * 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. * 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. */ /* 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); panic(__FILE__,"bp not valid in rw_chunk, this can't happen", NO_NUM);
}
if (rw_flag == WRITING && chunk != block_size && !block_spec && if (rw_flag == WRITING && chunk != block_size && !block_spec &&
ex64lo(position) >= rip->i_size && off == 0) { ex64lo(position) >= rip->i_size && off == 0) {
@ -611,19 +268,15 @@ int *completed; /* number of bytes copied */
if (rw_flag == READING) { if (rw_flag == READING) {
/* Copy a chunk from the block buffer to user space. */ /* 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, r = sys_safecopyto(FS_PROC_NR, gid, buf_off,
(vir_bytes) (bp->b_data+off), (phys_bytes) chunk, D); (vir_bytes) (bp->b_data+off), (phys_bytes) chunk, D);
} } else {
else {
/* Copy a chunk from user space to the block buffer. */ /* Copy a chunk from user space to the block buffer. */
r = sys_safecopyfrom(FS_PROC_NR, gid, buf_off, r = sys_safecopyfrom(FS_PROC_NR, gid, buf_off,
(vir_bytes) (bp->b_data+off), (phys_bytes) chunk, D); (vir_bytes) (bp->b_data+off), (phys_bytes) chunk, D);
bp->b_dirt = DIRTY; bp->b_dirt = DIRTY;
} }
n = (off + chunk == block_size ? FULL_DATA_BLOCK : PARTIAL_DATA_BLOCK); n = (off + chunk == block_size ? FULL_DATA_BLOCK : PARTIAL_DATA_BLOCK);
put_block(bp, n); put_block(bp, n);
@ -697,6 +350,7 @@ off_t position; /* position in file whose blk wanted */
return(b); return(b);
} }
/*===========================================================================* /*===========================================================================*
* rd_indir * * rd_indir *
*===========================================================================*/ *===========================================================================*/
@ -729,9 +383,11 @@ int index; /* index into *bp */
(long) zone, index); (long) zone, index);
panic(__FILE__,"check file system", NO_NUM); panic(__FILE__,"check file system", NO_NUM);
} }
return(zone); return(zone);
} }
/*===========================================================================* /*===========================================================================*
* read_ahead * * read_ahead *
*===========================================================================*/ *===========================================================================*/
@ -751,6 +407,7 @@ PUBLIC void read_ahead()
put_block(bp, PARTIAL_DATA_BLOCK); put_block(bp, PARTIAL_DATA_BLOCK);
} }
/*===========================================================================* /*===========================================================================*
* rahead * * rahead *
*===========================================================================*/ *===========================================================================*/
@ -781,11 +438,11 @@ unsigned bytes_ahead; /* bytes beyond position for immediate use */
STATICINIT(read_q, NR_BUFS); STATICINIT(read_q, NR_BUFS);
block_spec = (rip->i_mode & I_TYPE) == I_BLOCK_SPECIAL; block_spec = (rip->i_mode & I_TYPE) == I_BLOCK_SPECIAL;
if (block_spec) { if (block_spec)
dev = (dev_t) rip->i_zone[0]; dev = (dev_t) rip->i_zone[0];
} else { else
dev = rip->i_dev; dev = rip->i_dev;
}
block_size = get_block_size(dev); block_size = get_block_size(dev);
block = baseblock; 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 * * fs_getdents *
*===========================================================================*/ *===========================================================================*/
@ -891,155 +544,124 @@ PUBLIC int fs_getdents(void)
struct dirent *dep; struct dirent *dep;
char *cp; char *cp;
ino= fs_m_in.REQ_GDE_INODE; ino = fs_m_in.REQ_INODE_NR;
gid= fs_m_in.REQ_GDE_GRANT; gid = fs_m_in.REQ_GRANT;
size= fs_m_in.REQ_GDE_SIZE; size = fs_m_in.REQ_MEM_SIZE;
pos= fs_m_in.REQ_GDE_POS; pos = fs_m_in.REQ_SEEK_POS_LO;
/* Check whether the position is properly aligned */ /* Check whether the position is properly aligned */
if (pos % DIR_ENTRY_SIZE) if(pos % DIR_ENTRY_SIZE)
return ENOENT; return(ENOENT);
if ( (rip = get_inode(fs_dev, ino)) == NIL_INODE) { if( (rip = get_inode(fs_dev, ino)) == NIL_INODE)
printf("MFS(%d) get_inode by fs_getdents() failed\n", SELF_E); return(EINVAL);
return(EINVAL);
}
block_size= rip->i_sp->s_block_size; block_size = rip->i_sp->s_block_size;
off= (pos % block_size); /* Offset in block */ off = (pos % block_size); /* Offset in block */
block_pos= pos-off; block_pos = pos - off;
done= FALSE; /* Stop processing directory blocks done = FALSE; /* Stop processing directory blocks when done is set */
* 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 */ 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 /* The default position for the next request is EOF. If the user's buffer
* fills up before EOF, new_pos will be modified. * fills up before EOF, new_pos will be modified. */
*/ new_pos = rip->i_size;
new_pos= rip->i_size;
for (; block_pos < rip->i_size; block_pos += block_size) { for(; block_pos < rip->i_size; block_pos += block_size) {
b = read_map(rip, block_pos); /* get block number */ 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. */ if(bp == NO_BLOCK)
bp = get_block(rip->i_dev, b, NORMAL); /* get a dir block */ panic(__FILE__,"get_block returned NO_BLOCK", NO_NUM);
if (bp == NO_BLOCK) /* Search a directory block. */
panic(__FILE__,"get_block returned NO_BLOCK", NO_NUM); 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. */ /* Compute the length of the name */
if (block_pos < pos) cp = memchr(dp->d_name, '\0', NAME_MAX);
dp = &bp->b_dir[off / DIR_ENTRY_SIZE]; if (cp == NULL)
else len = NAME_MAX;
dp = &bp->b_dir[0]; else
for (; dp < &bp->b_dir[NR_DIR_ENTRIES(block_size)]; dp++) { len = cp-dp->d_name;
if (dp->d_ino == 0)
continue; /* Entry is not in use */
/* Compute the length of the name */
cp= memchr(dp->d_name, '\0', NAME_MAX);
if (cp == NULL)
len= NAME_MAX;
else
len= cp-dp->d_name;
/* Compute record length */
reclen = offsetof(struct dirent, d_name) + len + 1;
o = (reclen % sizeof(long));
if (o != 0)
reclen += sizeof(long) - o;
/* Compute record length */ /* Need the postition of this entry in the directory */
reclen= offsetof(struct dirent, d_name) + len + 1; ent_pos = block_pos + ((char *)dp - bp->b_data);
o= (reclen % sizeof(long));
if (o != 0)
reclen += sizeof(long)-o;
/* Need the postition of this entry in the directory */ if(tmpbuf_off + reclen > GETDENTS_BUFSIZ) {
ent_pos= block_pos + ((char *)dp - bp->b_data); r = sys_safecopyto(FS_PROC_NR, gid, userbuf_off,
(vir_bytes)getdents_buf,
if (tmpbuf_off + reclen > GETDENTS_BUFSIZ) tmpbuf_off, D);
{ if (r != OK)
r= sys_safecopyto(FS_PROC_NR, gid, userbuf_off, panic(__FILE__,
(vir_bytes)getdents_buf, tmpbuf_off, D);
if (r != OK)
{
panic(__FILE__,
"fs_getdents: sys_safecopyto failed\n", "fs_getdents: sys_safecopyto failed\n",
r); r);
}
userbuf_off += tmpbuf_off; userbuf_off += tmpbuf_off;
tmpbuf_off= 0; 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) dep = (struct dirent *)&getdents_buf[tmpbuf_off];
{ dep->d_ino = dp->d_ino;
/* The user has no space for one more record */ dep->d_off = ent_pos;
done= TRUE; 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 put_block(bp, DIRECTORY_BLOCK);
* starting point of the next request (unless the if(done)
* postion is modified with lseek). break;
*/
new_pos= ent_pos;
break;
}
dep= (struct dirent *)&getdents_buf[tmpbuf_off];
dep->d_ino= dp->d_ino;
dep->d_off= ent_pos;
dep->d_reclen= reclen;
memcpy(dep->d_name, dp->d_name, len);
dep->d_name[len]= '\0';
tmpbuf_off += reclen;
}
put_block(bp, DIRECTORY_BLOCK);
if (done)
break;
} }
if (tmpbuf_off != 0) if(tmpbuf_off != 0) {
{ r = sys_safecopyto(FS_PROC_NR, gid, userbuf_off,
r= sys_safecopyto(FS_PROC_NR, gid, userbuf_off, (vir_bytes) getdents_buf, tmpbuf_off, D);
(vir_bytes)getdents_buf, tmpbuf_off, D); if (r != OK)
if (r != OK) panic(__FILE__, "fs_getdents: sys_safecopyto failed\n", r);
panic(__FILE__, "fs_getdents: sys_safecopyto failed\n", r);
userbuf_off += tmpbuf_off; userbuf_off += tmpbuf_off;
} }
if (done && userbuf_off == 0) if(done && userbuf_off == 0)
r= EINVAL; /* The user's buffer is too small */ r = EINVAL; /* The user's buffer is too small */
else else {
{ fs_m_out.RES_NBYTES = userbuf_off;
fs_m_out.RES_GDE_CUM_IO= userbuf_off; fs_m_out.RES_SEEK_POS_LO = new_pos;
if (new_pos >= pos) rip->i_update |= ATIME;
fs_m_out.RES_GDE_POS_CHANGE= new_pos-pos; rip->i_dirt = DIRTY;
else r = OK;
fs_m_out.RES_GDE_POS_CHANGE= 0;
rip->i_update |= ATIME;
rip->i_dirt = DIRTY;
r= OK;
} }
put_inode(rip); /* release the inode */ put_inode(rip); /* release the inode */
return(r); 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);
}

View file

@ -1,5 +1,3 @@
#include "fs.h" #include "fs.h"
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/statfs.h> #include <sys/statfs.h>
@ -8,20 +6,17 @@
#include "buf.h" #include "buf.h"
#include "inode.h" #include "inode.h"
#include "super.h" #include "super.h"
#include <minix/vfsif.h> #include <minix/vfsif.h>
FORWARD _PROTOTYPE( int stat_inode, (struct inode *rip, int who_e,
FORWARD _PROTOTYPE( int stat_inode, (struct inode *rip, int pipe_pos, cp_grant_id_t gid) );
int who_e, cp_grant_id_t gid) );
/*===========================================================================* /*===========================================================================*
* stat_inode * * 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 */ register struct inode *rip; /* pointer to inode to stat */
int pipe_pos; /* position in a pipe, supplied by fstat() */
int who_e; /* Caller endpoint */ int who_e; /* Caller endpoint */
cp_grant_id_t gid; /* grant for the stat buf */ 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_gid = rip->i_gid;
statbuf.st_rdev = (dev_t) (s ? rip->i_zone[0] : NO_DEV); statbuf.st_rdev = (dev_t) (s ? rip->i_zone[0] : NO_DEV);
statbuf.st_size = rip->i_size; 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_atime = rip->i_atime;
statbuf.st_mtime = rip->i_mtime; statbuf.st_mtime = rip->i_mtime;
statbuf.st_ctime = rip->i_ctime; statbuf.st_ctime = rip->i_ctime;
@ -75,20 +64,19 @@ PUBLIC int fs_fstatfs()
struct inode *rip; struct inode *rip;
int r; int r;
if ((rip = find_inode(fs_dev, ROOT_INODE)) == NIL_INODE) { if((rip = find_inode(fs_dev, ROOT_INODE)) == NIL_INODE)
printf("mfs:fstatfs: couldn't find inode %d\n", ROOT_INODE); return(EINVAL);
return EINVAL;
}
st.f_bsize = rip->i_sp->s_block_size; st.f_bsize = rip->i_sp->s_block_size;
/* Copy the struct to user space. */ /* Copy the struct to user space. */
r = sys_safecopyto(fs_m_in.m_source, fs_m_in.REQ_GRANT, 0, r = sys_safecopyto(fs_m_in.m_source, fs_m_in.REQ_GRANT, 0, (vir_bytes) &st,
(vir_bytes) &st, (phys_bytes) sizeof(st), D); (phys_bytes) sizeof(st), D);
return(r); return(r);
} }
/*===========================================================================* /*===========================================================================*
* fs_stat * * fs_stat *
*===========================================================================*/ *===========================================================================*/
@ -97,15 +85,11 @@ PUBLIC int fs_stat()
register int r; /* return value */ register int r; /* return value */
register struct inode *rip; /* target inode */ register struct inode *rip; /* target inode */
if ( (rip = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_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);
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 */ put_inode(rip); /* release the inode */
return(r); return(r);
} }

View file

@ -142,6 +142,7 @@ bit_t bit_returned; /* number of bit to insert into the map */
put_block(bp, MAP_BLOCK); put_block(bp, MAP_BLOCK);
} }
/*===========================================================================* /*===========================================================================*
* get_super * * get_super *
*===========================================================================*/ *===========================================================================*/
@ -154,9 +155,10 @@ dev_t dev; /* device number whose super_block is sought */
if(superblock.s_dev != dev) if(superblock.s_dev != dev)
panic(__FILE__,"wrong superblock", (int) dev); panic(__FILE__,"wrong superblock", (int) dev);
return &superblock; return(&superblock);
} }
/*===========================================================================* /*===========================================================================*
* get_block_size * * get_block_size *
*===========================================================================*/ *===========================================================================*/
@ -165,43 +167,11 @@ PUBLIC int get_block_size(dev_t dev)
if (dev == NO_DEV) if (dev == NO_DEV)
panic(__FILE__,"request for block size of NO_DEV", NO_NUM); 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 * * 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, r = block_dev_io(MFS_DEV_READ, dev, SELF_E,
sbbuf, cvu64(SUPER_BLOCK_BYTES), _MIN_BLOCK_SIZE, 0); sbbuf, cvu64(SUPER_BLOCK_BYTES), _MIN_BLOCK_SIZE, 0);
if (r != _MIN_BLOCK_SIZE) { if (r != _MIN_BLOCK_SIZE)
return EINVAL; return(EINVAL);
}
memcpy(sp, sbbuf, sizeof(*sp)); memcpy(sp, sbbuf, sizeof(*sp));
sp->s_dev = NO_DEV; /* restore later */ sp->s_dev = NO_DEV; /* restore later */
magic = sp->s_magic; /* determines file system type */ 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); sp->s_nindirs = V2_INDIRECTS(sp->s_block_size);
} }
if (sp->s_block_size < _MIN_BLOCK_SIZE) { if (sp->s_block_size < _MIN_BLOCK_SIZE)
return EINVAL; return(EINVAL);
}
if ((sp->s_block_size % 512) != 0) { if ((sp->s_block_size % 512) != 0)
return EINVAL; return(EINVAL);
}
if (SUPER_SIZE > sp->s_block_size) { if (SUPER_SIZE > sp->s_block_size)
return EINVAL; return(EINVAL);
}
if ((sp->s_block_size % V2_INODE_SIZE) != 0 || if ((sp->s_block_size % V2_INODE_SIZE) != 0 ||
(sp->s_block_size % V1_INODE_SIZE) != 0) { (sp->s_block_size % V1_INODE_SIZE) != 0) {
return EINVAL; return(EINVAL);
} }
/* Limit s_max_size to LONG_MAX */ /* Limit s_max_size to LONG_MAX */
if ((unsigned long)sp->s_max_size > LONG_MAX) if ((unsigned long)sp->s_max_size > LONG_MAX)
{ sp->s_max_size = LONG_MAX;
printf("read_super: reducing s_max_size to LONG_MAX\n");
sp->s_max_size= LONG_MAX;
}
sp->s_isearch = 0; /* inode searches initially start at 0 */ sp->s_isearch = 0; /* inode searches initially start at 0 */
sp->s_zsearch = 0; /* zone 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 */ sp->s_dev = dev; /* restore device number */
return(OK); return(OK);
} }

View file

@ -15,59 +15,36 @@
PUBLIC _PROTOTYPE (int (*fs_call_vec[]), (void) ) = { PUBLIC _PROTOTYPE (int (*fs_call_vec[]), (void) ) = {
no_sys, /* 0 not used */ no_sys, /* 0 not used */
fs_getnode, /* 1 */ no_sys, /* 1 */ /* Was: fs_getnode */
fs_putnode, /* 2 */ fs_putnode, /* 2 */
fs_slink_s, /* 3 */ fs_slink, /* 3 */
fs_pipe, /* 4 */ fs_ftrunc, /* 4 */
fs_readwrite_o, /* 5 */ /* read() */ fs_chown, /* 5 */
fs_readwrite_o, /* 6 */ /* write() */ fs_chmod, /* 6 */
fs_clone_opcl, /* 7 */ fs_inhibread, /* 7 */
fs_ftrunc, /* 8 */ fs_stat, /* 8 */
fs_chown, /* 9 */ fs_utime, /* 9 */
fs_chmod, /* 10 */ fs_fstatfs, /* 10 */
fs_access_o, /* 11 */ fs_breadwrite, /* 11 */
fs_mknod_o, /* 12 */ fs_breadwrite, /* 12 */
fs_mkdir_o, /* 13 */ fs_unlink, /* 13 */
fs_inhibread, /* 14 */ /* for lseek() */ fs_unlink, /* 14 */
fs_stat, /* 15 */ fs_unmount, /* 15 */
fs_create_o, /* 16 */ fs_sync, /* 16 */
fs_unlink_o, /* 17 */ /* unlink() */ fs_new_driver, /* 17 */
fs_unlink_o, /* 18 */ /* rmdir() */ fs_flush, /* 18 */
fs_utime, /* 19 */ fs_readwrite, /* 19 */
fs_rdlink_so, /* 20 */ fs_readwrite, /* 20 */
fs_fstatfs, /* 21 */ fs_mknod, /* 21 */
fs_breadwrite_s, /* 22 */ fs_mkdir, /* 22 */
fs_breadwrite_s, /* 23 */ fs_create, /* 23 */
fs_unlink_s, /* 24 */ /* unlink() */ fs_link, /* 24 */
fs_link_o, /* 25 */ fs_rename, /* 25 */
fs_slink_o, /* 26 */ fs_lookup, /* 26 */
fs_rdlink_o, /* 27 */ fs_mountpoint, /* 27 */
fs_rename_o, /* 28 */ fs_readsuper, /* 28 */
fs_unlink_s, /* 29 */ /* rmdir() */ fs_newnode, /* 29 */
fs_mountpoint_o, /* 30 */ fs_rdlink, /* 30 */
fs_readsuper_o, /* 31 */ fs_getdents, /* 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 */
}; };

View file

@ -1,11 +1,7 @@
#include "fs.h" #include "fs.h"
#include <minix/callnr.h> #include <minix/callnr.h>
#include <minix/com.h> #include <minix/com.h>
#include "inode.h" #include "inode.h"
#include <minix/vfsif.h> #include <minix/vfsif.h>
@ -18,29 +14,20 @@ PUBLIC int fs_utime()
register int r; register int r;
/* Temporarily open the file. */ /* Temporarily open the file. */
if ( (rip = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) { 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);
return(EINVAL); return(EINVAL);
}
/* Only the owner of a file or the super_user can change its time. */ /* Only the owner of a file or the super_user can change its time. */
r = OK; r = OK;
if (read_only(rip) != OK) r = EROFS; /* not even su can touch if R/O */ if(read_only(rip) != OK) r = EROFS; /* not even su can touch if R/O */
if (r == OK) { if(r == OK) {
rip->i_atime = fs_m_in.REQ_ACTIME; rip->i_atime = fs_m_in.REQ_ACTIME;
rip->i_mtime = fs_m_in.REQ_MODTIME; rip->i_mtime = fs_m_in.REQ_MODTIME;
rip->i_update = CTIME; /* discard any stale ATIME and MTIME flags */
rip->i_update = CTIME; /* discard any stale ATIME and MTIME flags */ rip->i_dirt = DIRTY;
rip->i_dirt = DIRTY;
} }
put_inode(rip); put_inode(rip);
return(r); return(r);
} }
PUBLIC int fs_stime()
{
boottime = fs_m_in.REQ_BOOTTIME;
return OK;
}

View file

@ -1,17 +1,15 @@
#include "fs.h" #include "fs.h"
#include <sys/stat.h> #include <sys/stat.h>
#include <string.h> #include <string.h>
#include <minix/com.h> #include <minix/com.h>
#include <minix/callnr.h> #include <minix/callnr.h>
#include <stdlib.h> #include <stdlib.h>
#include "buf.h" #include "buf.h"
#include "inode.h" #include "inode.h"
#include "super.h" #include "super.h"
#include <minix/vfsif.h> #include <minix/vfsif.h>
/*===========================================================================* /*===========================================================================*
* no_sys * * no_sys *
*===========================================================================*/ *===========================================================================*/
@ -22,6 +20,7 @@ PUBLIC int no_sys()
return(EINVAL); return(EINVAL);
} }
/*===========================================================================* /*===========================================================================*
* conv2 * * conv2 *
*===========================================================================*/ *===========================================================================*/
@ -34,6 +33,7 @@ int w; /* promotion of 16-bit word to be swapped */
return( ((w&BYTE) << 8) | ( (w>>8) & BYTE)); return( ((w&BYTE) << 8) | ( (w>>8) & BYTE));
} }
/*===========================================================================* /*===========================================================================*
* conv4 * * conv4 *
*===========================================================================*/ *===========================================================================*/
@ -52,6 +52,7 @@ long x; /* 32-bit long to be byte swapped */
return(l); return(l);
} }
/*===========================================================================* /*===========================================================================*
* clock_time * * clock_time *
*===========================================================================*/ *===========================================================================*/
@ -65,20 +66,22 @@ PUBLIC time_t clock_time()
register int k; register int k;
clock_t uptime; clock_t uptime;
if (use_getuptime2) if (use_getuptime2) {
{
if ( (k=getuptime2(&uptime,&boottime)) != OK) if ( (k=getuptime2(&uptime,&boottime)) != OK)
panic(__FILE__,"clock_time: getuptme2 failed", k); panic(__FILE__,"clock_time: getuptme2 failed", k);
} } else {
else
{
if ( (k=getuptime(&uptime)) != OK) if ( (k=getuptime(&uptime)) != OK)
panic(__FILE__,"clock_time err", k); panic(__FILE__,"clock_time err", k);
} }
return( (time_t) (boottime + (uptime/sys_hz()))); 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) { if(v1 < 0 || v2 < 0) {
printf("mfs:%s:%d: strange string lengths: %d, %d\n", 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); panic(file, "strange string lengths", NO_NUM);
} }
if(v2 >= v1) return v1; if(v2 >= v1) return v1;
#if 0
printf("mfs:%s:%d: truncated %d to %d\n",
file, line, v1, v2);
#endif
return v2; 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) { if(len < 1) {
printf("mfs:%s:%d: %d-length string?!\n", file, line, len); 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", \ #define MYASSERT(c) if(!(c)) { printf("MFS:%s:%d: sanity check: %s failed\n", \
file, line, #c); panic("MFS", "sanity check " #c " failed", __LINE__); } 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); MYASSERT(SELF_E > 0);
if(superblock.s_dev != NO_DEV) { if(superblock.s_dev != NO_DEV) {

View file

@ -1,14 +1,12 @@
/* This file is the counterpart of "read.c". It contains the code for writing /* This file is the counterpart of "read.c". It contains the code for writing
* insofar as this is not contained in read_write(). * insofar as this is not contained in read_write().
* *
* The entry points into this file are * 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 * clear_zone: erase a zone in the middle of a file
* new_block: acquire a new block * 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" #include "fs.h"
@ -181,6 +179,7 @@ int op; /* special actions */
return(OK); return(OK);
} }
/*===========================================================================* /*===========================================================================*
* wr_indir * * 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); bp->b_v2_ind[index] = (zone_t) conv4(sp->s_native, (long) zone);
} }
/*===========================================================================* /*===========================================================================*
* empty_indir * * 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 /* Return nonzero if the indirect block pointed to by bp contains
* only NO_ZONE entries. * only NO_ZONE entries.
*/ */
int i; int i;
if(sb->s_version == V1) { if(sb->s_version == V1) {
for(i = 0; i < V1_INDIRECTS; i++) for(i = 0; i < V1_INDIRECTS; i++)
if(bp->b_v1_ind[i] != NO_ZONE) if(bp->b_v1_ind[i] != NO_ZONE)
return 0; return(0);
} else { } else {
for(i = 0; i < V2_INDIRECTS(sb->s_block_size); i++) for(i = 0; i < V2_INDIRECTS(sb->s_block_size); i++)
if(bp->b_v2_ind[i] != NO_ZONE) if(bp->b_v2_ind[i] != NO_ZONE)
return 0; return(0);
} }
return 1; return(1);
} }
/*===========================================================================* /*===========================================================================*
* clear_zone * * clear_zone *
*===========================================================================*/ *===========================================================================*/
@ -269,6 +270,7 @@ int flag; /* 0 if called by read_write, 1 by new_block */
} }
} }
/*===========================================================================* /*===========================================================================*
* new_block * * new_block *
*===========================================================================*/ *===========================================================================*/
@ -323,6 +325,7 @@ off_t position; /* file pointer */
return(bp); return(bp);
} }
/*===========================================================================* /*===========================================================================*
* zero_block * * zero_block *
*===========================================================================*/ *===========================================================================*/

View file

@ -7,6 +7,7 @@
#include "pm.h" #include "pm.h"
#include <minix/callnr.h> #include <minix/callnr.h>
#include <minix/endpoint.h> #include <minix/endpoint.h>
#include <limits.h>
#include <minix/com.h> #include <minix/com.h>
#include <signal.h> #include <signal.h>
#include "mproc.h" #include "mproc.h"
@ -22,8 +23,32 @@ PUBLIC int do_get()
register struct mproc *rmp = mp; register struct mproc *rmp = mp;
int r, proc; int r, proc;
int ngroups;
switch(call_nr) { 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: case GETUID:
r = rmp->mp_realuid; r = rmp->mp_realuid;
rmp->mp_reply.reply_res2 = rmp->mp_effuid; rmp->mp_reply.reply_res2 = rmp->mp_effuid;
@ -60,7 +85,8 @@ PUBLIC int do_set()
*/ */
register struct mproc *rmp = mp; register struct mproc *rmp = mp;
message m; message m;
int r; int r, i;
int ngroups;
switch(call_nr) { switch(call_nr) {
case SETUID: case SETUID:
@ -92,7 +118,34 @@ PUBLIC int do_set()
m.PM_RID = rmp->mp_realgid; m.PM_RID = rmp->mp_realgid;
break; 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: case SETSID:
if (rmp->mp_procgrp == rmp->mp_pid) return(EPERM); if (rmp->mp_procgrp == rmp->mp_pid) return(EPERM);
rmp->mp_procgrp = rmp->mp_pid; rmp->mp_procgrp = rmp->mp_pid;

View file

@ -102,6 +102,7 @@ PUBLIC int main()
case PM_FORK_NB_REPLY: case PM_FORK_NB_REPLY:
case PM_UNPAUSE_REPLY: case PM_UNPAUSE_REPLY:
case PM_REBOOT_REPLY: case PM_REBOOT_REPLY:
case PM_SETGROUPS_REPLY:
if (who_e == FS_PROC_NR) if (who_e == FS_PROC_NR)
{ {
handle_fs_reply(); handle_fs_reply();
@ -441,6 +442,7 @@ PRIVATE void handle_fs_reply()
switch (call_nr) { switch (call_nr) {
case PM_SETUID_REPLY: case PM_SETUID_REPLY:
case PM_SETGID_REPLY: case PM_SETGID_REPLY:
case PM_SETGROUPS_REPLY:
/* Wake up the original caller */ /* Wake up the original caller */
setreply(rmp-mproc, OK); setreply(rmp-mproc, OK);

View file

@ -4,6 +4,7 @@
* systems have tables that are also indexed by process, with the contents * systems have tables that are also indexed by process, with the contents
* of corresponding slots referring to the same process in all three. * of corresponding slots referring to the same process in all three.
*/ */
#include <limits.h>
#include <timers.h> #include <timers.h>
#include <signal.h> #include <signal.h>
@ -30,6 +31,10 @@ EXTERN struct mproc {
gid_t mp_realgid; /* process' real gid */ gid_t mp_realgid; /* process' real gid */
gid_t mp_effgid; /* process' effective 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. */ /* Signal handling information. */
sigset_t mp_ignore; /* 1 means ignore the signal, 0 means don't */ 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 */ sigset_t mp_catch; /* 1 means catch the signal, 0 means don't */

View file

@ -3,6 +3,8 @@
#define exec_len m1_i1 #define exec_len m1_i1
#define func m6_f1 #define func m6_f1
#define grp_id m1_i1 #define grp_id m1_i1
#define grp_no m1_i1
#define groupsp m1_p1
#define namelen m1_i2 #define namelen m1_i2
#define pid m1_i1 #define pid m1_i1
#define seconds m1_i1 #define seconds m1_i1

View file

@ -76,8 +76,8 @@ _PROTOTYPE (int (*call_vec[]), (void) ) = {
do_set, /* 62 = setsid */ do_set, /* 62 = setsid */
do_get, /* 63 = getpgrp */ do_get, /* 63 = getpgrp */
do_itimer, /* 64 = itimer */ do_itimer, /* 64 = itimer */
no_sys, /* 65 = unused */ do_get, /* 65 = getgroups */
no_sys, /* 66 = unused */ do_set, /* 66 = setgroups */
no_sys, /* 67 = unused */ no_sys, /* 67 = unused */
no_sys, /* 68 = unused */ no_sys, /* 68 = unused */
no_sys, /* 69 = unused */ no_sys, /* 69 = unused */

View file

@ -44,6 +44,7 @@ PUBLIC struct boot_image_priv boot_image_priv_table[] = {
{ MEM_PROC_NR, SRV_F, SRV_T, SRV_M, mem_kc }, { MEM_PROC_NR, SRV_F, SRV_T, SRV_M, mem_kc },
{ LOG_PROC_NR, SRV_F, SRV_T, SRV_M, drv_kc }, { LOG_PROC_NR, SRV_F, SRV_T, SRV_M, drv_kc },
{ MFS_PROC_NR, SRV_F, SRV_T, SRV_M, fs_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 }, { INIT_PROC_NR, RUSR_F, RUSR_T, RUSR_M, rusr_kc },
{ NULL_BOOT_NR, 0, 0, 0, no_kc } /* null entry */ { 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 */ /*endpoint, sys flags */
{ LOG_PROC_NR, SRVC_SF }, { LOG_PROC_NR, SRVC_SF },
{ MFS_PROC_NR, SRVC_SF }, { MFS_PROC_NR, SRVC_SF },
{ PFS_PROC_NR, SRVC_SF },
{ DEFAULT_BOOT_NR, SRV_SF } /* default entry */ { DEFAULT_BOOT_NR, SRV_SF } /* default entry */
}; };

View file

@ -27,7 +27,6 @@
#include <minix/u64.h> #include <minix/u64.h>
#include "file.h" #include "file.h"
#include "fproc.h" #include "fproc.h"
#include <minix/vfsif.h> #include <minix/vfsif.h>
#include "vnode.h" #include "vnode.h"
#include "vmnt.h" #include "vmnt.h"
@ -35,11 +34,12 @@
#define ELEMENTS(a) (sizeof(a)/sizeof((a)[0])) #define ELEMENTS(a) (sizeof(a)/sizeof((a)[0]))
FORWARD _PROTOTYPE( int safe_io_conversion, (endpoint_t, FORWARD _PROTOTYPE( int safe_io_conversion, (endpoint_t, cp_grant_id_t *,
cp_grant_id_t *, int *, cp_grant_id_t *, int, endpoint_t *, int *, cp_grant_id_t *, int,
void **, int *, vir_bytes, u32_t *)); endpoint_t *, void **, int *,
vir_bytes, u32_t *) );
FORWARD _PROTOTYPE( void safe_io_cleanup, (cp_grant_id_t, cp_grant_id_t *, FORWARD _PROTOTYPE( void safe_io_cleanup, (cp_grant_id_t, cp_grant_id_t *,
int)); int) );
FORWARD _PROTOTYPE( void restart_reopen, (int maj) ); FORWARD _PROTOTYPE( void restart_reopen, (int maj) );
extern int dmap_size; extern int dmap_size;
@ -64,8 +64,7 @@ int flags; /* mode bits and flags */
major = (dev >> MAJOR) & BYTE; major = (dev >> MAJOR) & BYTE;
if (major >= NR_DEVICES) major = 0; if (major >= NR_DEVICES) major = 0;
dp = &dmap[major]; dp = &dmap[major];
if (dp->dmap_driver == NONE) if (dp->dmap_driver == NONE) return(ENXIO);
return ENXIO;
r = (*dp->dmap_opcl)(DEV_OPEN, dev, proc, flags); r = (*dp->dmap_opcl)(DEV_OPEN, dev, proc, flags);
return(r); return(r);
} }
@ -89,11 +88,10 @@ int flags; /* mode bits and flags */
major = (dev >> MAJOR) & BYTE; major = (dev >> MAJOR) & BYTE;
if (major >= NR_DEVICES) major = 0; if (major >= NR_DEVICES) major = 0;
dp = &dmap[major]; dp = &dmap[major];
if (dp->dmap_driver == NONE) if (dp->dmap_driver == NONE) return(ENXIO);
return ENXIO;
r = (*dp->dmap_opcl)(DEV_REOPEN, dev, filp_no, flags); r = (*dp->dmap_opcl)(DEV_REOPEN, dev, filp_no, flags);
if (r == OK) panic(__FILE__,"OK on reopen from", dp->dmap_driver); if (r == OK) panic(__FILE__,"OK on reopen from", dp->dmap_driver);
if (r == SUSPEND) r= OK; if (r == SUSPEND) r = OK;
return(r); return(r);
} }
@ -108,13 +106,12 @@ int filp_no;
int r; int r;
/* See if driver is roughly valid. */ /* See if driver is roughly valid. */
if (dmap[(dev >> MAJOR)].dmap_driver == NONE) { if (dmap[(dev >> MAJOR)].dmap_driver == NONE) return(ENXIO);
return ENXIO; r = (*dmap[(dev >> MAJOR) & BYTE].dmap_opcl)(DEV_CLOSE, dev, filp_no, 0);
} return(r);
r= (*dmap[(dev >> MAJOR) & BYTE].dmap_opcl)(DEV_CLOSE, dev, filp_no, 0);
return r;
} }
/*===========================================================================* /*===========================================================================*
* suspended_ep * * 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 process is suspended on a driver for which FS issued
* a grant. Find out which process it was. * a grant. Find out which process it was.
*/ */
struct fproc *rfp; struct fproc *rfp;
for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) { for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
if(rfp->fp_pid == PID_FREE) if(rfp->fp_pid == PID_FREE) continue;
continue;
if(rfp->fp_blocked_on == FP_BLOCKED_ON_OTHER && if(rfp->fp_blocked_on == FP_BLOCKED_ON_OTHER &&
rfp->fp_task == driver && rfp->fp_grant == g) { rfp->fp_task == driver && rfp->fp_grant == g)
return rfp->fp_endpoint; return rfp->fp_endpoint;
}
} }
return NONE; return(NONE);
} }
/*===========================================================================* /*===========================================================================*
* dev_status * * dev_status *
*===========================================================================*/ *===========================================================================*/
PUBLIC void dev_status(message *m) PUBLIC void dev_status(message *m)
{ {
message st; message st;
int d, get_more = 1; int d, get_more = 1;
endpoint_t endpt; endpoint_t endpt;
for(d = 0; d < NR_DEVICES; d++) for(d = 0; d < NR_DEVICES; d++)
if (dmap[d].dmap_driver != NONE && if (dmap[d].dmap_driver != NONE && dmap[d].dmap_driver == m->m_source)
dmap[d].dmap_driver == m->m_source) break;
break;
if (d >= NR_DEVICES) if (d >= NR_DEVICES) return;
return; if (dmap[d].dmap_async_driver) {
printf("dev_status: not doing dev_status for async driver %d\n",
if (dmap[d].dmap_async_driver)
{
printf(
"dev_status: not doing dev_status for async driver %d\n",
m->m_source); m->m_source);
return; return;
} }
@ -164,7 +155,7 @@ PUBLIC void dev_status(message *m)
do { do {
int r; int r;
st.m_type = DEV_STATUS; 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); printf("DEV_STATUS failed to %d: %d\n", m->m_source, r);
if (r == EDEADSRCDST) return; if (r == EDEADSRCDST) return;
if (r == EDSTDIED) return; if (r == EDSTDIED) return;
@ -179,10 +170,9 @@ PUBLIC void dev_status(message *m)
endpt = suspended_ep(m->m_source, endpt = suspended_ep(m->m_source,
st.REP_IO_GRANT); st.REP_IO_GRANT);
if(endpt == NONE) { if(endpt == NONE) {
printf("FS: proc with " printf("FS: proc with grant %d"
"grant %d from %d not found (revive)\n", " from %d not found (revive)\n",
st.REP_IO_GRANT, st.REP_IO_GRANT, st.m_source);
st.m_source);
continue; continue;
} }
} }
@ -205,6 +195,7 @@ PUBLIC void dev_status(message *m)
return; return;
} }
/*===========================================================================* /*===========================================================================*
* safe_io_conversion * * safe_io_conversion *
*===========================================================================*/ *===========================================================================*/
@ -221,106 +212,97 @@ int *vec_grants;
vir_bytes bytes; vir_bytes bytes;
u32_t *pos_lo; u32_t *pos_lo;
{ {
int access = 0, size; int access = 0, size, j;
int j; iovec_t *v;
iovec_t *v; static iovec_t new_iovec[NR_IOREQS];
static iovec_t new_iovec[NR_IOREQS];
/* Number of grants allocated in vector I/O. */ /* Number of grants allocated in vector I/O. */
*vec_grants = 0; *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) { *gid = cpf_grant_magic(driver, *io_ept, (vir_bytes) *buf, bytes,
case VFS_DEV_READ: *op == DEV_READ_S ? CPF_WRITE : CPF_READ);
case VFS_DEV_WRITE: if (*gid < 0)
/* Change to safe op. */ panic(__FILE__, "cpf_grant_magic of buffer failed\n", NO_NUM);
*op = *op == VFS_DEV_READ ? DEV_READ_S : DEV_WRITE_S; 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, /* Grant access to my new i/o vector. */
(vir_bytes) *buf, bytes, *gid = cpf_grant_direct(driver, (vir_bytes) new_iovec,
*op == DEV_READ_S ? CPF_WRITE : CPF_READ)) < 0) { bytes * sizeof(iovec_t), CPF_READ|CPF_WRITE);
panic(__FILE__, if (*gid < 0)
"cpf_grant_magic of buffer failed\n", NO_NUM); 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; new_iovec[j].iov_addr =
case VFS_DEV_GATHER: gids[j] =
case VFS_DEV_SCATTER: cpf_grant_direct(driver, (vir_bytes) v[j].iov_addr, v[j].iov_size,
/* Change to safe op. */ *op == DEV_GATHER_S ? CPF_WRITE : CPF_READ);
*op = *op == VFS_DEV_GATHER ?
DEV_GATHER_S : DEV_SCATTER_S;
/* Grant access to my new i/o vector. */ if(!GRANT_VALID(gids[j]))
if((*gid = cpf_grant_direct(driver, panic(__FILE__, "grant to iovec buf failed", NO_NUM);
(vir_bytes) new_iovec, bytes * sizeof(iovec_t),
CPF_READ | CPF_WRITE)) < 0) { new_iovec[j].iov_size = v[j].iov_size;
panic(__FILE__, (*vec_grants)++;
"cpf_grant_direct of vector failed", NO_NUM); }
}
v = (iovec_t *) *buf;
/* Grant access to i/o buffers. */
for(j = 0; j < bytes; j++) {
if(j >= NR_IOREQS)
panic(__FILE__, "vec too big", bytes);
new_iovec[j].iov_addr = gids[j] =
cpf_grant_direct(driver, (vir_bytes)
v[j].iov_addr, v[j].iov_size,
*op == DEV_GATHER_S ? CPF_WRITE : CPF_READ);
if(!GRANT_VALID(gids[j])) {
panic(__FILE__, "grant to iovec buf failed",
NO_NUM);
}
new_iovec[j].iov_size = v[j].iov_size;
(*vec_grants)++;
}
/* Set user's vector to the new one. */ /* Set user's vector to the new one. */
*buf = new_iovec; *buf = new_iovec;
break; break;
case VFS_DEV_IOCTL: case VFS_DEV_IOCTL:
*pos_lo = *io_ept; /* Old endpoint in POSITION field. */ *pos_lo = *io_ept; /* Old endpoint in POSITION field. */
*op = DEV_IOCTL_S; *op = DEV_IOCTL_S;
if(_MINIX_IOCTL_IOR(m_in.REQUEST)) access |= CPF_WRITE; if(_MINIX_IOCTL_IOR(m_in.REQUEST)) access |= CPF_WRITE;
if(_MINIX_IOCTL_IOW(m_in.REQUEST)) access |= CPF_READ; if(_MINIX_IOCTL_IOW(m_in.REQUEST)) access |= CPF_READ;
if(_MINIX_IOCTL_BIG(m_in.REQUEST)) if(_MINIX_IOCTL_BIG(m_in.REQUEST))
size = _MINIX_IOCTL_SIZE_BIG(m_in.REQUEST); size = _MINIX_IOCTL_SIZE_BIG(m_in.REQUEST);
else else
size = _MINIX_IOCTL_SIZE(m_in.REQUEST); size = _MINIX_IOCTL_SIZE(m_in.REQUEST);
/* Do this even if no I/O happens with the ioctl, in /* Do this even if no I/O happens with the ioctl, in
* order to disambiguate requests with DEV_IOCTL_S. * order to disambiguate requests with DEV_IOCTL_S.
*/ */
if((*gid=cpf_grant_magic(driver, *io_ept, *gid = cpf_grant_magic(driver, *io_ept, (vir_bytes) *buf, size,
(vir_bytes) *buf, size, access)) < 0) { access);
panic(__FILE__, if (*gid < 0)
"cpf_grant_magic failed (ioctl)\n", panic(__FILE__, "cpf_grant_magic failed (ioctl)\n", NO_NUM);
NO_NUM);
} break;
break; case VFS_DEV_SELECT:
case VFS_DEV_SELECT: *op = DEV_SELECT;
*op = DEV_SELECT; break;
break; default:
default: panic(__FILE__,"safe_io_conversion: unknown operation", *op);
panic(__FILE__,"safe_io_conversion: unknown operation", }
*op);
}
/* If we have converted to a safe operation, I/O /* If we have converted to a safe operation, I/O
* endpoint becomes FS if it wasn't already. * endpoint becomes FS if it wasn't already.
*/ */
if(GRANT_VALID(*gid)) { if(GRANT_VALID(*gid)) {
*io_ept = FS_PROC_NR; *io_ept = FS_PROC_NR;
return 1; return 1;
} }
/* Not converted to a safe operation (because there is no /* Not converted to a safe operation (because there is no
* copying involved in this operation). * copying involved in this operation).
*/ */
return 0; return 0;
} }
/*===========================================================================* /*===========================================================================*
@ -332,14 +314,11 @@ cp_grant_id_t *gids;
int gids_size; int gids_size;
{ {
/* Free resources (specifically, grants) allocated by safe_io_conversion(). */ /* 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++)
for(j = 0; j < gids_size; j++) cpf_revoke(gids[j]);
cpf_revoke(gids[j]);
return;
} }
@ -376,11 +355,10 @@ int suspend_reopen; /* Just suspend the process */
/* See if driver is roughly valid. */ /* See if driver is roughly valid. */
if (dp->dmap_driver == NONE) { if (dp->dmap_driver == NONE) {
printf("FS: dev_io: no driver for dev %x\n", dev); printf("FS: dev_io: no driver for dev %x\n", dev);
return ENXIO; return(ENXIO);
} }
if (suspend_reopen) if (suspend_reopen) {
{
/* Suspend user. */ /* Suspend user. */
fp->fp_grant = GRANT_INVALID; fp->fp_grant = GRANT_INVALID;
fp->fp_ioproc = NONE; fp->fp_ioproc = NONE;
@ -390,9 +368,8 @@ int suspend_reopen; /* Just suspend the process */
} }
if(isokendpt(dp->dmap_driver, &dummyproc) != OK) { if(isokendpt(dp->dmap_driver, &dummyproc) != OK) {
printf("FS: dev_io: old driver for dev %x (%d)\n", printf("FS: dev_io: old driver for dev %x (%d)\n",dev,dp->dmap_driver);
dev, dp->dmap_driver); return(ENXIO);
return ENXIO;
} }
/* By default, these are right. */ /* By default, these are right. */
@ -401,9 +378,9 @@ int suspend_reopen; /* Just suspend the process */
/* Convert DEV_* to DEV_*_S variants. */ /* Convert DEV_* to DEV_*_S variants. */
buf_used = buf; buf_used = buf;
safe = safe_io_conversion(dp->dmap_driver, &gid, safe = safe_io_conversion(dp->dmap_driver, &gid, &op, gids, NR_IOREQS,
&op, gids, NR_IOREQS, (endpoint_t*) &dev_mess.IO_ENDPT, &buf_used, (endpoint_t*) &dev_mess.IO_ENDPT, &buf_used,
&vec_grants, bytes, &pos_lo); &vec_grants, bytes, &pos_lo);
if(buf != buf_used) if(buf != buf_used)
panic(__FILE__,"dev_io: safe_io_conversion changed buffer", NO_NUM); 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. */ /* Driver has vanished. */
printf("Driver gone?\n"); printf("Driver gone?\n");
if(safe) safe_io_cleanup(gid, gids, vec_grants); if(safe) safe_io_cleanup(gid, gids, vec_grants);
return EIO; return(EIO);
} }
/* Task has completed. See if call completed. */ /* Task has completed. See if call completed. */
if (dev_mess.REP_STATUS == SUSPEND) { if (dev_mess.REP_STATUS == SUSPEND) {
if(vec_grants > 0) { if(vec_grants > 0) panic(__FILE__,"SUSPEND on vectored i/o", NO_NUM);
panic(__FILE__,"SUSPEND on vectored i/o", NO_NUM);
}
/* fp is uninitialized at init time. */ /* fp is uninitialized at init time. */
if(!fp) if(!fp) panic(__FILE__,"SUSPEND on NULL fp", NO_NUM);
panic(__FILE__,"SUSPEND on NULL fp", NO_NUM);
if ((flags & O_NONBLOCK) && !dp->dmap_async_driver) { if ((flags & O_NONBLOCK) && !dp->dmap_async_driver) {
/* Not supposed to block. */ /* Not supposed to block. */
@ -452,8 +427,8 @@ int suspend_reopen; /* Just suspend the process */
* logic. Mode is expected in the COUNT field. * logic. Mode is expected in the COUNT field.
*/ */
dev_mess.COUNT = 0; dev_mess.COUNT = 0;
if(call_nr == READ) dev_mess.COUNT = R_BIT; if (call_nr == READ) dev_mess.COUNT = R_BIT;
else if(call_nr == WRITE) dev_mess.COUNT = W_BIT; else if (call_nr == WRITE) dev_mess.COUNT = W_BIT;
dev_mess.DEVICE = (dev >> MINOR) & BYTE; dev_mess.DEVICE = (dev >> MINOR) & BYTE;
(*dp->dmap_io)(dp->dmap_driver, &dev_mess); (*dp->dmap_io)(dp->dmap_driver, &dev_mess);
if (dev_mess.REP_STATUS == EINTR) dev_mess.REP_STATUS = EAGAIN; 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) { if (dp->dmap_driver == NONE) {
printf("FS: gen_opcl: no driver for dev %x\n", dev); printf("FS: gen_opcl: no driver for dev %x\n", dev);
return ENXIO; return(ENXIO);
} }
/* Call the task. */ /* Call the task. */
r= (*dp->dmap_io)(dp->dmap_driver, &dev_mess); r= (*dp->dmap_io)(dp->dmap_driver, &dev_mess);
if (r != OK) return r; if (r != OK) return(r);
return(dev_mess.REP_STATUS); return(dev_mess.REP_STATUS);
} }
@ -565,6 +540,7 @@ int flags; /* mode bits and flags */
return(r); return(r);
} }
/*===========================================================================* /*===========================================================================*
* ctty_opcl * * ctty_opcl *
*===========================================================================*/ *===========================================================================*/
@ -581,6 +557,7 @@ int flags; /* mode bits and flags */
return(fp->fp_tty == 0 ? ENXIO : OK); return(fp->fp_tty == 0 ? ENXIO : OK);
} }
/*===========================================================================* /*===========================================================================*
* pm_setsid * * pm_setsid *
*===========================================================================*/ *===========================================================================*/
@ -600,6 +577,7 @@ int proc_e;
rfp->fp_tty = 0; rfp->fp_tty = 0;
} }
/*===========================================================================* /*===========================================================================*
* do_ioctl * * do_ioctl *
*===========================================================================*/ *===========================================================================*/
@ -612,17 +590,18 @@ PUBLIC int do_ioctl()
register struct vnode *vp; register struct vnode *vp;
dev_t dev; 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 */ vp = f->filp_vno; /* get vnode pointer */
if ( (vp->v_mode & I_TYPE) != I_CHAR_SPECIAL if ((vp->v_mode & I_TYPE) != I_CHAR_SPECIAL &&
&& (vp->v_mode & I_TYPE) != I_BLOCK_SPECIAL) return(ENOTTY); (vp->v_mode & I_TYPE) != I_BLOCK_SPECIAL) return(ENOTTY);
suspend_reopen= (f->filp_state != FS_NORMAL); suspend_reopen= (f->filp_state != FS_NORMAL);
dev = (dev_t) vp->v_sdev; dev = (dev_t) vp->v_sdev;
return (dev_io(VFS_DEV_IOCTL, dev, who_e, m_in.ADDRESS, cvu64(0), return dev_io(VFS_DEV_IOCTL, dev, who_e, m_in.ADDRESS, cvu64(0),
m_in.REQUEST, f->filp_flags, suspend_reopen)); m_in.REQUEST, f->filp_flags, suspend_reopen);
} }
/*===========================================================================* /*===========================================================================*
* gen_io * * gen_io *
*===========================================================================*/ *===========================================================================*/
@ -636,40 +615,35 @@ message *mess_ptr; /* pointer to message for task */
int r, proc_e; int r, proc_e;
if(task_nr == SYSTEM) { if(task_nr == SYSTEM) printf("VFS: sending %d to SYSTEM\n", mess_ptr->m_type);
printf("VFS: sending %d to SYSTEM\n", mess_ptr->m_type);
}
proc_e = mess_ptr->IO_ENDPT; proc_e = mess_ptr->IO_ENDPT;
r = sendrec(task_nr, mess_ptr); r = sendrec(task_nr, mess_ptr);
if (r != OK) { if (r != OK) {
if (r == EDEADSRCDST || r == EDSTDIED || r == ESRCDIED) { if (r == EDEADSRCDST || r == EDSTDIED || r == ESRCDIED) {
printf("fs: dead driver %d\n", task_nr); printf("fs: dead driver %d\n", task_nr);
dmap_unmap_by_endpt(task_nr); dmap_unmap_by_endpt(task_nr);
return r; 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 == ELOCKED) {
/* Did the process we did the sendrec() for get a result? */ printf("fs: ELOCKED talking to %d\n", task_nr);
if (mess_ptr->REP_ENDPT != proc_e) { return(r);
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;
} }
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 * * asyn_io *
*===========================================================================*/ *===========================================================================*/
@ -685,15 +659,15 @@ message *mess_ptr; /* pointer to message for task */
proc_e = mess_ptr->IO_ENDPT; proc_e = mess_ptr->IO_ENDPT;
r= asynsend(task_nr, mess_ptr); r = asynsend(task_nr, mess_ptr);
if (r != OK) if (r != OK) panic(__FILE__, "asyn_io: asynsend failed", r);
panic(__FILE__, "asyn_io: asynsend failed", r);
/* Fake a SUSPEND */ /* Fake a SUSPEND */
mess_ptr->REP_STATUS= SUSPEND; mess_ptr->REP_STATUS = SUSPEND;
return OK; return(OK);
} }
/*===========================================================================* /*===========================================================================*
* ctty_io * * ctty_io *
*===========================================================================*/ *===========================================================================*/
@ -716,20 +690,19 @@ message *mess_ptr; /* pointer to message for task */
dp = &dmap[(fp->fp_tty >> MAJOR) & BYTE]; dp = &dmap[(fp->fp_tty >> MAJOR) & BYTE];
mess_ptr->DEVICE = (fp->fp_tty >> MINOR) & BYTE; mess_ptr->DEVICE = (fp->fp_tty >> MINOR) & BYTE;
if (dp->dmap_driver == NONE) { if (dp->dmap_driver == NONE) {
printf("FS: ctty_io: no driver for dev\n"); printf("FS: ctty_io: no driver for dev\n");
return EIO; return(EIO);
} }
if(isokendpt(dp->dmap_driver, &dummyproc) != OK) { if(isokendpt(dp->dmap_driver, &dummyproc) != OK) {
printf("FS: ctty_io: old driver %d\n", printf("FS: ctty_io: old driver %d\n", dp->dmap_driver);
dp->dmap_driver); return(EIO);
return EIO;
} }
(*dp->dmap_io)(dp->dmap_driver, mess_ptr); (*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. */ /* Called when doing i/o on a nonexistent device. */
printf("VFS: I/O on unmapped device number\n"); printf("VFS: I/O on unmapped device number\n");
return EIO; return(EIO);
} }
/*===========================================================================* /*===========================================================================*
* clone_opcl * * clone_opcl *
@ -787,20 +759,19 @@ int flags; /* mode bits and flags */
if (dp->dmap_driver == NONE) { if (dp->dmap_driver == NONE) {
printf("vfs:clone_opcl: no driver for dev %x\n", dev); printf("VFS clone_opcl: no driver for dev %x\n", dev);
return ENXIO; return(ENXIO);
} }
if(isokendpt(dp->dmap_driver, &dummyproc) != OK) { if(isokendpt(dp->dmap_driver, &dummyproc) != OK) {
printf("vfs:clone_opcl: bad driver endpoint for dev %x (%d)\n", printf("VFS clone_opcl: bad driver endpoint for dev %x (%d)\n", dev,
dev, dp->dmap_driver); dp->dmap_driver);
return ENXIO; return(ENXIO);
} }
/* Call the task. */ /* Call the task. */
r= (*dp->dmap_io)(dp->dmap_driver, &dev_mess); r = (*dp->dmap_io)(dp->dmap_driver, &dev_mess);
if (r != OK) if (r != OK) return(r);
return r;
if (op == DEV_OPEN && dev_mess.REP_STATUS >= 0) { if (op == DEV_OPEN && dev_mess.REP_STATUS >= 0) {
if (dev_mess.REP_STATUS != minor) { if (dev_mess.REP_STATUS != minor) {
@ -814,8 +785,7 @@ int flags; /* mode bits and flags */
*/ */
/* Device number of the new device. */ /* Device number of the new device. */
dev = (dev & ~(BYTE << MINOR)) | dev = (dev & ~(BYTE << MINOR)) | (dev_mess.REP_STATUS << MINOR);
(dev_mess.REP_STATUS << MINOR);
/* Issue request */ /* Issue request */
r = req_newnode(ROOT_FS_E, fp->fp_effuid, fp->fp_effgid, 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; vp = fp->fp_filp[m_in.fd]->filp_vno;
put_vnode(vp); put_vnode(vp);
if ((vp = get_free_vnode(__FILE__, __LINE__)) == NIL_VNODE) { if ((vp = get_free_vnode()) == NIL_VNODE)
printf(
"vfs:clone_opcl: failed to get a free vnode..\n");
vp = fp->fp_filp[m_in.fd]->filp_vno; vp = fp->fp_filp[m_in.fd]->filp_vno;
}
vp->v_fs_e = res.fs_e; vp->v_fs_e = res.fs_e;
if ((vmp = find_vmnt(vp->v_fs_e)) == NIL_VMNT) 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_vmnt = vmp;
vp->v_dev = vmp->m_dev; vp->v_dev = vmp->m_dev;
vp->v_fs_e = res.fs_e; vp->v_fs_e = res.fs_e;
vp->v_inode_nr = res.inode_nr; vp->v_inode_nr = res.inode_nr;
vp->v_mode = res.fmode; vp->v_mode = res.fmode;
@ -891,25 +857,22 @@ PUBLIC void dev_up(int maj)
/* Send new driver endpoint */ /* Send new driver endpoint */
if (OK != req_newdriver(vmp->m_fs_e, vmp->m_dev, new_driver_e)) if (OK != req_newdriver(vmp->m_fs_e, vmp->m_dev, new_driver_e))
printf( printf("VFSdev_up: error sending new driver endpoint."
"VFSdev_up: error sending new driver endpoint. FS_e: %d req_nr: %d\n", " FS_e: %d req_nr: %d\n", vmp->m_fs_e, REQ_NEW_DRIVER);
vmp->m_fs_e, REQ_NEW_DRIVER);
} }
/* Look for processes that are suspened in an OPEN call. Set SUSP_REOPEN /* 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. * to indicate that this process was suspended before the call to dev_up.
*/ */
for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) { for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
if(rfp->fp_pid == PID_FREE) if(rfp->fp_pid == PID_FREE) continue;
continue; if(rfp->fp_blocked_on != FP_BLOCKED_ON_DOPEN) continue;
if(rfp->fp_blocked_on != FP_BLOCKED_ON_DOPEN)
continue;
printf("dev_up: found process in FP_BLOCKED_ON_DOPEN, fd %d\n", printf("dev_up: found process in FP_BLOCKED_ON_DOPEN, fd %d\n",
rfp->fp_fd >> 8); rfp->fp_fd >> 8);
fd_nr= (rfp->fp_fd >> 8); fd_nr = (rfp->fp_fd >> 8);
fp= rfp->fp_filp[fd_nr]; fp = rfp->fp_filp[fd_nr];
vp= fp->filp_vno; vp = fp->filp_vno;
if (!vp) panic(__FILE__, "restart_reopen: no vp", NO_NUM); if (!vp) panic(__FILE__, "restart_reopen: no vp", NO_NUM);
if ((vp->v_mode & I_TYPE) != I_CHAR_SPECIAL) continue; if ((vp->v_mode & I_TYPE) != I_CHAR_SPECIAL) continue;
if (((vp->v_sdev >> MAJOR) & BYTE) != maj) 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_sdev >> MAJOR) & BYTE) != maj) continue;
if(!(vp->v_mode & (I_BLOCK_SPECIAL|I_CHAR_SPECIAL))) continue; if(!(vp->v_mode & (I_BLOCK_SPECIAL|I_CHAR_SPECIAL))) continue;
fp->filp_state= FS_NEEDS_REOPEN; fp->filp_state = FS_NEEDS_REOPEN;
needs_reopen= TRUE; needs_reopen = TRUE;
} }
if (needs_reopen) if (needs_reopen)
@ -935,6 +898,7 @@ PUBLIC void dev_up(int maj)
} }
/*===========================================================================* /*===========================================================================*
* restart_reopen * * restart_reopen *
*===========================================================================*/ *===========================================================================*/
@ -952,19 +916,12 @@ int maj;
if (fp->filp_state != FS_NEEDS_REOPEN) continue; if (fp->filp_state != FS_NEEDS_REOPEN) continue;
if (((vp->v_sdev >> MAJOR) & BYTE) != maj) continue; if (((vp->v_sdev >> MAJOR) & BYTE) != maj) continue;
if ((vp->v_mode & I_TYPE) != I_CHAR_SPECIAL) 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. */ /* File descriptor is to be closed when driver restarts. */
n = invalidate(fp);
/* The function inval_filp will set the fp_filp[]s of if (n != fp->filp_count) {
* 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)
{
printf("VFS: warning: invalidate/count " printf("VFS: warning: invalidate/count "
"discrepancy (%d, %d)\n", n, fp->filp_count); "discrepancy (%d, %d)\n", n, fp->filp_count);
} }
@ -972,20 +929,12 @@ int maj;
continue; continue;
} }
minor = ((vp->v_sdev >> MINOR) & BYTE);
r = dev_reopen(vp->v_sdev, fp-filp, vp->v_mode & (R_BIT|W_BIT)); r = dev_reopen(vp->v_sdev, fp-filp, vp->v_mode & (R_BIT|W_BIT));
if (r == OK) if (r == OK) return;
return;
/* This function will set the fp_filp[]s of processes /* Device could not be reopened. Invalidate all filps on that device.*/
* holding that fp to NULL, but _not_ clear n = invalidate(fp);
* fp_filp_inuse, so that fd can't be recycled until if (n != fp->filp_count) {
* it's close()d.
*/
n = inval_filp(fp);
if (n != fp->filp_count)
{
printf("VFS: warning: invalidate/count " printf("VFS: warning: invalidate/count "
"discrepancy (%d, %d)\n", n, fp->filp_count); "discrepancy (%d, %d)\n", n, fp->filp_count);
} }
@ -998,12 +947,9 @@ int maj;
driver_e= dmap[maj].dmap_driver; driver_e= dmap[maj].dmap_driver;
for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) { for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
if(rfp->fp_pid == PID_FREE) if(rfp->fp_pid == PID_FREE) continue;
continue;
if(rfp->fp_blocked_on == FP_BLOCKED_ON_OTHER && if(rfp->fp_blocked_on == FP_BLOCKED_ON_OTHER &&
rfp->fp_task == driver_e && rfp->fp_task == driver_e && (rfp->fp_flags & SUSP_REOPEN)) {
(rfp->fp_flags & SUSP_REOPEN))
{
rfp->fp_flags &= ~SUSP_REOPEN; rfp->fp_flags &= ~SUSP_REOPEN;
rfp->fp_blocked_on = FP_BLOCKED_ON_NONE; rfp->fp_blocked_on = FP_BLOCKED_ON_NONE;
reply(rfp->fp_endpoint, ERESTART); reply(rfp->fp_endpoint, ERESTART);
@ -1012,19 +958,16 @@ int maj;
/* Look for processes that are suspened in an OPEN call */ /* Look for processes that are suspened in an OPEN call */
for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) { for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
if (rfp->fp_pid == PID_FREE) if (rfp->fp_pid == PID_FREE) continue;
continue;
if (rfp->fp_blocked_on == FP_BLOCKED_ON_DOPEN || if (rfp->fp_blocked_on == FP_BLOCKED_ON_DOPEN ||
!(rfp->fp_flags & SUSP_REOPEN)) !(rfp->fp_flags & SUSP_REOPEN)) continue;
continue;
printf("restart_reopen: found process in FP_BLOCKED_ON_DOPEN, fd %d\n", printf("restart_reopen: found process in FP_BLOCKED_ON_DOPEN, fd %d\n",
rfp->fp_fd >> 8); rfp->fp_fd >> 8);
fd_nr= (rfp->fp_fd >> 8); fd_nr = (rfp->fp_fd >> 8);
fp= rfp->fp_filp[fd_nr]; fp = rfp->fp_filp[fd_nr];
if (!fp) if (!fp) {
{
/* Open failed, and automatic reopen was not requested */ /* Open failed, and automatic reopen was not requested */
rfp->fp_blocked_on = FP_BLOCKED_ON_NONE; rfp->fp_blocked_on = FP_BLOCKED_ON_NONE;
FD_CLR(fd_nr, &rfp->fp_filp_inuse); FD_CLR(fd_nr, &rfp->fp_filp_inuse);
@ -1032,7 +975,7 @@ int maj;
continue; continue;
} }
vp= fp->filp_vno; vp = fp->filp_vno;
if (!vp) panic(__FILE__, "restart_reopen: no vp", NO_NUM); if (!vp) panic(__FILE__, "restart_reopen: no vp", NO_NUM);
if ((vp->v_mode & I_TYPE) != I_CHAR_SPECIAL) continue; if ((vp->v_mode & I_TYPE) != I_CHAR_SPECIAL) continue;
if (((vp->v_sdev >> MAJOR) & BYTE) != maj) continue; if (((vp->v_sdev >> MAJOR) & BYTE) != maj) continue;
@ -1042,81 +985,71 @@ int maj;
} }
} }
/*===========================================================================* /*===========================================================================*
* reopen_reply * * reopen_reply *
*===========================================================================*/ *===========================================================================*/
PUBLIC void reopen_reply() PUBLIC void reopen_reply()
{ {
endpoint_t driver_e; endpoint_t driver_e;
int filp_no, status, maj; int filp_no, status, maj;
struct filp *fp; struct filp *fp;
struct vnode *vp; struct vnode *vp;
struct dmap *dp; struct dmap *dp;
driver_e= m_in.m_source; driver_e = m_in.m_source;
filp_no= m_in.REP_ENDPT; filp_no = m_in.REP_ENDPT;
status= m_in.REP_STATUS; status = m_in.REP_STATUS;
if (filp_no < 0 || filp_no >= NR_FILPS) if (filp_no < 0 || filp_no >= NR_FILPS) {
{ printf("reopen_reply: bad filp number %d from driver %d\n", filp_no,
printf("reopen_reply: bad filp number %d from driver %d\n", driver_e);
filp_no, driver_e); return;
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;
}
vp= fp->filp_vno; fp = &filp[filp_no];
if (!vp) if (fp->filp_count < 1) {
{ printf("reopen_reply: filp number %d not inuse (from driver %d)\n",
printf( filp_no, driver_e);
"reopen_reply: no vnode for filp number %d (from driver %d)\n", return;
filp_no, driver_e); }
return;
}
if (fp->filp_state != FS_NEEDS_REOPEN) vp = fp->filp_vno;
{ if (!vp) {
printf( printf("reopen_reply: no vnode for filp number %d (from driver %d)\n",
"reopen_reply: bad state %d for filp number %d (from driver %d)\n", filp_no, driver_e);
fp->filp_state, filp_no, driver_e); return;
return; }
}
if ((vp->v_mode & I_TYPE) != I_CHAR_SPECIAL) if (fp->filp_state != FS_NEEDS_REOPEN) {
{ printf("reopen_reply: bad state %d for filp number %d"
printf( " (from driver %d)\n", fp->filp_state, filp_no, driver_e);
"reopen_reply: bad mode 0%o for filp number %d (from driver %d)\n", return;
vp->v_mode, filp_no, driver_e); }
return;
}
maj= ((vp->v_sdev >> MAJOR) & BYTE); if ((vp->v_mode & I_TYPE) != I_CHAR_SPECIAL) {
dp = &dmap[maj]; printf("reopen_reply: bad mode 0%o for filp number %d"
if (dp->dmap_driver != driver_e) " (from driver %d)\n", vp->v_mode, filp_no, driver_e);
{ return;
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) maj = ((vp->v_sdev >> MAJOR) & BYTE);
{ dp = &dmap[maj];
fp->filp_state= FS_NORMAL; if (dp->dmap_driver != driver_e) {
} printf("reopen_reply: bad major %d for filp number %d "
else "(from driver %d, current driver is %d)\n", maj, filp_no,
{ driver_e, dp->dmap_driver);
printf("reopen_reply: should handle error status\n"); return;
return; }
}
restart_reopen(maj); if (status == OK) {
fp->filp_state= FS_NORMAL;
} else {
printf("reopen_reply: should handle error status\n");
return;
}
restart_reopen(maj);
} }
#if 0 #if 0

View file

@ -12,9 +12,6 @@
* *
* The entry points into this file are: * The entry points into this file are:
* pm_exec: perform the EXEC system call * pm_exec: perform the EXEC system call
*
* Changes for VFS:
* Aug 2006 (Balazs Gerofi)
*/ */
#include "fs.h" #include "fs.h"
@ -29,7 +26,6 @@
#include <dirent.h> #include <dirent.h>
#include "fproc.h" #include "fproc.h"
#include "param.h" #include "param.h"
#include "vnode.h" #include "vnode.h"
#include "vmnt.h" #include "vmnt.h"
#include <minix/vfsif.h> #include <minix/vfsif.h>
@ -71,193 +67,139 @@ vir_bytes frame_len;
* complete stack image, including pointers, args, environ, etc. The stack * complete stack image, including pointers, args, environ, etc. The stack
* is copied to a buffer inside FS, and then to the new core image. * 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; int r, r1, sep_id, round, proc_s, hdrlen, load_text, allow_setuid;
vir_bytes text_bytes, data_bytes, bss_bytes, pc; vir_bytes text_bytes, data_bytes, bss_bytes, pc;
phys_bytes tot_bytes; /* total space for program, including gap */ phys_bytes tot_bytes; /* total space for program, including gap */
vir_bytes stack_top, vsp; vir_bytes stack_top, vsp;
off_t off; off_t off;
uid_t new_uid; uid_t new_uid;
gid_t new_gid; gid_t new_gid;
struct fproc *rfp; struct fproc *rfp;
struct vnode *vp; struct vnode *vp;
time_t v_ctime; time_t v_ctime;
char *cp; char *cp;
struct stat sb; struct stat sb;
char progname[PROC_NAME_LEN]; char progname[PROC_NAME_LEN];
static char mbuf[ARG_MAX]; /* buffer for stack and zeroes */ static char mbuf[ARG_MAX]; /* buffer for stack and zeroes */
okendpt(proc_e, &proc_s); okendpt(proc_e, &proc_s);
rfp= fp= &fproc[proc_s]; rfp = fp = &fproc[proc_s];
who_e= proc_e; who_e = proc_e;
who_p= proc_s; who_p = proc_s;
super_user = (fp->fp_effuid == SU_UID ? TRUE : FALSE); /* su? */ super_user = (fp->fp_effuid == SU_UID ? TRUE : FALSE); /* su? */
/* Get the exec file name. */ /* Get the exec file name. */
r= fetch_name(path, path_len, 0); if ((r = fetch_name(path, path_len, 0)) != OK) return(r);
if (r != OK)
{
printf("pm_exec: fetch_name failed\n");
printf("return at %s, %d\n", __FILE__, __LINE__);
return(r); /* file name not in user data segment */
}
/* Fetch the stack from the user before destroying the old core image. */ /* Fetch the stack from the user before destroying the old core image. */
if (frame_len > ARG_MAX) if (frame_len > ARG_MAX) return(ENOMEM); /* stack too big */
{ r = sys_datacopy(proc_e, (vir_bytes) frame, SELF, (vir_bytes) mbuf,
return(ENOMEM); /* stack too big */ (phys_bytes) frame_len);
} if (r != OK) { /* can't fetch stack (e.g. bad virtual addr) */
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)
{
printf("pm_exec: sys_datacopy failed\n"); printf("pm_exec: sys_datacopy failed\n");
printf("return at %s, %d\n", __FILE__, __LINE__);
return(r); return(r);
} }
/* The default is the keep the original user and group IDs */ /* The default is to keep the original user and group IDs */
new_uid= rfp->fp_effuid; new_uid = rfp->fp_effuid;
new_gid= rfp->fp_effgid; new_gid = rfp->fp_effgid;
for (round= 0; round < 2; round++) for (round= 0; round < 2; round++) {
/* round = 0 (first attempt), or 1 (interpreted script) */ /* round = 0 (first attempt), or 1 (interpreted script) */
{
#if 0
printf("vfs:pm_exec: round %d, name '%s'\n", round, user_fullpath);
#endif
/* Save the name of the program */ /* Save the name of the program */
(cp= strrchr(user_fullpath, '/')) ? cp++ : (cp= user_fullpath); (cp= strrchr(user_fullpath, '/')) ? cp++ : (cp= user_fullpath);
strncpy(progname, cp, PROC_NAME_LEN-1); strncpy(progname, cp, PROC_NAME_LEN-1);
progname[PROC_NAME_LEN-1] = '\0'; progname[PROC_NAME_LEN-1] = '\0';
/* Request lookup */ /* Open executable */
if ((r = lookup_vp(0 /*flags*/, 0 /*!use_realuid*/, &vp)) != OK) if ((vp = eat_path(PATH_NOFLAGS)) == NIL_VNODE) return(err_code);
return r;
if ((vp->v_mode & I_TYPE) != I_REGULAR)
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); put_vnode(vp);
return ENOEXEC; return(r);
}
/* Check access. */
if ((r = forbidden(vp, X_BIT, 0 /*!use_realuid*/)) != OK)
{
put_vnode(vp);
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; v_ctime = sb.st_ctime;
if (round == 0) {
#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)
{
/* Deal with setuid/setgid executables */ /* Deal with setuid/setgid executables */
if (vp->v_mode & I_SET_UID_BIT) if (vp->v_mode & I_SET_UID_BIT) new_uid = vp->v_uid;
new_uid = vp->v_uid; if (vp->v_mode & I_SET_GID_BIT) new_gid = vp->v_gid;
if (vp->v_mode & I_SET_GID_BIT)
new_gid = vp->v_gid;
} }
/* Read the file header and extract the segment sizes. */ /* Read the file header and extract the segment sizes. */
r = read_header(vp, &sep_id, &text_bytes, &data_bytes, &bss_bytes, r = read_header(vp, &sep_id, &text_bytes, &data_bytes, &bss_bytes,
&tot_bytes, &pc, &hdrlen); &tot_bytes, &pc, &hdrlen);
if (r != ESCRIPT || round != 0) if (r != ESCRIPT || round != 0)
break; break;
/* Get fresh copy of the file name. */ /* Get fresh copy of the file name. */
r= fetch_name(path, path_len, 0); if ((r = fetch_name(path, path_len, 0)) != OK)
if (r != OK) printf("VFS pm_exec: 2nd fetch_name failed\n");
{ else if ((r = patch_stack(vp, mbuf, &frame_len)) != OK)
printf("pm_exec: 2nd fetch_name failed\n"); printf("VFS pm_exec: patch_stack failed\n");
put_vnode(vp); put_vnode(vp);
return(r); /* strange */ if (r != OK) return(r);
} }
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;
}
}
if (r != OK) if (r != OK) {
{ put_vnode(vp);
printf("pm_exec: returning ENOEXEC, r = %d\n", r); return(ENOEXEC);
printf("pm_exec: progname = '%s'\n", progname); }
put_vnode(vp);
return ENOEXEC;
}
r= exec_newmem(proc_e, text_bytes, data_bytes, bss_bytes, tot_bytes, 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, frame_len, sep_id, vp->v_dev, vp->v_inode_nr, v_ctime,
progname, new_uid, new_gid, &stack_top, &load_text, &allow_setuid); progname, new_uid, new_gid, &stack_top, &load_text,
if (r != OK) &allow_setuid);
{ if (r != OK) {
printf("VFS: pm_exec: exec_newmem failed: %d\n", r); printf("VFS: pm_exec: exec_newmem failed: %d\n", r);
put_vnode(vp); put_vnode(vp);
return r; return(r);
} }
/* Patch up stack and copy it from FS to new core image. */ /* Patch up stack and copy it from FS to new core image. */
vsp = stack_top; vsp = stack_top;
vsp -= frame_len; vsp -= frame_len;
patch_ptr(mbuf, vsp); patch_ptr(mbuf, vsp);
r = sys_datacopy(SELF, (vir_bytes) mbuf, if ((r = sys_datacopy(SELF, (vir_bytes) mbuf, proc_e, (vir_bytes) vsp,
proc_e, (vir_bytes) vsp, (phys_bytes)frame_len); (phys_bytes)frame_len)) != OK) {
if (r != OK) { printf("VFS: datacopy failed (%d) trying to copy to %p\n", r, vsp);
printf("vfs: datacopy returns %d trying to copy to %p\n", r, vsp); return(r);
return r; }
}
off = hdrlen; off = hdrlen;
/* Read in text and data segments. */ /* Read in text and data segments. */
if (load_text) { if (load_text) r = read_seg(vp, off, proc_e, T, text_bytes);
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);
off += text_bytes; put_vnode(vp);
if (r == OK) if (r != OK) return(r);
r= read_seg(vp, off, proc_e, D, data_bytes); clo_exec(rfp);
put_vnode(vp); if (allow_setuid) {
rfp->fp_effuid = new_uid;
rfp->fp_effgid = new_gid;
}
if (r != OK) /* This child has now exec()ced. */
{ rfp->fp_execced = 1;
return r;
}
clo_exec(rfp); /* Check if this is a driver that can now be useful. */
dmap_endpt_up(rfp->fp_endpoint);
if (allow_setuid) return(OK);
{
rfp->fp_effuid= new_uid;
rfp->fp_effgid= new_gid;
}
/* This child has now exec()ced. */
rfp->fp_execced = 1;
/* Check if this is a driver that can now be useful. */
dmap_endpt_up(rfp->fp_endpoint);
return OK;
} }
/*===========================================================================* /*===========================================================================*
* exec_newmem * * exec_newmem *
*===========================================================================*/ *===========================================================================*/
@ -281,41 +223,34 @@ vir_bytes *stack_topp;
int *load_textp; int *load_textp;
int *allow_setuidp; int *allow_setuidp;
{ {
int r; int r;
struct exec_newmem e; struct exec_newmem e;
message m; message m;
e.text_bytes= text_bytes; e.text_bytes = text_bytes;
e.data_bytes= data_bytes; e.data_bytes = data_bytes;
e.bss_bytes= bss_bytes; e.bss_bytes = bss_bytes;
e.tot_bytes= tot_bytes; e.tot_bytes = tot_bytes;
e.args_bytes= frame_len; e.args_bytes = frame_len;
e.sep_id= sep_id; e.sep_id = sep_id;
e.st_dev= st_dev; e.st_dev = st_dev;
e.st_ino= st_ino; e.st_ino = st_ino;
e.st_ctime= st_ctime; e.st_ctime = st_ctime;
e.new_uid= new_uid; e.new_uid = new_uid;
e.new_gid= new_gid; e.new_gid = new_gid;
strncpy(e.progname, progname, sizeof(e.progname)-1); strncpy(e.progname, progname, sizeof(e.progname)-1);
e.progname[sizeof(e.progname)-1]= '\0'; e.progname[sizeof(e.progname)-1] = '\0';
m.m_type= EXEC_NEWMEM; m.m_type = EXEC_NEWMEM;
m.EXC_NM_PROC= proc_e; m.EXC_NM_PROC = proc_e;
m.EXC_NM_PTR= (char *)&e; m.EXC_NM_PTR = (char *)&e;
r= sendrec(PM_PROC_NR, &m); if ((r = sendrec(PM_PROC_NR, &m)) != OK) return(r);
if (r != OK)
return r; *stack_topp = m.m1_i1;
#if 0 *load_textp = !!(m.m1_i2 & EXC_NM_RF_LOAD_TEXT);
printf("exec_newmem: r = %d, m_type = %d\n", r, m.m_type); *allow_setuidp = !!(m.m1_i2 & EXC_NM_RF_ALLOW_SETUID);
#endif
*stack_topp= m.m1_i1; return(m.m_type);
*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;
} }
@ -337,7 +272,7 @@ int *hdrlenp;
off_t pos; off_t pos;
int r; int r;
u64_t new_pos; u64_t new_pos;
unsigned int cum_io_incr; unsigned int cum_io;
struct exec hdr; /* a.out header is read in here */ struct exec hdr; /* a.out header is read in here */
/* Read the header and check the magic number. The standard MINIX header /* 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 */ pos= 0; /* Read from the start of the file */
/* Issue request */ /* Issue request */
r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, vp->v_index, r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, cvul64(pos), READING,
cvul64(pos), READING, FS_PROC_NR, (char*)&hdr, sizeof(hdr), &new_pos, FS_PROC_NR, (char*)&hdr, sizeof(hdr), &new_pos, &cum_io);
&cum_io_incr);
if (r != OK) return r; if (r != OK) return r;
/* Interpreted script? */ /* Interpreted script? */
if (((char*)&hdr)[0] == '#' && ((char*)&hdr)[1] == '!' && vp->v_size >= 2) if (((char*)&hdr)[0] == '#' && ((char*)&hdr)[1] == '!' && vp->v_size >= 2)
return ESCRIPT; return(ESCRIPT);
if (vp->v_size < A_MINHDR) return(ENOEXEC); if (vp->v_size < A_MINHDR) return(ENOEXEC);
@ -411,6 +345,7 @@ int *hdrlenp;
return(OK); return(OK);
} }
/*===========================================================================* /*===========================================================================*
* patch_stack * * patch_stack *
*===========================================================================*/ *===========================================================================*/
@ -428,7 +363,7 @@ vir_bytes *stk_bytes; /* size of initial stack */
off_t pos; off_t pos;
char *sp, *interp = NULL; char *sp, *interp = NULL;
u64_t new_pos; u64_t new_pos;
unsigned int cum_io_incr; unsigned int cum_io;
char buf[_MAX_BLOCK_SIZE]; char buf[_MAX_BLOCK_SIZE];
/* Make user_fullpath the new argv[0]. */ /* 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 */ pos = 0; /* Read from the start of the file */
/* Issue request */ /* Issue request */
r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, vp->v_index, cvul64(pos), r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, cvul64(pos), READING,
READING, FS_PROC_NR, buf, _MAX_BLOCK_SIZE, &new_pos, &cum_io_incr); FS_PROC_NR, buf, _MAX_BLOCK_SIZE, &new_pos, &cum_io);
if (r != OK) return r; if (r != OK) return(r);
n = vp->v_size; n = vp->v_size;
if (n > _MAX_BLOCK_SIZE) if (n > _MAX_BLOCK_SIZE)
@ -534,6 +469,7 @@ int replace;
return(TRUE); return(TRUE);
} }
/*===========================================================================* /*===========================================================================*
* patch_ptr * * patch_ptr *
*===========================================================================*/ *===========================================================================*/
@ -566,6 +502,7 @@ vir_bytes base; /* virtual address of stack base inside user */
} }
} }
/*===========================================================================* /*===========================================================================*
* read_seg * * read_seg *
*===========================================================================*/ *===========================================================================*/
@ -584,74 +521,53 @@ phys_bytes seg_bytes; /* how much is to be transferred? */
int r; int r;
unsigned n, o; unsigned n, o;
u64_t new_pos; u64_t new_pos;
unsigned int cum_io_incr; unsigned int cum_io;
char buf[1024]; char buf[1024];
/* Make sure that the file is big enough */ /* Make sure that the file is big enough */
if (vp->v_size < off+seg_bytes) { if (vp->v_size < off+seg_bytes) return(EIO);
return EIO;
}
if (seg != D) if (seg != D) {
{
/* We have to use a copy loop until safecopies support segments */ /* We have to use a copy loop until safecopies support segments */
o= 0; o = 0;
while (o < seg_bytes) while (o < seg_bytes) {
{ n = seg_bytes - o;
n= seg_bytes-o;
if (n > sizeof(buf)) if (n > sizeof(buf))
n= sizeof(buf); n = sizeof(buf);
#if 0 if ((r = req_readwrite(vp->v_fs_e,vp->v_inode_nr,cvul64(off+o), READING, FS_PROC_NR, buf,
printf("read_seg for user %d, seg %d: buf 0x%x, size %d, pos %d\n", n, &new_pos, &cum_io)) != OK) {
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) {
printf("VFS: read_seg: req_readwrite failed (text)\n"); printf("VFS: read_seg: req_readwrite failed (text)\n");
return r; return(r);
} }
if (cum_io_incr != n) if (cum_io != n) {
{
printf( printf(
"VFSread_seg segment has not been read properly by exec() \n"); "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, if ((r = sys_vircopy(FS_PROC_NR, D, (vir_bytes)buf, proc_e,
n); seg, o, n)) != OK) {
if (r != OK) {
printf("VFS: read_seg: copy failed (text)\n"); printf("VFS: read_seg: copy failed (text)\n");
return r; return(r);
} }
o += n; o += n;
} }
return OK; return(OK);
} }
#if 0 if ((r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, cvul64(off), READING,
printf("read_seg for user %d, seg %d: buf 0x%x, size %d, pos %d\n", proc_e, 0, seg_bytes, &new_pos, &cum_io)) != OK) {
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) {
printf("VFS: read_seg: req_readwrite failed (data)\n"); printf("VFS: read_seg: req_readwrite failed (data)\n");
return r; return(r);
} }
if (r == OK && cum_io_incr != seg_bytes) if (r == OK && cum_io != seg_bytes)
printf("VFSread_seg segment has not been read properly by exec() \n"); 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; int i;
/* Check the file desriptors one by one for presence of FD_CLOEXEC. */ /* Check the file desriptors one by one for presence of FD_CLOEXEC. */
for (i = 0; i < OPEN_MAX; i++) for (i = 0; i < OPEN_MAX; i++)
if ( FD_ISSET(i, &rfp->fp_cloexec_set)) if ( FD_ISSET(i, &rfp->fp_cloexec_set))
(void) close_fd(rfp, i); (void) close_fd(rfp, i);
} }

View file

@ -11,11 +11,9 @@
#include <sys/select.h> #include <sys/select.h>
#include <minix/u64.h> #include <minix/u64.h>
#include <assert.h> #include <assert.h>
#include "fs.h" #include "fs.h"
#include "file.h" #include "file.h"
#include "fproc.h" #include "fproc.h"
#include "vnode.h" #include "vnode.h"
/*===========================================================================* /*===========================================================================*
@ -64,6 +62,7 @@ PUBLIC int get_fd(int start, mode_t bits, int *k, struct filp **fpt)
return(ENFILE); return(ENFILE);
} }
/*===========================================================================* /*===========================================================================*
* get_filp * * get_filp *
*===========================================================================*/ *===========================================================================*/
@ -75,6 +74,7 @@ int fild; /* file descriptor */
return get_filp2(fp, fild); return get_filp2(fp, fild);
} }
/*===========================================================================* /*===========================================================================*
* get_filp2 * * get_filp2 *
*===========================================================================*/ *===========================================================================*/
@ -86,16 +86,14 @@ int fild; /* file descriptor */
err_code = EBADF; err_code = EBADF;
if (fild < 0 || fild >= OPEN_MAX ) return(NIL_FILP); if (fild < 0 || fild >= OPEN_MAX ) return(NIL_FILP);
if (rfp->fp_filp[fild] == NIL_FILP && FD_ISSET(fild, &rfp->fp_filp_inuse)) 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);
err_code = EIO; /* The filedes is not there, but is not closed either. err_code = EIO; /* The filedes is not there, but is not closed either.
*/ */
}
return(rfp->fp_filp[fild]); /* may also be NIL_FILP */ return(rfp->fp_filp[fild]); /* may also be NIL_FILP */
} }
/*===========================================================================* /*===========================================================================*
* find_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; /* Invalidate filp. fp_filp_inuse is not cleared, so filp can't be reused
for(f = 0; f < NR_PROCS; f++) { until it is closed first. */
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; 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. */
} }

View file

@ -23,6 +23,8 @@ EXTERN struct fproc {
uid_t fp_effuid; /* effective user id */ uid_t fp_effuid; /* effective user id */
gid_t fp_realgid; /* real group id */ gid_t fp_realgid; /* real group id */
gid_t fp_effgid; /* effective 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 */ dev_t fp_tty; /* major/minor of controlling tty */
int fp_fd; /* place to save fd if rd/wr can't finish */ 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*/ char *fp_buffer; /* place to save buffer if rd/wr can't finish*/

View file

@ -9,9 +9,6 @@
* do_truncate: perform the TRUNCATE system call * do_truncate: perform the TRUNCATE system call
* do_ftruncate: perform the FTRUNCATE system call * do_ftruncate: perform the FTRUNCATE system call
* do_rdlink: perform the RDLNK system call * do_rdlink: perform the RDLNK system call
*
* Changes for VFS:
* Jul 2006 (Balazs Gerofi)
*/ */
#include "fs.h" #include "fs.h"
@ -23,7 +20,6 @@
#include "file.h" #include "file.h"
#include "fproc.h" #include "fproc.h"
#include "param.h" #include "param.h"
#include <minix/vfsif.h> #include <minix/vfsif.h>
#include "vnode.h" #include "vnode.h"
@ -33,66 +29,40 @@
PUBLIC int do_link() PUBLIC int do_link()
{ {
/* Perform the link(name1, name2) system call. */ /* Perform the link(name1, name2) system call. */
int r; int r = OK;
endpoint_t linked_fs_e, link_lastdir_fs_e; 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) /* See if 'name1' (file to be linked to) exists. */
return(err_code); 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);
/* Request lookup */
if ((r = lookup_vp(0 /*flags*/, 0 /*!use_realuid*/, &vp_o)) != OK) return r;
linked_fs_e = vp_o->v_fs_e;
/* Does the final directory of 'name2' exist? */ /* Does the final directory of 'name2' exist? */
if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK) { if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK)
put_vnode(vp_o); r = err_code;
return(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. */ /* Check for links across devices. */
if (linked_fs_e != link_lastdir_fs_e) if(vp->v_fs_e != vp_d->v_fs_e)
{ r = EXDEV;
put_vnode(vp_o); else
put_vnode(vp_d); r = forbidden(vp_d, W_BIT | X_BIT);
return EXDEV;
}
/* Make sure that the object is a directory */ if (r == OK)
if ((vp_d->v_mode & I_TYPE) != I_DIRECTORY) r = req_link(vp->v_fs_e, vp_d->v_inode_nr, user_fullpath,
{ vp->v_inode_nr);
put_vnode(vp_o);
put_vnode(vp_d);
return ENOTDIR;
}
r= forbidden(vp_d, W_BIT|X_BIT, 0 /*!use_realuid*/); put_vnode(vp);
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_d); put_vnode(vp_d);
return r; return(r);
} }
/*===========================================================================* /*===========================================================================*
* do_unlink * * do_unlink *
*===========================================================================*/ *===========================================================================*/
@ -103,42 +73,49 @@ PUBLIC int do_unlink()
* may be used by the superuser to do dangerous things; rmdir() may not. * may be used by the superuser to do dangerous things; rmdir() may not.
*/ */
register struct fproc *rfp; register struct fproc *rfp;
struct vnode *vp; struct vnode *vldirp, *vp;
int r; int r;
if (fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code); /* Get the last directory in the path. */
if(fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code);
r= lookup_lastdir(0 /*!use_realuid*/, &vp); if ((vldirp = last_dir()) == NIL_VNODE) return(err_code);
if (r != OK)
return r;
/* Make sure that the object is a directory */ /* Make sure that the object is a directory */
if ((vp->v_mode & I_TYPE) != I_DIRECTORY) if((vldirp->v_mode & I_TYPE) != I_DIRECTORY) {
{ put_vnode(vldirp);
put_vnode(vp); return(ENOTDIR);
return ENOTDIR;
} }
/* The caller must have both search and execute permission */ /* The caller must have both search and execute permission */
r= forbidden(vp, X_BIT|W_BIT, 0 /*!use_realuid*/); if ((r = forbidden(vldirp, X_BIT | W_BIT)) != OK) {
if (r != OK) put_vnode(vldirp);
{ return(r);
put_vnode(vp);
return r;
} }
/* If a directory file has to be removed the following conditions have to met: /* Also, if the sticky bit is set, only the owner of the file or a privileged
* - The directory must not be the root of a mounted file system user is allowed to unlink */
* - The directory must not be anybody's root/working directory 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 */ if(call_nr == UNLINK)
r= ((call_nr == UNLINK) ? req_unlink : req_rmdir)(vp->v_fs_e, r = req_unlink(vldirp->v_fs_e, vldirp->v_inode_nr, user_fullpath);
vp->v_inode_nr, user_fullpath); else
r = req_rmdir(vldirp->v_fs_e, vldirp->v_inode_nr, user_fullpath);
put_vnode(vp);
put_vnode(vldirp);
return r; return(r);
} }
@ -148,81 +125,62 @@ PUBLIC int do_unlink()
PUBLIC int do_rename() PUBLIC int do_rename()
{ {
/* Perform the rename(name1, name2) system call. */ /* Perform the rename(name1, name2) system call. */
int r; int r = OK, r1;
int old_dir_inode;
int old_fs_e;
int new_dir_inode;
int new_fs_e;
size_t len; size_t len;
struct vnode *vp_od, *vp_nd; struct vnode *old_dirp, *new_dirp, *vp;
char old_name[PATH_MAX+1]; char old_name[PATH_MAX+1];
/* See if 'name1' (existing file) exists. Get dir and file inodes. */ /* 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); 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);
/* Request lookup */
if ((r = lookup_lastdir(0 /*!use_realuid*/, &vp_od)) != OK) return r;
r= forbidden(vp_od, W_BIT|X_BIT, 0 /*!use_realuid*/); /* If the sticky bit is set, only the owner of the file or a privileged
if (r != OK) user is allowed to rename */
{ if(old_dirp->v_mode & S_ISVTX == S_ISVTX) {
put_vnode(vp_od); /* Look up inode of file to unlink to retrieve owner */
return r; 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 */ /* Save the last component of the old name */
len= strlen(user_fullpath); if(strlen(user_fullpath) >= sizeof(old_name)) {
if (len >= sizeof(old_name)) put_vnode(old_dirp);
{ return(ENAMETOOLONG);
put_vnode(vp_od);
return ENAMETOOLONG;
} }
memcpy(old_name, user_fullpath, len+1); strcpy(old_name, user_fullpath);
/* See if 'name2' (new name) exists. Get dir inode */ /* See if 'name2' (new name) exists. Get dir inode */
if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK) if(fetch_name(m_in.name2, m_in.name2_length, M1) != OK)
{ r = err_code;
put_vnode(vp_od); else if ((new_dirp = last_dir()) == NIL_VNODE)
return err_code; r = err_code;
} if (r != OK) {
put_vnode(old_dirp);
/* Request lookup */ return r;
r = lookup_lastdir(0 /*!use_realuid*/, &vp_nd);
if (r != OK)
{
put_vnode(vp_od);
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. */ /* Both parent directories must be on the same device. */
if (old_fs_e != new_fs_e) if(old_dirp->v_fs_e != new_dirp->v_fs_e) r = EXDEV;
{
put_vnode(vp_od);
put_vnode(vp_nd);
return EXDEV;
}
/* Issue request */ /* Parent dirs must be writable, searchable and on a writable device */
r= req_rename(old_fs_e, vp_od->v_inode_nr, old_name, vp_nd->v_inode_nr, if ((r1 = forbidden(old_dirp, W_BIT|X_BIT)) != OK ||
user_fullpath); (r1 = forbidden(new_dirp, W_BIT|X_BIT)) != OK) r = r1;
put_vnode(vp_od);
put_vnode(vp_nd); if(r == OK)
return r; 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() 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 * 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 * by name or fd, do checks on it, and call truncate_inode() to do the
* work. * work.
@ -239,138 +197,106 @@ PUBLIC int do_truncate()
struct vnode *vp; struct vnode *vp;
int r; 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); put_vnode(vp);
return(r);
return r;
} }
/*===========================================================================* /*===========================================================================*
* do_ftruncate * * do_ftruncate *
*===========================================================================*/ *===========================================================================*/
PUBLIC int 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; int r;
struct filp *rfilp; struct filp *rfilp;
if ( (rfilp = get_filp(m_in.m2_i1)) == NIL_FILP) /* File is already opened; get a vnode pointer from filp */
return err_code; if ((rfilp = get_filp(m_in.m2_i1)) == NIL_FILP) return(err_code);
if (!(rfilp->filp_mode & W_BIT)) if (!(rfilp->filp_mode & W_BIT)) return(EBADF);
return EBADF; return truncate_vnode(rfilp->filp_vno, m_in.m2_l1);
return truncate_vn(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; struct vnode *vp;
off_t newsize; off_t newsize;
{ {
int r; int r, file_type;
if ( (vp->v_mode & I_TYPE) != I_REGULAR && file_type = vp->v_mode & I_TYPE;
(vp->v_mode & I_TYPE) != I_NAMED_PIPE) { if (file_type != I_REGULAR && file_type != I_NAMED_PIPE) return(EINVAL);
return EINVAL;
}
/* Issue request */ if ((r = req_ftrunc(vp->v_fs_e, vp->v_inode_nr, newsize, 0)) == OK)
if ((r = req_ftrunc(vp->v_fs_e, vp->v_inode_nr, newsize, 0)) != OK) return r; vp->v_size = newsize;
vp->v_size = newsize; return(r);
return OK;
} }
/*===========================================================================* /*===========================================================================*
* do_slink * * do_slink *
*===========================================================================*/ *===========================================================================*/
PUBLIC int do_slink() PUBLIC int do_slink()
{ {
/* Perform the symlink(name1, name2) system call. */ /* Perform the symlink(name1, name2) system call. */
int r; int r, linklen;
struct vnode *vp; struct vnode *vp;
char string[NAME_MAX]; /* last component of the new dir's path name */ 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) if(m_in.name1_length <= 1) return(ENOENT);
return(err_code); 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) if ((r = forbidden(vp, W_BIT|X_BIT)) == OK) {
return(ENAMETOOLONG); 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,
/* Request lookup */ fp->fp_effgid);
if ((r = lookup_lastdir(0 /*!use_realuid*/, &vp)) != OK)
{
printf("vfs:do_slink: lookup_lastdir failed with %d\n", r);
return r;
} }
#if 0
printf("vfs:do_slink: got dir inode %d on dev 0x%x, fs %d\n",
vp->v_inode_nr, vp->v_dev, vp->v_fs_e);
#endif
r= forbidden(vp, W_BIT|X_BIT, 0 /*!use_realuid*/);
if (r != OK)
{
put_vnode(vp);
return r;
}
/* 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); put_vnode(vp);
return(r);
return r;
} }
/*===========================================================================* /*===========================================================================*
* do_rdlink * * do_rdlink *
*===========================================================================*/ *===========================================================================*/
PUBLIC int do_rdlink() PUBLIC int do_rdlink()
{ {
/* Perform the readlink(name, buf) system call. */ /* Perform the readlink(name, buf, bufsize) system call. */
int r, copylen; int r, copylen;
struct vnode *vp; struct vnode *vp;
copylen = m_in.m1_i2; copylen = m_in.nbytes;
if(copylen < 0) return EINVAL; if(copylen < 0) return(EINVAL);
if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code); /* Temporarily open the file containing the symbolic link */
if(fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
/* Request lookup */ if ((vp = eat_path(PATH_RET_SYMLINK)) == NIL_VNODE) return(err_code);
r = lookup_vp(PATH_RET_SYMLINK, 0 /*!use_realuid*/, &vp);
if (r != OK) return r;
/* Make sure this is a symbolic link */ /* Make sure this is a symbolic link */
if ((vp->v_mode & I_TYPE) != I_SYMBOLIC_LINK) { if((vp->v_mode & I_TYPE) != I_SYMBOLIC_LINK)
put_vnode(vp); r = EINVAL;
else
return EINVAL; r = req_rdlink(vp->v_fs_e, vp->v_inode_nr, who_e, m_in.name2, copylen);
}
/* Issue request */
r= req_rdlink(vp->v_fs_e, vp->v_inode_nr, who_e, (vir_bytes)m_in.name2,
copylen);
put_vnode(vp); put_vnode(vp);
return(r);
return r;
} }

View file

@ -14,7 +14,6 @@
#include "fproc.h" #include "fproc.h"
#include "lock.h" #include "lock.h"
#include "param.h" #include "param.h"
#include "vnode.h" #include "vnode.h"
/*===========================================================================* /*===========================================================================*
@ -35,8 +34,8 @@ int req; /* either F_SETLK or F_SETLKW */
/* Fetch the flock structure from user space. */ /* Fetch the flock structure from user space. */
user_flock = (vir_bytes) m_in.name1; user_flock = (vir_bytes) m_in.name1;
r = sys_datacopy(who_e, (vir_bytes) user_flock, r = sys_datacopy(who_e, (vir_bytes) user_flock, FS_PROC_NR,
FS_PROC_NR, (vir_bytes) &flock, (phys_bytes) sizeof(flock)); (vir_bytes) &flock, (phys_bytes) sizeof(flock));
if (r != OK) return(EINVAL); if (r != OK) return(EINVAL);
/* Make some error checks. */ /* Make some error checks. */
@ -52,12 +51,10 @@ int req; /* either F_SETLK or F_SETLKW */
switch (flock.l_whence) { switch (flock.l_whence) {
case SEEK_SET: first = 0; break; case SEEK_SET: first = 0; break;
case SEEK_CUR: case SEEK_CUR:
if (ex64hi(f->filp_pos) != 0) if (ex64hi(f->filp_pos) != 0)
{ panic(__FILE__, "lock_op: position in file too high", NO_NUM);
panic(__FILE__, "lock_op: position in file too high", first = ex64lo(f->filp_pos);
NO_NUM); break;
}
first = ex64lo(f->filp_pos); break;
case SEEK_END: first = f->filp_vno->v_size; break; case SEEK_END: first = f->filp_vno->v_size; break;
default: return(EINVAL); default: return(EINVAL);
} }
@ -72,10 +69,10 @@ int req; /* either F_SETLK or F_SETLKW */
if (last < first) return(EINVAL); if (last < first) return(EINVAL);
/* Check if this region conflicts with any existing lock. */ /* 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++) { for (flp = &file_lock[0]; flp < & file_lock[NR_LOCKS]; flp++) {
if (flp->lock_type == 0) { if (flp->lock_type == 0) {
if (empty == (struct file_lock *) 0) empty = flp; if (empty == NIL_LOCK) empty = flp;
continue; /* 0 means unused slot */ continue; /* 0 means unused slot */
} }
if (flp->lock_vnode != f->filp_vno) continue; /* different file */ if (flp->lock_vnode != f->filp_vno) continue; /* different file */
@ -167,6 +164,7 @@ int req; /* either F_SETLK or F_SETLKW */
return(OK); return(OK);
} }
/*===========================================================================* /*===========================================================================*
* lock_revive * * lock_revive *
*===========================================================================*/ *===========================================================================*/
@ -190,3 +188,4 @@ PUBLIC void lock_revive()
} }
} }
} }

View file

@ -8,3 +8,6 @@ EXTERN struct file_lock {
off_t lock_first; /* offset of first byte locked */ off_t lock_first; /* offset of first byte locked */
off_t lock_last; /* offset of last byte locked */ off_t lock_last; /* offset of last byte locked */
} file_lock[NR_LOCKS]; } file_lock[NR_LOCKS];
#define NIL_LOCK (struct file_lock *) 0

View file

@ -425,7 +425,7 @@ PRIVATE void init_root()
struct dmap *dp; struct dmap *dp;
char *label; char *label;
message m; message m;
struct node_details resX; struct node_details res;
/* Open the root device. */ /* Open the root device. */
root_dev = DEV_IMGRD; root_dev = DEV_IMGRD;
@ -454,9 +454,9 @@ PRIVATE void init_root()
vmp = &vmnt[0]; vmp = &vmnt[0];
/* We'll need a vnode for the root inode, check whether there is one */ /* 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); panic(__FILE__,"Cannot get free vnode", r);
}
/* Get driver process' endpoint */ /* Get driver process' endpoint */
dp = &dmap[(root_dev >> MAJOR) & BYTE]; dp = &dmap[(root_dev >> MAJOR) & BYTE];
@ -472,22 +472,22 @@ PRIVATE void init_root()
/* Issue request */ /* Issue request */
r = req_readsuper(ROOT_FS_E, label, root_dev, 0 /*!readonly*/, r = req_readsuper(ROOT_FS_E, label, root_dev, 0 /*!readonly*/,
1 /*isroot*/, &resX); 1 /*isroot*/, &res);
if (r != OK) { if (r != OK) {
panic(__FILE__,"Cannot read superblock from root", r); panic(__FILE__,"Cannot read superblock from root", r);
} }
/* Fill in root node's fields */ /* Fill in root node's fields */
root_node->v_fs_e = resX.fs_e; root_node->v_fs_e = res.fs_e;
root_node->v_inode_nr = resX.inode_nr; root_node->v_inode_nr = res.inode_nr;
root_node->v_mode = resX.fmode; root_node->v_mode = res.fmode;
root_node->v_size = resX.fsize; root_node->v_size = res.fsize;
root_node->v_sdev = NO_DEV; root_node->v_sdev = NO_DEV;
root_node->v_fs_count = 1; root_node->v_fs_count = 1;
root_node->v_ref_count = 1; root_node->v_ref_count = 1;
/* Fill in max file size and blocksize for the vmnt */ /* 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_dev = root_dev;
vmp->m_flags = 0; 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.m_type = (call_nr == PM_FORK) ? PM_FORK_REPLY : PM_FORK_NB_REPLY;
m_out.PM_PROC = m_in.PM_PROC; 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; break;
case PM_UNPAUSE: case PM_UNPAUSE:
@ -597,4 +604,6 @@ PRIVATE void service_pm()
r = send(PM_PROC_NR, &m_out); r = send(PM_PROC_NR, &m_out);
if (r != OK) if (r != OK)
panic(__FILE__, "service_pm: send failed", r); panic(__FILE__, "service_pm: send failed", r);
} }

View file

@ -32,7 +32,6 @@
#include "file.h" #include "file.h"
#include "fproc.h" #include "fproc.h"
#include "param.h" #include "param.h"
#include <minix/vfsif.h> #include <minix/vfsif.h>
#include "vnode.h" #include "vnode.h"
#include "vmnt.h" #include "vmnt.h"
@ -44,13 +43,14 @@
PUBLIC unsigned long calls_stats[NCALLS]; PUBLIC unsigned long calls_stats[NCALLS];
#endif #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, 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, 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 #define FP_EXITING 1
@ -66,14 +66,11 @@ PUBLIC int do_getsysinfo()
size_t len; size_t len;
int s; int s;
if (!super_user) /* Only su may call do_getsysinfo. This call may leak information (and is not
{ * stable enough to be part of the API/ABI).
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 if (!super_user) return(EPERM);
* of the API/ABI).
*/
}
switch(m_in.info_what) { switch(m_in.info_what) {
case SI_PROC_ADDR: case SI_PROC_ADDR:
@ -100,8 +97,7 @@ PUBLIC int do_getsysinfo()
} }
dst_addr = (vir_bytes) m_in.info_where; dst_addr = (vir_bytes) m_in.info_where;
if (OK != (s=sys_datacopy(SELF, src_addr, who_e, dst_addr, len))) if (OK != (s = sys_datacopy(SELF, src_addr, who_e, dst_addr, len))) return(s);
return(s);
return(OK); return(OK);
} }
@ -129,7 +125,7 @@ PUBLIC int do_dup()
/* Distinguish between dup and dup2. */ /* Distinguish between dup and dup2. */
if (m_in.fd == rfd) { /* bit not on */ if (m_in.fd == rfd) { /* bit not on */
/* dup(fd) */ /* 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 { } else {
/* dup2(fd, fd2) */ /* dup2(fd, fd2) */
if (m_in.fd2 < 0 || m_in.fd2 >= OPEN_MAX) return(EBADF); if (m_in.fd2 < 0 || m_in.fd2 >= OPEN_MAX) return(EBADF);
@ -146,7 +142,6 @@ PUBLIC int do_dup()
} }
/*===========================================================================* /*===========================================================================*
* do_fcntl * * do_fcntl *
*===========================================================================*/ *===========================================================================*/
@ -161,10 +156,7 @@ PUBLIC int do_fcntl()
struct filp *dummy; struct filp *dummy;
/* Is the file descriptor valid? */ /* Is the file descriptor valid? */
if ((f = get_filp(m_in.fd)) == NIL_FILP) { if ((f = get_filp(m_in.fd)) == NIL_FILP) return(err_code);
/*printf("VFSfcntl: invalid filedesc %d\n", m_in.fd); */
return(err_code);
}
switch (m_in.request) { switch (m_in.request) {
case F_DUPFD: case F_DUPFD:
@ -207,62 +199,52 @@ PUBLIC int do_fcntl()
case F_FREESP: case F_FREESP:
{ {
/* Free a section of a file. Preparation is done here, /* Free a section of a file. Preparation is done here, actual freeing
* actual freeing in freesp_inode(). * in freesp_inode().
*/ */
off_t start, end; off_t start, end;
struct flock flock_arg; struct flock flock_arg;
signed long offset; signed long offset;
/* Check if it's a regular file. */ /* Check if it's a regular file. */
if((f->filp_vno->v_mode & I_TYPE) != I_REGULAR) { if((f->filp_vno->v_mode & I_TYPE) != I_REGULAR) return(EINVAL);
return EINVAL; if (!(f->filp_mode & W_BIT)) return(EBADF);
}
if (!(f->filp_mode & W_BIT))
return EBADF;
/* Copy flock data from userspace. */ /* Copy flock data from userspace. */
if((r = sys_datacopy(who_e, (vir_bytes) m_in.name1, if((r = sys_datacopy(who_e, (vir_bytes) m_in.name1, SELF,
SELF, (vir_bytes) &flock_arg, (vir_bytes) &flock_arg, (phys_bytes) sizeof(flock_arg))) != OK)
(phys_bytes) sizeof(flock_arg))) != OK) return(r);
return r;
/* Convert starting offset to signed. */ /* Convert starting offset to signed. */
offset = (signed long) flock_arg.l_start; offset = (signed long) flock_arg.l_start;
/* Figure out starting position base. */ /* Figure out starting position base. */
switch(flock_arg.l_whence) { switch(flock_arg.l_whence) {
case SEEK_SET: start = 0; if(offset < 0) return EINVAL; break; case SEEK_SET: start = 0; if(offset < 0) return EINVAL; break;
case SEEK_CUR: case SEEK_CUR:
if (ex64hi(f->filp_pos) != 0) if (ex64hi(f->filp_pos) != 0)
{ panic(__FILE__, "do_fcntl: position in file too high",
panic(__FILE__,
"do_fcntl: position in file too high",
NO_NUM); NO_NUM);
}
start = ex64lo(f->filp_pos); break; start = ex64lo(f->filp_pos);
case SEEK_END: start = f->filp_vno->v_size; break; break;
default: return EINVAL; case SEEK_END: start = f->filp_vno->v_size; break;
default: return EINVAL;
} }
/* Check for overflow or underflow. */ /* 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; start += offset;
if(flock_arg.l_len > 0) { if(flock_arg.l_len > 0) {
end = start + flock_arg.l_len; end = start + flock_arg.l_len;
if(end <= start) { if(end <= start) return EINVAL;
return EINVAL; } else {
}
}
else {
end = 0; end = 0;
} }
/* Issue request */ return req_ftrunc(f->filp_vno->v_fs_e, f->filp_vno->v_inode_nr, start,
return req_ftrunc(f->filp_vno->v_fs_e, f->filp_vno->v_inode_nr, end);
start, end);
} }
default: default:
@ -277,13 +259,11 @@ PUBLIC int do_fcntl()
PUBLIC int do_sync() PUBLIC int do_sync()
{ {
struct vmnt *vmp; struct vmnt *vmp;
for (vmp = &vmnt[1]; vmp < &vmnt[NR_MNTS]; ++vmp) { for (vmp = &vmnt[1]; vmp < &vmnt[NR_MNTS]; ++vmp)
if (vmp->m_dev != NO_DEV) { if (vmp->m_dev != NO_DEV)
/* Send sync request */
req_sync(vmp->m_fs_e); 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. */ /* Perform the fsync() system call. For now, don't be unnecessarily smart. */
do_sync(); do_sync();
return(OK); return(OK);
} }
void unmount_all(void) /*===========================================================================*
* unmount_all *
*===========================================================================*/
PRIVATE void unmount_all(void)
{ {
int i; /* Unmount all filesystems. File systems are mounted on other file systems,
int found = 0, worked = 0, remain = 0; * 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++) { for (i= 0; i < NR_MNTS; i++) {
struct vmnt *vmp; struct vmnt *vmp;
/* Unmount at least one. */ /* Unmount at least one. */
worked = remain = 0;
for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; vmp++) { for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; vmp++) {
if (vmp->m_dev != NO_DEV) { if (vmp->m_dev != NO_DEV)
found++; unmount(vmp->m_dev);
SANITYCHECK;
if(unmount(vmp->m_dev) == OK)
worked++;
else
remain++;
SANITYCHECK;
}
} }
} }
} }
@ -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 * * pm_setuid *
*===========================================================================*/ *===========================================================================*/

View file

@ -18,13 +18,12 @@
#include "param.h" #include "param.h"
#include <dirent.h> #include <dirent.h>
#include <assert.h> #include <assert.h>
#include <minix/vfsif.h> #include <minix/vfsif.h>
#include "vnode.h" #include "vnode.h"
#include "vmnt.h" #include "vmnt.h"
/*===========================================================================* /*===========================================================================*
* do_vm_mmap * * do_vm_mmap *
*===========================================================================*/ *===========================================================================*/
PUBLIC int do_vm_mmap() PUBLIC int do_vm_mmap()
{ {

View file

@ -3,9 +3,6 @@
* The entry points into this file are * The entry points into this file are
* do_mount: perform the MOUNT system call * do_mount: perform the MOUNT system call
* do_umount: perform the UMOUNT system call * do_umount: perform the UMOUNT system call
*
* Changes for VFS:
* Jul 2006 (Balazs Gerofi)
*/ */
#include "fs.h" #include "fs.h"
@ -23,7 +20,6 @@
#include "file.h" #include "file.h"
#include "fproc.h" #include "fproc.h"
#include "param.h" #include "param.h"
#include <minix/vfsif.h> #include <minix/vfsif.h>
#include "vnode.h" #include "vnode.h"
#include "vmnt.h" #include "vmnt.h"
@ -34,36 +30,40 @@ PRIVATE int allow_newroot = 1;
FORWARD _PROTOTYPE( dev_t name_to_dev, (void) ); FORWARD _PROTOTYPE( dev_t name_to_dev, (void) );
FORWARD _PROTOTYPE( int mount_fs, (endpoint_t fs_e) ); FORWARD _PROTOTYPE( int mount_fs, (endpoint_t fs_e) );
/*===========================================================================* /*===========================================================================*
* do_fslogin * * do_fslogin *
*===========================================================================*/ *===========================================================================*/
PUBLIC int do_fslogin() PUBLIC int do_fslogin()
{ {
int r;
/* Login before mount request */ /* Login before mount request */
if ((unsigned long)mount_m_in.m1_p3 != who_e) { if ((unsigned long)mount_m_in.m1_p3 != who_e) {
last_login_fs_e = who_e; last_login_fs_e = who_e;
return SUSPEND; r = SUSPEND;
} }
/* Login after a suspended mount */ /* Login after a suspended mount */
else { else {
/* Copy back original mount request message */ /* Copy back original mount request message */
m_in = mount_m_in; m_in = mount_m_in;
/* Set up last login FS */ /* Set up last login FS */
last_login_fs_e = who_e; last_login_fs_e = who_e;
/* Set up endpoint and call nr */ /* Set up endpoint and call nr */
who_e = m_in.m_source; who_e = m_in.m_source;
who_p = _ENDPOINT_P(who_e); who_p = _ENDPOINT_P(who_e);
call_nr = m_in.m_type; call_nr = m_in.m_type;
fp = &fproc[who_p]; /* pointer to proc table struct */ fp = &fproc[who_p]; /* pointer to proc table struct */
super_user = (fp->fp_effuid == SU_UID ? TRUE : FALSE); /* su? */ super_user = (fp->fp_effuid == SU_UID ? TRUE : FALSE); /* su? */
r = do_mount();
return do_mount();
} }
return(r);
} }
/*===========================================================================* /*===========================================================================*
* do_mount * * do_mount *
*===========================================================================*/ *===========================================================================*/
@ -71,17 +71,15 @@ PUBLIC int do_mount()
{ {
endpoint_t fs_e; endpoint_t fs_e;
SANITYCHECK;
/* Only the super-user may do MOUNT. */ /* Only the super-user may do MOUNT. */
if (!super_user) return(EPERM); if (!super_user) return(EPERM);
/* FS process' endpoint number */ /* 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. */ /* Sanity check on process number. */
if(fs_e <= 0) { 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; return EINVAL;
} }
@ -102,73 +100,66 @@ PRIVATE int mount_fs(endpoint_t fs_e)
struct dmap *dp; struct dmap *dp;
dev_t dev; dev_t dev;
message m; message m;
struct vnode *root_node, *mounted_on = NULL, *bspec; struct vnode *root_node, *vp = NULL, *bspec;
struct vmnt *vmp; struct vmnt *vmp;
char *label; char *label;
struct node_details res; struct node_details res;
SANITYCHECK;
/* Only the super-user may do MOUNT. */ /* Only the super-user may do MOUNT. */
if (!super_user) return(EPERM); if (!super_user) return(EPERM);
/* If FS not yet logged in, save message and suspend mount */ /* If FS not yet logged in, save message and suspend mount */
if (last_login_fs_e != fs_e) { if (last_login_fs_e != fs_e) {
mount_m_in = m_in; mount_m_in = m_in;
return SUSPEND; return(SUSPEND);
} }
/* Mount request got after FS login or /* Mount request got after FS login or FS login arrived after a suspended mount */
* FS login arrived after a suspended mount */
last_login_fs_e = NONE; last_login_fs_e = NONE;
/* Clear endpoint field */ /* 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 '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); 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); if ((dev = name_to_dev()) == NO_DEV) return(err_code);
/* Check whether there is a block special file open which uses the /* Check whether there is a block special file open which uses the
* same device (partition) */ * same device (partition) */
for (bspec = &vnode[0]; bspec < &vnode[NR_VNODES]; ++bspec) { for (bspec = &vnode[0]; bspec < &vnode[NR_VNODES]; ++bspec) {
if (bspec->v_ref_count > 0 && bspec->v_sdev == dev) { if (bspec->v_ref_count > 0 && bspec->v_sdev == dev) {
/* Found, sync the buffer cache */ /* Found, sync the buffer cache */
req_sync(bspec->v_fs_e); req_sync(bspec->v_fs_e);
break; break;
/* Note: there are probably some blocks in the FS process' buffer /* Note: there are probably some blocks in the FS process'
* cache which contain data on this minor, although they will be * buffer cache which contain data on this minor, although
* purged since the handling moves to the new FS process (if * they will be purged since the handling moves to the new
* everything goes well with the mount...) * FS process (if everything goes well with the mount...)
*/ */
} }
} }
/* Didn't find? */ /* Didn't find? */
if (bspec == &vnode[NR_VNODES] && bspec->v_sdev != dev) if (bspec == &vnode[NR_VNODES] && bspec->v_sdev != dev)
bspec = NULL; bspec = NULL;
/* Scan vmnt table to see if dev already mounted, if not, /* Scan vmnt table to see if dev already mounted. If not, find a free slot.*/
* find a free slot.*/
found = FALSE; found = FALSE;
vmp = NIL_VMNT; vmp = NIL_VMNT;
for (i = 0; i < NR_MNTS; ++i) { for (i = 0; i < NR_MNTS; ++i) {
if (vmnt[i].m_dev == dev) { if (vmnt[i].m_dev == dev) {
vmp = &vmnt[i]; vmp = &vmnt[i];
found = TRUE; found = TRUE;
break; break;
} } else if (!vmp && vmnt[i].m_dev == NO_DEV) {
else if (!vmp && vmnt[i].m_dev == NO_DEV) { vmp = &vmnt[i];
vmp = &vmnt[i]; }
}
} }
/* Partition was/is already mounted */ /* Partition was/is already mounted */
if (found) { if (found) {
/* It is possible that we have an old root lying around that /* It is possible that we have an old root lying around that
* needs to be remounted. */ * 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 /* Normally, m_mounted_on refers to the mount point. For a
* root filesystem, m_mounted_on is equal to the root vnode. * root filesystem, m_mounted_on is equal to the root vnode.
* We assume that the root of FS is always the real root. If * 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 * to the root of the filesystem we found, we found a
* filesystem that is in use. * filesystem that is in use.
*/ */
return EBUSY; /* already mounted */ return(EBUSY); /* already mounted */
} }
if(vmp->m_mounted_on) if(vmp->m_mounted_on)
panic("vfs", "root unexpectedly mounted somewhere", NO_NUM); panic("vfs", "root unexpectedly mounted somewhere", NO_NUM);
if (root_dev == vmp->m_dev) 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. */ /* Now get the inode of the file to be mounted on. */
if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK) { if (fetch_name(m_in.name2, m_in.name2_length, M1)!=OK) return(err_code);
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 */ /* Tell FS on which vnode it is mounted (glue into mount tree) */
r = lookup_vp(0 /*flags*/, 0 /*!use_realuid*/, &mounted_on); if ((r = req_mountpoint(vp->v_fs_e, vp->v_inode_nr)) == OK) {
if (r != OK) return r; root_node = vmp->m_root_node;
if (mounted_on->v_ref_count != 1) /* File types of 'vp' and 'root_node' may not conflict. */
{ mdir = ((vp->v_mode & I_TYPE) == I_DIRECTORY);/* TRUE iff dir*/
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 */
rdir = ((root_node->v_mode & I_TYPE) == I_DIRECTORY); 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) { if (r != OK) {
put_vnode(mounted_on); put_vnode(vp);
return(r); return(r);
} }
/* Nothing else can go wrong. Perform the mount. */ /* 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; vmp->m_flags = m_in.rd_only;
allow_newroot = 0; /* The root is now fixed */ 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 */ /* Fetch the name of the mountpoint */
if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK) { if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK) return(err_code);
return(err_code); isroot = (strcmp(user_fullpath, "/") == 0);
} replace_root = (isroot && allow_newroot);
isroot= (strcmp(user_fullpath, "/") == 0); if(!replace_root) {
replace_root= (isroot && allow_newroot); /* Get vnode of mountpoint */
if ((vp = eat_path(PATH_NOFLAGS)) == NIL_VNODE) return(err_code);
if (!replace_root) /* 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) {
/* Get mount point and inform the FS it is on. */ put_vnode(vp);
#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);
return r; return r;
} }
} }
/* We'll need a vnode for the root inode, check whether there is one */ /* 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) return(ENFILE);
printf("VFSmount: no free vnode available\n");
return ENFILE;
}
/* Get driver process' endpoint */ /* Get driver process' endpoint */
dp = &dmap[(dev >> MAJOR) & BYTE]; dp = &dmap[(dev >> MAJOR) & BYTE];
if (dp->dmap_driver == NONE) { if (dp->dmap_driver == NONE) {
printf("VFSmount: no driver for dev %x\n", dev); printf("VFS: no driver for dev %x\n", dev);
return(EINVAL); 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 */ label = dp->dmap_label;
r = req_readsuper(fs_e, label, dev, m_in.rd_only, isroot, &res); if (strlen(label) == 0)
if (r != OK) { panic(__FILE__, "VFS mount_fs: no label for major", dev >> MAJOR);
if (mounted_on)
put_vnode(mounted_on); /* Tell FS which device to mount */
return r; 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 */ /* 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_sdev = NO_DEV;
root_node->v_fs_count = 1; root_node->v_fs_count = 1;
root_node->v_ref_count = 1; root_node->v_ref_count = 1;
/* Fill in max file size and blocksize for the vmnt */ /* Fill in max file size and blocksize for the vmnt */
vmp->m_fs_e = res.fs_e; vmp->m_fs_e = res.fs_e;
vmp->m_dev = dev; vmp->m_dev = dev;
@ -314,68 +263,63 @@ PRIVATE int mount_fs(endpoint_t fs_e)
root_node->v_vmnt = vmp; root_node->v_vmnt = vmp;
root_node->v_dev = vmp->m_dev; root_node->v_dev = vmp->m_dev;
if (replace_root) { if(replace_root) {
/* Superblock and root node already read. /* Superblock and root node already read.
* Nothing else can go wrong. Perform the mount. */ * Nothing else can go wrong. Perform the mount. */
vmp->m_root_node = root_node; vmp->m_root_node = root_node;
vmp->m_mounted_on = NULL; vmp->m_mounted_on = NULL;
root_dev = dev; root_dev = dev;
ROOT_FS_E = fs_e; ROOT_FS_E = fs_e;
/* Replace all root and working directories */ /* Replace all root and working directories */
for (i= 0, tfp= fproc; i<NR_PROCS; i++, tfp++) { for (i= 0, tfp= fproc; i<NR_PROCS; i++, tfp++) {
if (tfp->fp_pid == PID_FREE) if (tfp->fp_pid == PID_FREE)
continue; continue;
#define MAKEROOT(what) { \ #define MAKEROOT(what) { \
put_vnode(what); \ put_vnode(what); \
dup_vnode(root_node); \ dup_vnode(root_node); \
what = root_node; \ what = root_node; \
} }
if(tfp->fp_rd) MAKEROOT(tfp->fp_rd); if(tfp->fp_rd) MAKEROOT(tfp->fp_rd);
if(tfp->fp_wd) MAKEROOT(tfp->fp_wd); if(tfp->fp_wd) MAKEROOT(tfp->fp_wd);
} }
SANITYCHECK; return(OK);
return(OK);
} }
/* File types may not conflict. */ /* File types may not conflict. */
if (r == OK) { if (r == OK) {
mdir = ((mounted_on->v_mode & I_TYPE) == I_DIRECTORY);/* TRUE iff dir */ mdir = ((vp->v_mode & I_TYPE) == I_DIRECTORY); /*TRUE iff dir*/
rdir = ((root_node->v_mode & I_TYPE) == I_DIRECTORY); rdir = ((root_node->v_mode & I_TYPE) == I_DIRECTORY);
if (!mdir && rdir) r = EISDIR; if (!mdir && rdir) r = EISDIR;
} }
/* If error, return the super block and both inodes; release the vmnt. */ /* If error, return the super block and both inodes; release the vmnt. */
if (r != OK) { if (r != OK) {
put_vnode(mounted_on); put_vnode(vp);
put_vnode(root_node); put_vnode(root_node);
vmp->m_dev = NO_DEV;
vmp->m_dev = NO_DEV; return(r);
return(r);
} }
/* Nothing else can go wrong. Perform the mount. */ /* 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; vmp->m_root_node = root_node;
/* The root is now fixed */ /* The root is now fixed */
allow_newroot = 0; allow_newroot = 0;
/* There was a block spec file open, and it should be handled by the /* There was a block spec file open, and it should be handled by the
* new FS proc now */ * new FS proc now */
if (bspec) { if (bspec) bspec->v_bfs_e = fs_e;
printf("VFSmount: moving opened block spec to new FS_e: %d...\n", fs_e);
bspec->v_bfs_e = fs_e;
}
SANITYCHECK;
return(OK); return(OK);
} }
/*===========================================================================* /*===========================================================================*
* do_umount * * do_umount *
*===========================================================================*/ *===========================================================================*/
@ -383,19 +327,14 @@ PUBLIC int do_umount()
{ {
/* Perform the umount(name) system call. */ /* Perform the umount(name) system call. */
dev_t dev; dev_t dev;
SANITYCHECK;
/* Only the super-user may do umount. */
/* Only the super-user may do UMOUNT. */
if (!super_user) return(EPERM); if (!super_user) return(EPERM);
SANITYCHECK;
/* If 'name' is not for a block special file, return error. */ /* 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); 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);
if ( (dev = name_to_dev()) == NO_DEV) return(err_code); return unmount(dev);
SANITYCHECK;
return(unmount(dev));
} }
@ -411,132 +350,74 @@ Dev_t dev;
int count, r; int count, r;
int fs_e; int fs_e;
SANITYCHECK; /* Find vmnt that is to be unmounted */
for(vmp_i = &vmnt[0]; vmp_i < &vmnt[NR_MNTS]; ++vmp_i) {
/* Find vmnt */ if (vmp_i->m_dev == dev) {
for (vmp_i = &vmnt[0]; vmp_i < &vmnt[NR_MNTS]; ++vmp_i) { if(vmp) panic(__FILE__,"device mounted more than once", dev);
if (vmp_i->m_dev == dev) { vmp = vmp_i;
if(vmp) panic(__FILE__, "device mounted more than once", dev); }
vmp = vmp_i;
}
} }
/* Device mounted? */ /* Did we find the vmnt (i.e., was dev a mounted device)? */
if(!vmp) if(!vmp) return(EINVAL);
return EINVAL;
/* See if the mounted device is busy. Only 1 vnode using it should be /* 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; count = 0;
for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; vp++) { for(vp = &vnode[0]; vp < &vnode[NR_VNODES]; vp++)
if (vp->v_ref_count > 0 && vp->v_dev == dev) { if(vp->v_ref_count > 0 && vp->v_dev == dev) count += vp->v_ref_count;
#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; i<NR_PROCS; i++, tfp++) {
int n;
if (tfp->fp_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;
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); vnode_clean_refs(vmp->m_root_node);
SANITYCHECK;
if (vmp->m_mounted_on) { if (vmp->m_mounted_on) {
put_vnode(vmp->m_mounted_on); put_vnode(vmp->m_mounted_on);
vmp->m_mounted_on->v_fs_count--; vmp->m_mounted_on = NIL_VNODE;
vmp->m_mounted_on = NIL_VNODE;
} }
put_vnode(vmp->m_root_node); /* Tell FS to unmount */
vmp->m_root_node->v_ref_count = 0;
vmp->m_root_node = NIL_VNODE;
/* Request FS the unmount */
if(vmp->m_fs_e <= 0 || vmp->m_fs_e == NONE) if(vmp->m_fs_e <= 0 || vmp->m_fs_e == NONE)
panic(__FILE__, "unmount: strange fs endpoint", vmp->m_fs_e); 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_dev = NO_DEV;
vmp->m_fs_e = NONE; vmp->m_fs_e = NONE;
SANITYCHECK;
/* Is there a block special file that was handled by that partition? */ /* Is there a block special file that was handled by that partition? */
for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; vp++) { for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; vp++) {
if ((vp->v_mode & I_TYPE) == I_BLOCK_SPECIAL && if((vp->v_mode & I_TYPE)==I_BLOCK_SPECIAL && vp->v_bfs_e==vmp->m_fs_e){
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 */ printf("VFS: umount moving block spec %d to root FS\n", dev);
dp = &dmap[(dev >> MAJOR) & BYTE]; vp->v_bfs_e = ROOT_FS_E;
if (dp->dmap_driver == NONE) {
printf("VFSblock_spec_open: driver not found for device %d\n", /* Send the (potentially new) driver endpoint */
dev); r = req_newdriver(vp->v_bfs_e, vp->v_sdev, dp->dmap_driver);
/* What should be done, panic??? */ if (r != OK)
continue; printf("VFS: error sending driver endpoint for"
} " moved block spec\n");
printf("VFSunmount: moving block spec %d to root FS\n", dev); }
vp->v_bfs_e = ROOT_FS_E;
/* Send the driver endpoint (even if it is known already...) */
if ((r = req_newdriver(vp->v_bfs_e, vp->v_sdev, dp->dmap_driver))
!= OK) {
printf("VFSunmount: error sending driver endpoint for block spec\n");
}
}
} }
SANITYCHECK;
return(OK); return(OK);
} }
/*===========================================================================* /*===========================================================================*
* name_to_dev * * name_to_dev *
*===========================================================================*/ *===========================================================================*/
@ -549,20 +430,18 @@ PRIVATE dev_t name_to_dev()
struct vnode *vp; struct vnode *vp;
/* Request lookup */ /* Request lookup */
if ((r = lookup_vp(0 /*flags*/, 0 /*!use_realuid*/, &vp)) != OK) { if ((vp = eat_path(PATH_NOFLAGS)) == NIL_VNODE) {
printf("vfs: name_to_dev: lookup of '%s' failed\n", user_fullpath); printf("VFS: name_to_dev: lookup of '%s' failed\n", user_fullpath);
return NO_DEV; return(NO_DEV);
} }
if ((vp->v_mode & I_TYPE) != I_BLOCK_SPECIAL) { if ((vp->v_mode & I_TYPE) != I_BLOCK_SPECIAL) {
err_code = ENOTBLK; err_code = ENOTBLK;
dev= NO_DEV; dev = NO_DEV;
} } else
else dev = vp->v_sdev;
dev= vp->v_sdev;
put_vnode(vp); put_vnode(vp);
return(dev);
return dev;
} }

View file

@ -8,9 +8,6 @@
* do_mkdir: perform the MKDIR system call * do_mkdir: perform the MKDIR system call
* do_close: perform the CLOSE system call * do_close: perform the CLOSE system call
* do_lseek: perform the LSEEK system call * do_lseek: perform the LSEEK system call
*
* Changes for VFS:
* Jul 2006 (Balazs Gerofi)
*/ */
#include "fs.h" #include "fs.h"
@ -27,21 +24,17 @@
#include "param.h" #include "param.h"
#include <dirent.h> #include <dirent.h>
#include <assert.h> #include <assert.h>
#include <minix/vfsif.h> #include <minix/vfsif.h>
#include "vnode.h" #include "vnode.h"
#include "vmnt.h" #include "vmnt.h"
#define offset_lo m2_l1 PRIVATE char mode_map[] = {R_BIT, W_BIT, R_BIT|W_BIT, 0};
#define offset_high m2_l2
FORWARD _PROTOTYPE( int common_open, (int oflags, mode_t omode) ); FORWARD _PROTOTYPE( int common_open, (int oflags, mode_t omode) );
FORWARD _PROTOTYPE( int create_open, (_mnx_Mode_t omode, int excl, FORWARD _PROTOTYPE( struct vnode *new_node, (mode_t bits) );
struct vnode **vpp, int *created) );
FORWARD _PROTOTYPE( int exists_open, (struct vnode *vp, _mnx_Mode_t bits,
int oflags));
FORWARD _PROTOTYPE( int pipe_open, (struct vnode *vp,mode_t bits,int oflags)); FORWARD _PROTOTYPE( int pipe_open, (struct vnode *vp,mode_t bits,int oflags));
/*===========================================================================* /*===========================================================================*
* do_creat * * do_creat *
*===========================================================================*/ *===========================================================================*/
@ -55,6 +48,7 @@ PUBLIC int do_creat()
return(r); return(r);
} }
/*===========================================================================* /*===========================================================================*
* do_open * * do_open *
*===========================================================================*/ *===========================================================================*/
@ -72,20 +66,20 @@ PUBLIC int do_open()
r = fetch_name(m_in.name, m_in.name_length, M3); r = fetch_name(m_in.name, m_in.name_length, M3);
} }
if (r != OK) { if (r != OK) return(err_code); /* name was bad */
return(err_code); /* name was bad */
}
r = common_open(m_in.mode, create_mode); r = common_open(m_in.mode, create_mode);
return(r); return(r);
} }
/*===========================================================================* /*===========================================================================*
* common_open * * common_open *
*===========================================================================*/ *===========================================================================*/
PRIVATE int common_open(register int oflags, mode_t omode) PRIVATE int common_open(register int oflags, mode_t omode)
{ {
/* Common code from do_creat and do_open. */ /* 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; mode_t bits;
struct filp *fil_ptr, *filp2; struct filp *fil_ptr, *filp2;
struct vnode *vp; struct vnode *vp;
@ -93,131 +87,135 @@ PRIVATE int common_open(register int oflags, mode_t omode)
struct dmap *dp; struct dmap *dp;
/* Remap the bottom two bits of oflags. */ /* Remap the bottom two bits of oflags. */
m = oflags & O_ACCMODE; bits = (mode_t) mode_map[oflags & O_ACCMODE];
switch(m) { if (!bits) return(EINVAL);
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;
}
/* See if file descriptor and filp slots are available. */ /* See if file descriptor and filp slots are available. */
if ((r = get_fd(0, bits, &m_in.fd, &fil_ptr)) != OK) return(r); 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) { if (oflags & O_CREAT) {
omode = I_REGULAR | (omode & ALL_MODES & fp->fp_umask); omode = I_REGULAR | (omode & ALL_MODES & fp->fp_umask);
} vp = new_node(omode);
r = err_code;
if (oflags & O_CREAT) if (r == OK) exist = FALSE; /* We just created the file */
r= create_open(omode, !!(oflags & O_EXCL), &vp, &created); else if (r != EEXIST) return(r); /* other error */
else else exist = !(oflags & O_EXCL); /* file exists, if the O_EXCL
{ flag is set this is an error */
#if 0 } else {
printf("vfs:common_open: path '%s'\n", user_fullpath); /* Scan path name */
#endif if ((vp = eat_path(PATH_NOFLAGS)) == NIL_VNODE) return(err_code);
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;
}
} }
/* Claim the file descriptor and filp slot and fill them in. */ /* Claim the file descriptor and filp slot and fill them in. */
fp->fp_filp[m_in.fd] = fil_ptr; fp->fp_filp[m_in.fd] = fil_ptr;
FD_SET(m_in.fd, &fp->fp_filp_inuse); FD_SET(m_in.fd, &fp->fp_filp_inuse);
fil_ptr->filp_count = 1; fil_ptr->filp_count = 1;
fil_ptr->filp_flags = oflags;
fil_ptr->filp_vno = vp; fil_ptr->filp_vno = vp;
fil_ptr->filp_flags = oflags;
switch (vp->v_mode & I_TYPE) {
case I_CHAR_SPECIAL:
/* Invoke the driver for special processing. */
r = dev_open(vp->v_sdev, who_e, bits | (oflags & ~O_ACCMODE));
if (r == SUSPEND)
suspend(FP_BLOCKED_ON_DOPEN); /* suspend caller */
break;
case I_BLOCK_SPECIAL: /* Only do the normal open code if didn't just create the file. */
/* Invoke the driver for special processing. */ if(exist) {
r = dev_open(vp->v_sdev, who_e, bits | (oflags & ~O_ACCMODE)); /* Check protections. */
if (r != OK) if ((r = forbidden(vp, bits)) == OK) {
break; /* Opening reg. files, directories, and special files differ */
switch (vp->v_mode & I_TYPE) {
/* Check whether the device is mounted or not */ case I_REGULAR:
found = 0; /* Truncate regular file if O_TRUNC. */
for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; ++vmp) { if (oflags & O_TRUNC) {
if (vmp->m_dev == vp->v_sdev) { if ((r = forbidden(vp, W_BIT)) != OK)
found = 1; break;
break; truncate_vnode(vp, 0);
} }
} break;
case I_DIRECTORY:
/* Who is going to be responsible for this device? */ /* Directories may be read but not written. */
if (found) { r = (bits & W_BIT ? EISDIR : OK);
vp->v_bfs_e = vmp->m_fs_e; break;
} case I_CHAR_SPECIAL:
else { /* To be handled in the root FS proc if not mounted */ /* Invoke the driver for special processing. */
vp->v_bfs_e = ROOT_FS_E; dev = (dev_t) vp->v_sdev;
} r = dev_open(dev, who_e, bits | (oflags & ~O_ACCMODE));
if (r == SUSPEND) suspend(FP_BLOCKED_ON_DOPEN);
/* Get the driver endpoint of the block spec device */ break;
dp = &dmap[(vp->v_sdev >> MAJOR) & BYTE]; case I_BLOCK_SPECIAL:
if (dp->dmap_driver == NONE) { /* Invoke the driver for special processing. */
printf("VFSblock_spec_open: driver not found for device %d\n", dev = (dev_t) vp->v_sdev;
vp->v_sdev); r = dev_open(dev, who_e, bits | (oflags & ~O_ACCMODE));
r = EINVAL;
break;
}
/* Send the driver endpoint (even if it is known already...) */ /* Check whether the device is mounted or not. If so,
if ((r = req_newdriver(vp->v_bfs_e, vp->v_sdev, dp->dmap_driver)) then that FS is responsible for this device. Else
!= OK) { we default to ROOT_FS. */
printf("VFSblock_spec_open: error sending driver endpoint\n"); vp->v_bfs_e = ROOT_FS_E; /* By default */
} for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; ++vmp)
break; if (vmp->m_dev == vp->v_sdev)
vp->v_bfs_e = vmp->m_fs_e;
case I_NAMED_PIPE: /* Get the driver endpoint of the block spec device */
vp->v_pipe = I_PIPE; dp = &dmap[(vp->v_sdev >> MAJOR) & BYTE];
oflags |= O_APPEND; /* force append mode */ if (dp->dmap_driver == NONE) {
fil_ptr->filp_flags = oflags; printf("VFS: driver not found for device %d\n",
r = pipe_open(vp, bits, oflags); vp->v_sdev);
if (r != ENXIO) { r = ENXIO;
/* See if someone else is doing a rd or wt on break;
* the FIFO. If so, use its filp entry so the }
* file position will be automatically shared.
*/
b = (bits & R_BIT ? R_BIT : W_BIT);
assert(fil_ptr->filp_count == 1);
fil_ptr->filp_count = 0; /* don't find self */
if ((filp2 = find_filp(vp, b)) != NIL_FILP) {
/* Co-reader or writer found. Use it.*/
fp->fp_filp[m_in.fd] = filp2;
filp2->filp_count++;
filp2->filp_vno = vp;
filp2->filp_flags = oflags;
/* v_count was incremented after the vnode has /* Send the driver endpoint (even when known already)*/
* been found, i_count was incremented incorrectly if ((r = req_newdriver(vp->v_bfs_e, vp->v_sdev,
* by eatpath in FS, not knowing that we were going to dp->dmap_driver)) != OK) {
* use an existing filp entry. Correct this error. printf("VFS: error sending driver endpoint\n");
*/ r = ENXIO;
put_vnode(vp); }
} else { break;
/* Nobody else found. Claim filp. */
fil_ptr->filp_count = 1; case I_NAMED_PIPE:
} /* Create a mapped inode on PFS which handles reads
} and writes to this named pipe. */
break; 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. */ /* 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) PRIVATE struct vnode *new_node(mode_t bits)
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<SYMLOOP_MAX; i++)
{
#if 0
printf("vfs:create_open: path #%d '%s'\n", i+1, user_fullpath);
#endif
r= lookup_lastdir_rel(start_vp, 0 /*!use_realuid*/, &dir_vp);
put_vnode(start_vp);
if (r != OK)
return r;
/* Save the last component of the path */
len= strlen(user_fullpath)+1;
if (len > 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;
{ {
struct vnode *dirp, *vp;
int r; int r;
struct node_details res;
struct vnode *rest;
/* Check protections. */ /* See if the path can be opened down to the last directory. */
if ((r = forbidden(vp, bits, 0 /*!use_realuid*/)) != OK) if ((dirp = last_dir()) == NIL_VNODE) return(NIL_VNODE);
return r;
/* Opening reg. files directories and special files differ. */ /* The final directory is accessible. Get final component of the path. */
switch (vp->v_mode & I_TYPE) { vp = advance(dirp, 0);
case I_REGULAR: if (vp == NIL_VNODE && err_code == ENOENT) {
/* Truncate regular file if O_TRUNC. */ /* Last path component does not exist. Make a new directory entry. */
if (oflags & O_TRUNC) { if ((vp = get_free_vnode()) == NIL_VNODE) {
if ((r = forbidden(vp, W_BIT, 0 /*!use_realuid*/)) !=OK) break; /* Can't create new vnode: out of vnodes. */
truncate_vn(vp, 0); put_vnode(dirp);
return(NIL_VNODE);
} }
break; if ((r = forbidden(dirp, W_BIT|X_BIT)) != OK ||
(r = req_create(dirp->v_fs_e, dirp->v_inode_nr,bits, fp->fp_effuid,
case I_DIRECTORY: fp->fp_effgid, user_fullpath, &res)) != OK ) {
/* Directories may be read but not written. */ /* Can't create new directory entry: either no permission or
r = (bits & W_BIT ? EISDIR : OK); something else is wrong. */
break; put_vnode(dirp);
err_code = r;
case I_CHAR_SPECIAL: return(NIL_VNODE);
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);
} }
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; vp->v_pipe = I_PIPE;
if((bits & (R_BIT|W_BIT)) == (R_BIT|W_BIT)) { if((bits & (R_BIT|W_BIT)) == (R_BIT|W_BIT)) return(ENXIO);
printf("pipe opened RW.\n");
return ENXIO;
}
if (find_filp(vp, bits & W_BIT ? R_BIT : W_BIT) == NIL_FILP) { if (find_filp(vp, bits & W_BIT ? R_BIT : W_BIT) == NIL_FILP) {
if (oflags & O_NONBLOCK) { 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 */ suspend(FP_BLOCKED_ON_POPEN); /* suspend caller */
return(SUSPEND); 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, OPEN, susp_count);
release(vp, CREAT, susp_count); release(vp, CREAT, susp_count);
} }
@ -527,35 +331,29 @@ PUBLIC int do_mknod()
register mode_t bits, mode_bits; register mode_t bits, mode_bits;
int r; int r;
struct vnode *vp; struct vnode *vp;
/* Only the super_user may make nodes other than fifos. */ /* Only the super_user may make nodes other than fifos. */
mode_bits = (mode_t) m_in.mk_mode; /* mode of the inode */ 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(!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);
bits = (mode_bits & I_TYPE) | (mode_bits & ALL_MODES & fp->fp_umask); bits = (mode_bits & I_TYPE) | (mode_bits & ALL_MODES & fp->fp_umask);
/* Request lookup */ /* Open directory that's going to hold the new node. */
if ((r = lookup_lastdir(0 /*!use_realuid*/, &vp)) != OK) return r; 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 */ /* Make sure that the object is a directory */
if ((vp->v_mode & I_TYPE) != I_DIRECTORY) if((vp->v_mode & I_TYPE) != I_DIRECTORY) {
{ put_vnode(vp);
put_vnode(vp); return(ENOTDIR);
return ENOTDIR;
} }
r= forbidden(vp, W_BIT|X_BIT, 0 /*!use_realuid*/); if ((r = forbidden(vp, W_BIT|X_BIT)) == OK) {
if (r != 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);
put_vnode(vp);
return r;
} }
/* 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); put_vnode(vp);
return r; return(r);
} }
@ -569,37 +367,29 @@ PUBLIC int do_mkdir()
int r; int r;
struct vnode *vp; 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); bits = I_DIRECTORY | (m_in.mode & RWX_MODES & fp->fp_umask);
/* Request lookup */ /* 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 */ /* Make sure that the object is a directory */
if ((vp->v_mode & I_TYPE) != I_DIRECTORY) if ((vp->v_mode & I_TYPE) != I_DIRECTORY) {
{ put_vnode(vp);
put_vnode(vp); return(ENOTDIR);
return ENOTDIR;
} }
r= forbidden(vp, W_BIT|X_BIT, 0 /*!use_realuid*/); if ((r = forbidden(vp, W_BIT|X_BIT)) == OK) {
if (r != OK) 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;
} }
/* 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); put_vnode(vp);
return r; return(r);
} }
/*===========================================================================* /*===========================================================================*
* do_lseek * * do_lseek *
*===========================================================================*/ *===========================================================================*/
@ -625,7 +415,7 @@ PUBLIC int do_lseek()
default: return(EINVAL); default: return(EINVAL);
} }
offset= m_in.offset_lo; offset = m_in.offset_lo;
if (offset >= 0) if (offset >= 0)
newpos= add64ul(pos, offset); newpos= add64ul(pos, offset);
else else
@ -633,11 +423,11 @@ PUBLIC int do_lseek()
/* Check for overflow. */ /* Check for overflow. */
if (ex64hi(newpos) != 0) if (ex64hi(newpos) != 0)
return EINVAL; return(EINVAL);
if (cmp64(newpos, rfilp->filp_pos) != 0) { /* Inhibit read ahead request */ 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); 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; rfilp->filp_pos = newpos;
@ -673,7 +463,7 @@ PUBLIC int do_llseek()
default: return(EINVAL); 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. */ /* Check for overflow. */
if (((long)m_in.offset_high > 0) && cmp64(newpos, pos) < 0) 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 */ 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); 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; rfilp->filp_pos = newpos;
@ -757,14 +547,13 @@ struct filp *fp;
if (mode_word == I_CHAR_SPECIAL || mode_word == I_BLOCK_SPECIAL) { if (mode_word == I_CHAR_SPECIAL || mode_word == I_BLOCK_SPECIAL) {
dev = (dev_t) vp->v_sdev; dev = (dev_t) vp->v_sdev;
if (mode_word == I_BLOCK_SPECIAL) { 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 /* Invalidate the cache unless the special is
* mounted. Assume that the root filesystem's * mounted. Assume that the root filesystem's
* is open only for fsck. * is open only for fsck.
*/ */
req_flush(vp->v_bfs_e, dev); req_flush(vp->v_bfs_e, dev);
} }
} }
/* Do any special processing on device close. */ /* Do any special processing on device close. */
(void) dev_close(dev, fp-filp); (void) dev_close(dev, fp-filp);
@ -785,14 +574,14 @@ struct filp *fp;
/* Last reader or writer is going. Tell MFS about latest /* Last reader or writer is going. Tell MFS about latest
* pipe size. * pipe size.
*/ */
truncate_vn(vp, vp->v_size); truncate_vnode(vp, vp->v_size);
} }
put_vnode(fp->filp_vno); put_vnode(fp->filp_vno);
} }
} }
/*===========================================================================* /*===========================================================================*
* close_reply * * close_reply *
*===========================================================================*/ *===========================================================================*/
@ -807,72 +596,73 @@ PUBLIC void close_reply()
*===========================================================================*/ *===========================================================================*/
PUBLIC int do_vm_open() PUBLIC int do_vm_open()
{ {
int len, r, n; int len, r, n;
endpoint_t ep; endpoint_t ep;
len = m_in.VMVO_NAME_LENGTH; len = m_in.VMVO_NAME_LENGTH;
m_out.VMV_ENDPOINT = ep = m_in.VMVO_ENDPOINT; m_out.VMV_ENDPOINT = ep = m_in.VMVO_ENDPOINT;
/* Do open() call on behalf of any process, performed by VM. */ /* Do open() call on behalf of any process, performed by VM. */
if(len < 2 || len > sizeof(user_fullpath)) { if(len < 2 || len > sizeof(user_fullpath)) {
printf("do_vm_open: strange length %d\n", len); printf("do_vm_open: strange length %d\n", len);
m_out.VMVRO_FD = EINVAL; m_out.VMVRO_FD = EINVAL;
return VM_VFS_REPLY_OPEN; return(VM_VFS_REPLY_OPEN);
} }
/* Do open on behalf of which process? */ /* Do open on behalf of which process? */
if(isokendpt(ep, &n) != OK) { if(isokendpt(ep, &n) != OK) {
printf("do_vm_open: strange endpoint %d\n", ep); printf("do_vm_open: strange endpoint %d\n", ep);
m_out.VMVRO_FD = EINVAL; m_out.VMVRO_FD = EINVAL;
return VM_VFS_REPLY_OPEN; return(VM_VFS_REPLY_OPEN);
} }
/* XXX - do open on behalf of this process */ /* XXX - do open on behalf of this process */
fp = &fproc[n]; fp = &fproc[n];
/* Get path name from VM address space. */ /* Get path name from VM address space. */
if((r=sys_safecopyfrom(VM_PROC_NR, m_in.VMVO_NAME_GRANT, 0, if((r=sys_safecopyfrom(VM_PROC_NR, m_in.VMVO_NAME_GRANT, 0,
(vir_bytes) user_fullpath, len, D)) != OK) { (vir_bytes) user_fullpath, len, D)) != OK) {
printf("do_vm_open: sys_safecopyfrom failed: %d\n", r); printf("do_vm_open: sys_safecopyfrom failed: %d\n", r);
m_out.VMVRO_FD = EPERM; m_out.VMVRO_FD = EPERM;
return VM_VFS_REPLY_OPEN; return(VM_VFS_REPLY_OPEN);
} }
/* Check if path is null-terminated. */ /* Check if path is null-terminated. */
if(user_fullpath[len-1] != '\0') { if(user_fullpath[len-1] != '\0') {
printf("do_vm_open: name (len %d) not 0-terminated\n", len); printf("do_vm_open: name (len %d) not 0-terminated\n", len);
m_out.VMVRO_FD = EINVAL; m_out.VMVRO_FD = EINVAL;
return VM_VFS_REPLY_OPEN; return(VM_VFS_REPLY_OPEN);
} }
/* Perform open(). */ /* Perform open(). */
m_out.VMVRO_FD = common_open(m_in.VMVO_FLAGS, m_in.VMVO_MODE); m_out.VMVRO_FD = common_open(m_in.VMVO_FLAGS, m_in.VMVO_MODE);
m_out.VMV_ENDPOINT = ep; m_out.VMV_ENDPOINT = ep;
/* Send open() reply. */ /* Send open() reply. */
return VM_VFS_REPLY_OPEN; return(VM_VFS_REPLY_OPEN);
} }
/*===========================================================================* /*===========================================================================*
* do_vm_close * * do_vm_close *
*===========================================================================*/ *===========================================================================*/
PUBLIC int do_vm_close() PUBLIC int do_vm_close()
{ {
int len, r, n; int len, r, n;
endpoint_t ep; 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. */ /* Do close() call on behalf of any process, performed by VM. */
m_out.VMV_ENDPOINT = ep = m_in.VMVC_ENDPOINT; m_out.VMV_ENDPOINT = ep = m_in.VMVC_ENDPOINT;
if(isokendpt(ep, &n) != OK) { if(isokendpt(ep, &n) != OK) {
printf("do_vm_close: strange endpoint %d\n", ep); printf("do_vm_close: strange endpoint %d\n", ep);
return VM_VFS_REPLY_CLOSE; return(VM_VFS_REPLY_CLOSE);
} }
/* Perform close(). */ /* Perform close(). */
r = close_fd(&fproc[n], m_in.VMVC_FD); r = close_fd(&fproc[n], m_in.VMVC_FD);
return VM_VFS_REPLY_CLOSE; return(VM_VFS_REPLY_CLOSE);
} }

View file

@ -13,6 +13,7 @@
#define c_mode m1_i3 #define c_mode m1_i3
#define c_name m1_p1 #define c_name m1_p1
#define name m3_p1 #define name m3_p1
#define flength m2_l1
#define name1 m1_p1 #define name1 m1_p1
#define name2 m1_p2 #define name2 m1_p2
#define name_length m3_i1 #define name_length m3_i1
@ -23,6 +24,8 @@
#define pathname m3_ca1 #define pathname m3_ca1
#define pid m1_i3 #define pid m1_i3
#define ENDPT m1_i1 #define ENDPT m1_i1
#define offset_lo m2_l1
#define offset_high m2_l2
#define ctl_req m4_l1 #define ctl_req m4_l1
#define driver_nr m4_l2 #define driver_nr m4_l2
#define dev_nr m4_l3 #define dev_nr m4_l3
@ -32,6 +35,7 @@
#define request m1_i2 #define request m1_i2
#define sig m1_i2 #define sig m1_i2
#define endpt1 m1_i1 #define endpt1 m1_i1
#define fs_endpt m1_p3
#define tp m2_l1 #define tp m2_l1
#define utime_actime m2_l1 #define utime_actime m2_l1
#define utime_modtime m2_l2 #define utime_modtime m2_l2

View file

@ -1,9 +1,6 @@
/* lookup() is the main routine that controls the path name lookup. It /* lookup() is the main routine that controls the path name lookup. It
* handles mountpoints and symbolic links. The actual lookup requests * handles mountpoints and symbolic links. The actual lookup requests
* are sent through the req_lookup wrapper function. * are sent through the req_lookup wrapper function.
*
* Jul 2006 (Balazs Gerofi)
*/ */
#include "fs.h" #include "fs.h"
@ -14,7 +11,6 @@
#include <minix/const.h> #include <minix/const.h>
#include <minix/endpoint.h> #include <minix/endpoint.h>
#include <unistd.h> #include <unistd.h>
#include <minix/vfsif.h> #include <minix/vfsif.h>
#include "fproc.h" #include "fproc.h"
#include "vmnt.h" #include "vmnt.h"
@ -31,47 +27,36 @@
*/ */
#define DO_POSIX_PATHNAME_RES 0 #define DO_POSIX_PATHNAME_RES 0
FORWARD _PROTOTYPE( int lookup_rel, (struct vnode *start_node, FORWARD _PROTOTYPE( int lookup, (struct vnode *dirp, int flags,
int flags, int use_realuid, node_details_t *node) ); node_details_t *node) );
/*===========================================================================* /*===========================================================================*
* lookup_rel_vp * * advance *
*===========================================================================*/ *===========================================================================*/
PUBLIC int lookup_rel_vp(start_node, flags, use_realuid, vpp) PUBLIC struct vnode *advance(dirp, flags)
struct vnode *start_node; struct vnode *dirp;
int flags; int flags;
int use_realuid;
struct vnode **vpp;
{ {
/* Resolve a pathname (in user_fullpath) starting at start_node to a vnode. */ /* Resolve a pathname (in user_fullpath) starting at dirp to a vnode. */
int r, lookup_res; int r;
struct vnode *new_vp, *vp; struct vnode *new_vp, *vp;
struct vmnt *vmp; struct vmnt *vmp;
struct node_details res; struct node_details res;
/* See if free vnode is available */ /* Get a free vnode */
if ((new_vp = get_free_vnode(__FILE__, __LINE__)) == NIL_VNODE) { if((new_vp = get_free_vnode()) == NIL_VNODE) return(NIL_VNODE);
printf("vfs:lookup_rel_vp: no free vnode available\n");
*vpp= NULL; /* Lookup vnode belonging to the file. */
return EINVAL; 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 */ /* Check whether vnode is already in use or not */
if ((vp = find_vnode(res.fs_e, res.inode_nr)) != NIL_VNODE) { if ((vp = find_vnode(res.fs_e, res.inode_nr)) != NIL_VNODE) {
vp->v_ref_count++; dup_vnode(vp);
vp->v_fs_count++; /* We got a reference from the FS */ vp->v_fs_count++; /* We got a reference from the FS */
*vpp= vp; return(vp);
return OK;
} }
/* Fill in the free vnode's fields */ /* Fill in the free vnode's fields */
@ -82,159 +67,115 @@ struct vnode **vpp;
new_vp->v_uid = res.uid; new_vp->v_uid = res.uid;
new_vp->v_gid = res.gid; new_vp->v_gid = res.gid;
new_vp->v_sdev = res.dev; new_vp->v_sdev = res.dev;
if ( (vmp = find_vmnt(new_vp->v_fs_e)) == NIL_VMNT) if( (vmp = find_vmnt(new_vp->v_fs_e)) == NIL_VMNT)
panic(__FILE__, "vfs:lookup_rel_vp: vmnt not found", NO_NUM); panic(__FILE__, "VFS advance: vmnt not found", NO_NUM);
new_vp->v_vmnt = vmp; new_vp->v_vmnt = vmp;
new_vp->v_dev = vmp->m_dev; new_vp->v_dev = vmp->m_dev;
new_vp->v_fs_count = 1; new_vp->v_fs_count = 1;
new_vp->v_ref_count = 1; new_vp->v_ref_count = 1;
*vpp= new_vp; return(new_vp);
return OK;
} }
/*===========================================================================* /*===========================================================================*
* lookup_vp * * eat_path *
*===========================================================================*/ *===========================================================================*/
PUBLIC int lookup_vp(flags, use_realuid, vpp) PUBLIC struct vnode *eat_path(flags)
int flags; int flags;
int use_realuid;
struct vnode **vpp;
{ {
/* Resolve a pathname (in user_fullpath) starting to a vnode. Call /* Resolve 'user_fullpath' to a vnode. advance does the actual work. */
* lookup_rel_vp to do the actual work.
*/
struct vnode *vp; struct vnode *vp;
if(!fp->fp_rd || !fp->fp_wd) { vp = (user_fullpath[0] == '/' ? fp->fp_rd : fp->fp_wd);
printf("VFS: lookup_vp %d: no rd/wd\n", fp->fp_endpoint); return advance(vp, flags);
return ENOENT;
}
vp= (user_fullpath[0] == '/' ? fp->fp_rd : fp->fp_wd);
return lookup_rel_vp(vp, flags, use_realuid, vpp);
} }
/*===========================================================================* /*===========================================================================*
* lookup_lastdir_rel * * last_dir *
*===========================================================================*/ *===========================================================================*/
PUBLIC int lookup_lastdir_rel(start_node, use_realuid, vpp) PUBLIC struct vnode *last_dir(void)
struct vnode *start_node;
int use_realuid;
struct vnode **vpp;
{ {
/* This function is for calls that insert or delete entries from a /* Parse a path, 'user_fullpath', as far as the last directory, fetch the vnode
* directory. The path name (implicitly taken from user_fullpath) * for the last directory into the vnode table, and return a pointer to the
* is split into to parts: the name of the directory and the * vnode. In addition, return the final component of the path in 'string'. If
* directory entry. The name of the directory is resolved to a * the last directory can't be opened, return NIL_VNODE and the reason for
* vnode. The directory entry is copied back to user_fullpath. * failure in 'err_code'. We can't parse component by component as that would
* The lookup starts at start_node. * be too expensive. Alternatively, we cut off the last component of the path,
*/ * and parse the path up to the penultimate component.
int r; */
size_t len;
char *cp;
char dir_entry[PATH_MAX+1];
len= strlen(user_fullpath); int r;
if (len == 0) size_t len;
{ char *cp;
/* Empty path, always fail */ char dir_entry[PATH_MAX+1];
return ENOENT; 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 #if !DO_POSIX_PATHNAME_RES
/* Remove trailing slashes */ /* Remove trailing slashes */
while (len > 1 && user_fullpath[len-1] == '/') while (len > 1 && user_fullpath[len-1] == '/') {
{ len--;
len--; user_fullpath[len]= '\0';
user_fullpath[len]= '\0'; }
}
#endif #endif
cp= strrchr(user_fullpath, '/'); cp = strrchr(user_fullpath, '/');
if (cp == NULL) if (cp == NULL) {
{ /* Just one entry in the current working directory */
/* Just one entry in the current working directory */ dup_vnode(vp);
dup_vnode(start_node); return(vp);
*vpp= start_node; } else if (cp[1] == '\0') {
/* Path ends in a slash. The directory entry is '.' */
return OK; strcpy(dir_entry, ".");
} } else {
else if (cp[1] == '\0') /* A path name for the directory and a directory entry */
{ strcpy(dir_entry, cp+1);
/* Path ends in a slash. The directory entry is '.' */ cp[1]= '\0';
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;
} }
vp= (user_fullpath[0] == '/' ? fp->fp_rd : fp->fp_wd); /* Remove trailing slashes */
return lookup_lastdir_rel(vp, use_realuid, vpp); 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; struct vnode *start_node;
int flags; int flags;
int use_realuid;
node_details_t *node; 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; int r, symloop;
endpoint_t fs_e; endpoint_t fs_e;
size_t path_off; size_t path_off, path_left_len;
ino_t dir_ino, root_ino; ino_t dir_ino, root_ino;
uid_t uid; uid_t uid;
gid_t gid; gid_t gid;
@ -245,102 +186,90 @@ node_details_t *node;
/* Empty (start) path? */ /* Empty (start) path? */
if (user_fullpath[0] == '\0') { if (user_fullpath[0] == '\0') {
node->inode_nr = 0; node->inode_nr = 0;
#if 0 return(ENOENT);
printf("vfs:lookup_rel: returning ENOENT\n");
#endif
return ENOENT;
} }
if(!fp->fp_rd || !fp->fp_wd) { if(!fp->fp_rd || !fp->fp_wd) {
printf("VFS: lookup_rel %d: no rd/wd\n", fp->fp_endpoint); printf("VFS: lookup_rel %d: no rd/wd\n", fp->fp_endpoint);
return ENOENT; return(ENOENT);
} }
fs_e = start_node->v_fs_e; fs_e = start_node->v_fs_e;
path_off = 0;
dir_ino = start_node->v_inode_nr; dir_ino = start_node->v_inode_nr;
/* Is the process' root directory on the same partition?, /* Is the process' root directory on the same partition?,
* if so, set the chroot directory too. */ * if so, set the chroot directory too. */
if (fp->fp_rd->v_dev == fp->fp_wd->v_dev) 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 else
root_ino = 0; root_ino = 0;
/* Set user and group ids according to the system call */ /* Set user and group ids according to the system call */
uid = (use_realuid ? fp->fp_realuid : fp->fp_effuid); uid = (call_nr == ACCESS ? fp->fp_realuid : fp->fp_effuid);
gid = (use_realuid ? fp->fp_realgid : fp->fp_effgid); 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 */ /* 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 (r != OK && r != EENTERMOUNT && r != ELEAVEMOUNT && r != ESYMLINK)
{ return(r); /* i.e., an error occured */
#if 0
printf("vfs:lookup_rel: req_lookup_s failed with %d\n", r);
#endif
return r;
}
/* While the response is related to mount control set the /* While the response is related to mount control set the
* new requests respectively */ * new requests respectively */
while (r == EENTERMOUNT || r == ELEAVEMOUNT || r == ESYMLINK) { while(r == EENTERMOUNT || r == ELEAVEMOUNT || r == ESYMLINK) {
/* Save the place in the (possibly updated) path where we have to /* Update user_fullpath to reflect what's left to be parsed. */
* continue witht henext lookup request. path_off = res.char_processed;
*/ path_left_len = strlen(&user_fullpath[path_off]);
path_off= res.char_processed; 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 */ /* Update the current value of the symloop counter */
symloop += res.symloop; symloop += res.symloop;
if (symloop > SYMLOOP_MAX) if (symloop > SYMLOOP_MAX)
{ return(ELOOP);
printf("vfs:lookup_rel: returning ELOOP\n");
return ELOOP;
}
/* Symlink encountered with absolute path */ /* Symlink encountered with absolute path */
if (r == ESYMLINK) { if (r == ESYMLINK) {
dir_vp = fp->fp_rd; dir_vp = fp->fp_rd;
} } else if (r == EENTERMOUNT) {
else if (r == EENTERMOUNT) {
/* Entering a new partition */ /* Entering a new partition */
dir_vp = 0; dir_vp = 0;
/* Start node is now the mounted partition's root node */ /* Start node is now the mounted partition's root node */
for (vmp = &vmnt[0]; vmp != &vmnt[NR_MNTS]; ++vmp) { for (vmp = &vmnt[0]; vmp != &vmnt[NR_MNTS]; ++vmp) {
if (vmp->m_dev != NO_DEV) { if (vmp->m_dev != NO_DEV) {
if(vmp->m_mounted_on && if (vmp->m_mounted_on->v_inode_nr == res.inode_nr &&
vmp->m_mounted_on->v_inode_nr == vmp->m_mounted_on->v_fs_e == res.fs_e) {
res.inode_nr &&
vmp->m_mounted_on->v_fs_e == res.fs_e) {
dir_vp = vmp->m_root_node; dir_vp = vmp->m_root_node;
if(!dir_vp) {
panic(__FILE__,
"vfs: root_node NULL", NO_NUM);
}
break; 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);
}
} if (!dir_vp) {
else { panic(__FILE__,
"VFS lookup: can't find mounted partition",
NO_NUM);
}
} else {
/* Climbing up mount */ /* Climbing up mount */
/* Find the vmnt that represents the partition on /* Find the vmnt that represents the partition on
* which we "climb up". */ * which we "climb up". */
if ((vmp = find_vmnt(res.fs_e)) == NIL_VMNT) { if ((vmp = find_vmnt(res.fs_e)) == NIL_VMNT) {
panic(__FILE__, panic(__FILE__,
"vfs:lookup_s: couldn't find vmnt during the climbup", "VFS lookup: can't find parent vmnt",NO_NUM);
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 /* Start node is the vnode on which the partition is
* mounted */ * mounted */
dir_vp = vmp->m_mounted_on; dir_vp = vmp->m_mounted_on;
@ -349,24 +278,18 @@ node_details_t *node;
/* Set the starting directories inode number and FS endpoint */ /* Set the starting directories inode number and FS endpoint */
fs_e = dir_vp->v_fs_e; fs_e = dir_vp->v_fs_e;
dir_ino = dir_vp->v_inode_nr; dir_ino = dir_vp->v_inode_nr;
/* Is the process' root directory on the same partition?, /* Is the process' root directory on the same partition?,
* if so, set the chroot directory too. */ * 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; root_ino = fp->fp_rd->v_inode_nr;
else else
root_ino = 0; root_ino = 0;
/* Issue the request */ r = req_lookup(fs_e, dir_ino, root_ino, uid, gid, flags, &res);
r = req_lookup(fs_e, path_off, dir_ino, root_ino, uid, gid, flags,
&res);
if (r != OK && r != EENTERMOUNT && r != ELEAVEMOUNT && r != ESYMLINK) if(r != OK && r != EENTERMOUNT && r != ELEAVEMOUNT && r != ESYMLINK)
{ return(r);
#if 0
printf("vfs:lookup_rel: req_lookup_s failed with %d\n", r);
#endif
return r;
}
} }
/* Fill in response fields */ /* Fill in response fields */
@ -378,5 +301,5 @@ node_details_t *node;
node->uid = res.uid; node->uid = res.uid;
node->gid = res.gid; node->gid = res.gid;
return r; return(r);
} }

View file

@ -13,9 +13,6 @@
* revive: mark a suspended process as able to run again * revive: mark a suspended process as able to run again
* unsuspend_by_endpt: revive all processes blocking on a given process * 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 * do_unpause: a signal has been sent to a process; see if it suspended
*
* Changes for VFS:
* Jul 2006 (Balazs Gerofi)
*/ */
#include "fs.h" #include "fs.h"
@ -32,14 +29,11 @@
#include "fproc.h" #include "fproc.h"
#include "param.h" #include "param.h"
#include "select.h" #include "select.h"
#include <minix/vfsif.h> #include <minix/vfsif.h>
#include "vnode.h" #include "vnode.h"
#include "vmnt.h" #include "vmnt.h"
/*===========================================================================* /*===========================================================================*
* do_pipe * * do_pipe *
*===========================================================================*/ *===========================================================================*/
@ -56,62 +50,53 @@ PUBLIC int do_pipe()
struct node_details res; struct node_details res;
/* See if a free vnode is available */ /* See if a free vnode is available */
if ( (vp = get_free_vnode(__FILE__, __LINE__)) == NIL_VNODE) { if ( (vp = get_free_vnode()) == NIL_VNODE) return(err_code);
printf("VFS: no vnode available!\n");
return err_code;
}
/* Acquire two file descriptors. */ /* Acquire two file descriptors. */
rfp = fp; 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; rfp->fp_filp[fil_des[0]] = fil_ptr0;
FD_SET(fil_des[0], &rfp->fp_filp_inuse); FD_SET(fil_des[0], &rfp->fp_filp_inuse);
fil_ptr0->filp_count = 1; fil_ptr0->filp_count = 1;
if ( (r = get_fd(0, W_BIT, &fil_des[1], &fil_ptr1)) != OK) { if ((r = get_fd(0, W_BIT, &fil_des[1], &fil_ptr1)) != OK) {
rfp->fp_filp[fil_des[0]] = NIL_FILP; rfp->fp_filp[fil_des[0]] = NIL_FILP;
FD_CLR(fil_des[0], &rfp->fp_filp_inuse); FD_CLR(fil_des[0], &rfp->fp_filp_inuse);
fil_ptr0->filp_count = 0; fil_ptr0->filp_count = 0;
return(r); return(r);
} }
rfp->fp_filp[fil_des[1]] = fil_ptr1; rfp->fp_filp[fil_des[1]] = fil_ptr1;
FD_SET(fil_des[1], &rfp->fp_filp_inuse); FD_SET(fil_des[1], &rfp->fp_filp_inuse);
fil_ptr1->filp_count = 1; fil_ptr1->filp_count = 1;
/* Send request */ /* Create a named pipe inode on PipeFS */
r = req_newnode(ROOT_FS_E, fp->fp_effuid, fp->fp_effgid, I_NAMED_PIPE, r = req_newnode(PFS_PROC_NR, fp->fp_effuid, fp->fp_effgid, I_NAMED_PIPE,
(dev_t)0, &res); (dev_t) 0, &res);
/* Handle error */
if (r != OK) { if (r != OK) {
rfp->fp_filp[fil_des[0]] = NIL_FILP; rfp->fp_filp[fil_des[0]] = NIL_FILP;
FD_CLR(fil_des[0], &rfp->fp_filp_inuse); FD_CLR(fil_des[0], &rfp->fp_filp_inuse);
fil_ptr0->filp_count = 0; fil_ptr0->filp_count = 0;
rfp->fp_filp[fil_des[1]] = NIL_FILP; rfp->fp_filp[fil_des[1]] = NIL_FILP;
FD_CLR(fil_des[1], &rfp->fp_filp_inuse); FD_CLR(fil_des[1], &rfp->fp_filp_inuse);
fil_ptr1->filp_count = 0; fil_ptr1->filp_count = 0;
return r; return(r);
} }
/* Fill in vnode */ /* Fill in vnode */
vp->v_fs_e = res.fs_e; vp->v_fs_e = res.fs_e;
vp->v_mapfs_e = res.fs_e;
vp->v_inode_nr = res.inode_nr; vp->v_inode_nr = res.inode_nr;
vp->v_mapinode_nr = res.inode_nr;
vp->v_mode = res.fmode; vp->v_mode = res.fmode;
vp->v_index = res.inode_index;
vp->v_pipe = I_PIPE; vp->v_pipe = I_PIPE;
vp->v_pipe_rd_pos= 0; vp->v_pipe_rd_pos= 0;
vp->v_pipe_wr_pos= 0; vp->v_pipe_wr_pos= 0;
vp->v_fs_count = 1; vp->v_fs_count = 1;
vp->v_mapfs_count = 1;
vp->v_ref_count = 1; vp->v_ref_count = 1;
vp->v_size = 0; vp->v_size = 0;
vp->v_vmnt = NIL_VMNT;
if ( (vmp = find_vmnt(vp->v_fs_e)) == NIL_VMNT) { vp->v_dev = NO_DEV;
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;
}
/* Fill in filp objects */ /* Fill in filp objects */
fil_ptr0->filp_vno = vp; fil_ptr0->filp_vno = vp;
@ -126,10 +111,36 @@ PUBLIC int do_pipe()
return(OK); 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 * * 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 */ register struct vnode *vp; /* the inode of the pipe */
int rw_flag; /* READING or WRITING */ int rw_flag; /* READING or WRITING */
int oflags; /* flags set by open or fcntl */ 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. * pipe and no one is reading from it, give a broken pipe error.
*/ */
off_t pos; off_t pos;
int r = OK;
if (ex64hi(position) != 0) if (ex64hi(position) != 0)
panic(__FILE__, "pipe_check: position too large in pipe", NO_NUM); panic(__FILE__, "pipe_check: position too large in pipe", NO_NUM);
pos= ex64lo(position); pos = ex64lo(position);
/* If reading, check for empty pipe. */ /* If reading, check for empty pipe. */
if (rw_flag == READING) { if (rw_flag == READING) {
if (pos >= vp->v_size) { if (pos >= vp->v_size) {
/* Process is reading from an empty pipe. */ /* Process is reading from an empty pipe. */
int r = 0;
if (find_filp(vp, W_BIT) != NIL_FILP) { if (find_filp(vp, W_BIT) != NIL_FILP) {
/* Writer exists */ /* Writer exists */
if (oflags & O_NONBLOCK) { if (oflags & O_NONBLOCK)
r = EAGAIN; r = EAGAIN;
} else { else
r = SUSPEND; r = SUSPEND;
}
/* If need be, activate sleeping writers. */ /* If need be, activate sleeping writers. */
if (susp_count > 0) if (susp_count > 0)
release(vp, WRITE, susp_count); release(vp, WRITE, susp_count);
} }
return(r); return(r);
} }
return(bytes);
return bytes;
} }
/* Process is writing to a pipe. */ /* Process is writing to a pipe. */
if (find_filp(vp, R_BIT) == NIL_FILP) { if (find_filp(vp, R_BIT) == NIL_FILP) {
/* Tell kernel to generate a SIGPIPE signal. */ /* Process is writing, but there is no reader. Tell kernel to generate
if (!notouch) { * a SIGPIPE signal. */
sys_kill(fp->fp_endpoint, SIGPIPE); if (!notouch) sys_kill(fp->fp_endpoint, SIGPIPE);
}
return(EPIPE); return(EPIPE);
} }
/* Calculate how many bytes can be written. */
if (pos + bytes > PIPE_BUF) { if (pos + bytes > PIPE_BUF) {
if (oflags & O_NONBLOCK) if (oflags & O_NONBLOCK) {
{
if (bytes <= PIPE_BUF) { if (bytes <= PIPE_BUF) {
/* Write has to be atomic */ /* Write has to be atomic */
return(EAGAIN); return(EAGAIN);
} }
/* Compute available space */ /* Compute available space */
bytes= PIPE_BUF-pos; bytes = PIPE_BUF - pos;
if (bytes > 0) { if (bytes > 0) {
/* Do a partial write. Need to wakeup reader */ /* Do a partial write. Need to wakeup reader */
@ -203,7 +213,7 @@ int notouch; /* check only */
if (bytes > PIPE_BUF) { if (bytes > PIPE_BUF) {
/* Compute available space */ /* Compute available space */
bytes= PIPE_BUF-pos; bytes = PIPE_BUF - pos;
if (bytes > 0) { if (bytes > 0) {
/* Do a partial write. Need to wakeup reader /* 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); return(SUSPEND);
} }
@ -224,9 +234,10 @@ int notouch; /* check only */
release(vp, READ, susp_count); release(vp, READ, susp_count);
/* Requested amount fits */ /* Requested amount fits */
return bytes; return(bytes);
} }
/*===========================================================================* /*===========================================================================*
* suspend * * suspend *
*===========================================================================*/ *===========================================================================*/
@ -269,14 +280,19 @@ PUBLIC void suspend(int why)
} }
} }
/*===========================================================================*
* wait_for *
*===========================================================================*/
PUBLIC void wait_for(endpoint_t who) PUBLIC void wait_for(endpoint_t who)
{ {
if(who == NONE || who == ANY) if(who == NONE || who == ANY)
panic(__FILE__,"suspend on NONE or ANY",NO_NUM); panic(__FILE__,"suspend on NONE or ANY",NO_NUM);
suspend(FP_BLOCKED_ON_OTHER); suspend(FP_BLOCKED_ON_OTHER);
fp->fp_task = who; fp->fp_task = who;
} }
/*===========================================================================* /*===========================================================================*
* pipe_suspend * * pipe_suspend *
*===========================================================================*/ *===========================================================================*/
@ -305,6 +321,7 @@ size_t size;
fp->fp_nbytes = size; fp->fp_nbytes = size;
} }
/*===========================================================================* /*===========================================================================*
* unsuspend_by_endpt * * unsuspend_by_endpt *
*===========================================================================*/ *===========================================================================*/
@ -347,10 +364,6 @@ int count; /* max number of processes to release */
register struct fproc *rp; register struct fproc *rp;
struct filp *f; 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 /* Trying to perform the call also includes SELECTing on it with that
* operation. * operation.
*/ */
@ -372,9 +385,8 @@ int count; /* max number of processes to release */
/* Search the proc table. */ /* Search the proc table. */
for (rp = &fproc[0]; rp < &fproc[NR_PROCS] && count > 0; rp++) { for (rp = &fproc[0]; rp < &fproc[NR_PROCS] && count > 0; rp++) {
if (rp->fp_pid != PID_FREE && fp_is_blocked(rp) && if (rp->fp_pid != PID_FREE && fp_is_blocked(rp) &&
rp->fp_revived == NOT_REVIVING && rp->fp_revived == NOT_REVIVING && (rp->fp_fd & BYTE) == call_nr &&
(rp->fp_fd & BYTE) == call_nr && rp->fp_filp[rp->fp_fd>>8]->filp_vno == vp) {
rp->fp_filp[rp->fp_fd>>8]->filp_vno == vp) {
revive(rp->fp_endpoint, 0); revive(rp->fp_endpoint, 0);
susp_count--; /* keep track of who is suspended */ susp_count--; /* keep track of who is suspended */
if(susp_count < 0) if(susp_count < 0)
@ -384,6 +396,7 @@ int count; /* max number of processes to release */
} }
} }
/*===========================================================================* /*===========================================================================*
* revive * * revive *
*===========================================================================*/ *===========================================================================*/
@ -399,12 +412,10 @@ int returned; /* if hanging on task, how many bytes read */
int fd_nr, proc_nr; int fd_nr, proc_nr;
struct filp *fil_ptr; struct filp *fil_ptr;
if(isokendpt(proc_nr_e, &proc_nr) != OK) if(isokendpt(proc_nr_e, &proc_nr) != OK) return;
return;
rfp = &fproc[proc_nr]; rfp = &fproc[proc_nr];
if (!fp_is_blocked(rfp) || rfp->fp_revived == REVIVING) if (!fp_is_blocked(rfp) || rfp->fp_revived == REVIVING) return;
return;
/* The 'reviving' flag only applies to pipes. Processes waiting for TTY get /* 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. * 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. */ /* Revive a process suspended on a pipe or lock. */
rfp->fp_revived = REVIVING; rfp->fp_revived = REVIVING;
reviving++; /* process was waiting on pipe or lock */ 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; rfp->fp_blocked_on = FP_BLOCKED_ON_NONE;
fd_nr= rfp->fp_fd>>8; fd_nr = rfp->fp_fd>>8;
if (returned < 0) if (returned < 0) {
{ fil_ptr = rfp->fp_filp[fd_nr];
fil_ptr= rfp->fp_filp[fd_nr];
rfp->fp_filp[fd_nr] = NIL_FILP; rfp->fp_filp[fd_nr] = NIL_FILP;
FD_CLR(fd_nr, &rfp->fp_filp_inuse); 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", panic(__FILE__, "revive: bad count in filp",
fil_ptr->filp_count); fil_ptr->filp_count);
} }
fil_ptr->filp_count= 0; fil_ptr->filp_count = 0;
put_vnode(fil_ptr->filp_vno); put_vnode(fil_ptr->filp_vno);
fil_ptr->filp_vno = NIL_VNODE; fil_ptr->filp_vno = NIL_VNODE;
reply(proc_nr_e, returned); reply(proc_nr_e, returned);
} } else
else
reply(proc_nr_e, fd_nr); reply(proc_nr_e, fd_nr);
} } else {
else {
rfp->fp_blocked_on = FP_BLOCKED_ON_NONE; 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 */ /* process blocked in open or create */
reply(proc_nr_e, rfp->fp_fd>>8); 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); reply(proc_nr_e, returned);
} } else {
else {
/* Revive a process suspended on TTY or other device. /* Revive a process suspended on TTY or other device.
* Pretend it wants only what there is. * Pretend it wants only what there is.
*/ */
@ -491,18 +495,15 @@ int proc_nr_e;
} }
rfp = &fproc[proc_nr_p]; rfp = &fproc[proc_nr_p];
if (!fp_is_blocked(rfp)) if (!fp_is_blocked(rfp)) return;
return;
blocked_on = rfp->fp_blocked_on; blocked_on = rfp->fp_blocked_on;
if (rfp->fp_revived == REVIVING) if (rfp->fp_revived == REVIVING) {
{
rfp->fp_revived = NOT_REVIVING; rfp->fp_revived = NOT_REVIVING;
reviving--; reviving--;
wasreviving = 1; wasreviving = 1;
} }
switch (blocked_on) { switch (blocked_on) {
case FP_BLOCKED_ON_PIPE:/* process trying to read or write a pipe */ case FP_BLOCKED_ON_PIPE:/* process trying to read or write a pipe */
break; break;
@ -522,13 +523,12 @@ int proc_nr_e;
return; return;
case FP_BLOCKED_ON_OTHER: /* process trying to do device I/O (e.g. tty)*/ 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. /* Process is suspended while waiting for a reopen.
* Just reply EINTR. * Just reply EINTR.
*/ */
rfp->fp_flags &= ~SUSP_REOPEN; rfp->fp_flags &= ~SUSP_REOPEN;
status= EINTR; status = EINTR;
break; break;
} }
@ -585,7 +585,7 @@ PUBLIC int select_request_pipe(struct filp *f, int *ops, int block)
int orig_ops, r = 0, err, canwrite; int orig_ops, r = 0, err, canwrite;
orig_ops = *ops; orig_ops = *ops;
if ((*ops & (SEL_RD|SEL_ERR))) { 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) 1, f->filp_pos, 1)) != SUSPEND)
r |= SEL_RD; r |= SEL_RD;
if (err < 0 && err != SUSPEND) if (err < 0 && err != SUSPEND)
@ -597,8 +597,9 @@ PUBLIC int select_request_pipe(struct filp *f, int *ops, int block)
r &= ~SEL_ERR; r &= ~SEL_ERR;
} }
} }
if ((*ops & (SEL_WR|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) 1, f->filp_pos, 1)) != SUSPEND)
r |= SEL_WR; r |= SEL_WR;
if (err < 0 && err != SUSPEND) 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; f->filp_pipe_select_ops |= orig_ops;
} }
return SEL_OK; return(SEL_OK);
} }
/*===========================================================================* /*===========================================================================*
* select_match_pipe * * select_match_pipe *
*===========================================================================*/ *===========================================================================*/

View file

@ -1,4 +1,3 @@
/* This file deals with protection in the file system. It contains the code /* This file deals with protection in the file system. It contains the code
* for four system calls that relate to protection. * for four system calls that relate to protection.
* *
@ -7,9 +6,6 @@
* do_chown: perform the CHOWN and FCHOWN system calls * do_chown: perform the CHOWN and FCHOWN system calls
* do_umask: perform the UMASK system call * do_umask: perform the UMASK system call
* do_access: perform the ACCESS system call * do_access: perform the ACCESS system call
*
* Changes for VFS:
* Jul 2006 (Balazs Gerofi)
*/ */
#include "fs.h" #include "fs.h"
@ -18,47 +14,39 @@
#include "file.h" #include "file.h"
#include "fproc.h" #include "fproc.h"
#include "param.h" #include "param.h"
#include <minix/vfsif.h> #include <minix/vfsif.h>
#include "vnode.h" #include "vnode.h"
#include "vmnt.h" #include "vmnt.h"
FORWARD _PROTOTYPE( in_group, (gid_t grp) );
/*===========================================================================* /*===========================================================================*
* do_chmod * * do_chmod *
*===========================================================================*/ *===========================================================================*/
PUBLIC int do_chmod() PUBLIC int do_chmod()
{ {
/* Perform the chmod(name, mode) and fchmod(fd, mode) system calls. */
struct filp *flp; struct filp *flp;
struct vnode *vp; struct vnode *vp;
int r; int r;
uid_t uid;
gid_t gid;
mode_t new_mode; mode_t new_mode;
if (call_nr == CHMOD) { if (call_nr == CHMOD) {
/* Perform the chmod(name, mode) system call. */ /* Temporarily open the file */
if (fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code); 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 */ } else { /* call_nr == FCHMOD */
r = lookup_vp(0 /*flags*/, 0 /*!use_realuid*/, &vp); /* File is already opened; get a pointer to vnode from filp. */
if (r != OK) return r; 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. /* 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. * 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; r = EPERM;
else else
r = read_only(vp); 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 */ /* 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; m_in.mode &= ~I_SET_GID_BIT;
/* Issue request */ if ((r = req_chmod(vp->v_fs_e, vp->v_inode_nr, m_in.mode, &new_mode)) == OK)
r = req_chmod(vp->v_fs_e, vp->v_inode_nr, m_in.mode, &new_mode); vp->v_mode = new_mode;
if (r == OK)
vp->v_mode = new_mode;
put_vnode(vp); put_vnode(vp);
return(OK);
return OK;
} }
/*===========================================================================* /*===========================================================================*
* do_chown * * do_chown *
*===========================================================================*/ *===========================================================================*/
PUBLIC int do_chown() PUBLIC int do_chown()
{ {
/* Perform the chmod(name, mode) and fchmod(fd, mode) system calls. */
int inode_nr; int inode_nr;
int fs_e; int fs_e;
struct filp *flp; struct filp *flp;
@ -98,56 +85,43 @@ PUBLIC int do_chown()
mode_t new_mode; mode_t new_mode;
if (call_nr == CHOWN) { if (call_nr == CHOWN) {
/* Perform the chmod(name, mode) system call. */ /* Temporarily open the file. */
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);
if ((vp = eat_path(PATH_NOFLAGS)) == NIL_VNODE) return(err_code);
/* Request lookup */ } else { /* call_nr == FCHOWN */
r = lookup_vp(0 /*flags*/, 0 /*!use_realuid*/, &vp); /* File is already opened; get a pointer to the vnode from filp. */
if (r != OK) return r; if (!(flp = get_filp(m_in.fd))) return(err_code);
} vp = flp->filp_vno;
else if (call_nr == FCHOWN) {
if (!(flp = get_filp(m_in.m1_i1))) return err_code;
vp= flp->filp_vno;
dup_vnode(vp); dup_vnode(vp);
} }
else panic(__FILE__, "do_chmod called with strange call_nr", call_nr);
uid= fp->fp_effuid; r = read_only(vp);
gid= fp->fp_effgid; if (r == OK) {
/* FS is R/W. Whether call is allowed depends on ownership, etc. */
r= OK; /* The super user can do anything, so check permissions only if we're
if (uid == SU_UID) { a regular user. */
/* The super user can do anything. */ if (fp->fp_effuid != SU_UID) {
} else { /* Regular users can only change groups of their own files. */
/* Regular users can only change groups of their own files. */ if (vp->v_uid != fp->fp_effuid) r = EPERM;
if (vp->v_uid != uid) if (vp->v_uid != m_in.owner) r = EPERM; /* no giving away */
r = EPERM; /* File does not belong to the caller */ if (fp->fp_effgid != m_in.group) r = EPERM;
if (vp->v_uid != m_in.owner) }
r = EPERM; /* no giving away */
if (gid != m_in.group)
r = EPERM; /* only change to the current gid */
} }
if (r == OK) if (r == OK) {
r = read_only(vp); /* Do not change uid/gid if new uid/gid is -1. */
uid = (m_in.owner == (uid_t)-1 ? vp->v_uid : m_in.owner);
if (r != OK) { gid = (m_in.group == (gid_t)-1 ? vp->v_gid : m_in.group);
put_vnode(vp); if ((r = req_chown(vp->v_fs_e, vp->v_inode_nr, uid, gid,
return r; &new_mode)) == OK) {
} vp->v_uid = uid;
vp->v_gid = gid;
/* Issue request */ vp->v_mode = new_mode;
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;
} }
put_vnode(vp); 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) if ( (m_in.mode & ~(R_OK | W_OK | X_OK)) != 0 && m_in.mode != F_OK)
return(EINVAL); return(EINVAL);
/* Temporarily open the file. */
if (fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code); 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 = forbidden(vp, m_in.mode);
r = lookup_vp(0 /*flags*/, TRUE /*use_realuid*/, &vp);
if (r != OK) return r;
r= forbidden(vp, m_in.mode, 1 /*use_realuid*/);
put_vnode(vp); put_vnode(vp);
return r; return(r);
} }
/*===========================================================================* /*===========================================================================*
* forbidden * * 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 * 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 * caller's uid in the 'fproc' table. If access is allowed, OK is returned
* if it is forbidden, EACCES 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; gid_t gid;
int r, shift, type; int r, shift, type;
if (vp->v_uid == (uid_t)-1 || vp->v_gid == (gid_t)-1) if (vp->v_uid == (uid_t) -1 || vp->v_gid == (gid_t) -1) return(EACCES);
{
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;
}
/* Isolate the relevant rwx bits from the mode. */ /* Isolate the relevant rwx bits from the mode. */
bits = vp->v_mode; bits = vp->v_mode;
if (use_realuid) uid = (call_nr == ACCESS ? fp->fp_realuid : fp->fp_effuid);
{ gid = (call_nr == ACCESS ? fp->fp_realgid : fp->fp_effgid);
uid= fp->fp_realuid;
gid= fp->fp_realgid;
}
else
{
uid= fp->fp_effuid;
gid= fp->fp_effgid;
}
if (uid == SU_UID) { if (uid == SU_UID) {
/* Grant read and write permission. Grant search permission for /* Grant read and write permission. Grant search permission for
* directories. Grant execute permission (for non-directories) if * 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 else
perm_bits = R_BIT | W_BIT; perm_bits = R_BIT | W_BIT;
} else { } else {
if (uid == vp->v_uid) shift = 6; /* owner */ if (uid == vp->v_uid) shift = 6; /* owner */
else if (gid == vp->v_gid ) shift = 3; /* group */ 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 */ else shift = 0; /* other */
perm_bits = (bits >> shift) & (R_BIT | W_BIT | X_BIT); perm_bits = (bits >> shift) & (R_BIT | W_BIT | X_BIT);
} }
/* If access desired is not a subset of what is allowed, it is refused. */ /* If access desired is not a subset of what is allowed, it is refused. */
r = OK; r = OK;
if ((perm_bits | access_desired) != perm_bits) { if ((perm_bits | access_desired) != perm_bits) r = EACCES;
r = EACCES;
}
/* Check to see if someone is trying to write on a file system that is /* Check to see if someone is trying to write on a file system that is
* mounted read-only. * 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 * * read_only *
*===========================================================================*/ *===========================================================================*/

View file

@ -51,10 +51,10 @@ _PROTOTYPE( int pm_exec, (int proc_e, char *path, vir_bytes path_len,
/* filedes.c */ /* filedes.c */
_PROTOTYPE( struct filp *find_filp, (struct vnode *vp, mode_t bits) ); _PROTOTYPE( struct filp *find_filp, (struct vnode *vp, mode_t bits) );
_PROTOTYPE( int get_fd, (int start, mode_t bits, int *k, _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_filp, (int fild) );
_PROTOTYPE( struct filp *get_filp2, (struct fproc *rfp, 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 */ /* fscall.c */
_PROTOTYPE( void nested_fs_call, (message *m) ); _PROTOTYPE( void nested_fs_call, (message *m) );
@ -65,7 +65,7 @@ _PROTOTYPE( int do_unlink, (void) );
_PROTOTYPE( int do_rename, (void) ); _PROTOTYPE( int do_rename, (void) );
_PROTOTYPE( int do_truncate, (void) ); _PROTOTYPE( int do_truncate, (void) );
_PROTOTYPE( int do_ftruncate, (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 */ /* lock.c */
_PROTOTYPE( int lock_op, (struct filp *f, int req) ); _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_fork, (int pproc, int cproc, int cpid) );
_PROTOTYPE( void pm_setgid, (int proc_e, int egid, int rgid) ); _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_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_sync, (void) );
_PROTOTYPE( int do_fsync, (void) ); _PROTOTYPE( int do_fsync, (void) );
_PROTOTYPE( void pm_reboot, (void) ); _PROTOTYPE( void pm_reboot, (void) );
@ -114,18 +115,15 @@ _PROTOTYPE( int do_vm_open, (void) );
_PROTOTYPE( int do_vm_close, (void) ); _PROTOTYPE( int do_vm_close, (void) );
/* path.c */ /* path.c */
_PROTOTYPE( int lookup_rel_vp, (struct vnode *start_node, int flags, _PROTOTYPE( struct vnode *advance, (struct vnode *dirp, int flags) );
int use_realuid, struct vnode **vpp) ); _PROTOTYPE( struct vnode *eat_path, (int flags) );
_PROTOTYPE( int lookup_vp, (int flags, int use_realuid, _PROTOTYPE( struct vnode *last_dir, (void) );
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) );
/* pipe.c */ /* pipe.c */
_PROTOTYPE( int do_pipe, (void) ); _PROTOTYPE( int do_pipe, (void) );
_PROTOTYPE( int map_vnode, (struct vnode *vp) );
_PROTOTYPE( void unpause, (int proc_nr_e) ); _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) ); int oflags, int bytes, u64_t position, int notouch) );
_PROTOTYPE( void release, (struct vnode *vp, int call_nr, int count) ); _PROTOTYPE( void release, (struct vnode *vp, int call_nr, int count) );
_PROTOTYPE( void revive, (int proc_nr, int bytes) ); _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_chmod, (void) );
_PROTOTYPE( int do_chown, (void) ); _PROTOTYPE( int do_chown, (void) );
_PROTOTYPE( int do_umask, (void) ); _PROTOTYPE( int do_umask, (void) );
_PROTOTYPE( int forbidden, (struct vnode *vp, _PROTOTYPE( int forbidden, (struct vnode *vp, mode_t access_desired) );
mode_t access_desired, int use_realuid) );
_PROTOTYPE( int read_only, (struct vnode *vp) ); _PROTOTYPE( int read_only, (struct vnode *vp) );
/* read.c */ /* 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_fstatfs, (int fs_e, int who_e, char *buf) );
_PROTOTYPE( int req_ftrunc, (endpoint_t fs_e, ino_t inode_nr, _PROTOTYPE( int req_ftrunc, (endpoint_t fs_e, ino_t inode_nr,
off_t start, off_t end) ); off_t start, off_t end) );
_PROTOTYPE( int req_getdents, (endpoint_t fs_e, ino_t inode_nr, _PROTOTYPE( int req_getdents, (endpoint_t fs_e, ino_t inode_nr, u64_t pos,
off_t pos, cp_grant_id_t gid, size_t size, off_t *pos_change) ); char *buf, size_t size, u64_t *new_pos) );
_PROTOTYPE( int req_inhibread, (endpoint_t fs_e, ino_t inode_nr) ); _PROTOTYPE( int req_inhibread, (endpoint_t fs_e, ino_t inode_nr) );
_PROTOTYPE( int req_link, (endpoint_t fs_e, ino_t link_parent, _PROTOTYPE( int req_link, (endpoint_t fs_e, ino_t link_parent,
char *lastc, ino_t linked_file) ); char *lastc, ino_t linked_file) );
_PROTOTYPE( int req_lookup, (endpoint_t fs_e, size_t path_off, _PROTOTYPE( int req_lookup, (endpoint_t fs_e, ino_t dir_ino, ino_t root_ino,
ino_t dir_ino, ino_t root_ino, _mnx_Uid_t uid, _mnx_Uid_t uid, _mnx_Gid_t gid, int flags,
_mnx_Gid_t gid, int flags, lookup_res_t *res) ); lookup_res_t *res) );
_PROTOTYPE( int req_mkdir, (endpoint_t fs_e, ino_t inode_nr, _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) ); 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, _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) ); Dev_t dev, struct node_details *res) );
_PROTOTYPE( int req_putnode, (int fs_e, ino_t inode_nr, int count) ); _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, _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, _PROTOTYPE( int req_readsuper, (endpoint_t fs_e, char *driver_name,
Dev_t dev, int readonly, int isroot, Dev_t dev, int readonly, int isroot,
struct node_details *res_nodep) ); struct node_details *res_nodep) );
_PROTOTYPE( int req_readwrite, (endpoint_t fs_e, ino_t inode_nr, _PROTOTYPE( int req_readwrite, (endpoint_t fs_e, ino_t inode_nr,
int inode_index, u64_t pos, int rw_flag, u64_t pos, int rw_flag,
endpoint_t user_e, char *user_addr, endpoint_t user_e, char *user_addr,
unsigned int num_of_bytes, u64_t *new_posp, unsigned int num_of_bytes, u64_t *new_posp,
unsigned int *cum_iop) ); unsigned int *cum_iop) );
_PROTOTYPE( int req_rename, (endpoint_t fs_e, ino_t old_dir, _PROTOTYPE( int req_rename, (endpoint_t fs_e, ino_t old_dir,
char *old_name, ino_t new_dir, char *new_name) ); char *old_name, ino_t new_dir, char *new_name) );
_PROTOTYPE( int req_rmdir, (endpoint_t fs_e, ino_t inode_nr, _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) ); _PROTOTYPE( struct vmnt *find_vmnt, (int fs_e) );
/* vnode.c */ /* 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( struct vnode *find_vnode, (int fs_e, int numb) );
_PROTOTYPE( void dup_vnode, (struct vnode *vp) ); _PROTOTYPE( void dup_vnode, (struct vnode *vp) );
_PROTOTYPE( void put_vnode, (struct vnode *vp) ); _PROTOTYPE( void put_vnode, (struct vnode *vp) );

View file

@ -8,8 +8,6 @@
* do_getdents: read entries from a directory (GETDENTS) * do_getdents: read entries from a directory (GETDENTS)
* read_write: actually do the work of READ and WRITE * read_write: actually do the work of READ and WRITE
* *
* Changes for VFS:
* Jul 2006 (Balazs Gerofi)
*/ */
#include "fs.h" #include "fs.h"
@ -22,11 +20,11 @@
#include "param.h" #include "param.h"
#include <dirent.h> #include <dirent.h>
#include <assert.h> #include <assert.h>
#include <minix/vfsif.h> #include <minix/vfsif.h>
#include "vnode.h" #include "vnode.h"
#include "vmnt.h" #include "vmnt.h"
/*===========================================================================* /*===========================================================================*
* do_read * * do_read *
*===========================================================================*/ *===========================================================================*/
@ -47,7 +45,7 @@ int rw_flag; /* READING or WRITING */
register struct vnode *vp; register struct vnode *vp;
off_t bytes_left; off_t bytes_left;
u64_t position, res_pos, new_pos; 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 op, oflags, r, chunk, usr, block_spec, char_spec;
int regular; int regular;
mode_t mode_word; mode_t mode_word;
@ -60,152 +58,104 @@ int rw_flag; /* READING or WRITING */
panic(__FILE__, panic(__FILE__,
"read_write: special read/write calls by PM no longer supported", "read_write: special read/write calls by PM no longer supported",
NO_NUM); NO_NUM);
} } else {
else { usr = who_e; /* normal case */
usr = who_e; /* normal case */
} }
/* If the file descriptor is valid, get the vnode, size and mode. */ /* If the file descriptor is valid, get the vnode, size and mode. */
if (m_in.nbytes < 0) if (m_in.nbytes < 0) return(EINVAL);
return(EINVAL); if ((f = get_filp(m_in.fd)) == NIL_FILP) return(err_code);
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 (((f->filp_mode) & (rw_flag == READING ? R_BIT : W_BIT)) == 0) {
#if 0 return(f->filp_mode == FILP_CLOSED ? EIO : EBADF);
printf("vfs:read_write: returning error\n");
#endif
return(f->filp_mode == FILP_CLOSED ? EIO : EBADF);
} }
if (m_in.nbytes == 0) 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; position = f->filp_pos;
oflags = f->filp_flags; oflags = f->filp_flags;
vp = f->filp_vno; vp = f->filp_vno;
r = OK;
cum_io = 0;
if (vp->v_pipe == I_PIPE) if (vp->v_pipe == I_PIPE) {
{ if (fp->fp_cum_io_partial != 0) {
if (fp->fp_cum_io_partial != 0)
{
panic(__FILE__, "read_write: fp_cum_io_partial not clear", 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); 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); op = (rw_flag == READING ? VFS_DEV_READ : VFS_DEV_WRITE);
mode_word = vp->v_mode & I_TYPE; mode_word = vp->v_mode & I_TYPE;
regular = mode_word == I_REGULAR; regular = mode_word == I_REGULAR;
if ((char_spec = (mode_word == I_CHAR_SPECIAL ? 1 : 0))) { if ((char_spec = (mode_word == I_CHAR_SPECIAL ? 1 : 0))) {
if (vp->v_sdev == NO_DEV) if (vp->v_sdev == NO_DEV)
panic(__FILE__,"read_write tries to read from " panic(__FILE__, "read_write tries to read from "
"character device NO_DEV", NO_NUM); "character device NO_DEV", NO_NUM);
} }
if ((block_spec = (mode_word == I_BLOCK_SPECIAL ? 1 : 0))) { if ((block_spec = (mode_word == I_BLOCK_SPECIAL ? 1 : 0))) {
if (vp->v_sdev == NO_DEV) if (vp->v_sdev == NO_DEV)
panic(__FILE__,"read_write tries to read from " panic(__FILE__, "read_write tries to read from "
" block device NO_DEV", NO_NUM); " block device NO_DEV", NO_NUM);
} }
/* Character special files. */ if (char_spec) { /* Character special files. */
if (char_spec) {
dev_t dev; dev_t dev;
int suspend_reopen; int suspend_reopen;
suspend_reopen= (f->filp_state != FS_NORMAL); suspend_reopen = (f->filp_state != FS_NORMAL);
dev = (dev_t) vp->v_sdev; dev = (dev_t) vp->v_sdev;
r = dev_io(op, dev, usr, m_in.buffer, position, m_in.nbytes, oflags, r = dev_io(op, dev, usr, m_in.buffer, position, m_in.nbytes, oflags,
suspend_reopen); suspend_reopen);
if (r >= 0) { if (r >= 0) {
cum_io = r; cum_io = r;
position = add64ul(position, r); position = add64ul(position, r);
r = OK; r = OK;
} }
} } else if (block_spec) { /* Block special files. */
/* Block special files. */ r = req_breadwrite(vp->v_bfs_e, usr, vp->v_sdev, position, m_in.nbytes,
else if (block_spec) { 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 */ /* Issue request */
r = req_breadwrite(vp->v_bfs_e, usr, vp->v_sdev, position, r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, position, rw_flag, usr,
m_in.nbytes, m_in.buffer, rw_flag, &res_pos, &res_cum_io); m_in.buffer, m_in.nbytes, &new_pos, &cum_io_incr);
position = res_pos; if (r >= 0) {
cum_io += res_cum_io; if (ex64hi(new_pos))
} panic(__FILE__, "read_write: bad new pos", NO_NUM);
/* Regular files */
else {
if (rw_flag == WRITING && block_spec == 0) {
/* Check for O_APPEND flag. */
if (oflags & O_APPEND) position = cvul64(vp->v_size);
}
position = new_pos;
/* Fill in request structure */ cum_io += cum_io_incr;
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;
}
} }
/* On write, update file size and access time. */ /* On write, update file size and access time. */
if (rw_flag == WRITING) { if (rw_flag == WRITING) {
if (regular || mode_word == I_DIRECTORY) { if (regular || mode_word == I_DIRECTORY) {
if (cmp64ul(position, vp->v_size) > 0) if (cmp64ul(position, vp->v_size) > 0) {
{ if (ex64hi(position) != 0) {
if (ex64hi(position) != 0) panic(__FILE__,
{ "read_write: file size too big ", NO_NUM);
panic(__FILE__, }
"read_write: file size too big for v_size", vp->v_size = ex64lo(position);
NO_NUM);
} }
vp->v_size = ex64lo(position); }
}
}
} }
f->filp_pos = position; f->filp_pos = position;
if (r == OK) return(cum_io);
if (r == OK) { return(r);
return cum_io;
}
return r;
} }
@ -216,7 +166,7 @@ PUBLIC int do_getdents()
{ {
/* Perform the getdents(fd, buf, size) system call. */ /* Perform the getdents(fd, buf, size) system call. */
int r; int r;
off_t pos_change; u64_t new_pos;
cp_grant_id_t gid; cp_grant_id_t gid;
register struct filp *rfilp; register struct filp *rfilp;
@ -226,78 +176,55 @@ PUBLIC int do_getdents()
} }
if (!(rfilp->filp_mode & R_BIT)) if (!(rfilp->filp_mode & R_BIT))
return EBADF; return(EBADF);
if ((rfilp->filp_vno->v_mode & I_TYPE) != I_DIRECTORY) 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) if (ex64hi(rfilp->filp_pos) != 0)
panic(__FILE__, "do_getdents: should handle large offsets", NO_NUM); 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, 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); rfilp->filp_pos, m_in.buffer, m_in.nbytes, &new_pos);
cpf_revoke(gid);
if (r > 0) if (r > 0)
rfilp->filp_pos= add64ul(rfilp->filp_pos, pos_change); rfilp->filp_pos = new_pos;
return r; return(r);
} }
/*===========================================================================* /*===========================================================================*
* rw_pipe * * 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 */ int rw_flag; /* READING or WRITING */
endpoint_t usr; endpoint_t usr_e;
int fd_nr; int fd_nr;
struct filp *f; struct filp *f;
char *buf; char *buf;
size_t req_size; size_t req_size;
{ {
int r, oflags, op, partial_pipe; int r, oflags, op, partial_pipe = 0, r2;
size_t size, cum_io, cum_io_incr; size_t size, size2, cum_io, cum_io_incr, cum_io_incr2;
struct vnode *vp; struct vnode *vp;
u64_t position, new_pos; u64_t position, new_pos, new_pos2;
oflags = f->filp_flags; oflags = f->filp_flags;
vp = f->filp_vno; vp = f->filp_vno;
position = cvu64((rw_flag == READING) ? vp->v_pipe_rd_pos : position = cvu64((rw_flag == READING) ? vp->v_pipe_rd_pos :
vp->v_pipe_wr_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 */ /* fp->fp_cum_io_partial is only nonzero when doing partial writes */
cum_io = fp->fp_cum_io_partial; cum_io = fp->fp_cum_io_partial;
op = (rw_flag == READING ? VFS_DEV_READ : VFS_DEV_WRITE); op = (rw_flag == READING ? VFS_DEV_READ : VFS_DEV_WRITE);
r = Xpipe_check(vp, rw_flag, oflags, req_size, position, 0); r = pipe_check(vp, rw_flag, oflags, req_size, position, 0);
if (r <= 0) if (r <= 0) {
{ if (r == SUSPEND) pipe_suspend(rw_flag, fd_nr, buf, req_size);
if (r == SUSPEND)
pipe_suspend(rw_flag, fd_nr, buf, req_size);
return(r); return(r);
} }
size = r; size = r;
if (r < req_size) if (size < req_size) partial_pipe = 1;
partial_pipe = 1;
else
partial_pipe = 0;
/* Truncate read request at size. */ /* Truncate read request at size. */
if((rw_flag == READING) && if((rw_flag == READING) &&
@ -309,14 +236,22 @@ size_t req_size;
pos32 = cv64ul(position); pos32 = cv64ul(position);
assert(pos32 >= 0); assert(pos32 >= 0);
assert(pos32 <= LONG_MAX); assert(pos32 <= LONG_MAX);
size2 = size;
size = vp->v_size - pos32; 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)) if (ex64hi(new_pos))
panic(__FILE__, "read_write: bad new pos", NO_NUM); panic(__FILE__, "read_write: bad new pos", NO_NUM);
@ -325,26 +260,20 @@ size_t req_size;
buf += cum_io_incr; buf += cum_io_incr;
req_size -= cum_io_incr; req_size -= cum_io_incr;
} }
/* On write, update file size and access time. */ /* On write, update file size and access time. */
if (rw_flag == WRITING) { if (rw_flag == WRITING) {
if (cmp64ul(position, vp->v_size) > 0) if (cmp64ul(position, vp->v_size) > 0) {
{ if (ex64hi(position) != 0) {
if (ex64hi(position) != 0)
{
panic(__FILE__, panic(__FILE__,
"read_write: file size too big for v_size", "read_write: file size too big for v_size",
NO_NUM); NO_NUM);
} }
vp->v_size = ex64lo(position); vp->v_size = ex64lo(position);
} }
} } else {
else {
if (cmp64ul(position, vp->v_size) >= 0) { if (cmp64ul(position, vp->v_size) >= 0) {
/* Reset pipe pointers */ /* Reset pipe pointers */
#if 0
printf("vfs:rw_pipe: resetting pipe size/positions\n");
#endif
vp->v_size = 0; vp->v_size = 0;
vp->v_pipe_rd_pos= 0; vp->v_pipe_rd_pos= 0;
vp->v_pipe_wr_pos= 0; vp->v_pipe_wr_pos= 0;
@ -371,11 +300,9 @@ size_t req_size;
} }
} }
fp->fp_cum_io_partial = 0; fp->fp_cum_io_partial = 0;
return cum_io; return(cum_io);
} }
return r; return(r);
} }

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -4,13 +4,10 @@
* The entry points into this file are * The entry points into this file are
* do_chdir: perform the CHDIR system call * do_chdir: perform the CHDIR system call
* do_chroot: perform the CHROOT system call * do_chroot: perform the CHROOT system call
* do_lstat: perform the LSTAT system call
* do_stat: perform the STAT system call * do_stat: perform the STAT system call
* do_fstat: perform the FSTAT system call * do_fstat: perform the FSTAT system call
* do_fstatfs: perform the FSTATFS 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" #include "fs.h"
@ -22,7 +19,6 @@
#include "file.h" #include "file.h"
#include "fproc.h" #include "fproc.h"
#include "param.h" #include "param.h"
#include <minix/vfsif.h> #include <minix/vfsif.h>
#include "vnode.h" #include "vnode.h"
#include "vmnt.h" #include "vmnt.h"
@ -30,6 +26,7 @@
FORWARD _PROTOTYPE( int change, (struct vnode **iip, char *name_ptr, int len)); FORWARD _PROTOTYPE( int change, (struct vnode **iip, char *name_ptr, int len));
FORWARD _PROTOTYPE( int change_into, (struct vnode **iip, struct vnode *vp)); FORWARD _PROTOTYPE( int change_into, (struct vnode **iip, struct vnode *vp));
/*===========================================================================* /*===========================================================================*
* do_fchdir * * do_fchdir *
*===========================================================================*/ *===========================================================================*/
@ -37,30 +34,13 @@ PUBLIC int do_fchdir()
{ {
/* Change directory on already-opened fd. */ /* Change directory on already-opened fd. */
struct filp *rfilp; 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? */ /* 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);
/* 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 */
return change_into(&fp->fp_wd, rfilp->filp_vno); return change_into(&fp->fp_wd, rfilp->filp_vno);
} }
/*===========================================================================* /*===========================================================================*
* do_chdir * * do_chdir *
*===========================================================================*/ *===========================================================================*/
@ -73,23 +53,11 @@ PUBLIC int do_chdir()
int r; int r;
register struct fproc *rfp; 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) { if (who_e == PM_PROC_NR) {
int slot; int slot;
if(isokendpt(m_in.endpt1, &slot) != OK) if(isokendpt(m_in.endpt1, &slot) != OK) return(EINVAL);
return EINVAL;
rfp = &fproc[slot]; 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); put_vnode(fp->fp_rd);
dup_vnode(fp->fp_rd = rfp->fp_rd); dup_vnode(fp->fp_rd = rfp->fp_rd);
put_vnode(fp->fp_wd); put_vnode(fp->fp_wd);
@ -109,10 +77,10 @@ PUBLIC int do_chdir()
} }
/* Perform the chdir(name) system call. */ /* Perform the chdir(name) system call. */
r = change(&fp->fp_wd, m_in.name, m_in.name_length); return change(&fp->fp_wd, m_in.name, m_in.name_length);
return(r);
} }
/*===========================================================================* /*===========================================================================*
* do_chroot * * do_chroot *
*===========================================================================*/ *===========================================================================*/
@ -120,18 +88,8 @@ PUBLIC int do_chroot()
{ {
/* Perform the chroot(name) system call. */ /* Perform the chroot(name) system call. */
register int r;
if (!super_user) return(EPERM); /* only su may chroot() */ if (!super_user) return(EPERM); /* only su may chroot() */
return change(&fp->fp_rd, m_in.name, m_in.name_length);
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);
} }
@ -147,25 +105,9 @@ int len; /* length of the directory name string */
struct vnode *vp; struct vnode *vp;
int r; int r;
/* Try to open the directory */
if (fetch_name(name_ptr, len, M3) != OK) return(err_code); if (fetch_name(name_ptr, len, M3) != OK) return(err_code);
if ((vp = eat_path(PATH_NOFLAGS)) == NIL_VNODE) return(err_code);
/* Request lookup */
if ((r = lookup_vp(0 /*flags*/, 0 /*!use_realuid*/, &vp)) != OK) return r;
/* 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;
}
return change_into(iip, vp); 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 **iip; /* pointer to the inode pointer for the dir */
struct vnode *vp; /* this is what the inode has to become */ 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. */ /* Everything is OK. Make the change. */
put_vnode(*iip); /* release the old directory */ put_vnode(*iip); /* release the old directory */
*iip = vp; /* acquire the new one */ *iip = vp; /* acquire the new one */
return(OK); return(OK);
} }
@ -195,19 +150,14 @@ PUBLIC int do_stat()
struct vnode *vp; 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);
if ((vp = eat_path(PATH_NOFLAGS)) == NIL_VNODE) return(err_code);
/* Request lookup */ r = req_stat(vp->v_fs_e, vp->v_inode_nr, who_e, m_in.name2, 0);
if ((r = lookup_vp(0 /*flags*/, 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);
put_vnode(vp); put_vnode(vp);
return r; return r;
} }
/*===========================================================================* /*===========================================================================*
* do_fstat * * do_fstat *
*===========================================================================*/ *===========================================================================*/
@ -218,46 +168,38 @@ PUBLIC int do_fstat()
int pipe_pos = 0; int pipe_pos = 0;
/* Is the file descriptor valid? */ /* Is the file descriptor valid? */
if ( (rfilp = get_filp(m_in.fd)) == NIL_FILP) { if ((rfilp = get_filp(m_in.fd)) == NIL_FILP) return(err_code);
return(err_code);
}
/* If we read from a pipe, send position too */ /* If we read from a pipe, send position too */
pipe_pos= 0;
if (rfilp->filp_vno->v_pipe == I_PIPE) { if (rfilp->filp_vno->v_pipe == I_PIPE) {
if (rfilp->filp_mode & R_BIT) 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", panic(__FILE__, "do_fstat: bad position in pipe",
NO_NUM); 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, 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 * * do_fstatfs *
*===========================================================================*/ *===========================================================================*/
PUBLIC int do_fstatfs() PUBLIC int do_fstatfs()
{ {
/* Perform the fstatfs(fd, buf) system call. */ /* Perform the fstatfs(fd, buf) system call. */
register struct filp *rfilp; struct filp *rfilp;
/* Is the file descriptor valid? */ /* 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); return req_fstatfs(rfilp->filp_vno->v_fs_e, who_e, m_in.buffer);
} }
/*===========================================================================* /*===========================================================================*
* do_lstat * * do_lstat *
*===========================================================================*/ *===========================================================================*/
@ -268,18 +210,11 @@ PUBLIC int do_lstat()
int r; int r;
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);
if ((vp = eat_path(PATH_RET_SYMLINK)) == NIL_VNODE) return(err_code);
/* Request lookup */ r = req_stat(vp->v_fs_e, vp->v_inode_nr, who_e, m_in.name2, 0);
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);
put_vnode(vp); put_vnode(vp);
return(r);
return r;
} }

View file

@ -10,7 +10,6 @@
#include "file.h" #include "file.h"
#include "fproc.h" #include "fproc.h"
#include "lock.h" #include "lock.h"
#include "vnode.h" #include "vnode.h"
#include "vmnt.h" #include "vmnt.h"
@ -62,7 +61,7 @@ PUBLIC _PROTOTYPE (int (*call_vec[]), (void) ) = {
no_sys, /* 43 = times */ no_sys, /* 43 = times */
no_sys, /* 44 = (prof) */ no_sys, /* 44 = (prof) */
do_slink, /* 45 = symlink */ do_slink, /* 45 = symlink */
no_sys, /* 46 = (setgid) */ no_sys, /* 46 = (setgid)*/
no_sys, /* 47 = getgid */ no_sys, /* 47 = getgid */
no_sys, /* 48 = (signal)*/ no_sys, /* 48 = (signal)*/
do_rdlink, /* 49 = readlink*/ do_rdlink, /* 49 = readlink*/
@ -75,18 +74,18 @@ PUBLIC _PROTOTYPE (int (*call_vec[]), (void) ) = {
no_sys, /* 56 = (mpx) */ no_sys, /* 56 = (mpx) */
do_fslogin, /* 57 = FS proc login */ do_fslogin, /* 57 = FS proc login */
no_sys, /* 58 = unused */ no_sys, /* 58 = unused */
no_sys, /* 59 = (execve) */ no_sys, /* 59 = (execve)*/
do_umask, /* 60 = umask */ do_umask, /* 60 = umask */
do_chroot, /* 61 = chroot */ do_chroot, /* 61 = chroot */
no_sys, /* 62 = (setsid) */ no_sys, /* 62 = (setsid)*/
no_sys, /* 63 = (getpgrp) */ no_sys, /* 63 = (getpgrp)*/
no_sys, /* 64 = (itimer) */ no_sys, /* 64 = (itimer)*/
no_sys, /* 65 = unused */ no_sys, /* 65 = unused */
no_sys, /* 66 = unused */ no_sys, /* 66 = unused */
no_sys, /* 67 = unused */ no_sys, /* 67 = unused */
no_sys, /* 68 = unused */ no_sys, /* 68 = unused */
no_sys, /* 69 = unused */ no_sys, /* 69 = unused */
no_sys, /* 70 = unused */ no_sys, /* 70 = unused */
no_sys, /* 71 = (sigaction) */ no_sys, /* 71 = (sigaction) */
no_sys, /* 72 = (sigsuspend) */ no_sys, /* 72 = (sigsuspend) */
no_sys, /* 73 = (sigpending) */ no_sys, /* 73 = (sigpending) */

View file

@ -2,7 +2,6 @@
* *
* The entry points into this file are * The entry points into this file are
* do_utime: perform the UTIME system call * do_utime: perform the UTIME system call
* do_stime: PM informs FS about STIME system call
*/ */
#include "fs.h" #include "fs.h"
@ -12,7 +11,6 @@
#include "fproc.h" #include "fproc.h"
#include "param.h" #include "param.h"
#include "vnode.h" #include "vnode.h"
#include <minix/vfsif.h> #include <minix/vfsif.h>
#include "vmnt.h" #include "vmnt.h"
@ -29,48 +27,31 @@ PUBLIC int do_utime()
struct vnode *vp; struct vnode *vp;
/* Adjust for case of 'timep' being NULL; /* 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; 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); if (fetch_name(m_in.utime_file, len, M1) != OK) return(err_code);
if ((vp = eat_path(PATH_NOFLAGS)) == NIL_VNODE) return(err_code);
/* Request lookup */
if ((r = lookup_vp(0 /*flags*/, 0 /*!use_realuid*/, &vp)) != OK) return r;
/* Fill in request fields.*/ /* Only the owner of a file or the super user can change its name. */
if (m_in.utime_length == 0) { r = OK;
actime = modtime = clock_time(); if (vp->v_uid != fp->fp_effuid && fp->fp_effuid != SU_UID) r = EPERM;
} else { if (m_in.utime_length == 0 && r != OK) r = forbidden(vp, W_BIT);
actime = m_in.utime_actime; if (read_only(vp) != OK) r = EROFS; /* Not even su can touch if R/O */
modtime = m_in.utime_modtime; 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); put_vnode(vp);
return r; return(r);
} }

View file

@ -2,7 +2,6 @@
*/ */
#include "fs.h" #include "fs.h"
#include <timers.h> #include <timers.h>
#include <minix/syslib.h> #include <minix/syslib.h>
#include <minix/com.h> #include <minix/com.h>

View file

@ -37,23 +37,16 @@ int flag; /* M3 means path may be in message */
int r, count; int r, count;
if (len > PATH_MAX) { if (len > PATH_MAX) {
#if 0
printf("VFS: fetch_name: len (%d) > %d\n", len, PATH_MAX);
util_stacktrace();
#endif
err_code = ENAMETOOLONG; err_code = ENAMETOOLONG;
return(EGENERIC); return(EGENERIC);
} }
if(len >= sizeof(user_fullpath)) { if(len >= sizeof(user_fullpath))
panic(__FILE__, "fetch_name: len too much for user_fullpath", len); panic(__FILE__, "fetch_name: len too much for user_fullpath", len);
}
/* Check name length for validity. */ /* Check name length for validity. */
if (len <= 0) { if (len <= 0) {
err_code = EINVAL; err_code = EINVAL;
printf("vfs: fetch_name: len %d?\n", len);
util_stacktrace();
return(EGENERIC); 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); FS_PROC_NR, (vir_bytes) user_fullpath, (phys_bytes) len);
} }
if(user_fullpath[len-1] != '\0') { if (user_fullpath[len - 1] != '\0') {
int i; err_code = ENAMETOOLONG;
printf("vfs: fetch_name: name not null-terminated: "); return(EGENERIC);
for(i = 0; i < len; i++) {
printf("%c", user_fullpath[i]);
}
printf("\n");
user_fullpath[len-1] = '\0';
} }
return(r); return(r);
} }
/*===========================================================================* /*===========================================================================*
* no_sys * * no_sys *
*===========================================================================*/ *===========================================================================*/
PUBLIC int no_sys() PUBLIC int no_sys()
{ {
/* Somebody has used an illegal system call number */ /* 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); return(ENOSYS);
} }
/*===========================================================================* /*===========================================================================*
* isokendpt_f * * isokendpt_f *
*===========================================================================*/ *===========================================================================*/
PUBLIC int isokendpt_f(char *file, int line, int endpoint, int *proc, int fatal) PUBLIC int isokendpt_f(char *file, int line, int endpoint, int *proc, int fatal)
{ {
int failed = 0; int failed = 0;
endpoint_t ke; endpoint_t ke;
*proc = _ENDPOINT_P(endpoint); *proc = _ENDPOINT_P(endpoint);
if(endpoint == NONE) { if(endpoint == NONE) {
printf("vfs:%s: endpoint is NONE\n", file, line, endpoint); printf("vfs:%s: endpoint is NONE\n", file, line, endpoint);
failed = 1; failed = 1;
} else if(*proc < 0 || *proc >= NR_PROCS) { } else if(*proc < 0 || *proc >= NR_PROCS) {
printf("vfs:%s:%d: proc (%d) from endpoint (%d) out of range\n", printf("vfs:%s:%d: proc (%d) from endpoint (%d) out of range\n",
file, line, *proc, endpoint); file, line, *proc, endpoint);
failed = 1; failed = 1;
} else if((ke=fproc[*proc].fp_endpoint) != endpoint) { } else if((ke=fproc[*proc].fp_endpoint) != endpoint) {
if(ke == NONE) { 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); file, line, endpoint, *proc);
assert(fproc[*proc].fp_pid == PID_FREE); assert(fproc[*proc].fp_pid == PID_FREE);
} else { } else {
printf("vfs:%s:%d: proc (%d) from endpoint (%d) doesn't match " printf("vfs:%s:%d: proc (%d) from endpoint (%d) doesn't match "
"known endpoint (%d)\n", "known endpoint (%d)\n", file, line, *proc, endpoint,
file, line, *proc, endpoint, fproc[*proc].fp_endpoint); fproc[*proc].fp_endpoint);
assert(fproc[*proc].fp_pid != PID_FREE); assert(fproc[*proc].fp_pid != PID_FREE);
} }
failed = 1; failed = 1;
} }
if(failed && fatal) if(failed && fatal)
panic(__FILE__, "isokendpt_f failed", NO_NUM); panic(__FILE__, "isokendpt_f failed", NO_NUM);
return failed ? EDEADSRCDST : OK; return(failed ? EDEADSRCDST : OK);
} }
/*===========================================================================* /*===========================================================================*
* clock_time * * clock_time *
*===========================================================================*/ *===========================================================================*/
@ -142,7 +133,7 @@ PUBLIC time_t clock_time()
clock_t uptime; clock_t uptime;
time_t boottime; time_t boottime;
r= getuptime2(&uptime, &boottime); r = getuptime2(&uptime, &boottime);
if (r != OK) if (r != OK)
panic(__FILE__,"clock_time err", r); panic(__FILE__,"clock_time err", r);

View file

@ -1,6 +1,5 @@
/* Virtual mount table related routines. /* Virtual mount table related routines.
* *
* Jul 2006 (Balazs Gerofi)
*/ */
#include "fs.h" #include "fs.h"
@ -14,24 +13,23 @@ PUBLIC struct vmnt *get_free_vmnt(short *index)
{ {
struct vmnt *vp; struct vmnt *vp;
*index = 0; *index = 0;
for (vp = &vmnt[0]; vp < &vmnt[NR_MNTS]; ++vp, ++(*index)) { for (vp = &vmnt[0]; vp < &vmnt[NR_MNTS]; ++vp, ++(*index))
if (vp->m_dev == NO_DEV) return vp; if (vp->m_dev == NO_DEV) return(vp);
}
return NIL_VMNT; return(NIL_VMNT);
} }
/*===========================================================================* /*===========================================================================*
* find_vmnt * * find_vmnt *
*===========================================================================*/ *===========================================================================*/
PUBLIC struct vmnt *find_vmnt(int fs_e) PUBLIC struct vmnt *find_vmnt(int fs_e)
{ {
struct vmnt *vp; struct vmnt *vp;
for (vp = &vmnt[0]; vp < &vmnt[NR_MNTS]; ++vp) { for (vp = &vmnt[0]; vp < &vmnt[NR_MNTS]; ++vp)
if (vp->m_fs_e == fs_e) return vp; if (vp->m_fs_e == fs_e) return(vp);
}
return NIL_VMNT; return(NIL_VMNT);
} }

View file

@ -1,4 +1,3 @@
/* This file contains the routines related to vnodes. /* This file contains the routines related to vnodes.
* The entry points are: * The entry points are:
* *
@ -7,16 +6,13 @@
* find_vnode - find a vnode according to the FS endpoint and the inode num. * find_vnode - find a vnode according to the FS endpoint and the inode num.
* dup_vnode - duplicate vnode (i.e. increase counter) * dup_vnode - duplicate vnode (i.e. increase counter)
* put_vnode - drop vnode (i.e. decrease counter) * put_vnode - drop vnode (i.e. decrease counter)
*
* Jul 2006 (Balazs Gerofi)
*/ */
#include "fs.h" #include "fs.h"
#include "vnode.h" #include "vnode.h"
#include "vmnt.h" #include "vmnt.h"
#include "fproc.h" #include "fproc.h"
#include "file.h" #include "file.h"
#include <minix/vfsif.h> #include <minix/vfsif.h>
/* Is vnode pointer reasonable? */ /* Is vnode pointer reasonable? */
@ -37,30 +33,28 @@
/*===========================================================================* /*===========================================================================*
* get_free_vnode * * get_free_vnode *
*===========================================================================*/ *===========================================================================*/
PUBLIC struct vnode *get_free_vnode(file, line) PUBLIC struct vnode *get_free_vnode()
char *file;
int line;
{ {
/* 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; struct vnode *vp;
for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; ++vp) for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; ++vp) {
if (vp->v_ref_count == 0) if (vp->v_ref_count == 0) {
{ vp->v_pipe = NO_PIPE;
vp->v_pipe= NO_PIPE; vp->v_uid = -1;
vp->v_uid= -1; vp->v_gid = -1;
vp->v_gid= -1; vp->v_sdev = NO_DEV;
vp->v_sdev= -1; vp->v_mapfs_e = 0;
vp->v_file= file; vp->v_mapinode_nr = 0;
vp->v_line= line; return(vp);
return vp;
} }
}
err_code = ENFILE; err_code = ENFILE;
return NIL_VNODE; return(NIL_VNODE);
} }
/*===========================================================================* /*===========================================================================*
* find_vnode * * find_vnode *
*===========================================================================*/ *===========================================================================*/
@ -71,10 +65,10 @@ PUBLIC struct vnode *find_vnode(int fs_e, int numb)
struct vnode *vp; struct vnode *vp;
for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; ++vp) for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; ++vp)
if (vp->v_ref_count > 0 && vp->v_inode_nr == numb if (vp->v_ref_count > 0 && vp->v_inode_nr == numb && vp->v_fs_e == fs_e)
&& vp->v_fs_e == fs_e) return vp; 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) PUBLIC void put_vnode(struct vnode *vp)
{ {
/* Decrease vnode's usage counter and decrease inode's usage counter in the /* 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); ASSERTVP(vp);
if (vp->v_ref_count > 1) if (vp->v_ref_count > 1) {
{
/* Decrease counter */ /* Decrease counter */
vp->v_ref_count--; vp->v_ref_count--;
if (vp->v_fs_count > 256) if (vp->v_fs_count > 256)
vnode_clean_refs(vp); vnode_clean_refs(vp);
return; 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); printf("put_vnode: bad v_ref_count %d\n", vp->v_ref_count);
panic(__FILE__, "put_vnode failed", NO_NUM); 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); printf("put_vnode: bad v_fs_count %d\n", vp->v_fs_count);
panic(__FILE__, "put_vnode failed", NO_NUM); panic(__FILE__, "put_vnode failed", NO_NUM);
} }
/* Send request */ /* Tell FS we don't need this inode to be open anymore. */
if (req_putnode(vp->v_fs_e, vp->v_inode_nr, vp->v_fs_count) != OK) req_putnode(vp->v_fs_e, vp->v_inode_nr, vp->v_fs_count);
printf("VFSput_vnode Warning: inode doesn't exist\n");
vp->v_fs_count= 0; /* This inode could've been mapped. If so, tell PFS to close it as well. */
vp->v_ref_count= 0; 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_pipe = NO_PIPE;
vp->v_sdev = NO_DEV; 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) PUBLIC void vnode_clean_refs(struct vnode *vp)
{ {
/* Tell the underlying FS to drop all reference but one. */ /* Tell the underlying FS to drop all reference but one. */
if (vp == NIL_VNODE) {
return;
}
if (vp->v_fs_count <= 1) if (vp == NIL_VNODE) return;
return; /* Nothing to do */ 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"); /* Drop all references except one */
vp->v_fs_count= 1; 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++; } #define REFVP(v) { vp = (v); CHECKVN(v); vp->v_ref_check++; }
#if DO_SANITYCHECKS #if DO_SANITYCHECKS

View file

@ -2,30 +2,28 @@
EXTERN struct vnode { EXTERN struct vnode {
endpoint_t v_fs_e; /* FS process' endpoint number */ 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_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. */ mode_t v_mode; /* file type, protection, etc. */
uid_t v_uid; uid_t v_uid; /* uid of inode. */
gid_t v_gid; gid_t v_gid; /* gid of inode. */
off_t v_size; /* current file size in bytes */ off_t v_size; /* current file size in bytes */
int v_ref_count; /* # times vnode used; 0 means slot is free */ int v_ref_count; /* # times vnode used; 0 means slot is free */
int v_fs_count; /* # reference at the underlying FS */ 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 */ int v_ref_check; /* for consistency checks */
#endif
char v_pipe; /* set to I_PIPE if pipe */ char v_pipe; /* set to I_PIPE if pipe */
off_t v_pipe_rd_pos; off_t v_pipe_rd_pos;
off_t v_pipe_wr_pos; off_t v_pipe_wr_pos;
endpoint_t v_bfs_e; /* endpoint number for the FS proces in case endpoint_t v_bfs_e; /* endpoint number for the FS proces in case
of a block special file */ of a block special file */
dev_t v_dev; /* device number on which the corresponding dev_t v_dev; /* device number on which the corresponding
inode resides */ inode resides */
dev_t v_sdev; /* device number for special files */ 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 */ struct vmnt *v_vmnt; /* vmnt object of the partition */
/* For debugging */
char *v_file;
int v_line;
} vnode[NR_VNODES]; } vnode[NR_VNODES];
#define NIL_VNODE (struct vnode *) 0 /* indicates absence of vnode slot */ #define NIL_VNODE (struct vnode *) 0 /* indicates absence of vnode slot */

View file

@ -13,7 +13,7 @@ OBJ= test1 test2 test3 test4 test5 test6 test7 test8 test9 \
test42 test44 test45 test42 test44 test45
BIGOBJ= test20 test24 BIGOBJ= test20 test24
ROOTOBJ= test11 test33 test43 ROOTOBJ= test11 test33 test43 test46
GCCOBJ= test45-gcc GCCOBJ= test45-gcc
all: $(OBJ) $(BIGOBJ) $(GCCOBJ) $(ROOTOBJ) all: $(OBJ) $(BIGOBJ) $(GCCOBJ) $(ROOTOBJ)
@ -93,4 +93,5 @@ test43: test43.c
test44: test44.c test44: test44.c
test45: test45.c test45.h test45: test45.c test45.h
test45-gcc: test45.c test45.h test45-gcc: test45.c test45.h
test46: test46.c

View file

@ -13,13 +13,13 @@ badones= # list of tests that failed
# Print test welcome message # Print test welcome message
clr 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 " " echo " "
# Run all the tests, keeping track of who failed. # 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 \ 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 \ 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 do
if [ -x ./test$i ] if [ -x ./test$i ]
then then

View file

@ -107,7 +107,7 @@ int main(int argc, char **argv) {
if(end-start != TIME - TIME) { if(end-start != TIME - TIME) {
snprintf(errorbuf,sizeof(errorbuf),"time spent blocking is not %d, but %ld", snprintf(errorbuf,sizeof(errorbuf),"time spent blocking is not %d, but %ld",
TIME - TIME, (long int) (end-start)); 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. */ /* Wait for read to become ready on O_WRONLY. This should fail immediately. */

View file

@ -25,7 +25,6 @@ _PROTOTYPE(void test2d, (void));
_PROTOTYPE(void test2e, (void)); _PROTOTYPE(void test2e, (void));
_PROTOTYPE(void test2f, (void)); _PROTOTYPE(void test2f, (void));
_PROTOTYPE(void test2g, (void)); _PROTOTYPE(void test2g, (void));
_PROTOTYPE(void test2h, (void));
_PROTOTYPE(void sigpip, (int s)); _PROTOTYPE(void sigpip, (int s));
_PROTOTYPE(void quit, (void)); _PROTOTYPE(void quit, (void));
_PROTOTYPE(void e, (int n)); _PROTOTYPE(void e, (int n));
@ -55,7 +54,6 @@ char *argv[];
if (m & 0020) test2e(); if (m & 0020) test2e();
if (m & 0040) test2f(); if (m & 0040) test2f();
if (m & 0100) test2g(); if (m & 0100) test2g();
if (m & 0200) test2h();
} }
subtest = 100; subtest = 100;
if (cumsig != ITERATIONS) e(101); if (cumsig != ITERATIONS) e(101);
@ -357,19 +355,6 @@ void test2g()
if (tmsbuf.tms_cstime < 0) e(11); 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) void sigpip(s)
int s; /* for ANSI */ int s; /* for ANSI */
{ {

View file

@ -16,6 +16,7 @@ PROGRAMS= ../kernel/kernel \
../servers/ds/ds \ ../servers/ds/ds \
../servers/mfs/mfs \ ../servers/mfs/mfs \
../servers/vm/vm \ ../servers/vm/vm \
../servers/pfs/pfs \
../servers/init/init ../servers/init/init
usage: usage: