- 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);
/* Change id. */
#if __minix_vmd
initgroups(pwd->pw_name, pwd->pw_gid);
#endif
setgid(pwd->pw_gid);
setuid(pwd->pw_uid);

View file

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

View file

@ -61,7 +61,7 @@
#define _POSIX_MAX_CANON 255 /* size of the canonical input queue */
#define _POSIX_MAX_INPUT 255 /* you can type 255 chars ahead */
#define _POSIX_NAME_MAX DIRSIZ /* max. file name length */
#define _POSIX_NGROUPS_MAX 0 /* supplementary group IDs are optional */
#define _POSIX_NGROUPS_MAX 8 /* max. number of supplemental groups */
#define _POSIX_OPEN_MAX 16 /* a process may have 16 files open */
#define _POSIX_PATH_MAX 255 /* a pathname may contain 255 chars */
#define _POSIX_PIPE_BUF 512 /* pipes writes of 512 bytes must be atomic */
@ -72,12 +72,13 @@
* traversed in the resolution of a pathname
* in the absence of a loop.
*/
#define _POSIX_SYMLINK_MAX 255 /* The number of bytes in a symbolic link */
/* Values actually implemented by MINIX (Tables 2-4, 2-5, 2-6, and 2-7). */
/* Some of these old names had better be defined when not POSIX. */
#define _NO_LIMIT 100 /* arbitrary number; limit not enforced */
#define NGROUPS_MAX 0 /* supplemental group IDs not available */
#define NGROUPS_MAX 8 /* max. number of supplemental groups */
#if _EM_WSIZE > 2
#define ARG_MAX 262144 /* # bytes of args + environ for exec() */
#else
@ -98,6 +99,7 @@
#define STREAM_MAX 20 /* must be the same as FOPEN_MAX in stdio.h */
#define TZNAME_MAX 3 /* maximum bytes in a time zone name is 3 */
#define SSIZE_MAX 32767 /* max defined byte count for read() */
#define SYMLINK_MAX 1024 /* # bytes in a symbolic link */
#define SYMLOOP_MAX 16 /* maximum number of symbolic links that can
* be reliably traversed in the resolution of
* a pathname in the absence of a loop.

View file

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

View file

@ -71,7 +71,8 @@
#define DS_PROC_NR 6 /* data store server */
#define MFS_PROC_NR 7 /* minix root filesystem */
#define VM_PROC_NR 8 /* memory server */
#define INIT_PROC_NR 9 /* init -- goes multiuser */
#define PFS_PROC_NR 9 /* pipe filesystem */
#define INIT_PROC_NR 10 /* init -- goes multiuser */
/* Root system process and root user process. */
#define ROOT_SYS_PROC_NR RS_PROC_NR
@ -752,6 +753,7 @@
#define PM_FORK_NB (PM_RQ_BASE + 8) /* Non-blocking fork */
#define PM_UNPAUSE (PM_RQ_BASE + 9) /* Interrupt process call */
#define PM_REBOOT (PM_RQ_BASE + 10) /* System reboot */
#define PM_SETGROUPS (PM_RQ_BASE + 11) /* Tell VFS about setgroups */
/* Replies from VFS to PM */
#define PM_SETUID_REPLY (PM_RS_BASE + 21)
@ -764,6 +766,7 @@
#define PM_FORK_NB_REPLY (PM_RS_BASE + 28)
#define PM_UNPAUSE_REPLY (PM_RS_BASE + 29)
#define PM_REBOOT_REPLY (PM_RS_BASE + 30)
#define PM_SETGROUPS_REPLY (PM_RS_BASE + 31)
/* Standard parameters for all requests and replies, except PM_REBOOT */
# define PM_PROC m1_i1 /* process */
@ -772,6 +775,11 @@
# define PM_EID m1_i2 /* effective user/group id */
# define PM_RID m1_i3 /* real user/group id */
/* Additional parameter for PM_SETGROUPS */
#define PM_GROUP_NO m1_i2 /* number of groups */
#define PM_GROUP_ADDR m1_p1 /* struct holding group data */
/* Additional parameters for PM_EXEC */
# define PM_PATH m1_p1 /* executable */
# define PM_PATH_LEN m1_i2 /* length of path including

View file

@ -108,10 +108,11 @@
#define I_BLOCK_SPECIAL 0060000 /* block special file */
#define I_DIRECTORY 0040000 /* file is a directory */
#define I_CHAR_SPECIAL 0020000 /* character special file */
#define I_NAMED_PIPE 0010000 /* named pipe (FIFO) */
#define I_NAMED_PIPE 0010000 /* named pipe (FIFO) */
#define I_SET_UID_BIT 0004000 /* set effective uid_t on exec */
#define I_SET_GID_BIT 0002000 /* set effective gid_t on exec */
#define ALL_MODES 0006777 /* all bits for user, group and others */
#define I_SET_STCKY_BIT 0001000 /* sticky bit */
#define ALL_MODES 0007777 /* all bits for user, group and others */
#define RWX_MODES 0000777 /* mode bits for RWX only */
#define R_BIT 0000004 /* Rwx protection bit */
#define W_BIT 0000002 /* rWx protection bit */

View file

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

View file

@ -1,200 +1,120 @@
#ifndef __MINIX_VFSIF_H
#define __MINIX_VFSIF_H
/* Fields of VFS/FS request messages */
#define REQ_INODE_NR m6_l1
#define REQ_CHROOT_NR m6_l2
#define REQ_DEVx m6_l2
#define REQ_GRANT2 m6_l2
#define REQ_UID m6_s1
#define REQ_GID m6_c1
#define REQ_MODE m6_s3
#define REQ_PATH m6_p1
#define REQ_PATH_LEN m6_s2
#define REQ_FLAGS m6_l3
#define REQ_DEV m6_l3
#define REQ_WHO_E m6_l3
#define REQ_GRANT m6_l3
#define REQ_USER_ADDR m6_p2
#define REQ_LENGTH m6_l3
#define REQ_SYMLOOP m6_c2
#define REQ_COUNT m6_l2
#include <sys/types.h>
#include <limits.h>
#define REQ_NEW_UID m6_s3
#define REQ_NEW_GID m6_c2
#define REQ_INODE_INDEX m6_l3
#define REQ_ACTIME m6_l2
#define REQ_MODTIME m6_l3
#define REQ_VMNT_IND m6_c2
#define REQ_SLINK_STORAGE m6_p1
#define REQ_BOOTTIME m6_l1
#define REQ_DRIVER_E m6_l2
#define REQ_READONLY m6_c1
#define REQ_ISROOT m6_c2
#define REQ_REMOUNT m6_c2
#define REQ_LINKED_FILE m6_l1
#define REQ_LINK_PARENT m6_l2
#define REQ_OLD_DIR m6_l2
#define REQ_NEW_DIR m6_l3
#define REQ_SLENGTH m6_s3
#define REQ_PIPE_POS m6_l1
#define REQ_FD_INODE_NR m2_i1
#define REQ_FD_WHO_E m2_i2
#define REQ_FD_GID m2_i2
#define REQ_FD_POS m2_i3
#define REQ_FD_NBYTES m2_l1
#define REQ_FD_SEG m2_l2
#define REQ_FD_INODE_INDEX m2_s1
#define REQ_FD_USER_ADDR m2_p1
#define REQ_FD_LENGTH m2_i2
#define REQ_FD_START m2_i2
#define REQ_FD_END m2_i3
#define REQ_FD_BDRIVER_E m2_i1
#define REQ_XFD_BDEV m2_i1
#define REQ_XFD_WHO_E m2_i2
#define REQ_XFD_GID m2_i2
#define REQ_XFD_NBYTES m2_i3
#define REQ_XFD_POS_LO m2_l1
#define REQ_XFD_POS_HI m2_l2
#define REQ_XFD_USER_ADDR m2_p1
/* #define REQ_XFD_BLOCK_SIZE m2_s1 */
#define REQ_L_GRANT m9_l1
#define REQ_L_PATH_LEN m9_s1
#define REQ_L_PATH_SIZE m9_s2
#define REQ_L_PATH_OFF m9_l2
#define REQ_L_DIR_INO m9_l3
#define REQ_L_ROOT_INO m9_l4
#define REQ_L_FLAGS m9_c1
#define REQ_L_UID m9_s3
#define REQ_L_GID m9_c2
/* For REQ_GETDENTS */
#define REQ_GDE_INODE m2_i1
#define REQ_GDE_GRANT m2_i2
#define REQ_GDE_SIZE m2_i3
#define REQ_GDE_POS m2_l1
/* For REQ_RENAME_S */
#define REQ_REN_OLD_DIR m2_l1
#define REQ_REN_NEW_DIR m2_l2
#define REQ_REN_GRANT_OLD m2_i1
#define REQ_REN_LEN_OLD m2_i2
#define REQ_REN_GRANT_NEW m2_i3
#define REQ_REN_LEN_NEW m2_s1
/* Fields of VFS/FS respons messages */
#define RES_MOUNTED m6_s1
#define RES_OFFSET m6_s2
#define RES_INODE_NR m6_l1
#define RES_MODE m6_s1
#define RES_FILE_SIZE m6_l2
#define RES_DEV m6_l3
#define RES_INODE_INDEX m6_s2
#define RES_NLINKS m6_s3
#define RES_SYMLOOP m6_c1
#define RES_SYMLOOP2 m6_c2
#define RES_UID m6_s3
#define RES_GID m6_c1
#define RES_CTIME m6_l3 /* Should be removed */
#define RES_FD_POS m2_i1
#define RES_FD_CUM_IO m2_i2
#define RES_FD_SIZE m2_i3
#define RES_XFD_POS_LO m2_l1
#define RES_XFD_POS_HI m2_l2
#define RES_XFD_CUM_IO m2_i1
#define RES_DIR m6_l1
#define RES_FILE m6_l2
#define RES_MAXSIZE m6_l3 /* Should be removed */
#define RES_BLOCKSIZE m6_s2 /* Should be removed */
/* For REQ_GETDENTS */
#define RES_GDE_POS_CHANGE m2_l1
#define RES_GDE_CUM_IO m2_i1
/* For REQ_RDLINK */
#define RES_RDL_LENGTH m6_l1
/* Request numbers */
#define REQ_GETNODE (VFS_BASE + 1) /* Should be removed */
#define REQ_PUTNODE (VFS_BASE + 2)
#define REQ_SLINK_S (VFS_BASE + 3)
#define REQ_PIPE (VFS_BASE + 4) /* Replaced with REQ_NEWNODE */
#define REQ_READ_O (VFS_BASE + 5) /* Replaced with REQ_READ_S */
#define REQ_WRITE_O (VFS_BASE + 6) /* Replaced with REQ_WRITE_S */
#define REQ_CLONE_OPCL (VFS_BASE + 7) /* Replaced with REQ_NEWNODE */
#define REQ_FTRUNC (VFS_BASE + 8)
#define REQ_CHOWN (VFS_BASE + 9)
#define REQ_CHMOD (VFS_BASE + 10)
#define REQ_ACCESS_O (VFS_BASE + 11) /* Removed */
#define REQ_MKNOD_O (VFS_BASE + 12) /* Replaced with REQ_MKNOD_S */
#define REQ_MKDIR_O (VFS_BASE + 13) /* Replaced with REQ_MKDIR_S */
#define REQ_INHIBREAD (VFS_BASE + 14)
#define REQ_STAT (VFS_BASE + 15)
#define REQ_CREATE_O (VFS_BASE + 16) /* Replaced with REQ_CREATE_S */
#define REQ_UNLINK_O (VFS_BASE + 17) /* Replaced with REQ_UNLINK_S */
#define REQ_RMDIR_O (VFS_BASE + 18) /* Replaced with REQ_RMDIR_S */
#define REQ_UTIME (VFS_BASE + 19)
#define REQ_RDLINK_SO (VFS_BASE + 20) /* Replaced with REQ_RDLINK_S */
#define REQ_FSTATFS (VFS_BASE + 21)
#define REQ_BREAD_S (VFS_BASE + 22)
#define REQ_BWRITE_S (VFS_BASE + 23)
#define REQ_UNLINK_S (VFS_BASE + 24)
#define REQ_LINK_O (VFS_BASE + 25) /* Replaced with REQ_LINK_S */
#define REQ_SLINK_O (VFS_BASE + 26) /* Replaced with REQ_SLINK_S */
#define REQ_RDLINK_O (VFS_BASE + 27) /* Replaced with REQ_RDLINK_S */
#define REQ_RENAME_O (VFS_BASE + 28) /* Replaced with REQ_RENAME_S */
#define REQ_RMDIR_S (VFS_BASE + 29)
#define REQ_MOUNTPOINT_O (VFS_BASE + 30) /* Replaced with REQ_MOUNTPOINT_S */
#define REQ_READSUPER_O (VFS_BASE + 31) /* Replaced with REQ_READSUPER_S */
#define REQ_UNMOUNT (VFS_BASE + 32)
#define REQ_TRUNC (VFS_BASE + 33) /* Should be removed */
#define REQ_SYNC (VFS_BASE + 34)
#define REQ_LOOKUP_O (VFS_BASE + 35) /* Replaced with REQ_LOOKUP_S */
#define REQ_STIME (VFS_BASE + 36) /* To be removed */
#define REQ_NEW_DRIVER (VFS_BASE + 37)
#define REQ_BREAD_O (VFS_BASE + 38) /* Replaced with REQ_BREAD_S */
#define REQ_BWRITE_O (VFS_BASE + 39) /* Replaced with REQ_BWRITE_S */
#define REQ_GETDENTS_O (VFS_BASE + 40) /* Replaced with REQ_GETDENTS */
#define REQ_FLUSH (VFS_BASE + 41)
#define REQ_READ_S (VFS_BASE + 42)
#define REQ_WRITE_S (VFS_BASE + 43)
#define REQ_MKNOD_S (VFS_BASE + 44)
#define REQ_MKDIR_S (VFS_BASE + 45)
#define REQ_CREATE_S (VFS_BASE + 46)
#define REQ_LINK_S (VFS_BASE + 47)
#define REQ_RENAME_S (VFS_BASE + 48)
#define REQ_LOOKUP_S (VFS_BASE + 49)
#define REQ_MOUNTPOINT_S (VFS_BASE + 50)
#define REQ_READSUPER_S (VFS_BASE + 51)
#define REQ_NEWNODE (VFS_BASE + 52)
#define REQ_RDLINK_S (VFS_BASE + 53)
#define REQ_GETDENTS (VFS_BASE + 54)
#define NREQS 55
/* VFS/FS request fields */
#define REQ_ACTIME m9_l2
#define REQ_COUNT m9_l2
#define REQ_DEV m9_l5
#define REQ_DEV2 m9_l1
#define REQ_DIR_INO m9_l3
#define REQ_DRIVER_E m9_l2
#define REQ_FLAGS m9_s3
#define REQ_GID m9_s1
#define REQ_GRANT m9_l2
#define REQ_GRANT2 m9_l1
#define REQ_GRANT3 m9_l3
#define REQ_INODE_NR m9_l1
#define REQ_MEM_SIZE m9_l5
#define REQ_MODE m9_s3
#define REQ_MODTIME m9_l3
#define REQ_NBYTES m9_l5
#define REQ_PATH_LEN m9_s2
#define REQ_PATH_SIZE m9_l5
#define REQ_REN_GRANT_NEW m9_l1
#define REQ_REN_GRANT_OLD m9_l2
#define REQ_REN_LEN_NEW m9_s2
#define REQ_REN_LEN_OLD m9_s1
#define REQ_REN_NEW_DIR m9_l4
#define REQ_REN_OLD_DIR m9_l3
#define REQ_ROOT_INO m9_l4
#define REQ_SEEK_POS_HI m9_l3
#define REQ_SEEK_POS_LO m9_l4
#define REQ_TRC_END_HI m9_l4
#define REQ_TRC_END_LO m9_l5
#define REQ_TRC_START_HI m9_l2
#define REQ_TRC_START_LO m9_l3
#define REQ_UCRED_SIZE m9_s4
#define REQ_UID m9_s4
/* VFS/FS reply fields */
#define RES_DEV m9_l4
#define RES_GID m9_s1
#define RES_INODE_NR m9_l1
#define RES_FILE_SIZE_HI m9_l2
#define RES_FILE_SIZE_LO m9_l3
#define RES_MODE m9_s2
#define RES_NBYTES m9_l5
#define RES_OFFSET m9_s2
#define RES_SEEK_POS_HI m9_l3
#define RES_SEEK_POS_LO m9_l4
#define RES_SYMLOOP m9_s3
#define RES_UID m9_s4
/* VFS/FS flags */
#define REQ_RDONLY 001
#define REQ_ISROOT 002
#define PATH_NOFLAGS 000
#define PATH_RET_SYMLINK 001 /* Return a symlink object (i.e.
* do not continue with the contents
* of the symlink if it is the last
* component in a path). */
#define PATH_GET_UCRED 002 /* Request provides a grant ID in m9_l1
* and struct ucred size in m9_s4 (as
* opposed to a REQ_UID). */
/* VFS/FS error messages */
#define EENTERMOUNT (-301)
#define ELEAVEMOUNT (-302)
#define ESYMLINK (-303)
/* REQ_L_FLAGS */
#define PATH_RET_SYMLINK 1 /* Return a symlink object (i.e.
* do not continue with the contents
* of the symlink if it is the last
* component in a path).
*/
/* VFS/FS types */
/* User credential structure */
typedef struct {
uid_t vu_uid;
gid_t vu_gid;
int vu_ngroups;
gid_t vu_sgroups[NGROUPS_MAX];
} vfs_ucred_t;
/* Request numbers */
#define REQ_GETNODE (VFS_BASE + 1) /* Should be removed */
#define REQ_PUTNODE (VFS_BASE + 2)
#define REQ_SLINK (VFS_BASE + 3)
#define REQ_FTRUNC (VFS_BASE + 4)
#define REQ_CHOWN (VFS_BASE + 5)
#define REQ_CHMOD (VFS_BASE + 6)
#define REQ_INHIBREAD (VFS_BASE + 7)
#define REQ_STAT (VFS_BASE + 8)
#define REQ_UTIME (VFS_BASE + 9)
#define REQ_FSTATFS (VFS_BASE + 10)
#define REQ_BREAD (VFS_BASE + 11)
#define REQ_BWRITE (VFS_BASE + 12)
#define REQ_UNLINK (VFS_BASE + 13)
#define REQ_RMDIR (VFS_BASE + 14)
#define REQ_UNMOUNT (VFS_BASE + 15)
#define REQ_SYNC (VFS_BASE + 16)
#define REQ_NEW_DRIVER (VFS_BASE + 17)
#define REQ_FLUSH (VFS_BASE + 18)
#define REQ_READ (VFS_BASE + 19)
#define REQ_WRITE (VFS_BASE + 20)
#define REQ_MKNOD (VFS_BASE + 21)
#define REQ_MKDIR (VFS_BASE + 22)
#define REQ_CREATE (VFS_BASE + 23)
#define REQ_LINK (VFS_BASE + 24)
#define REQ_RENAME (VFS_BASE + 25)
#define REQ_LOOKUP (VFS_BASE + 26)
#define REQ_MOUNTPOINT (VFS_BASE + 27)
#define REQ_READSUPER (VFS_BASE + 28)
#define REQ_NEWNODE (VFS_BASE + 29)
#define REQ_RDLINK (VFS_BASE + 30)
#define REQ_GETDENTS (VFS_BASE + 31)
#define NREQS 32
#endif

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -2,52 +2,17 @@
setgroups.c
*/
#include <errno.h>
#include <lib.h>
#include <unistd.h>
#include <string.h>
#include <grp.h>
int setgroups(int ngroups, const gid_t *gidset)
{
if(ngroups > 1) {
/* Supplementary groups not implemented */
errno= EINVAL;
return -1;
}
message m;
if(ngroups == 1)
return setgid(gidset[0]);
m.m1_p1 = gidset;
m.m1_i1 = ngroups;
return 0;
return(_syscall(MM, SETGROUPS, &m));
}
int initgroups(const char *name, gid_t basegid)
{
struct group *gr;
int r, found = 0;
if((r = setgid(basegid)) < 0)
return r;
setgrent();
while (!found && (gr = getgrent()) != NULL) {
char **mem;
for(mem = gr->gr_mem; mem && *mem; mem++) {
if(!strcmp(name, *mem)) {
found = 1;
break;
}
}
}
endgrent();
/* Because supplemental groups aren't implemented, this call
* should fail if the user is in any supplemental groups.
*/
if(found) {
errno = EINVAL;
return -1;
}
return 0;
}

View file

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

View file

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

View file

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

View file

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

View file

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

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
* buffer cache to pick up*/
/*===========================================================================*
* get_block *
*===========================================================================*/
@ -103,7 +104,7 @@ register struct buf *bp; /* buffer pointer */
if (r != block_size) {
if (r >= 0) r = END_OF_FILE;
if (r != END_OF_FILE)
printf("ISO9660FS(%d) I/O error on device %d/%d, block %ld\n",
printf("ISOFS(%d) I/O error on device %d/%d, block %ld\n",
SELF_E, (fs_dev>>MAJOR)&BYTE, (fs_dev>>MINOR)&BYTE,
bp->b_blocknr);

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

View file

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

View file

@ -6,125 +6,87 @@
#include "buf.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 *
*===========================================================================*/
PUBLIC int fs_putnode()
{
/* Find the inode specified by the request message and decrease its counter.
*/
/* Find the inode specified by the request message and decrease its counter. */
int count;
struct dir_record *dir = (void *)0;
struct dir_record *dir = NULL;
/* if (fs_m_in.REQ_INODE_INDEX >= 0 && */
/* fs_m_in.REQ_INODE_INDEX <= NR_DIR_RECORDS && */
/* ID_DIR_RECORD((dir_records + fs_m_in.REQ_INODE_INDEX)) == fs_m_in.REQ_INODE_NR) { */
/* dir = &dir_records[fs_m_in.REQ_INODE_INDEX]; */
/* /\* In this case the dir record by the dir record table *\/ */
/* } else { */
dir = get_dir_record(fs_m_in.REQ_INODE_NR);
/* Get dir record increased the counter. We must decrease it releasing
* it */
release_dir_record(dir);
if (dir == (void *)0) {
panic(__FILE__, "fs_putnode failed", NO_NUM);
}
count= fs_m_in.REQ_COUNT; /* I will check that the values of the count
* are the same */
count = fs_m_in.REQ_COUNT;
if (count <= 0) {
printf("put_inode: bad value for count: %d\n", count);
panic(__FILE__, "fs_putnode failed", NO_NUM);
return EINVAL;
}
if (count <= 0) return(EINVAL);
if (count > dir->d_count) {
printf("put_inode: count too high: %d > %d\n", count, dir->d_count);
panic(__FILE__, "fs_putnode failed", NO_NUM);
return EINVAL;
printf("put_inode: count too high: %d > %d\n", count, dir->d_count);
return(EINVAL);
}
if (dir->d_count > 1)
dir->d_count = dir->d_count - count + 1; /* If the dir record should be released this
operation will bring the counter to 1.
The next function will further decreases it
releasing it completely. */
dir->d_count = dir->d_count - count + 1;/*Keep at least one reference*/
release_dir_record(dir); /* I finally release it */
release_dir_record(dir); /* Actual inode release, might be last reference */
return OK;
return(OK);
}
/* Release a dir record (decrement the counter) */
/*===========================================================================*
* release_dir_record *
*===========================================================================*/
PUBLIC int release_dir_record(dir)
register struct dir_record *dir;
struct dir_record *dir;
{
/* Release a dir record (decrement the counter) */
if (dir == NULL)
return EINVAL;
return(EINVAL);
if (--dir->d_count == 0) {
if (dir->ext_attr != NULL)
dir->ext_attr->count = 0;
dir->ext_attr = NULL;
dir->d_mountpoint = FALSE;
/* This if checks we remove the good dir record and not another one
* associated to the same id.*/
/* if (dir->id != NULL && dir->id->h_dir_record == dir) */
/* dir->id->h_dir_record = NULL; */
if (dir->ext_attr != NULL)
dir->ext_attr->count = 0;
dir->ext_attr = NULL;
dir->d_mountpoint = FALSE;
dir->d_prior = NULL;
if (dir->d_next != NULL)
release_dir_record(dir);
dir->d_next = NULL;
dir->d_prior = NULL;
if (dir->d_next != NULL)
release_dir_record(dir);
dir->d_next = NULL;
}
return OK;
return(OK);
}
/* Get a free dir record */
/*===========================================================================*
* get_free_dir_record *
*===========================================================================*/
PUBLIC struct dir_record *get_free_dir_record(void)
{
/* Get a free dir record */
struct dir_record *dir;
for(dir = dir_records;dir<&dir_records[NR_ATTR_RECS]; dir++) {
if (dir->d_count == 0) { /* The record is free */
dir->d_count = 1; /* Set count to 1 */
dir->ext_attr = NULL;
return dir;
}
for(dir = dir_records; dir < &dir_records[NR_ATTR_RECS]; dir++) {
if (dir->d_count == 0) { /* The record is free */
dir->d_count = 1; /* Set count to 1 */
dir->ext_attr = NULL;
return(dir);
}
}
return NULL;
return(NULL);
}
/* This function is a wrapper. It calls dir_record_by_id */
/*===========================================================================*
* get_dir_record *
*===========================================================================*/
PUBLIC struct dir_record *get_dir_record(id_dir_record)
ino_t id_dir_record;
ino_t id_dir_record;
{
struct dir_record *dir = NULL;
u32_t address;
@ -132,43 +94,51 @@ PUBLIC struct dir_record *get_dir_record(id_dir_record)
/* Search through the cache if the inode is still present */
for(i = 0; i < NR_DIR_RECORDS && dir == NULL; ++i) {
if (dir_records[i].d_ino_nr == id_dir_record && dir_records[i].d_count > 0) {
dir = dir_records + i;
dir->d_count++;
}
if (dir_records[i].d_ino_nr == id_dir_record
&& dir_records[i].d_count > 0) {
dir = dir_records + i;
dir->d_count++;
}
}
if (dir == NULL) {
address = (u32_t)id_dir_record;
dir = load_dir_record_from_disk(address);
address = (u32_t)id_dir_record;
dir = load_dir_record_from_disk(address);
}
if (dir == NULL)
return NULL;
else
return dir;
if (dir == NULL) return(NULL);
return(dir);
}
/* Get a free extended attribute structure in a similar way than the dir
* record */
/*===========================================================================*
* get_free_ext_attr *
*===========================================================================*/
PUBLIC struct ext_attr_rec *get_free_ext_attr(void) {
/* Get a free extended attribute structure */
struct ext_attr_rec *dir;
for(dir = ext_attr_recs;dir<&ext_attr_recs[NR_ATTR_RECS]; dir++) {
if (dir->count == 0) { /* The record is free */
dir->count = 1;
return dir;
}
for(dir = ext_attr_recs; dir < &ext_attr_recs[NR_ATTR_RECS]; dir++) {
if (dir->count == 0) { /* The record is free */
dir->count = 1;
return(dir);
}
}
return NULL;
return(NULL);
}
/* Fill an extent structure from the data read on the device */
/*===========================================================================*
* create_ext_attr *
*===========================================================================*/
PUBLIC int create_ext_attr(struct ext_attr_rec *ext,char *buffer)
{
if (ext == NULL) return EINVAL;
/* Fill an extent structure from the data read on the device */
if (ext == NULL) return(EINVAL);
/* In input we have a stream of bytes that are physically read from the
* device. This stream of data is copied in the data structure. */
* device. This stream of data is copied to the data structure. */
memcpy(&ext->own_id,buffer,sizeof(u32_t));
memcpy(&ext->group_id,buffer + 4,sizeof(u32_t));
memcpy(&ext->permissions,buffer + 8,sizeof(u16_t));
@ -184,21 +154,25 @@ PUBLIC int create_ext_attr(struct ext_attr_rec *ext,char *buffer)
memcpy(&ext->ext_attr_rec_ver,buffer + 180,sizeof(u8_t));
memcpy(&ext->len_esc_seq,buffer + 181,sizeof(u8_t));
return OK;
return(OK);
}
/*===========================================================================*
* create_ext_attr *
*===========================================================================*/
PUBLIC int create_dir_record(dir,buffer,address)
struct dir_record *dir;
char *buffer;
u32_t address;
{
/* Fills a dir record structure from the data read on the device */
/* If the flag assign id is active it will return the id associated;
* otherwise it will return OK. */
PUBLIC int create_dir_record(dir,buffer,address)
struct dir_record *dir;
char *buffer;
u32_t address;
{
short size;
size = buffer[0];
if (dir == NULL) return EINVAL;
if (dir == NULL) return(EINVAL);
/* The data structure dir record is filled with the stream of data
* that is read. */
@ -219,11 +193,11 @@ PUBLIC int create_dir_record(dir,buffer,address)
/* set memory attrs */
if ((dir->file_flags & D_TYPE) == D_DIRECTORY)
dir->d_mode = I_DIRECTORY;
dir->d_mode = I_DIRECTORY;
else
dir->d_mode = I_REGULAR;
dir->d_mode = I_REGULAR;
/* I set the rights to read only ones. Equals for all the users */
/* Set permission to read only. Equal for all users. */
dir->d_mode |= R_BIT | X_BIT;
dir->d_mode |= R_BIT << 3 | X_BIT << 3;
dir->d_mode |= R_BIT << 6 | X_BIT << 6;
@ -235,20 +209,21 @@ PUBLIC int create_dir_record(dir,buffer,address)
/* Set physical address of the dir record */
dir->d_phy_addr = address;
dir->d_ino_nr = (ino_t)address; /* u32_t e ino_t are the same datatype so
dir->d_ino_nr = (ino_t) address; /* u32_t e ino_t are the same datatype so
* the cast is safe */
/* if (assign_id == ASSIGN_ID) { */
/* assign_id_to_dir_record(dir); */
/* return ID_DIR_RECORD(dir->id); */
/* } else */
return OK;
return(OK);
}
/*===========================================================================*
* load_dir_record_from_disk *
*===========================================================================*/
PUBLIC struct dir_record *load_dir_record_from_disk(address)
u32_t address;
{
/* This function load a particular dir record from a specific address
* on the device */
PUBLIC struct dir_record *load_dir_record_from_disk(address)
u32_t address;
{
int block_nr, offset, block_size, new_pos;
struct buf *bp;
struct dir_record *dir, *dir_next, *dir_parent, *dir_tmp;
@ -262,57 +237,60 @@ PUBLIC struct dir_record *load_dir_record_from_disk(address)
bp = get_block(block_nr); /* Read the block from the device */
if (bp == NIL_BUF)
return NULL;
return(NULL);
dir = get_free_dir_record(); /* Get a free record */
if (dir == NULL)
return NULL;
return(NULL);
/* Fullfill the dir record with the data read from the device */
/* Fill the dir record with the data read from the device */
create_dir_record(dir,bp->b_data + offset, address);
/* In case the file is composed of more file sections I load also the next in the structure */
/* In case the file is composed of more file sections, load also the
* next section into the structure */
new_pos = offset + dir->length;
dir_parent = dir;
new_address = address + dir->length;
while (new_pos < block_size) {
dir_next = get_free_dir_record();
create_dir_record(dir_next, bp->b_data + new_pos, new_address);
if (dir_next->length > 0) {
strncpy(name,dir_next->file_id,dir_next->length_file_id);
name[dir_next->length_file_id] = '\0';
strncpy(old_name,dir_parent->file_id,dir_parent->length_file_id);
old_name[dir_parent->length_file_id] = '\0';
dir_next = get_free_dir_record();
create_dir_record(dir_next, bp->b_data + new_pos, new_address);
if (dir_next->length > 0) {
strncpy(name,dir_next->file_id,dir_next->length_file_id);
name[dir_next->length_file_id] = '\0';
strncpy(old_name, dir_parent->file_id,
dir_parent->length_file_id);
old_name[dir_parent->length_file_id] = '\0';
if (strcmp(name,old_name) == 0) {
dir_parent->d_next = dir_next;
dir_next->d_prior = dir_parent;
if (strcmp(name, old_name) == 0) {
dir_parent->d_next = dir_next;
dir_next->d_prior = dir_parent;
/* Link the dir records */
dir_tmp = dir_next;
size = dir_tmp->data_length_l;
/* Link the dir records */
dir_tmp = dir_next;
size = dir_tmp->data_length_l;
/* Update the file size */
while (dir_tmp->d_prior != NULL) {
dir_tmp = dir_tmp->d_prior;
size += dir_tmp->data_length_l;
dir_tmp->d_file_size = size;
/* Update the file size */
while (dir_tmp->d_prior != NULL) {
dir_tmp = dir_tmp->d_prior;
size += dir_tmp->data_length_l;
dir_tmp->d_file_size = size;
}
new_pos += dir_parent->length;
new_address += dir_next->length;
dir_parent = dir_next;
} else { /* This is another inode. */
release_dir_record(dir_next);
new_pos = block_size;
}
} else { /* record not valid */
release_dir_record(dir_next);
new_pos = block_size; /* Exit from the while */
}
new_pos += dir_parent->length;
new_address += dir_next->length;
dir_parent = dir_next;
} else { /* This is another inode. */
release_dir_record(dir_next);
new_pos = block_size;
}
} else { /* record not valid */
release_dir_record(dir_next);
new_pos = block_size; /* Exit from the while */
}
}
put_block(bp); /* Release the block read. */
return dir;
return(dir);
}

View file

@ -25,44 +25,43 @@ PUBLIC int main(void) {
fs_m_in.m_type = FS_READY;
if (send(FS_PROC_NR, &fs_m_in) != OK) {
printf("ISO9660FS(%d): Error sending login to VFS\n", SELF_E);
printf("ISOFS (%d): Error sending login to VFS\n", SELF_E);
return -1;
}
for (;;) {
/* Wait for request message. */
get_work(&fs_m_in);
error = OK;
/* Wait for request message. */
get_work(&fs_m_in);
error = OK;
caller_uid = -1; /* To trap errors */
caller_gid = -1;
caller_uid = -1; /* To trap errors */
caller_gid = -1;
who_e = fs_m_in.m_source; /* source of the request */
who_e = fs_m_in.m_source; /* source of the request */
if (who_e != FS_PROC_NR) { /* If the message is not for us just
* continue */
continue;
}
if (who_e != FS_PROC_NR) { /* If the message is not for us just
* continue */
continue;
}
req_nr = fs_m_in.m_type;
req_nr = fs_m_in.m_type;
if (req_nr < VFS_BASE) {
fs_m_in.m_type += VFS_BASE;
req_nr = fs_m_in.m_type;
}
if (req_nr < VFS_BASE) {
fs_m_in.m_type += VFS_BASE;
req_nr = fs_m_in.m_type;
}
ind= req_nr-VFS_BASE;
ind = req_nr-VFS_BASE;
if (ind < 0 || ind >= NREQS) {
error = EINVAL;
}
else
error = (*fs_call_vec[ind])(); /* Process the request calling
* the appropriate function. */
if (ind < 0 || ind >= NREQS) {
error = EINVAL;
} else
error = (*fs_call_vec[ind])(); /* Process the request calling
* the appropriate function. */
fs_m_out.m_type = error;
reply(who_e, &fs_m_out); /* returns the response to VFS */
fs_m_out.m_type = error;
reply(who_e, &fs_m_out); /* returns the response to VFS */
}
}
@ -90,7 +89,7 @@ message *m_in; /* pointer to message */
{
int s; /* receive status */
if (OK != (s = receive(ANY, m_in))) /* wait for message */
panic("I9660FS","receive failed", s);
panic("ISOFS","receive failed", s);
}
/*===========================================================================*
@ -101,5 +100,5 @@ int who;
message *m_out; /* report result */
{
if (OK != send(who, m_out)) /* send the message */
printf("I9660FS(%d) was unable to send reply\n", SELF_E);
printf("ISOFS(%d) was unable to send reply\n", SELF_E);
}

View file

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

View file

@ -3,112 +3,76 @@
#include <minix/com.h>
#include <minix/vfsif.h>
#include <minix/ds.h>
#include "const.h"
#include "glo.h"
/* Function of mounting and unmounting for ISO9660 */
/* Reads the super inode. This function is requested at the mounting of the
* filesystem. */
/*===========================================================================*
* fs_readsuper *
*===========================================================================*/
PUBLIC int fs_readsuper() {
int r = OK;
fs_dev = fs_m_in.REQ_DEV;
driver_endpoints[(fs_dev >> MAJOR) & BYTE].driver_e = fs_m_in.REQ_DRIVER_E;
vfs_slink_storage = fs_m_in.REQ_SLINK_STORAGE;
r = read_vds(&v_pri, fs_dev); /* This function reads the super block on the
* device and save it in v_pri */
if (r != OK) return(r);
/* Return some root inode properties */
fs_m_out.RES_INODE_NR = ID_DIR_RECORD(v_pri.dir_rec_root);
fs_m_out.RES_MODE = I_DIRECTORY;
fs_m_out.RES_FILE_SIZE = v_pri.dir_rec_root->d_file_size;
/* and some partition properties */
fs_m_out.RES_MAXSIZE = v_pri.volume_space_size_l; /* Volume space */
fs_m_out.RES_BLOCKSIZE = v_pri.logical_block_size_l; /* block size */
return r;
}
/*===========================================================================*
* fs_readsuper_s *
*===========================================================================*/
PUBLIC int fs_readsuper_s() {
cp_grant_id_t label_gid;
size_t label_len;
int r = OK;
unsigned long tasknr;
endpoint_t driver_e;
int readonly, isroot;
fs_dev = fs_m_in.REQ_DEV;
fs_dev = fs_m_in.REQ_DEV;
label_gid = fs_m_in.REQ_GRANT;
label_len = fs_m_in.REQ_PATH_LEN;
readonly = 1; /* Always mount devices read only. */
isroot = (fs_m_in.REQ_FLAGS & REQ_ISROOT) ? 1 : 0;
label_gid= fs_m_in.REQ_GRANT2;
label_len= fs_m_in.REQ_PATH_LEN;
if (label_len > sizeof(fs_dev_label))
return(EINVAL);
if (label_len > sizeof(fs_dev_label)) {
printf("iso9660fs:fs_readsuper: label too long\n");
return EINVAL;
}
r= sys_safecopyfrom(fs_m_in.m_source, label_gid, 0, (vir_bytes)fs_dev_label,
label_len, D);
r = sys_safecopyfrom(fs_m_in.m_source, label_gid, 0, (vir_bytes)fs_dev_label,
label_len, D);
if (r != OK) {
printf("iso9660fs: fs_readsuper: safecopyfrom failed: %d\n", r);
return EINVAL;
printf("ISOFS %s:%d safecopyfrom failed: %d\n", __FILE__, __LINE__, r);
return(EINVAL);
}
r= ds_retrieve_u32(fs_dev_label, &tasknr);
r = ds_retrieve_u32(fs_dev_label, &tasknr);
if (r != OK) {
printf("mfs:fs_readsuper: ds_retrieve_u32 failed for '%s': %d\n",
fs_dev_label, r);
return EINVAL;
printf("ISOFS %s:%d ds_retrieve_u32 failed for '%s': %d\n",
__FILE__, __LINE__, fs_dev_label, r);
return(EINVAL);
}
driver_e= tasknr;
driver_e = tasknr;
/* Map the driver endpoint for this major */
driver_endpoints[(fs_dev >> MAJOR) & BYTE].driver_e = driver_e;
/* Open the device the file system lives on */
if (dev_open(driver_e, fs_dev, driver_e,
fs_m_in.REQ_READONLY ? R_BIT : (R_BIT|W_BIT)) != OK) {
readonly ? R_BIT : (R_BIT|W_BIT)) != OK) {
return(EINVAL);
}
r = read_vds(&v_pri, fs_dev); /* This function reads the super block on the
* device and save it in v_pri */
/* Read the superblock */
r = read_vds(&v_pri, fs_dev);
if (r != OK)
return(r);
return(r);
/* Return some root inode properties */
fs_m_out.RES_INODE_NR = ID_DIR_RECORD(v_pri.dir_rec_root);
fs_m_out.RES_MODE = v_pri.dir_rec_root->d_mode;
fs_m_out.RES_FILE_SIZE = v_pri.dir_rec_root->d_file_size;
fs_m_out.RES_UID = 0; /* root */
fs_m_out.RES_GID = 0; /* operator */
fs_m_out.RES_FILE_SIZE_LO = v_pri.dir_rec_root->d_file_size;
fs_m_out.RES_UID = SYS_UID; /* Always root */
fs_m_out.RES_GID = SYS_GID; /* operator */
/* and some partition properties */
fs_m_out.RES_MAXSIZE = v_pri.volume_space_size_l; /* Volume space */
fs_m_out.RES_BLOCKSIZE = v_pri.logical_block_size_l; /* block size */
return r;
return(r);
}
/*===========================================================================*
* fs_mountpoint_s *
* fs_mountpoint *
*===========================================================================*/
PUBLIC int fs_mountpoint_s() {
PUBLIC int fs_mountpoint() {
/* This function looks up the mount point, it checks the condition whether
* the partition can be mounted on the inode or not.
*/
@ -118,34 +82,31 @@ PUBLIC int fs_mountpoint_s() {
mode_t bits;
/* Temporarily open the file. */
if ((rip = get_dir_record(fs_m_in.REQ_INODE_NR)) == NULL) {
printf("ISO9660FS(%d) get_inode by fs_mountpoint() failed\n", SELF_E);
return(EINVAL);
}
if ((rip = get_dir_record(fs_m_in.REQ_INODE_NR)) == NULL)
return(EINVAL);
if (rip->d_mountpoint)
r= EBUSY;
r = EBUSY;
/* If the inode is not a dir returns error */
if ((rip->d_mode & I_TYPE) != I_DIRECTORY)
r = ENOTDIR;
r = ENOTDIR;
release_dir_record(rip);
if (r == OK)
rip->d_mountpoint = TRUE;
return r;
return(r);
}
/* Unmount the filesystem */
/*===========================================================================*
* fs_unmount *
*===========================================================================*/
PUBLIC int fs_unmount(void) {
release_v_pri(&v_pri); /* Release the super block */
dev_close(driver_endpoints[(fs_dev >> MAJOR) & BYTE].driver_e, fs_dev);
return OK;
return(OK);
}

View file

@ -5,159 +5,75 @@
#include "buf.h"
FORWARD _PROTOTYPE(char *get_name, (char *old_name, char string [NAME_MAX]));
FORWARD _PROTOTYPE( char *get_name_s, (char *name, char string[NAME_MAX+1]) );
FORWARD _PROTOTYPE( int parse_path_s, (ino_t dir_ino, ino_t root_ino,
int flags, struct dir_record **res_inop,
size_t *offsetp));
FORWARD _PROTOTYPE( int advance_s, (struct dir_record *dirp,
char string[NAME_MAX], struct dir_record **resp));
FORWARD _PROTOTYPE( char *get_name, (char *name, char string[NAME_MAX+1]) );
FORWARD _PROTOTYPE( int parse_path, (ino_t dir_ino, ino_t root_ino, int flags,
struct dir_record **res_inop,
size_t *offsetp) );
/* Lookup is a function used to ``look up" a particular path. It is called
* very often. */
/*===========================================================================*
* lookup *
*===========================================================================*/
PUBLIC int lookup()
{
char string[PATH_MAX];
int s_error, flags;
int len;
struct dir_record *dir;
string[0] = '\0';
/* Check length. */
len = fs_m_in.REQ_PATH_LEN;
if(len > sizeof(user_path)) return E2BIG; /* too big for buffer */
if(len < 1) return EINVAL; /* too small for \0 */
/* Copy the pathname and set up caller's user and group id */
err_code = sys_datacopy(FS_PROC_NR, (vir_bytes) fs_m_in.REQ_PATH, SELF,
(vir_bytes) user_path, (phys_bytes) len);
if (err_code != OK) {
printf("i9660fs:%s:%d: sys_datacopy failed: %d\n", __FILE__, __LINE__, err_code);
return err_code;
}
/* Verify this is a null-terminated path. */
if(user_path[len-1] != '\0') {
printf("i9660fs:lookup: didn't get null-terminated string.\n");
return EINVAL;
}
caller_uid = fs_m_in.REQ_UID;
caller_gid = fs_m_in.REQ_GID;
flags = fs_m_in.REQ_FLAGS;
/* Clear RES_OFFSET for ENOENT */
fs_m_out.RES_OFFSET= 0;
/* Lookup inode */
dir = parse_path(user_path, string, flags);
/* Copy back the last name if it is required */
if (err_code != OK || (flags & PATH_PENULTIMATE)) {
s_error = sys_datacopy(SELF_E, (vir_bytes) string, FS_PROC_NR,
(vir_bytes) fs_m_in.REQ_USER_ADDR, (phys_bytes) NAME_MAX);
if (s_error != OK) {
printf("i9660fs:%s:%d: sys_datacopy failed: %d\n",
__FILE__, __LINE__, s_error);
return s_error;
}
}
/* Error or mount point encountered */
if (dir == NULL) {
if (err_code != EENTERMOUNT)
fs_m_out.RES_INODE_NR = 0; /* signal no inode */
return err_code;
}
fs_m_out.RES_INODE_NR = ID_DIR_RECORD(dir);
fs_m_out.RES_MODE = dir->d_mode;
fs_m_out.RES_FILE_SIZE = dir->d_file_size;
/* Drop inode (path parse increased the counter) */
release_dir_record(dir);
return err_code;
}
/*===========================================================================*
* fs_lookup_s *
* fs_lookup *
*===========================================================================*/
PUBLIC int fs_lookup_s() {
PUBLIC int fs_lookup() {
cp_grant_id_t grant;
int r, r1, len, flags;
size_t offset, size;
ino_t dir_ino, root_ino;
struct dir_record *dir;
grant= fs_m_in.REQ_L_GRANT;
size= fs_m_in.REQ_L_PATH_SIZE; /* Size of the buffer */
len = fs_m_in.REQ_L_PATH_LEN; /* including terminating nul */
offset= fs_m_in.REQ_L_PATH_OFF; /* offset in buffer */
dir_ino= fs_m_in.REQ_L_DIR_INO;
root_ino= fs_m_in.REQ_L_ROOT_INO;
flags = fs_m_in.REQ_L_FLAGS;
caller_uid = fs_m_in.REQ_L_UID;
caller_gid = fs_m_in.REQ_L_GID;
grant = fs_m_in.REQ_GRANT;
size = fs_m_in.REQ_PATH_SIZE; /* Size of the buffer */
len = fs_m_in.REQ_PATH_LEN; /* including terminating nul */
dir_ino = fs_m_in.REQ_DIR_INO;
root_ino = fs_m_in.REQ_ROOT_INO;
flags = fs_m_in.REQ_FLAGS;
caller_uid = fs_m_in.REQ_UID;
caller_gid = fs_m_in.REQ_GID;
/* Check length. */
if(len > sizeof(user_path)) return E2BIG; /* too big for buffer */
if(len < 1)return EINVAL; /* too small */
if(len > sizeof(user_path)) return(E2BIG); /* too big for buffer */
if(len < 1) return(EINVAL); /* too small */
/* Copy the pathname and set up caller's user and group id */
r = sys_safecopyfrom(FS_PROC_NR, grant, offset,
(vir_bytes) user_path, (phys_bytes) len, D);
r = sys_safecopyfrom(FS_PROC_NR, grant, 0, (vir_bytes) user_path,
(phys_bytes) len, D);
if (r != OK) {
printf("iso9660fs:fs_lookup_s: sys_safecopyfrom failed: %d\n", r);
return r;
printf("ISOFS %s:%d sys_safecopyfrom failed: %d\n",
__FILE__, __LINE__, r);
return(r);
}
/* Verify this is a null-terminated path. */
if(user_path[len-1] != '\0') {
printf("iso9660fs:fs_lookup_s: didn't get null-terminated string.\n");
return EINVAL;
}
if(user_path[len-1] != '\0') return(EINVAL);
/* Lookup inode */
dir = NULL;
r = parse_path_s(dir_ino, root_ino, flags, &dir, &offset);
offset = 0;
r = parse_path(dir_ino, root_ino, flags, &dir, &offset);
if (r == ELEAVEMOUNT) {
/* Report offset and the error */
fs_m_out.RES_OFFSET = offset;
fs_m_out.RES_SYMLOOP = 0;
if (dir) panic(__FILE__, "fs_lookup_s: dir should be clear",
(unsigned)dir);
return r;
/* Report offset and the error */
fs_m_out.RES_OFFSET = offset;
fs_m_out.RES_SYMLOOP = 0;
return(r);
}
if (r != OK && r != EENTERMOUNT) {
if (dir)
panic(__FILE__, "fs_lookup_s: dir should be clear",
(unsigned)dir);
return r;
if (r != OK && r != EENTERMOUNT) return(r);
fs_m_out.RES_INODE_NR = ID_DIR_RECORD(dir);
fs_m_out.RES_MODE = dir->d_mode;
fs_m_out.RES_FILE_SIZE_LO = dir->d_file_size;
fs_m_out.RES_SYMLOOP = 0;
fs_m_out.RES_UID = SYS_UID; /* root */
fs_m_out.RES_GID = SYS_GID; /* operator */
if (r == EENTERMOUNT) {
fs_m_out.RES_OFFSET = offset;
release_dir_record(dir);
}
fs_m_out.RES_OFFSET = offset;
fs_m_out.RES_INODE_NR = ID_DIR_RECORD(dir);
fs_m_out.RES_MODE = dir->d_mode;
fs_m_out.RES_FILE_SIZE = dir->d_file_size;
fs_m_out.RES_SYMLOOP2 = 0;
fs_m_out.RES_UID = 0; /* root */
fs_m_out.RES_GID = 0; /* operator */
/* /\* Drop inode (path parse increased the counter) *\/ */
/* release_dir_record(dir); */
if (r == EENTERMOUNT)
release_dir_record(dir);
return r;
return(r);
}
/* The search dir actually performs the operation of searching for the
@ -266,127 +182,11 @@ PUBLIC int search_dir(ldir_ptr,string,numb)
return EINVAL;
}
/* Parse path will parse a particular path and return the final dir record.
* The final component of this path will be returned in string. It works in
* two ways: the first is PATH_PENULTIMATE and it returns the last dir of the
* path while the second is PATH_NON_SYMBOLIC where it returns the last
* component of the path. */
/*===========================================================================*
* parse_path *
*===========================================================================*/
PUBLIC struct dir_record *parse_path(path, string, action)
char *path; /* the path name to be parsed */
char string[NAME_MAX]; /* the final component is returned here */
int action; /* action on last part of path */
{
/* This is the actual code for last_dir and eat_path. Return the inode of
* the last directory and the name of object within that directory, or the
* inode of the last object (an empty name will be returned). Names are
* returned in string. If string is null the name is discarded. The action
* code determines how "last" is defined. If an error occurs, NIL_INODE
* will be returned with an error code in err_code.
*/
char *new_name;
char lstring[NAME_MAX];
struct dir_record *start_dir, *chroot_dir, *old_dir, *dir;
/* Find starting inode inode according to the request message */
if ((start_dir = get_dir_record(fs_m_in.REQ_INODE_NR)) == NULL) {
printf("I9660FS: couldn't find starting inode req_nr: %d %s\n", req_nr,
user_path);
err_code = ENOENT;
printf("%s, %d\n", __FILE__, __LINE__);
return NULL;
}
/* Set user and group ID */
caller_uid = fs_m_in.REQ_UID;
caller_gid = fs_m_in.REQ_GID;
/* No characters were processed yet */
path_processed = 0;
/* Current number of symlinks encountered */
symloop = fs_m_in.REQ_SYMLOOP;
if (*path == '\0') {
return start_dir;
}
if (string == (char *) 0) string = lstring;
/* Scan the path component by component. */
while (TRUE) {
int slashes = 0;
/* Extract one component. Skip slashes first. */
while (path[slashes] == '/') {
slashes++;
path_processed++;
}
fs_m_out.RES_OFFSET = path_processed; /* For ENOENT */
if ((new_name = get_name(path+slashes, string)) == (char*) 0) {
release_dir_record(start_dir); /* bad path in user space */
return(NULL);
}
if (*new_name == '\0' && (action & PATH_PENULTIMATE)) {
if ((start_dir->file_flags & I_TYPE) ==I_DIRECTORY) {
return(start_dir); /* normal exit */
} else {
/* last file of path prefix is not a directory */
release_dir_record(start_dir);
err_code = ENOTDIR;
return(NULL);
}
}
/* There is more path. Keep parsing. */
old_dir = start_dir;
start_dir = advance(&old_dir, string);
if (start_dir == NULL) {
if (*new_name == '\0' && (action & PATH_NONSYMBOLIC) != 0) {
return(old_dir);
}
else if (err_code == ENOENT) {
return(old_dir);
}
else {
release_dir_record(old_dir);
return(NULL);
}
}
if (*new_name != '\0') {
release_dir_record(old_dir);
path = new_name;
continue;
}
/* Either last name reached or symbolic link is opaque */
if ((action & PATH_NONSYMBOLIC) != 0) {
release_dir_record(start_dir);
return(old_dir);
} else {
release_dir_record(old_dir);
return(start_dir);
}
}
}
/* Parse the path in user_path, starting at dir_ino. If the path is the empty
* string, just return dir_ino. It is upto the caller to treat an empty
* path in a special way. Otherwise, if the path consists of just one or
* more slash ('/') characters, the path is replaced with ".". Otherwise,
* just look up the first (or only) component in path after skipping any
* leading slashes.
*/
/*===========================================================================*
* parse_path_s *
*===========================================================================*/
PRIVATE int parse_path_s(dir_ino, root_ino, flags, res_inop, offsetp)
PRIVATE int parse_path(dir_ino, root_ino, flags, res_inop, offsetp)
ino_t dir_ino;
ino_t root_ino;
int flags;
@ -400,10 +200,8 @@ size_t *offsetp;
/* Find starting inode inode according to the request message */
if ((start_dir = get_dir_record(dir_ino)) == NULL) {
printf("I9660FS: couldn't find starting inode req_nr: %d %s\n", req_nr,
user_path);
printf("%s, %d\n", __FILE__, __LINE__);
return ENOENT;
printf("ISOFS: couldn't find starting inode %d\n", dir_ino);
return(ENOENT);
}
cp = user_path;
@ -433,10 +231,10 @@ size_t *offsetp;
ncp = cp;
}
else
ncp = get_name_s(cp, string);
ncp = get_name(cp, string);
} else
/* Just get the first component */
ncp = get_name_s(cp, string);
ncp = get_name(cp, string);
/* Special code for '..'. A process is not allowed to leave a chrooted
* environment. A lookup of '..' at the root of a mounted filesystem
@ -471,7 +269,7 @@ size_t *offsetp;
/* There is more path. Keep parsing. */
old_dir = start_dir;
r = advance_s(old_dir, string, &start_dir);
r = advance(old_dir, string, &start_dir);
if (r != OK) {
release_dir_record(old_dir);
@ -483,55 +281,11 @@ size_t *offsetp;
}
}
/* This function will return the componsent in ``string" looking in the dir
* pdirp... */
/*===========================================================================*
* advance *
*===========================================================================*/
PUBLIC struct dir_record *advance(pdirp, string)
struct dir_record **pdirp; /* inode for directory to be searched */
char string[NAME_MAX]; /* component name to look for */
{
/* Given a directory and a component of a path, look up the component in
* the directory, find the inode, open it, and return a pointer to its inode
* slot. If it can't be done, return NULL.
*/
register struct dir_record *rip, *dirp;
int r, inumb;
dev_t mnt_dev;
ino_t numb;
dirp = *pdirp;
/* If 'string' is empty, yield same inode straight away. */
if (string[0] == '\0') {
return dirp;
}
/* Check for NULL. */
if (dirp == NULL) {
return(NULL);
}
/* If 'string' is not present in the directory, signal error. */
if ( (r = search_dir(dirp, string, &numb)) != OK) {
err_code = r;
return(NULL);
}
/* The component has been found in the directory. Get inode. */
if ( (rip = get_dir_record((int) numb)) == NULL) {
return(NULL);
}
return(rip);
}
/*===========================================================================*
* advance_s *
*===========================================================================*/
PRIVATE int advance_s(dirp, string, resp)
PUBLIC int advance(dirp, string, resp)
struct dir_record *dirp; /* inode for directory to be searched */
char string[NAME_MAX]; /* component name to look for */
struct dir_record **resp; /* resulting inode */
@ -570,55 +324,11 @@ struct dir_record **resp; /* resulting inode */
return OK;
}
/*===========================================================================*
* get_name *
*===========================================================================*/
PRIVATE char *get_name(old_name, string)
char *old_name; /* path name to parse */
char string[NAME_MAX]; /* component extracted from 'old_name' */
{
/* Given a pointer to a path name in fs space, 'old_name', copy the next
* component to 'string' and pad with zeros. A pointer to that part of
* the name as yet unparsed is returned. Roughly speaking,
* 'get_name' = 'old_name' - 'string'.
*
* This routine follows the standard convention that /usr/ast, /usr//ast,
* //usr///ast and /usr/ast/ are all equivalent.
*/
register int c;
register char *np, *rnp;
np = string; /* 'np' points to current position */
rnp = old_name; /* 'rnp' points to unparsed string */
c = *rnp;
/* Copy the unparsed path, 'old_name', to the array, 'string'. */
while ( rnp < &old_name[PATH_MAX] && c != '/' && c != '\0') {
if (np < &string[NAME_MAX]) *np++ = c;
c = *++rnp; /* advance to next character */
path_processed++; /* count characters */
}
/* To make /usr/ast/ equivalent to /usr/ast, skip trailing slashes. */
while (c == '/' && rnp < &old_name[PATH_MAX]) {
c = *++rnp;
path_processed++; /* count characters */
}
if (np < &string[NAME_MAX]) *np = '\0'; /* Terminate string */
if (rnp >= &old_name[PATH_MAX]) {
err_code = ENAMETOOLONG;
return((char *) 0);
}
return(rnp);
}
/*===========================================================================*
* get_name_s *
*===========================================================================*/
PRIVATE char *get_name_s(path_name, string)
PRIVATE char *get_name(path_name, string)
char *path_name; /* path name to parse */
char string[NAME_MAX+1]; /* component extracted from 'old_name' */
{
@ -626,7 +336,7 @@ char string[NAME_MAX+1]; /* component extracted from 'old_name' */
* component to 'string' (truncated if necessary, always nul terminated).
* A pointer to the string after the first component of the name as yet
* unparsed is returned. Roughly speaking,
* 'get_name_s' = 'path_name' - 'string'.
* 'get_name' = 'path_name' - 'string'.
*
* This routine follows the standard convention that /usr/ast, /usr//ast,
* //usr///ast and /usr/ast/ are all equivalent.

View file

@ -20,7 +20,7 @@ PUBLIC int fs_access()
/* Temporarily open the file. */
if ( (rip = get_dir_record(fs_m_in.REQ_INODE_NR)) == NULL) {
printf("I9660FS(%d) get_dir_record by fs_access() failed\n", SELF_E);
printf("ISOFS(%d) get_dir_record by fs_access() failed\n", SELF_E);
return(EINVAL);
}

View file

@ -4,80 +4,73 @@ struct dir_record;
struct ext_attr_rec;
struct iso9660_vd_pri;
int fs_getnode(void);
int fs_putnode(void);
int fs_new_driver(void);
int fs_sync(void);
int lookup(void);
int fs_access(void);
int fs_getdents(void);
int fs_getdents_o(void);
/* main.c */
_PROTOTYPE( int main, (void) );
_PROTOTYPE( void reply, (int who, message *m_out) );
/* cache.c */
_PROTOTYPE(struct buf *get_block,(block_t block));
_PROTOTYPE(void put_block,(struct buf *bp));
/* device.c */
_PROTOTYPE( int block_dev_io, (int op, Dev_t dev, int proc, void *buf,
u64_t pos, int bytes, int flags));
u64_t pos, int bytes, int flags) );
_PROTOTYPE( int dev_open, (endpoint_t driver_e, Dev_t dev, int proc,
int flags));
_PROTOTYPE( void dev_close, (endpoint_t driver_e, Dev_t dev));
/* super.c */
_PROTOTYPE(int release_v_pri,(struct iso9660_vd_pri *v_pri));
_PROTOTYPE(int read_vds,(struct iso9660_vd_pri *v_pri, Dev_t dev));
_PROTOTYPE(int create_v_pri,(struct iso9660_vd_pri *v_pri, char *buffer,unsigned long address));
int flags) );
_PROTOTYPE( void dev_close, (endpoint_t driver_e, Dev_t dev) );
_PROTOTYPE( int fs_new_driver, (void) );
/* inode.c */
_PROTOTYPE(int release_dir_record,(struct dir_record *dir));
_PROTOTYPE(struct dir_record *get_free_dir_record,(void));
_PROTOTYPE(struct dir_record *get_dir_record,(ino_t id_dir));
_PROTOTYPE(struct ext_attr_rec *get_free_ext_attr,(void));
_PROTOTYPE(int create_ext_attr,(struct ext_attr_rec *ext,
char *buffer));
_PROTOTYPE(int create_dir_record,(struct dir_record *dir, char *buffer,
u32_t address));
_PROTOTYPE(struct dir_record *load_dir_record_from_disk,(u32_t address));
_PROTOTYPE( int create_dir_record,(struct dir_record *dir, char *buffer,
u32_t address) );
_PROTOTYPE( int create_ext_attr,(struct ext_attr_rec *ext, char *buffer));
_PROTOTYPE( int fs_getnode, (void) );
_PROTOTYPE( int fs_putnode, (void) );
_PROTOTYPE( struct dir_record *get_dir_record, (ino_t id_dir) );
_PROTOTYPE( struct dir_record *get_free_dir_record, (void) );
_PROTOTYPE( struct ext_attr_rec *get_free_ext_attr, (void) );
_PROTOTYPE( struct dir_record *load_dir_record_from_disk,(u32_t address));
_PROTOTYPE( int release_dir_record, (struct dir_record *dir) );
/* misc.c */
_PROTOTYPE( int fs_sync, (void) );
/* mount.c */
_PROTOTYPE( int fs_readsuper, (void) );
_PROTOTYPE( int fs_mountpoint, (void) );
_PROTOTYPE( int fs_unmount, (void) );
/* path.c */
int fs_lookup_s(void);
_PROTOTYPE(struct dir_record *advance,(struct dir_record **dirp,
char string[NAME_MAX]));
_PROTOTYPE( int fs_lookup, (void) );
_PROTOTYPE( int advance, (struct dir_record *dirp, char string[NAME_MAX],
struct dir_record **resp) );
_PROTOTYPE( int search_dir, (struct dir_record *ldir_ptr,
char string [NAME_MAX], ino_t *numb));
_PROTOTYPE( struct dir_record *parse_path, (char *path,
char string[NAME_MAX],
int action));
char string [NAME_MAX], ino_t *numb) );
/* protect.c */
_PROTOTYPE( int fs_access, (void) );
/* read.c */
int fs_read_s(void);
int fs_read(void);
int fs_bread(void);
int fs_bread_s(void);
_PROTOTYPE(int read_chunk,(struct dir_record *dir, u64_t position,
unsigned off, int chunk, char *buff, int seg,
int usr, int block_size, int *completed));
_PROTOTYPE( int fs_read, (void) );
_PROTOTYPE( int fs_bread, (void) );
_PROTOTYPE( int fs_getdents, (void) );
_PROTOTYPE( int read_chunk, (struct dir_record *rip, u64_t position,
unsigned off, int chunk, unsigned left,
cp_grant_id_t gid, unsigned buf_off,
int block_size, int *completed) );
/* stadir.c */
_PROTOTYPE( int fs_stat, (void) );
_PROTOTYPE( int fs_fstatfs, (void) );
/* super.c */
_PROTOTYPE(int release_v_pri, (struct iso9660_vd_pri *v_pri) );
_PROTOTYPE(int read_vds, (struct iso9660_vd_pri *v_pri, Dev_t dev) );
_PROTOTYPE(int create_v_pri, (struct iso9660_vd_pri *v_pri, char *buffer,
unsigned long address) );
/* utility.c */
_PROTOTYPE(int no_sys, (void));
_PROTOTYPE(void panic, (char *who, char *mess, int num));
/* cache.c */
_PROTOTYPE(struct buf *get_block,(block_t block));
_PROTOTYPE(void put_block,(struct buf *bp));
/* ids.c */
/* _PROTOTYPE(void hash_init, (void)); */
/* _PROTOTYPE(int assign_id_to_dir_record, (struct dir_record *dir)); */
/* _PROTOTYPE(struct dir_record *get_dir_record_by_id,(int id)); */
/* mount.c */
int fs_readsuper(void);
int fs_readsuper_s(void);
int fs_mountpoint_s(void);
int fs_unmount(void);
/* stadir.c */
int fs_stat(void);
int fs_fstatfs(void);

View file

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

View file

@ -9,12 +9,9 @@
FORWARD _PROTOTYPE(int stat_dir_record, (struct dir_record *dir, int pipe_pos,
int who_e, cp_grant_id_t gid));
int who_e, cp_grant_id_t gid) );
/* This function returns all the info about a particular inode. It's missing
* the recording date because of a bug in the standard functions stdtime.
* Once the bug is fixed the function can be called inside this function to
* return the date. */
/*===========================================================================*
* stat_dir_record *
*===========================================================================*/
@ -24,6 +21,10 @@ int pipe_pos; /* position in a pipe, supplied by fstat() */
int who_e; /* Caller endpoint */
cp_grant_id_t gid; /* grant for the stat buf */
{
/* This function returns all the info about a particular inode. It's missing
* the recording date because of a bug in the standard functions stdtime.
* Once the bug is fixed the function can be called inside this function to
* return the date. */
/* Common code for stat and fstat system calls. */
struct stat statbuf;
@ -50,7 +51,7 @@ cp_grant_id_t gid; /* grant for the stat buf */
ltime.tm_isdst = 0;
if (dir->rec_date[6] != 0)
ltime.tm_hour += dir->rec_date[6] / 4;
ltime.tm_hour += dir->rec_date[6] / 4;
time1 = mktime(&ltime);
@ -60,13 +61,12 @@ cp_grant_id_t gid; /* grant for the stat buf */
/* Copy the struct to user space. */
r = sys_safecopyto(who_e, gid, 0, (vir_bytes) &statbuf,
(phys_bytes) sizeof(statbuf), D);
(phys_bytes) sizeof(statbuf), D);
return(r);
}
/* This function is a wrapper to the function above. It is called with the
* request. */
/*===========================================================================*
* fs_stat *
*===========================================================================*/
@ -77,14 +77,14 @@ PUBLIC int fs_stat()
r = EINVAL;
if ((dir = get_dir_record(fs_m_in.REQ_INODE_NR)) != NULL) {
r = stat_dir_record(dir, 0, fs_m_in.m_source, fs_m_in.REQ_GRANT);
release_dir_record(dir);
} else
printf("I9660FS(%d) fs_stat() failed\n", SELF_E);
r = stat_dir_record(dir, 0, fs_m_in.m_source, fs_m_in.REQ_GRANT);
release_dir_record(dir);
}
return r;
return(r);
}
/*===========================================================================*
* fs_fstatfs *
*===========================================================================*/
@ -97,7 +97,7 @@ PUBLIC int fs_fstatfs()
/* Copy the struct to user space. */
r = sys_safecopyto(fs_m_in.m_source, fs_m_in.REQ_GRANT, 0,
(vir_bytes) &st, (phys_bytes) sizeof(st), D);
(vir_bytes) &st, (phys_bytes) sizeof(st), D);
return(r);
}

View file

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

View file

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

View file

@ -303,14 +303,6 @@ int rw_flag; /* READING or WRITING */
/* Report read errors to interested parties. */
if (rw_flag == READING) rdwt_err = r;
}
if(op == MFS_DEV_READ) {
int i;
#if 0
printf("mfsread after contents: 0x%lx, ", bp->b_data);
for(i = 0; i < 10; i++) printf("%02lx ", (unsigned char) bp->b_data[i]);
printf("\n");
#endif
}
}
bp->b_dirt = CLEAN;

View file

@ -5,6 +5,7 @@
#define V2_NR_TZONES 10 /* total # zone numbers in a V2 inode */
#define NR_INODES 256 /* # slots in "in core" inode table */
#define GETDENTS_BUFSIZ 257
#define INODE_HASH_LOG2 7 /* 2 based logarithm of the inode hash size */
#define INODE_HASH_SIZE ((unsigned long)1<<INODE_HASH_LOG2)
@ -47,6 +48,9 @@
/* write_map() args */
#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_PENULTIMATE 001 /* parse_path stops at last but one 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 NR_DIR_ENTRIES(b) ((b)/DIR_ENTRY_SIZE) /* # dir entries/blk */
#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_BITCHUNK_BITS (usizeof(bitchunk_t) * CHAR_BIT)

View file

@ -1,4 +1,3 @@
#include "fs.h"
#include <fcntl.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) );
FORWARD _PROTOTYPE( int gen_io, (int task_nr, message *mess_ptr) );
/*===========================================================================*
* fs_clone_opcl *
*===========================================================================*/
PUBLIC int fs_clone_opcl(void)
{
/* A new minor device number has been returned.
* Create a temporary device file to hold it.
*/
struct inode *ip;
dev_t dev;
dev = fs_m_in.REQ_DEV; /* Device number */
ip = alloc_inode(fs_dev, ALL_MODES | I_CHAR_SPECIAL);
if (ip == NIL_INODE) return err_code;
ip->i_zone[0] = dev;
fs_m_out.m_source = ip->i_dev;
fs_m_out.RES_INODE_NR = ip->i_num;
fs_m_out.RES_MODE = ip->i_mode;
return OK;
}
/*===========================================================================*
* fs_new_driver *
@ -60,8 +34,8 @@ PUBLIC int fs_new_driver(void)
{
/* New driver endpoint for this device */
driver_endpoints[(fs_m_in.REQ_DEV >> MAJOR) & BYTE].driver_e =
fs_m_in.REQ_DRIVER_E;
return OK;
fs_m_in.REQ_DRIVER_E;
return(OK);
}
@ -80,81 +54,77 @@ void **buf;
int *vec_grants;
vir_bytes bytes;
{
int access = 0, size;
int j;
iovec_t *v;
static iovec_t *new_iovec;
int access = 0, size;
int j;
iovec_t *v;
static iovec_t *new_iovec;
STATICINIT(new_iovec, NR_IOREQS);
STATICINIT(new_iovec, NR_IOREQS);
/* Number of grants allocated in vector I/O. */
*vec_grants = 0;
/* Number of grants allocated in vector I/O. */
*vec_grants = 0;
/* Driver can handle it - change request to a safe one. */
*gid = GRANT_INVALID;
switch(*op) {
case MFS_DEV_READ:
case MFS_DEV_WRITE:
/* Change to safe op. */
*op = *op == MFS_DEV_READ ? DEV_READ_S : DEV_WRITE_S;
if((*gid=cpf_grant_direct(driver, (vir_bytes) *buf, bytes,
*op == DEV_READ_S?CPF_WRITE:CPF_READ))<0) {
panic(__FILE__,"cpf_grant_magic of buffer failed\n", NO_NUM);
}
/* Driver can handle it - change request to a safe one. */
break;
case MFS_DEV_GATHER:
case MFS_DEV_SCATTER:
/* Change to safe op. */
*op = *op == MFS_DEV_GATHER ? DEV_GATHER_S : DEV_SCATTER_S;
*gid = GRANT_INVALID;
/* Grant access to my new i/o vector. */
if((*gid = cpf_grant_direct(driver, (vir_bytes) new_iovec,
bytes * sizeof(iovec_t),
CPF_READ | CPF_WRITE)) < 0) {
panic(__FILE__, "cpf_grant_direct of vector failed", NO_NUM);
}
v = (iovec_t *) *buf;
/* Grant access to i/o buffers. */
for(j = 0; j < bytes; j++) {
if(j >= NR_IOREQS)
panic(__FILE__, "vec too big", bytes);
new_iovec[j].iov_addr = gids[j] =
cpf_grant_direct(driver, (vir_bytes) v[j].iov_addr,
v[j].iov_size,
*op == DEV_GATHER_S ? CPF_WRITE : CPF_READ);
if(!GRANT_VALID(gids[j])) {
panic(__FILE__, "mfs: grant to iovec buf failed",
NO_NUM);
}
new_iovec[j].iov_size = v[j].iov_size;
(*vec_grants)++;
}
switch(*op) {
case MFS_DEV_READ:
case MFS_DEV_WRITE:
/* Change to safe op. */
*op = *op == MFS_DEV_READ ? DEV_READ_S : DEV_WRITE_S;
/* Set user's vector to the new one. */
*buf = new_iovec;
break;
}
if((*gid=cpf_grant_direct(driver, (vir_bytes) *buf,
bytes, *op == DEV_READ_S ? CPF_WRITE :
CPF_READ)) < 0) {
panic(__FILE__,
"cpf_grant_magic of buffer failed\n", NO_NUM);
}
/* If we have converted to a safe operation, I/O
* endpoint becomes FS if it wasn't already.
*/
if(GRANT_VALID(*gid)) {
*io_ept = SELF_E;
return 1;
}
break;
case MFS_DEV_GATHER:
case MFS_DEV_SCATTER:
/* Change to safe op. */
*op = *op == MFS_DEV_GATHER ?
DEV_GATHER_S : DEV_SCATTER_S;
/* Grant access to my new i/o vector. */
if((*gid = cpf_grant_direct(driver,
(vir_bytes) new_iovec, bytes * sizeof(iovec_t),
CPF_READ | CPF_WRITE)) < 0) {
panic(__FILE__,
"cpf_grant_direct of vector failed", NO_NUM);
}
v = (iovec_t *) *buf;
/* Grant access to i/o buffers. */
for(j = 0; j < bytes; j++) {
if(j >= NR_IOREQS)
panic(__FILE__, "vec too big", bytes);
new_iovec[j].iov_addr = gids[j] =
cpf_grant_direct(driver, (vir_bytes)
v[j].iov_addr, v[j].iov_size,
*op == DEV_GATHER_S ? CPF_WRITE : CPF_READ);
if(!GRANT_VALID(gids[j])) {
panic(__FILE__, "mfs: grant to iovec buf failed",
NO_NUM);
}
new_iovec[j].iov_size = v[j].iov_size;
(*vec_grants)++;
}
/* Set user's vector to the new one. */
*buf = new_iovec;
break;
}
/* If we have converted to a safe operation, I/O
* endpoint becomes FS if it wasn't already.
*/
if(GRANT_VALID(*gid)) {
*io_ept = SELF_E;
return 1;
}
/* Not converted to a safe operation (because there is no
* copying involved in this operation).
*/
return 0;
/* Not converted to a safe operation (because there is no
* copying involved in this operation).
*/
return 0;
}
/*===========================================================================*
@ -166,14 +136,14 @@ cp_grant_id_t *gids;
int gids_size;
{
/* Free resources (specifically, grants) allocated by safe_io_conversion(). */
int j;
int j;
cpf_revoke(gid);
cpf_revoke(gid);
for(j = 0; j < gids_size; j++)
cpf_revoke(gids[j]);
for(j = 0; j < gids_size; j++)
cpf_revoke(gids[j]);
return;
return;
}
/*===========================================================================*
@ -208,7 +178,7 @@ int flags; /* special flags, like O_NONBLOCK */
/* See if driver is roughly valid. */
if (driver_e == NONE) {
printf("MFS(%d) block_dev_io: no driver for dev %x\n", SELF_E, dev);
return EDSTDIED;
return(EDSTDIED);
}
/* The io vector copying relies on this I/O being for FS itself. */
@ -381,9 +351,9 @@ message *mess_ptr; /* pointer to message for task */
mess_ptr->m_type,
proc_e,
mess_ptr->REP_ENDPT);
return EIO;
return(EIO);
}
return OK;
return(OK);
}

View file

@ -4,6 +4,8 @@
#define EXTERN
#endif
#include <minix/vfsif.h>
EXTERN off_t rdahedpos; /* position to read ahead */
EXTERN struct inode *rdahed_inode; /* pointer to inode to read ahead */
@ -21,6 +23,7 @@ extern _PROTOTYPE (int (*fs_call_vec[]), (void) ); /* fs call table */
EXTERN message fs_m_in;
EXTERN message fs_m_out;
EXTERN int FS_STATE;
EXTERN vfs_ucred_t credentials;
EXTERN uid_t caller_uid;
EXTERN gid_t caller_gid;

View file

@ -11,25 +11,23 @@
* free_inode: mark an inode as available for a new file
* update_times: update atime, ctime, and mtime
* rw_inode: read a disk block and extract an inode, or corresp. write
* old_icopy: copy to/from in-core inode struct and disk inode (V1.x)
* new_icopy: copy to/from in-core inode struct and disk inode (V2.x)
* dup_inode: indicate that someone else is using an inode table entry
* find_inode: retrieve pointer to inode in inode cache
*
* Updates:
* 2007-06-01: jfdsmit@gmail.com added i_zsearch initialization
*/
#include "fs.h"
#include "buf.h"
#include "inode.h"
#include "super.h"
#include <minix/vfsif.h>
FORWARD _PROTOTYPE( void old_icopy, (struct inode *rip, d1_inode *dip,
int direction, int norm));
FORWARD _PROTOTYPE( int addhash_inode, (struct inode *node) );
FORWARD _PROTOTYPE( void new_icopy, (struct inode *rip, d2_inode *dip,
int direction, int norm));
FORWARD _PROTOTYPE( void old_icopy, (struct inode *rip, d1_inode *dip,
int direction, int norm));
FORWARD _PROTOTYPE( int unhash_inode, (struct inode *node) );
/*===========================================================================*
@ -37,80 +35,36 @@ FORWARD _PROTOTYPE( void new_icopy, (struct inode *rip, d2_inode *dip,
*===========================================================================*/
PUBLIC int fs_putnode()
{
/* Find the inode specified by the request message and decrease its counter.
*/
/* Find the inode specified by the request message and decrease its counter.*/
struct inode *rip;
int count;
/* Sanity check for the direct index */
if (fs_m_in.REQ_INODE_INDEX >= 0 &&
fs_m_in.REQ_INODE_INDEX < NR_INODES &&
inode[fs_m_in.REQ_INODE_INDEX].i_num == fs_m_in.REQ_INODE_NR) {
rip = &inode[fs_m_in.REQ_INODE_INDEX];
if(!rip) {
panic(__FILE__, "null rip", NO_NUM);
}
}
/* Otherwise find it */
else {
if(!(rip = find_inode(fs_dev, fs_m_in.REQ_INODE_NR))) {
printf("FSput_inode: inode #%d dev: %d not found, req_nr: %d\n",
fs_m_in.REQ_INODE_NR, fs_dev, req_nr);
}
rip = find_inode(fs_dev, fs_m_in.REQ_INODE_NR);
if(!rip) {
printf("%s:%d put_inode: inode #%d dev: %d not found\n", __FILE__,
__LINE__, fs_m_in.REQ_INODE_NR, fs_dev);
panic(__FILE__, "fs_putnode failed", NO_NUM);
}
if (!rip)
{
count = fs_m_in.REQ_COUNT;
if (count <= 0) {
printf("%s:%d put_inode: bad value for count: %d\n", __FILE__,
__LINE__, count);
panic(__FILE__, "fs_putnode failed", NO_NUM);
} else if(count > rip->i_count) {
printf("%s:%d put_inode: count too high: %d > %d\n", __FILE__,
__LINE__, count, rip->i_count);
panic(__FILE__, "fs_putnode failed", NO_NUM);
}
count= fs_m_in.REQ_COUNT;
if (count <= 0)
{
printf("put_inode: bad value for count: %d\n", count);
panic(__FILE__, "fs_putnode failed", NO_NUM);
return EINVAL;
}
if (count > rip->i_count)
{
printf("put_inode: count too high: %d > %d\n", count, rip->i_count);
panic(__FILE__, "fs_putnode failed", NO_NUM);
return EINVAL;
}
/* Decrease reference counter, but keep one reference; it will be consumed by
* put_inode(). */
rip->i_count -= count - 1;
put_inode(rip);
return OK;
}
/*===========================================================================*
* fs_getnode *
*===========================================================================*/
PUBLIC int fs_getnode()
{
/* Increase the inode's counter specified in the request message
*/
struct inode *rip;
/* Get the inode */
rip = get_inode(fs_dev, fs_m_in.REQ_INODE_NR);
if (!rip) {
printf("FS: inode #%d couldn't be found\n", fs_m_in.REQ_INODE_NR);
return EINVAL;
}
/* Transfer back the inode's details */
fs_m_out.m_source = rip->i_dev;
fs_m_out.RES_INODE_NR = rip->i_num;
fs_m_out.RES_MODE = rip->i_mode;
fs_m_out.RES_FILE_SIZE = rip->i_size;
fs_m_out.RES_DEV = (Dev_t) rip->i_zone[0];
fs_m_out.RES_UID = rip->i_uid;
fs_m_out.RES_GID = rip->i_gid;
return OK;
return(OK);
}
@ -149,9 +103,10 @@ PRIVATE int addhash_inode(struct inode *node)
/* insert into hash table */
LIST_INSERT_HEAD(&hash_inodes[hashi], node, i_hash);
return OK;
return(OK);
}
/*===========================================================================*
* unhash_inode *
*===========================================================================*/
@ -159,9 +114,10 @@ PRIVATE int unhash_inode(struct inode *node)
{
/* remove from hash table */
LIST_REMOVE(node, i_hash);
return OK;
return(OK);
}
/*===========================================================================*
* get_inode *
*===========================================================================*/
@ -186,7 +142,7 @@ int numb; /* inode number (ANSI: may not be unshort) */
TAILQ_REMOVE(&unused_inodes, rip, i_unused);
}
++rip->i_count;
return rip;
return(rip);
}
}
@ -195,7 +151,7 @@ int numb; /* inode number (ANSI: may not be unshort) */
/* Inode is not on the hash, get a free one */
if (TAILQ_EMPTY(&unused_inodes)) {
err_code = ENFILE;
return NIL_INODE;
return(NIL_INODE);
}
rip = TAILQ_FIRST(&unused_inodes);
@ -213,10 +169,6 @@ int numb; /* inode number (ANSI: may not be unshort) */
if (dev != NO_DEV) rw_inode(rip, READING); /* get inode from disk */
rip->i_update = 0; /* all the times are initially up-to-date */
rip->i_zsearch = NO_ZONE; /* no zones searched for yet */
if ((rip->i_mode & I_TYPE) == I_NAMED_PIPE)
rip->i_pipe = I_PIPE;
else
rip->i_pipe = NO_PIPE;
rip->i_mountpoint= FALSE;
/* Add to hash */
@ -225,6 +177,7 @@ int numb; /* inode number (ANSI: may not be unshort) */
return(rip);
}
/*===========================================================================*
* find_inode *
*===========================================================================*/
@ -242,11 +195,11 @@ int numb; /* inode number (ANSI: may not be unshort) */
/* Search inode in the hash table */
LIST_FOREACH(rip, &hash_inodes[hashi], i_hash) {
if (rip->i_count > 0 && rip->i_num == numb && rip->i_dev == dev) {
return rip;
return(rip);
}
}
return NIL_INODE;
return(NIL_INODE);
}
@ -274,9 +227,7 @@ register struct inode *rip; /* pointer to inode to be released */
rip->i_dirt = DIRTY;
free_inode(rip->i_dev, rip->i_num);
}
else {
if (rip->i_pipe == I_PIPE) truncate_inode(rip, 0);
}
rip->i_mountpoint = FALSE;
if (rip->i_dirt == DIRTY) rw_inode(rip, WRITING);
@ -285,8 +236,7 @@ register struct inode *rip; /* pointer to inode to be released */
unhash_inode(rip);
rip->i_num = 0;
TAILQ_INSERT_HEAD(&unused_inodes, rip, i_unused);
}
else {
} else {
/* unused, put at the back of the LRU (cache it) */
TAILQ_INSERT_TAIL(&unused_inodes, rip, i_unused);
}
@ -350,6 +300,7 @@ PUBLIC struct inode *alloc_inode(dev_t dev, mode_t bits)
return(rip);
}
/*===========================================================================*
* wipe_inode *
*===========================================================================*/
@ -389,6 +340,7 @@ ino_t inumb; /* number of inode to be freed */
if (b < sp->s_isearch) sp->s_isearch = b;
}
/*===========================================================================*
* update_times *
*===========================================================================*/
@ -458,6 +410,7 @@ int rw_flag; /* READING or WRITING */
rip->i_dirt = CLEAN;
}
/*===========================================================================*
* old_icopy *
*===========================================================================*/
@ -466,7 +419,6 @@ register struct inode *rip; /* pointer to the in-core inode struct */
register d1_inode *dip; /* pointer to the d1_inode inode struct */
int direction; /* READING (from disk) or WRITING (to disk) */
int norm; /* TRUE = do not swap bytes; FALSE = swap */
{
/* The V1.x IBM disk, the V1.x 68000 disk, and the V2 disk (same for IBM and
* 68000) all have different inode layouts. When an inode is read or written
@ -504,6 +456,7 @@ int norm; /* TRUE = do not swap bytes; FALSE = swap */
}
}
/*===========================================================================*
* new_icopy *
*===========================================================================*/
@ -512,7 +465,6 @@ register struct inode *rip; /* pointer to the in-core inode struct */
register d2_inode *dip; /* pointer to the d2_inode struct */
int direction; /* READING (from disk) or WRITING (to disk) */
int norm; /* TRUE = do not swap bytes; FALSE = swap */
{
/* Same as old_icopy, but to/from V2 disk layout. */
@ -547,6 +499,7 @@ int norm; /* TRUE = do not swap bytes; FALSE = swap */
}
}
/*===========================================================================*
* dup_inode *
*===========================================================================*/
@ -559,3 +512,4 @@ struct inode *ip; /* The inode to be duplicated. */
ip->i_count++;
}

View file

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

File diff suppressed because it is too large Load diff

View file

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

View file

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

View file

@ -1,5 +1,3 @@
#include "fs.h"
#include <fcntl.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
* and sends back the details of them. Note, that the FS process does not
@ -32,48 +30,44 @@ PUBLIC int fs_readsuper_s()
int r = OK;
unsigned long tasknr;
endpoint_t driver_e;
int readonly, isroot;
fs_dev = fs_m_in.REQ_DEV;
label_gid= fs_m_in.REQ_GRANT2;
label_len= fs_m_in.REQ_PATH_LEN;
fs_dev = fs_m_in.REQ_DEV;
label_gid = fs_m_in.REQ_GRANT;
label_len = fs_m_in.REQ_PATH_LEN;
readonly = (fs_m_in.REQ_FLAGS & REQ_RDONLY) ? 1 : 0;
isroot = (fs_m_in.REQ_FLAGS & REQ_ISROOT) ? 1 : 0;
if (label_len > sizeof(fs_dev_label))
{
printf("mfs:fs_readsuper: label too long\n");
return EINVAL;
return(EINVAL);
r = sys_safecopyfrom(fs_m_in.m_source, label_gid, 0,
(vir_bytes)fs_dev_label, label_len, D);
if (r != OK) {
printf("%s:%d fs_readsuper: safecopyfrom failed: %d\n",
__FILE__, __LINE__, r);
return(EINVAL);
}
r= sys_safecopyfrom(fs_m_in.m_source, label_gid, 0, (vir_bytes)fs_dev_label,
label_len, D);
if (r != OK)
{
printf("mfs:fs_readsuper: safecopyfrom failed: %d\n", r);
return EINVAL;
r = ds_retrieve_u32(fs_dev_label, &tasknr);
if (r != OK) {
printf("%s:%d fs_readsuper: ds_retrieve_u32 failed for '%s': %d\n",
fs_dev_label, __FILE__, __LINE__, r);
return(EINVAL);
}
r= ds_retrieve_u32(fs_dev_label, &tasknr);
if (r != OK)
{
printf("mfs:fs_readsuper: ds_retrieve_u32 failed for '%s': %d\n",
fs_dev_label, r);
return EINVAL;
}
driver_e= tasknr;
driver_e = tasknr;
/* Map the driver endpoint for this major */
driver_endpoints[(fs_dev >> MAJOR) & BYTE].driver_e = driver_e;
use_getuptime2= TRUE; /* Should be removed with old
* getuptime call.
*/
use_getuptime2 = TRUE; /* Should be removed with old getuptime call. */
vfs_slink_storage = (char *)0xdeadbeef; /* Should be removed together
* with old lookup code.
*/;
/* Open the device the file system lives on. */
if (dev_open(driver_e, fs_dev, driver_e,
fs_m_in.REQ_READONLY ? R_BIT : (R_BIT|W_BIT)) != OK) {
if (dev_open(driver_e, fs_dev, driver_e,
readonly ? R_BIT : (R_BIT|W_BIT)) != OK) {
return(EINVAL);
}
@ -91,158 +85,39 @@ PUBLIC int fs_readsuper_s()
set_blocksize(superblock.s_block_size);
/* Get the root inode of the mounted file system. */
if ( (root_ip = get_inode(fs_dev, ROOT_INODE)) == NIL_INODE) {
printf("MFS: couldn't get root inode?!\n");
superblock.s_dev = NO_DEV;
dev_close(driver_e, fs_dev);
return EINVAL;
if( (root_ip = get_inode(fs_dev, ROOT_INODE)) == NIL_INODE) {
printf("MFS: couldn't get root inode\n");
superblock.s_dev = NO_DEV;
dev_close(driver_e, fs_dev);
return(EINVAL);
}
if (root_ip != NIL_INODE && root_ip->i_mode == 0) {
printf("MFS: zero mode for root inode?!\n");
put_inode(root_ip);
superblock.s_dev = NO_DEV;
dev_close(driver_e, fs_dev);
return EINVAL;
if(root_ip != NIL_INODE && root_ip->i_mode == 0) {
printf("%s:%d zero mode for root inode?\n", __FILE__, __LINE__);
put_inode(root_ip);
superblock.s_dev = NO_DEV;
dev_close(driver_e, fs_dev);
return(EINVAL);
}
superblock.s_rd_only = fs_m_in.REQ_READONLY;
superblock.s_is_root = fs_m_in.REQ_ISROOT;
superblock.s_rd_only = readonly;
superblock.s_is_root = isroot;
/* Root inode properties */
fs_m_out.RES_INODE_NR = root_ip->i_num;
fs_m_out.RES_MODE = root_ip->i_mode;
fs_m_out.RES_FILE_SIZE = root_ip->i_size;
fs_m_out.RES_FILE_SIZE_LO = root_ip->i_size;
fs_m_out.RES_UID = root_ip->i_uid;
fs_m_out.RES_GID = root_ip->i_gid;
return r;
return(r);
}
/*===========================================================================*
* fs_readsuper_o *
* fs_mountpoint *
*===========================================================================*/
PUBLIC int fs_readsuper_o()
{
/* This function reads the superblock of the partition, gets the root inode
* and sends back the details of them. Note, that the FS process does not
* know the index of the vmnt object which refers to it, whenever the pathname
* lookup leaves a partition an ELEAVEMOUNT error is transferred back
* so that the VFS knows that it has to find the vnode on which this FS
* process' partition is mounted on.
*/
struct super_block *xp;
struct inode *root_ip;
int r = OK;
phys_bytes ph;
fs_dev = fs_m_in.REQ_DEV;
/* Map the driver endpoint for this major */
driver_endpoints[(fs_dev >> MAJOR) & BYTE].driver_e = fs_m_in.REQ_DRIVER_E;
boottime = fs_m_in.REQ_BOOTTIME;
vfs_slink_storage = fs_m_in.REQ_SLINK_STORAGE;
/* Fill in the super block. */
superblock.s_dev = fs_dev; /* read_super() needs to know which dev */
r = read_super(&superblock);
/* Is it recognized as a Minix filesystem? */
if (r != OK) {
superblock.s_dev = NO_DEV;
return(r);
}
set_blocksize(superblock.s_block_size);
/* Get the root inode of the mounted file system. */
root_ip = NIL_INODE; /* if 'r' not OK, make sure this is defined */
if (r == OK) {
if ( (root_ip = get_inode(fs_dev, ROOT_INODE)) == NIL_INODE)
r = err_code;
}
if (root_ip != NIL_INODE && root_ip->i_mode == 0) {
put_inode(root_ip);
r = EINVAL;
}
if (r != OK) return r;
superblock.s_rd_only = fs_m_in.REQ_READONLY;
superblock.s_is_root = fs_m_in.REQ_ISROOT;
/* Root inode properties */
fs_m_out.RES_INODE_NR = root_ip->i_num;
fs_m_out.RES_MODE = root_ip->i_mode;
fs_m_out.RES_FILE_SIZE = root_ip->i_size;
/* Partition properties */
fs_m_out.RES_MAXSIZE = superblock.s_max_size;
fs_m_out.RES_BLOCKSIZE = superblock.s_block_size;
return r;
}
/*===========================================================================*
* fs_mountpoint_o *
*===========================================================================*/
PUBLIC int fs_mountpoint_o()
{
/* This function looks up the mount point, it checks the condition whether
* the partition can be mounted on the inode or not. If ok, it gets the
* mountpoint inode's details and stores the mounted vmnt's index (in the
* vmnt table) so that it can be transferred back when the pathname lookup
* encounters a mountpoint.
*/
register struct inode *rip;
int r = OK;
mode_t bits;
/* Get inode */
caller_uid = fs_m_in.REQ_UID;
caller_gid = fs_m_in.REQ_GID;
/* Temporarily open the file. */
if ( (rip = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) {
printf("MFS(%d) get_inode by fs_mountpoint() failed\n", SELF_E);
return(EINVAL);
}
/* It may not be busy. */
if (rip->i_count > 2)
{
printf("mfs:fs_mountpoint: i_count = %d\n", rip->i_count);
r = EBUSY;
}
/* It may not be special. */
bits = rip->i_mode & I_TYPE;
if (bits == I_BLOCK_SPECIAL || bits == I_CHAR_SPECIAL) r = ENOTDIR;
if ((rip->i_mode & I_TYPE) != I_DIRECTORY) r = ENOTDIR;
if (r != OK) {
put_inode(rip);
return r;
}
rip->i_mountpoint = TRUE;
fs_m_out.m_source = rip->i_dev;/* Filled with the FS endp by the system */
fs_m_out.RES_INODE_NR = rip->i_num;
fs_m_out.RES_FILE_SIZE = rip->i_size;
fs_m_out.RES_MODE = rip->i_mode;
return r;
}
/*===========================================================================*
* fs_mountpoint_s *
*===========================================================================*/
PUBLIC int fs_mountpoint_s()
PUBLIC int fs_mountpoint()
{
/* This function looks up the mount point, it checks the condition whether
* the partition can be mounted on the inode or not.
@ -252,23 +127,21 @@ PUBLIC int fs_mountpoint_s()
mode_t bits;
/* Temporarily open the file. */
if ( (rip = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) {
printf("MFS(%d) get_inode by fs_mountpoint() failed\n", SELF_E);
return(EINVAL);
}
if (rip->i_mountpoint)
r= EBUSY;
if( (rip = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE)
return(EINVAL);
if(rip->i_mountpoint) r = EBUSY;
/* It may not be special. */
bits = rip->i_mode & I_TYPE;
if (bits == I_BLOCK_SPECIAL || bits == I_CHAR_SPECIAL) r = ENOTDIR;
put_inode(rip);
if (r == OK)
rip->i_mountpoint = TRUE;
return r;
if(r == OK) rip->i_mountpoint = TRUE;
return(r);
}
@ -280,38 +153,35 @@ PUBLIC int fs_unmount()
/* Unmount a file system by device number. */
struct super_block *sp1;
int count;
register struct inode *rip;
struct inode *rip, *root_ip;
if(superblock.s_dev != fs_dev) return(EINVAL);
/* See if the mounted device is busy. Only 1 inode using it should be
* open --the root inode-- and that inode only 1 time. */
count = 0;
for (rip = &inode[0]; rip < &inode[NR_INODES]; rip++)
if (rip->i_count > 0 && rip->i_dev == fs_dev) count += rip->i_count;
if ((root_ip = find_inode(fs_dev, ROOT_INODE)) == NIL_INODE) {
printf("MFS: couldn't find root inode. Unmount failed.\n");
panic(__FILE__, "MFS: couldn't find root inode", EINVAL);
return(EINVAL);
}
if (count > 1) return(EBUSY); /* can't umount a busy file system */
put_inode(root_ip);
/* force any cached blocks out of memory */
(void) fs_sync();
/* Close the device the file system lives on. */
dev_close(driver_endpoints[(fs_dev >> MAJOR) & BYTE].driver_e, fs_dev);
if(superblock.s_dev != fs_dev)
return EINVAL;
/* See if the mounted device is busy. Only 1 inode using it should be
* open -- the root inode -- and that inode only 1 time.
*/
count = 0;
for (rip = &inode[0]; rip < &inode[NR_INODES]; rip++) {
if (rip->i_count > 0 && rip->i_dev == fs_dev) {
count += rip->i_count;
}
}
if (count > 1) {
return(EBUSY); /* can't umount a busy file system */
}
/* Sync the disk, and invalidate cache. */
(void) fs_sync(); /* force any cached blocks out of memory */
/* Finish off the unmount. */
superblock.s_dev = NO_DEV;
unmountdone = TRUE;
return OK;
return(OK);
}

View file

@ -1,5 +1,3 @@
#include "fs.h"
#include <sys/stat.h>
#include <fcntl.h>
@ -10,152 +8,17 @@
#include "buf.h"
#include "inode.h"
#include "super.h"
#include <minix/vfsif.h>
PRIVATE char mode_map[] = {R_BIT, W_BIT, R_BIT|W_BIT, 0};
FORWARD _PROTOTYPE( struct inode *new_node_o, (struct inode *ldirp,
FORWARD _PROTOTYPE( struct inode *new_node, (struct inode *ldirp,
char *string, mode_t bits, zone_t z0));
FORWARD _PROTOTYPE( struct inode *new_node_s, (struct inode *ldirp,
char *string, mode_t bits, zone_t z0));
#if 0
/*===========================================================================*
* fs_open *
*===========================================================================*/
PUBLIC int fs_open()
{
int r, b, exist = TRUE;
struct inode *ldirp;
struct inode *rip;
int oflags;
mode_t omode;
mode_t bits;
char lastc[NAME_MAX];
/* Read request message */
oflags = fs_m_in.REQ_FLAGS;
omode = fs_m_in.REQ_MODE;
caller_uid = fs_m_in.REQ_UID;
caller_gid = fs_m_in.REQ_GID;
/* Device number only for device special files */
fs_m_out.RES_DEV = NO_DEV;
/* Remap the bottom two bits of oflags. */
bits = (mode_t) mode_map[oflags & O_ACCMODE];
/* If O_CREATE is set, try to make the file. */
if (oflags & O_CREAT) {
phys_bytes len;
/* Copy the last component */
len = MFS_MIN(fs_m_in.REQ_PATH_LEN, sizeof(lastc));
err_code = sys_datacopy(FS_PROC_NR, (vir_bytes) fs_m_in.REQ_PATH,
SELF, (vir_bytes) lastc, (phys_bytes) len);
if (err_code != OK) return err_code;
MFS_NUL(lastc, len, sizeof(lastc));
/* Get last directory inode */
if ((ldirp = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) {
printf("MFS(%d) get_inode for parent dir by creat() failed\n", SELF_E);
return ENOENT;
}
/* Create a new inode by calling new_node(). */
rip = new_node(ldirp, lastc, omode, NO_ZONE);
r = err_code;
if (r == OK) exist = FALSE; /* we just created the file */
else if (r != EEXIST) {
put_inode(ldirp);
return(r); /* other error */
}
else exist = !(oflags & O_EXCL); /* file exists, if the O_EXCL
flag is set this is an error */
}
else {
/* Get file inode. */
if ( (rip = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) {
printf("MFS(%d) get_inode by open() failed\n", SELF_E);
return ENOENT;
}
ldirp = NIL_INODE;
}
/* Only do the normal open code if we didn't just create the file. */
if (exist) {
/* Check protections. */
if ((r = forbidden(rip, bits)) == OK) {
/* Opening reg. files directories and special files differ. */
switch (rip->i_mode & I_TYPE) {
case I_REGULAR:
/* Truncate regular file if O_TRUNC. */
if (oflags & O_TRUNC) {
panic(__FILE__, "O_TRUNC in mfs.", oflags);
#if 0
if ((r = forbidden(rip, W_BIT)) !=OK) break;
truncate_inode(rip, 0);
wipe_inode(rip);
/* Send the inode from the inode cache to the
* block cache, so it gets written on the next
* cache flush.
*/
rw_inode(rip, WRITING);
#endif
}
break;
case I_DIRECTORY:
/* Directories may be read but not written. */
r = (bits & W_BIT ? EISDIR : OK);
break;
case I_CHAR_SPECIAL:
case I_BLOCK_SPECIAL:
/* Send back the device number */
fs_m_out.RES_DEV = (Dev_t) rip->i_zone[0];
break;
case I_NAMED_PIPE:
rip->i_pipe = I_PIPE;
break;
}
}
}
/* If error, release inode. */
if (r != OK) {
put_inode(ldirp);
put_inode(rip);
return(r);
}
/* Reply message */
fs_m_out.m_source = rip->i_dev; /* filled with FS endpoint by the system */
fs_m_out.RES_INODE_NR = rip->i_num;
fs_m_out.RES_MODE = rip->i_mode;
fs_m_out.RES_FILE_SIZE = rip->i_size;
fs_m_out.RES_INODE_INDEX = (rip - &inode[0]) / sizeof(struct inode);
/* This values are needed for the execution */
fs_m_out.RES_UID = rip->i_uid;
fs_m_out.RES_GID = rip->i_gid;
if ((rip->i_mode & I_TYPE) == I_REGULAR) fs_m_out.RES_CTIME = rip->i_ctime;
/* Drop parent dir */
put_inode(ldirp);
return OK;
}
#endif
/*===========================================================================*
* fs_create_o *
* fs_create *
*===========================================================================*/
PUBLIC int fs_create_o()
PUBLIC int fs_create()
{
phys_bytes len;
int r, b;
@ -166,156 +29,54 @@ PUBLIC int fs_create_o()
/* Read request message */
omode = fs_m_in.REQ_MODE;
caller_uid = fs_m_in.REQ_UID;
caller_gid = fs_m_in.REQ_GID;
/* Try to make the file. */
/* Copy the last component */
len = MFS_MIN(fs_m_in.REQ_PATH_LEN, sizeof(lastc));
err_code = sys_datacopy(FS_PROC_NR, (vir_bytes) fs_m_in.REQ_PATH,
SELF, (vir_bytes) lastc, (phys_bytes) len);
if (err_code != OK) return err_code;
MFS_NUL(lastc, len, sizeof(lastc));
/* Get last directory inode */
if ((ldirp = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) {
printf("MFS(%d) get_inode for parent dir by creat() failed\n", SELF_E);
return ENOENT;
}
/* Create a new inode by calling new_node(). */
rip = new_node_o(ldirp, lastc, omode, NO_ZONE);
r = err_code;
/* If error, release inode. */
if (r != OK) {
put_inode(ldirp);
put_inode(rip);
return(r);
}
/* Reply message */
fs_m_out.m_source = rip->i_dev; /* filled with FS endpoint by the system */
fs_m_out.RES_INODE_NR = rip->i_num;
fs_m_out.RES_MODE = rip->i_mode;
fs_m_out.RES_FILE_SIZE = rip->i_size;
fs_m_out.RES_INODE_INDEX = (rip - &inode[0]) / sizeof(struct inode);
/* This values are needed for the execution */
fs_m_out.RES_UID = rip->i_uid;
fs_m_out.RES_GID = rip->i_gid;
if ((rip->i_mode & I_TYPE) == I_REGULAR) fs_m_out.RES_CTIME = rip->i_ctime;
/* Drop parent dir */
put_inode(ldirp);
return OK;
}
/*===========================================================================*
* fs_create_s *
*===========================================================================*/
PUBLIC int fs_create_s()
{
phys_bytes len;
int r, b;
struct inode *ldirp;
struct inode *rip;
mode_t omode;
char lastc[NAME_MAX];
/* Read request message */
omode = fs_m_in.REQ_MODE;
caller_uid = fs_m_in.REQ_UID;
caller_gid = fs_m_in.REQ_GID;
/* Try to make the file. */
/* Copy the last component */
/* Copy the last component (i.e., file name) */
len = MFS_MIN(fs_m_in.REQ_PATH_LEN, sizeof(lastc));
err_code = sys_safecopyfrom(FS_PROC_NR, fs_m_in.REQ_GRANT, 0,
(vir_bytes) lastc, (phys_bytes) len, D);
(vir_bytes) lastc, (phys_bytes) len, D);
if (err_code != OK) return err_code;
MFS_NUL(lastc, len, sizeof(lastc));
/* Get last directory inode */
if ((ldirp = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) {
printf("MFS(%d) get_inode for parent dir by creat() failed\n", SELF_E);
return ENOENT;
}
/* Get last directory inode (i.e., directory that will hold the new inode) */
if ((ldirp = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE)
return(ENOENT);
/* Create a new inode by calling new_node(). */
rip = new_node_s(ldirp, lastc, omode, NO_ZONE);
rip = new_node(ldirp, lastc, omode, NO_ZONE);
r = err_code;
/* If error, release inode. */
/* If an error occurred, release inode. */
if (r != OK) {
put_inode(ldirp);
put_inode(rip);
return(r);
put_inode(ldirp);
put_inode(rip);
return(r);
}
/* Reply message */
fs_m_out.m_source = rip->i_dev; /* filled with FS endpoint by the system */
fs_m_out.RES_INODE_NR = rip->i_num;
fs_m_out.RES_MODE = rip->i_mode;
fs_m_out.RES_FILE_SIZE = rip->i_size;
fs_m_out.RES_INODE_INDEX = (rip - &inode[0]) / sizeof(struct inode);
fs_m_out.RES_FILE_SIZE_LO = rip->i_size;
/* This values are needed for the execution */
fs_m_out.RES_UID = rip->i_uid;
fs_m_out.RES_GID = rip->i_gid;
if ((rip->i_mode & I_TYPE) == I_REGULAR) fs_m_out.RES_CTIME = rip->i_ctime;
/* Drop parent dir */
put_inode(ldirp);
return OK;
return(OK);
}
/*===========================================================================*
* fs_mknod_o *
* fs_mknod *
*===========================================================================*/
PUBLIC int fs_mknod_o()
{
struct inode *ip, *ldirp;
char lastc[NAME_MAX];
phys_bytes len;
/* Copy the last component and set up caller's user and group id */
len = MFS_MIN(fs_m_in.REQ_PATH_LEN, sizeof(lastc));
err_code = sys_datacopy(FS_PROC_NR, (vir_bytes) fs_m_in.REQ_PATH, SELF,
(vir_bytes) lastc, (phys_bytes) len);
if (err_code != OK) return err_code;
MFS_NUL(lastc, len, sizeof(lastc));
caller_uid = fs_m_in.REQ_UID;
caller_gid = fs_m_in.REQ_GID;
/* Get last directory inode */
if ((ldirp = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) {
printf("MFS(%d) get_inode for parent dir by mknod() failed\n", SELF_E);
return ENOENT;
}
/* Try to create the new node */
ip = new_node_o(ldirp, lastc, fs_m_in.REQ_MODE, (zone_t) fs_m_in.REQ_DEV);
put_inode(ip);
put_inode(ldirp);
return(err_code);
}
/*===========================================================================*
* fs_mknod_s *
*===========================================================================*/
PUBLIC int fs_mknod_s()
PUBLIC int fs_mknod()
{
struct inode *ip, *ldirp;
char lastc[NAME_MAX];
@ -324,21 +85,19 @@ PUBLIC int fs_mknod_s()
/* Copy the last component and set up caller's user and group id */
len = MFS_MIN(fs_m_in.REQ_PATH_LEN, sizeof(lastc));
err_code = sys_safecopyfrom(FS_PROC_NR, fs_m_in.REQ_GRANT, 0,
(vir_bytes) lastc, (phys_bytes) len, D);
(vir_bytes) lastc, (phys_bytes) len, D);
if (err_code != OK) return err_code;
MFS_NUL(lastc, len, sizeof(lastc));
caller_uid = fs_m_in.REQ_UID;
caller_gid = fs_m_in.REQ_GID;
/* Get last directory inode */
if ((ldirp = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) {
printf("MFS(%d) get_inode for parent dir by mknod() failed\n", SELF_E);
return ENOENT;
}
if((ldirp = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE)
return(ENOENT);
/* Try to create the new node */
ip = new_node_s(ldirp, lastc, fs_m_in.REQ_MODE, (zone_t) fs_m_in.REQ_DEVx);
ip = new_node(ldirp, lastc, fs_m_in.REQ_MODE, (zone_t) fs_m_in.REQ_DEV);
put_inode(ip);
put_inode(ldirp);
@ -347,77 +106,9 @@ printf("MFS(%d) get_inode for parent dir by mknod() failed\n", SELF_E);
/*===========================================================================*
* fs_mkdir_o *
* fs_mkdir *
*===========================================================================*/
PUBLIC int fs_mkdir_o()
{
int r1, r2; /* status codes */
ino_t dot, dotdot; /* inode numbers for . and .. */
struct inode *rip, *ldirp;
char lastc[NAME_MAX]; /* last component */
phys_bytes len;
/* Copy the last component and set up caller's user and group id */
len = MFS_MIN(fs_m_in.REQ_PATH_LEN, sizeof(lastc));
err_code = sys_datacopy(FS_PROC_NR, (vir_bytes) fs_m_in.REQ_PATH, SELF,
(vir_bytes) lastc, (phys_bytes) len);
if (err_code != OK) return err_code;
MFS_NUL(lastc, len, sizeof(lastc));
caller_uid = fs_m_in.REQ_UID;
caller_gid = fs_m_in.REQ_GID;
/* Get last directory inode */
if ((ldirp = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) {
printf("MFS(%d) get_inode for parent dir by mkdir() failed\n", SELF_E);
return ENOENT;
}
/* Next make the inode. If that fails, return error code. */
rip = new_node_o(ldirp, lastc, fs_m_in.REQ_MODE, (zone_t) 0);
if (rip == NIL_INODE || err_code == EEXIST) {
put_inode(rip); /* can't make dir: it already exists */
put_inode(ldirp);
return(err_code);
}
/* Get the inode numbers for . and .. to enter in the directory. */
dotdot = ldirp->i_num; /* parent's inode number */
dot = rip->i_num; /* inode number of the new dir itself */
/* Now make dir entries for . and .. unless the disk is completely full. */
/* Use dot1 and dot2, so the mode of the directory isn't important. */
rip->i_mode = fs_m_in.REQ_MODE; /* set mode */
r1 = search_dir(rip, dot1, &dot, ENTER); /* enter . in the new dir */
r2 = search_dir(rip, dot2, &dotdot, ENTER); /* enter .. in the new dir */
/* If both . and .. were successfully entered, increment the link counts. */
if (r1 == OK && r2 == OK) {
/* Normal case. It was possible to enter . and .. in the new dir. */
rip->i_nlinks++; /* this accounts for . */
ldirp->i_nlinks++; /* this accounts for .. */
ldirp->i_dirt = DIRTY; /* mark parent's inode as dirty */
} else {
/* It was not possible to enter . or .. probably disk was full -
* links counts haven't been touched.
*/
if(search_dir(ldirp, lastc, (ino_t *) 0, DELETE) != OK)
panic(__FILE__, "Dir disappeared ", rip->i_num);
rip->i_nlinks--; /* undo the increment done in new_node() */
}
rip->i_dirt = DIRTY; /* either way, i_nlinks has changed */
put_inode(ldirp); /* return the inode of the parent dir */
put_inode(rip); /* return the inode of the newly made dir */
return(err_code); /* new_node() always sets 'err_code' */
}
/*===========================================================================*
* fs_mkdir_s *
*===========================================================================*/
PUBLIC int fs_mkdir_s()
PUBLIC int fs_mkdir()
{
int r1, r2; /* status codes */
ino_t dot, dotdot; /* inode numbers for . and .. */
@ -428,28 +119,26 @@ PUBLIC int fs_mkdir_s()
/* Copy the last component and set up caller's user and group id */
len = MFS_MIN(fs_m_in.REQ_PATH_LEN, sizeof(lastc));
err_code = sys_safecopyfrom(FS_PROC_NR, fs_m_in.REQ_GRANT, 0,
(vir_bytes) lastc, (phys_bytes) len, D);
if (err_code != OK) return err_code;
(vir_bytes) lastc, (phys_bytes) len, D);
if(err_code != OK) return(err_code);
MFS_NUL(lastc, len, sizeof(lastc));
caller_uid = fs_m_in.REQ_UID;
caller_gid = fs_m_in.REQ_GID;
/* Get last directory inode */
if ((ldirp = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) {
printf("MFS(%d) get_inode for parent dir by mkdir() failed\n", SELF_E);
return ENOENT;
}
if((ldirp = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE)
return(ENOENT);
/* Next make the inode. If that fails, return error code. */
rip = new_node_s(ldirp, lastc, fs_m_in.REQ_MODE, (zone_t) 0);
if (rip == NIL_INODE || err_code == EEXIST) {
put_inode(rip); /* can't make dir: it already exists */
put_inode(ldirp);
return(err_code);
rip = new_node(ldirp, lastc, fs_m_in.REQ_MODE, (zone_t) 0);
if(rip == NIL_INODE || err_code == EEXIST) {
put_inode(rip); /* can't make dir: it already exists */
put_inode(ldirp);
return(err_code);
}
/* Get the inode numbers for . and .. to enter in the directory. */
dotdot = ldirp->i_num; /* parent's inode number */
dot = rip->i_num; /* inode number of the new dir itself */
@ -457,23 +146,22 @@ printf("MFS(%d) get_inode for parent dir by mkdir() failed\n", SELF_E);
/* Now make dir entries for . and .. unless the disk is completely full. */
/* Use dot1 and dot2, so the mode of the directory isn't important. */
rip->i_mode = fs_m_in.REQ_MODE; /* set mode */
r1 = search_dir_nocheck(rip, dot1, &dot, ENTER); /* enter . in the new dir */
r2 = search_dir_nocheck(rip, dot2, &dotdot, ENTER); /* enter .. in the new
dir */
r1 = search_dir(rip, dot1, &dot, ENTER, IGN_PERM);/* enter . in the new dir*/
r2 = search_dir(rip, dot2, &dotdot, ENTER, IGN_PERM); /* enter .. in the new
dir */
/* If both . and .. were successfully entered, increment the link counts. */
if (r1 == OK && r2 == OK) {
/* Normal case. It was possible to enter . and .. in the new dir. */
rip->i_nlinks++; /* this accounts for . */
ldirp->i_nlinks++; /* this accounts for .. */
ldirp->i_dirt = DIRTY; /* mark parent's inode as dirty */
/* Normal case. It was possible to enter . and .. in the new dir. */
rip->i_nlinks++; /* this accounts for . */
ldirp->i_nlinks++; /* this accounts for .. */
ldirp->i_dirt = DIRTY; /* mark parent's inode as dirty */
} else {
/* It was not possible to enter . or .. probably disk was full -
* links counts haven't been touched.
*/
if(search_dir_nocheck(ldirp, lastc, (ino_t *) 0, DELETE) != OK)
panic(__FILE__, "Dir disappeared ", rip->i_num);
rip->i_nlinks--; /* undo the increment done in new_node() */
/* It was not possible to enter . or .. probably disk was full -
* links counts haven't been touched. */
if(search_dir(ldirp, lastc, (ino_t *) 0, DELETE, IGN_PERM) != OK)
panic(__FILE__, "Dir disappeared ", rip->i_num);
rip->i_nlinks--; /* undo the increment done in new_node() */
}
rip->i_dirt = DIRTY; /* either way, i_nlinks has changed */
@ -484,9 +172,9 @@ printf("MFS(%d) get_inode for parent dir by mkdir() failed\n", SELF_E);
/*===========================================================================*
* fs_slink_o *
* fs_slink *
*===========================================================================*/
PUBLIC int fs_slink_o()
PUBLIC int fs_slink()
{
phys_bytes len;
struct inode *sip; /* inode containing symbolic link */
@ -498,139 +186,60 @@ PUBLIC int fs_slink_o()
caller_uid = fs_m_in.REQ_UID;
caller_gid = fs_m_in.REQ_GID;
/* Copy the link name's last component */
len = MFS_MIN(fs_m_in.REQ_PATH_LEN, sizeof(string));
r = sys_datacopy(FS_PROC_NR, (vir_bytes) fs_m_in.REQ_PATH,
SELF, (vir_bytes) string, (phys_bytes) len);
if (r != OK) return r;
MFS_NUL(string, len, sizeof(string));
/* Temporarily open the dir. */
if ( (ldirp = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) {
return(EINVAL);
}
/* Create the inode for the symlink. */
sip = new_node_o(ldirp, string, (mode_t) (I_SYMBOLIC_LINK | RWX_MODES),
(zone_t) 0);
/* Allocate a disk block for the contents of the symlink.
* Copy contents of symlink (the name pointed to) into first disk block.
*/
if ((r = err_code) == OK) {
r = (bp = new_block(sip, (off_t) 0)) == NIL_BUF ? err_code :
sys_vircopy(fs_m_in.REQ_WHO_E, D, (vir_bytes) fs_m_in.REQ_USER_ADDR,
SELF, D, (vir_bytes) bp->b_data,
(vir_bytes) fs_m_in.REQ_SLENGTH);
if(r == OK) {
bp->b_data[_MIN_BLOCK_SIZE-1] = '\0';
sip->i_size = strlen(bp->b_data);
/*if(sip->i_size != m_in.name1_length-1) {*/
if(sip->i_size != fs_m_in.REQ_SLENGTH) {
/* This can happen if the user provides a buffer
* with a \0 in it. This can cause a lot of trouble
* when the symlink is used later. We could just use
* the strlen() value, but we want to let the user
* know he did something wrong. ENAMETOOLONG doesn't
* exactly describe the error, but there is no
* ENAMETOOWRONG.
*/
r = ENAMETOOLONG;
}
}
put_block(bp, DIRECTORY_BLOCK); /* put_block() accepts NIL_BUF. */
if (r != OK) {
sip->i_nlinks = 0;
if (search_dir(ldirp, string, (ino_t *) 0, DELETE) != OK)
panic(__FILE__, "Symbolic link vanished", NO_NUM);
}
}
/* put_inode() accepts NIL_INODE as a noop, so the below are safe. */
put_inode(sip);
put_inode(ldirp);
return(r);
}
/*===========================================================================*
* fs_slink_s *
*===========================================================================*/
PUBLIC int fs_slink_s()
{
phys_bytes len;
struct inode *sip; /* inode containing symbolic link */
struct inode *ldirp; /* directory containing link */
register int r; /* error code */
char string[NAME_MAX]; /* last component of the new dir's path name */
struct buf *bp; /* disk buffer for link */
caller_uid = fs_m_in.REQ_UID;
caller_gid = fs_m_in.REQ_GID;
#if 0
printf("mfs:fs_slink_s: creating link in dir inode %d dev 0x%x\n",
fs_m_in.REQ_INODE_NR, fs_dev);
#endif
/* Copy the link name's last component */
len = MFS_MIN(fs_m_in.REQ_PATH_LEN, sizeof(string));
r = sys_safecopyfrom(FS_PROC_NR, fs_m_in.REQ_GRANT, 0,
(vir_bytes) string, (phys_bytes) len, D);
if (r != OK) return r;
(vir_bytes) string, (phys_bytes) len, D);
if (r != OK) return(r);
MFS_NUL(string, len, sizeof(string));
/* Temporarily open the dir. */
if ( (ldirp = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) {
return(EINVAL);
}
if( (ldirp = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE)
return(EINVAL);
/* Create the inode for the symlink. */
sip = new_node_s(ldirp, string, (mode_t) (I_SYMBOLIC_LINK | RWX_MODES),
(zone_t) 0);
sip = new_node(ldirp, string, (mode_t) (I_SYMBOLIC_LINK | RWX_MODES),
(zone_t) 0);
/* Allocate a disk block for the contents of the symlink.
* Copy contents of symlink (the name pointed to) into first disk block.
*/
if ((r = err_code) == OK) {
r = (bp = new_block(sip, (off_t) 0)) == NIL_BUF ? err_code :
sys_safecopyfrom(FS_PROC_NR, fs_m_in.REQ_GRANT2, 0,
(vir_bytes) bp->b_data, (vir_bytes) fs_m_in.REQ_SLENGTH, D);
* Copy contents of symlink (the name pointed to) into first disk block. */
if( (r = err_code) == OK) {
r = (bp = new_block(sip, (off_t) 0)) == NIL_BUF ? err_code :
sys_safecopyfrom(FS_PROC_NR, fs_m_in.REQ_GRANT3, 0,
(vir_bytes) bp->b_data,
(vir_bytes) fs_m_in.REQ_MEM_SIZE, D);
if(r == OK) {
bp->b_data[_MIN_BLOCK_SIZE-1] = '\0';
sip->i_size = strlen(bp->b_data);
if(sip->i_size != fs_m_in.REQ_SLENGTH) {
/* This can happen if the user provides a buffer
* with a \0 in it. This can cause a lot of trouble
* when the symlink is used later. We could just use
* the strlen() value, but we want to let the user
* know he did something wrong. ENAMETOOLONG doesn't
* exactly describe the error, but there is no
* ENAMETOOWRONG.
*/
r = ENAMETOOLONG;
}
}
if(r == OK) {
bp->b_data[_MIN_BLOCK_SIZE-1] = '\0';
sip->i_size = strlen(bp->b_data);
if(sip->i_size != fs_m_in.REQ_MEM_SIZE) {
/* This can happen if the user provides a buffer
* with a \0 in it. This can cause a lot of trouble
* when the symlink is used later. We could just use
* the strlen() value, but we want to let the user
* know he did something wrong. ENAMETOOLONG doesn't
* exactly describe the error, but there is no
* ENAMETOOWRONG.
*/
r = ENAMETOOLONG;
}
}
put_block(bp, DIRECTORY_BLOCK); /* put_block() accepts NIL_BUF. */
put_block(bp, DIRECTORY_BLOCK); /* put_block() accepts NIL_BUF. */
if (r != OK) {
sip->i_nlinks = 0;
if (search_dir_nocheck(ldirp, string, (ino_t *) 0, DELETE) != OK)
panic(__FILE__, "Symbolic link vanished", NO_NUM);
}
if(r != OK) {
sip->i_nlinks = 0;
if(search_dir(ldirp, string, (ino_t *) 0, DELETE,
IGN_PERM) != OK)
panic(__FILE__, "Symbolic link vanished", NO_NUM);
}
}
/* put_inode() accepts NIL_INODE as a noop, so the below are safe. */
put_inode(sip);
put_inode(ldirp);
return(r);
}
@ -646,23 +255,17 @@ PUBLIC int fs_newnode()
caller_uid = fs_m_in.REQ_UID;
caller_gid = fs_m_in.REQ_GID;
bits= fs_m_in.REQ_MODE;
bits = fs_m_in.REQ_MODE;
/* Try to allocate the inode */
if ( (rip = alloc_inode(fs_dev, bits) ) == NIL_INODE) {
return err_code;
}
if( (rip = alloc_inode(fs_dev, bits) ) == NIL_INODE)
return err_code;
switch (bits & S_IFMT)
{
case S_IFBLK:
case S_IFCHR:
rip->i_zone[0] = fs_m_in.REQ_DEVx; /* major/minor device numbers */
break;
case S_IFIFO:
rip->i_pipe = I_PIPE;
break;
switch (bits & S_IFMT) {
case S_IFBLK:
case S_IFCHR:
rip->i_zone[0] = fs_m_in.REQ_DEV; /* major/minor dev numbers*/
break;
}
rw_inode(rip, WRITING); /* mark inode as allocated */
@ -671,21 +274,19 @@ PUBLIC int fs_newnode()
/* Fill in the fields of the response message */
fs_m_out.RES_INODE_NR = rip->i_num;
fs_m_out.RES_MODE = rip->i_mode;
fs_m_out.RES_INODE_INDEX = (rip - &inode[0]);
fs_m_out.RES_FILE_SIZE = rip->i_size;
fs_m_out.RES_FILE_SIZE_LO = rip->i_size;
fs_m_out.RES_UID = rip->i_uid;
fs_m_out.RES_GID = rip->i_gid;
fs_m_out.RES_DEV = (dev_t) rip->i_zone[0];
return OK;
return(OK);
}
/*===========================================================================*
* new_node_o *
* new_node *
*===========================================================================*/
PRIVATE struct inode *new_node_o(struct inode *ldirp,
PRIVATE struct inode *new_node(struct inode *ldirp,
char *string, mode_t bits, zone_t z0)
{
/* New_node() is called by fs_open(), fs_mknod(), and fs_mkdir().
@ -703,7 +304,7 @@ PRIVATE struct inode *new_node_o(struct inode *ldirp,
register int r;
/* Get final component of the path. */
rip = advance_o(&ldirp, string);
rip = advance(ldirp, string, IGN_PERM);
if (S_ISDIR(bits) &&
(ldirp)->i_nlinks >= ((ldirp)->i_sp->s_version == V1 ?
@ -730,7 +331,7 @@ PRIVATE struct inode *new_node_o(struct inode *ldirp,
rw_inode(rip, WRITING); /* force inode to disk now */
/* New inode acquired. Try to make directory entry. */
if ((r = search_dir(ldirp, string, &rip->i_num, ENTER)) != OK) {
if((r=search_dir(ldirp, string, &rip->i_num, ENTER, IGN_PERM)) != OK) {
rip->i_nlinks--; /* pity, have to free disk inode */
rip->i_dirt = DIRTY; /* dirty inodes are written out */
put_inode(rip); /* this call frees the inode */
@ -738,81 +339,11 @@ PRIVATE struct inode *new_node_o(struct inode *ldirp,
return(NIL_INODE);
}
} else {
} else if (err_code == EENTERMOUNT || err_code == ELEAVEMOUNT) {
r = EEXIST;
} else {
/* Either last component exists, or there is some problem. */
if (rip != NIL_INODE || err_code == EENTERMOUNT ||
err_code == ELEAVEMOUNT)
r = EEXIST;
else
r = err_code;
}
/* The caller has to return the directory inode (*ldirp). */
err_code = r;
return(rip);
}
/*===========================================================================*
* new_node_s *
*===========================================================================*/
PRIVATE struct inode *new_node_s(struct inode *ldirp,
char *string, mode_t bits, zone_t z0)
{
/* New_node() is called by fs_open(), fs_mknod(), and fs_mkdir().
* In all cases it allocates a new inode, makes a directory entry for it in
* the ldirp directory with string name, and initializes it.
* It returns a pointer to the inode if it can do this;
* otherwise it returns NIL_INODE. It always sets 'err_code'
* to an appropriate value (OK or an error code).
*
* The parsed path rest is returned in 'parsed' if parsed is nonzero. It
* has to hold at least NAME_MAX bytes.
*/
register struct inode *rip;
register int r;
/* Get final component of the path. */
rip = advance_nocheck(&ldirp, string);
if (S_ISDIR(bits) &&
(ldirp)->i_nlinks >= ((ldirp)->i_sp->s_version == V1 ?
CHAR_MAX : SHRT_MAX)) {
/* New entry is a directory, alas we can't give it a ".." */
put_inode(rip);
err_code = EMLINK;
return(NIL_INODE);
}
if ( rip == NIL_INODE && err_code == ENOENT) {
/* Last path component does not exist. Make new directory entry. */
if ( (rip = alloc_inode((ldirp)->i_dev, bits)) == NIL_INODE) {
/* Can't creat new inode: out of inodes. */
return(NIL_INODE);
}
/* Force inode to the disk before making directory entry to make
* the system more robust in the face of a crash: an inode with
* no directory entry is much better than the opposite.
*/
rip->i_nlinks++;
rip->i_zone[0] = z0; /* major/minor device numbers */
rw_inode(rip, WRITING); /* force inode to disk now */
/* New inode acquired. Try to make directory entry. */
if ((r = search_dir_nocheck(ldirp, string, &rip->i_num, ENTER)) != OK) {
rip->i_nlinks--; /* pity, have to free disk inode */
rip->i_dirt = DIRTY; /* dirty inodes are written out */
put_inode(rip); /* this call frees the inode */
err_code = r;
return(NIL_INODE);
}
} else {
/* Either last component exists, or there is some problem. */
if (rip != NIL_INODE || err_code == EENTERMOUNT ||
err_code == ELEAVEMOUNT)
if (rip != NIL_INODE)
r = EEXIST;
else
r = err_code;
@ -831,14 +362,12 @@ PUBLIC int fs_inhibread()
{
struct inode *rip;
if ((rip = find_inode(fs_dev, fs_m_in.REQ_INODE_NR))== NIL_INODE){
printf("FSinhibread: couldn't find inode %d\n", fs_m_in.REQ_INODE_NR);
return EINVAL;
}
if((rip = find_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE)
return(EINVAL);
/* inhibit read ahead */
rip->i_seek = ISEEK;
return OK;
return(OK);
}

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 <unistd.h>
#include <minix/callnr.h>
#include "buf.h"
#include "inode.h"
#include "super.h"
#include <minix/vfsif.h>
FORWARD _PROTOTYPE( in_group, (gid_t grp) );
/*===========================================================================*
* fs_chmod *
@ -21,10 +20,8 @@ PUBLIC int fs_chmod()
register int r;
/* Temporarily open the file. */
if ( (rip = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) {
printf("MFS(%d) get_inode by fs_chmod() failed\n", SELF_E);
return(EINVAL);
}
if( (rip = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE)
return(EINVAL);
/* Now make the change. Clear setgid bit if file is not in caller's grp */
rip->i_mode = (rip->i_mode & ~ALL_MODES) | (fs_m_in.REQ_MODE & ALL_MODES);
@ -46,57 +43,28 @@ PUBLIC int fs_chown()
{
register struct inode *rip;
register int r;
/* Temporarily open the file. */
caller_uid = fs_m_in.REQ_UID;
caller_gid = fs_m_in.REQ_GID;
/* Temporarily open the file. */
if ( (rip = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) {
printf("MFS(%d) get_inode by fs_chown() failed\n", SELF_E);
return(EINVAL);
}
if( (rip = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE)
return(EINVAL);
/* Not permitted to change the owner of a file on a read-only file sys. */
r = read_only(rip);
if (r == OK) {
rip->i_uid = fs_m_in.REQ_NEW_UID;
rip->i_gid = fs_m_in.REQ_NEW_GID;
rip->i_mode &= ~(I_SET_UID_BIT | I_SET_GID_BIT);
rip->i_update |= CTIME;
rip->i_dirt = DIRTY;
rip->i_uid = fs_m_in.REQ_UID;
rip->i_gid = fs_m_in.REQ_GID;
rip->i_mode &= ~(I_SET_UID_BIT | I_SET_GID_BIT);
rip->i_update |= CTIME;
rip->i_dirt = DIRTY;
}
/* Update caller on current mode, as it may have changed. */
fs_m_out.RES_MODE = rip->i_mode;
put_inode(rip);
return(r);
}
/*===========================================================================*
* fs_access_o *
*===========================================================================*/
PUBLIC int fs_access_o()
{
struct inode *rip;
register int r;
/* Temporarily open the file whose access is to be checked. */
caller_uid = fs_m_in.REQ_UID;
caller_gid = fs_m_in.REQ_GID;
/* Temporarily open the file. */
if ( (rip = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) {
printf("MFS(%d) get_inode by fs_access() failed\n", SELF_E);
return(EINVAL);
}
/* Now check the permissions. */
r = forbidden(rip, (mode_t) fs_m_in.REQ_MODE);
put_inode(rip);
return(r);
}
/*===========================================================================*
* forbidden *
@ -112,22 +80,7 @@ PUBLIC int forbidden(register struct inode *rip, mode_t access_desired)
register struct inode *old_rip = rip;
register struct super_block *sp;
register mode_t bits, perm_bits;
int r, shift, type;
if (caller_uid == (uid_t)-1 && caller_gid == (uid_t)-1)
{
printf(
"forbidden: warning caller_uid and caller_gid not initialized\n");
}
/*
if (rip->i_mount == I_MOUNT)
for (sp = &super_block[1]; sp < &super_block[NR_SUPERS]; sp++)
if (sp->s_imount == rip) {
rip = get_inode(sp->s_dev, ROOT_INODE);
break;
}
*/
int r, shift;
/* Isolate the relevant rwx bits from the mode. */
bits = rip->i_mode;
@ -143,7 +96,8 @@ PUBLIC int forbidden(register struct inode *rip, mode_t access_desired)
perm_bits = R_BIT | W_BIT;
} else {
if (caller_uid == rip->i_uid) shift = 6; /* owner */
else if (caller_gid == rip->i_gid ) shift = 3; /* group */
else if (caller_gid == rip->i_gid) shift = 3; /* group */
else if (in_group(rip->i_gid) == OK) shift = 3; /* other groups */
else shift = 0; /* other */
perm_bits = (bits >> shift) & (R_BIT | W_BIT | X_BIT);
}
@ -155,22 +109,30 @@ PUBLIC int forbidden(register struct inode *rip, mode_t access_desired)
/* Check to see if someone is trying to write on a file system that is
* mounted read-only.
*/
type = rip->i_mode & I_TYPE;
if (r == OK)
if (access_desired & W_BIT)
r = read_only(rip);
#if 0
if (r != OK) printf(
"forbidden: caller uid/gid %d/%d object uid/gid %d/%d, returning %d\n",
caller_uid, caller_gid, rip->i_uid, rip->i_gid, r);
#endif
if (rip != old_rip) put_inode(rip);
return(r);
}
/*===========================================================================*
* in_group *
*===========================================================================*/
PRIVATE int in_group(gid_t grp)
{
int i;
for(i = 0; i < credentials.vu_ngroups; i++)
if (credentials.vu_sgroups[i] == grp)
return(OK);
return(EINVAL);
}
/*===========================================================================*
* read_only *
*===========================================================================*/
@ -187,5 +149,3 @@ struct inode *ip; /* ptr to inode whose file sys is to be cked */
return(sp->s_rd_only ? EROFS : OK);
}

View file

@ -1,7 +1,5 @@
/* Function prototypes. */
#include "timers.h"
/* Structs used in prototypes must be declared as such first. */
struct buf;
struct filp;
@ -9,32 +7,9 @@ struct inode;
struct super_block;
int fs_putnode(void);
int fs_getnode(void);
int fs_pipe(void);
int fs_clone_opcl(void);
int fs_new_driver(void);
int fs_ftrunc(void);
int fs_chown(void);
int fs_chmod(void);
int fs_inhibread(void);
int fs_stat(void);
int fs_utime(void);
int fs_fstatfs(void);
int fs_unmount(void);
int fs_trunc(void);
int fs_sync(void);
int fs_stime(void);
int fs_getdents_o(void);
int fs_getdents(void);
int fs_flush(void);
void init_inode_cache(void);
/* cache.c */
_PROTOTYPE( zone_t alloc_zone, (Dev_t dev, zone_t z) );
_PROTOTYPE( void buf_pool, (void) );
_PROTOTYPE( void flushall, (Dev_t dev) );
_PROTOTYPE( void free_zone, (Dev_t dev, zone_t numb) );
_PROTOTYPE( struct buf *get_block, (Dev_t dev, block_t block,int only_search));
@ -43,7 +18,6 @@ _PROTOTYPE( void put_block, (struct buf *bp, int block_type) );
_PROTOTYPE( void set_blocksize, (int blocksize) );
_PROTOTYPE( void rw_scattered, (Dev_t dev,
struct buf **bufq, int bufqsize, int rw_flag) );
_PROTOTYPE( void buf_pool, (void) );
/* device.c */
_PROTOTYPE( int block_dev_io, (int op, Dev_t dev, int proc, void *buf,
@ -51,14 +25,17 @@ _PROTOTYPE( int block_dev_io, (int op, Dev_t dev, int proc, void *buf,
_PROTOTYPE( int dev_open, (endpoint_t driver_e, Dev_t dev, int proc,
int flags) );
_PROTOTYPE( void dev_close, (endpoint_t driver_e, Dev_t dev) );
_PROTOTYPE( int fs_clone_opcl, (void) );
_PROTOTYPE( int fs_new_driver, (void) );
/* inode.c */
_PROTOTYPE( struct inode *find_inode, (Dev_t dev, int numb) );
_PROTOTYPE( struct inode *alloc_inode, (dev_t dev, mode_t bits) );
_PROTOTYPE( void dup_inode, (struct inode *ip) );
_PROTOTYPE( struct inode *find_inode, (Dev_t dev, int numb) );
_PROTOTYPE( void free_inode, (Dev_t dev, Ino_t numb) );
_PROTOTYPE( int fs_getnode, (void) );
_PROTOTYPE( int fs_putnode, (void) );
_PROTOTYPE( void init_inode_cache, (void) );
_PROTOTYPE( struct inode *get_inode, (Dev_t dev, int numb) );
_PROTOTYPE( void put_inode, (struct inode *rip) );
_PROTOTYPE( void update_times, (struct inode *rip) );
@ -66,66 +43,53 @@ _PROTOTYPE( void rw_inode, (struct inode *rip, int rw_flag) );
_PROTOTYPE( void wipe_inode, (struct inode *rip) );
/* link.c */
int fs_link_o(void);
int fs_link_s(void);
int fs_rdlink_o(void);
int fs_rdlink_so(void);
int fs_rdlink_s(void);
int fs_rename_o(void);
int fs_rename_s(void);
int fs_unlink_o(void);
int fs_unlink_s(void);
_PROTOTYPE( int truncate_inode, (struct inode *rip, off_t len) );
_PROTOTYPE( int freesp_inode, (struct inode *rip, off_t st, off_t end) );
_PROTOTYPE( int fs_ftrunc, (void) );
_PROTOTYPE( int fs_link, (void) );
_PROTOTYPE( int fs_rdlink, (void) );
_PROTOTYPE( int fs_rename, (void) );
_PROTOTYPE( int fs_unlink, (void) );
_PROTOTYPE( int truncate_inode, (struct inode *rip, off_t len) );
/* main.c */
_PROTOTYPE( void reply, (int who, message *m_out) );
/* misc.c */
_PROTOTYPE( int fs_flush, (void) );
_PROTOTYPE( int fs_sync, (void) );
/* mount.c */
int fs_mountpoint_o(void);
int fs_mountpoint_s(void);
int fs_readsuper_o(void);
int fs_readsuper_s(void);
_PROTOTYPE( int unmount, (Dev_t dev) );
_PROTOTYPE( int fs_mountpoint, (void) );
_PROTOTYPE( int fs_readsuper, (void) );
_PROTOTYPE( int fs_unmount, (void) );
/* open.c */
int fs_create_o(void);
int fs_create_s(void);
int fs_mkdir_o(void);
int fs_mkdir_s(void);
int fs_mknod_o(void);
int fs_mknod_s(void);
int fs_slink_o(void);
int fs_slink_s(void);
int fs_newnode(void);
_PROTOTYPE( int fs_create, (void) );
_PROTOTYPE( int fs_inhibread, (void) );
_PROTOTYPE( int fs_mkdir, (void) );
_PROTOTYPE( int fs_mknod, (void) );
_PROTOTYPE( int fs_newnode, (void) );
_PROTOTYPE( int fs_slink, (void) );
/* path.c */
int lookup_o(void);
int fs_lookup_s(void);
_PROTOTYPE( struct inode *advance_o,(struct inode **dirp,
char string[NAME_MAX]) );
_PROTOTYPE( struct inode *advance_nocheck,(struct inode **dirp,
char string[NAME_MAX]) );
_PROTOTYPE( int search_dir, (struct inode *ldir_ptr,
char string [NAME_MAX], ino_t *numb, int flag) );
_PROTOTYPE( int search_dir_nocheck, (struct inode *ldir_ptr,
char string [NAME_MAX], ino_t *numb, int flag) );
_PROTOTYPE( struct inode *eat_path_o, (char *path) );
_PROTOTYPE( struct inode *last_dir_o, (char *path, char string [NAME_MAX]));
_PROTOTYPE( struct inode *parse_path_o, (char *path,
char string[NAME_MAX], int action) );
_PROTOTYPE( int fs_lookup, (void) );
_PROTOTYPE( struct inode *advance, (struct inode *dirp,
char string[NAME_MAX], int chk_perm) );
_PROTOTYPE( int search_dir, (struct inode *ldir_ptr,
char string [NAME_MAX], ino_t *numb, int flag,
int check_permissions) );
/* protect.c */
int fs_access_o(void);
_PROTOTYPE( int fs_chmod, (void) );
_PROTOTYPE( int fs_chown, (void) );
_PROTOTYPE( int fs_getdents, (void) );
_PROTOTYPE( int forbidden, (struct inode *rip, mode_t access_desired) );
_PROTOTYPE( int read_only, (struct inode *ip) );
/* read.c */
int fs_breadwrite_o(void);
int fs_breadwrite_s(void);
int fs_readwrite_o(void);
int fs_readwrite_s(void);
_PROTOTYPE( int fs_breadwrite, (void) );
_PROTOTYPE( int fs_readwrite, (void) );
_PROTOTYPE( struct buf *rahead, (struct inode *rip, block_t baseblock,
u64_t position, unsigned bytes_ahead) );
_PROTOTYPE( void read_ahead, (void) );
@ -133,29 +97,37 @@ _PROTOTYPE( block_t read_map, (struct inode *rip, off_t pos) );
_PROTOTYPE( int read_write, (int rw_flag) );
_PROTOTYPE( zone_t rd_indir, (struct buf *bp, int index) );
/* stadir.c */
_PROTOTYPE( int fs_fstatfs, (void) );
_PROTOTYPE( int fs_stat, (void) );
/* super.c */
_PROTOTYPE( bit_t alloc_bit, (struct super_block *sp, int map, bit_t origin));
_PROTOTYPE( void free_bit, (struct super_block *sp, int map,
bit_t bit_returned) );
_PROTOTYPE( int get_block_size, (dev_t dev) );
_PROTOTYPE( struct super_block *get_super, (Dev_t dev) );
_PROTOTYPE( int mounted, (struct inode *rip) );
_PROTOTYPE( int read_super, (struct super_block *sp) );
_PROTOTYPE( int get_block_size, (dev_t dev) );
/* time.c */
_PROTOTYPE( int fs_utime, (void) );
/* utility.c */
_PROTOTYPE( time_t clock_time, (void) );
_PROTOTYPE( unsigned conv2, (int norm, int w) );
_PROTOTYPE( long conv4, (int norm, long x) );
_PROTOTYPE( int no_sys, (void) );
_PROTOTYPE( void mfs_nul_f, (char *file, int line, char *str, int len, int maxlen));
_PROTOTYPE( int fetch_name, (char *path, int len, int flag) );
_PROTOTYPE( void mfs_nul_f, (char *file, int line, char *str, int len,
int maxlen) );
_PROTOTYPE( int mfs_min_f, (char *file, int line, int len1, int len2) );
_PROTOTYPE( void sanitycheck, (char *file, int line) );
_PROTOTYPE( int no_sys, (void) );
_PROTOTYPE( int isokendpt_f, (char *f, int l, int e, int *p, int ft));
_PROTOTYPE( void sanitycheck, (char *file, int line) );
#define SANITYCHECK sanitycheck(__FILE__, __LINE__)
/* write.c */
_PROTOTYPE( void clear_zone, (struct inode *rip, off_t pos, int flag) );
_PROTOTYPE( int do_write, (void) );
_PROTOTYPE( struct buf *new_block, (struct inode *rip, off_t position) );
_PROTOTYPE( void zero_block, (struct buf *bp) );
_PROTOTYPE( int write_map, (struct inode *, off_t, zone_t, int) );

View file

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

View file

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

View file

@ -142,6 +142,7 @@ bit_t bit_returned; /* number of bit to insert into the map */
put_block(bp, MAP_BLOCK);
}
/*===========================================================================*
* get_super *
*===========================================================================*/
@ -154,9 +155,10 @@ dev_t dev; /* device number whose super_block is sought */
if(superblock.s_dev != dev)
panic(__FILE__,"wrong superblock", (int) dev);
return &superblock;
return(&superblock);
}
/*===========================================================================*
* get_block_size *
*===========================================================================*/
@ -165,43 +167,11 @@ PUBLIC int get_block_size(dev_t dev)
if (dev == NO_DEV)
panic(__FILE__,"request for block size of NO_DEV", NO_NUM);
return fs_block_size;
return(fs_block_size);
#if 0
if(superblock.s_dev == dev) {
if(superblock.s_block_size != fs_block_size) {
printf("mounted blocksize: %d my blocksize: %d\n",
superblock.s_block_size, fs_block_size);
}
ASSERT(superblock.s_block_size == fs_block_size);
return(superblock.s_block_size);
}
/* not the mounted filesystem? use this block size then. */
return _MIN_BLOCK_SIZE;
#endif
}
/*===========================================================================*
* mounted *
*===========================================================================*/
/* Report on whether the given inode is on a mounted (or ROOT) file system. */
/*
PUBLIC int mounted(rip)
register struct inode *rip;
{
register dev_t dev;
dev = (dev_t) rip->i_zone[0];
if (dev == root_dev) return(TRUE);
if(superblock.s_dev == dev)
return TRUE;
return(FALSE);
}
*/
/*===========================================================================*
* read_super *
*===========================================================================*/
@ -222,9 +192,9 @@ register struct super_block *sp; /* pointer to a superblock */
r = block_dev_io(MFS_DEV_READ, dev, SELF_E,
sbbuf, cvu64(SUPER_BLOCK_BYTES), _MIN_BLOCK_SIZE, 0);
if (r != _MIN_BLOCK_SIZE) {
return EINVAL;
}
if (r != _MIN_BLOCK_SIZE)
return(EINVAL);
memcpy(sp, sbbuf, sizeof(*sp));
sp->s_dev = NO_DEV; /* restore later */
magic = sp->s_magic; /* determines file system type */
@ -282,26 +252,23 @@ register struct super_block *sp; /* pointer to a superblock */
sp->s_nindirs = V2_INDIRECTS(sp->s_block_size);
}
if (sp->s_block_size < _MIN_BLOCK_SIZE) {
return EINVAL;
}
if ((sp->s_block_size % 512) != 0) {
return EINVAL;
}
if (SUPER_SIZE > sp->s_block_size) {
return EINVAL;
}
if (sp->s_block_size < _MIN_BLOCK_SIZE)
return(EINVAL);
if ((sp->s_block_size % 512) != 0)
return(EINVAL);
if (SUPER_SIZE > sp->s_block_size)
return(EINVAL);
if ((sp->s_block_size % V2_INODE_SIZE) != 0 ||
(sp->s_block_size % V1_INODE_SIZE) != 0) {
return EINVAL;
return(EINVAL);
}
/* Limit s_max_size to LONG_MAX */
if ((unsigned long)sp->s_max_size > LONG_MAX)
{
printf("read_super: reducing s_max_size to LONG_MAX\n");
sp->s_max_size= LONG_MAX;
}
if ((unsigned long)sp->s_max_size > LONG_MAX)
sp->s_max_size = LONG_MAX;
sp->s_isearch = 0; /* inode searches initially start at 0 */
sp->s_zsearch = 0; /* zone searches initially start at 0 */
@ -322,3 +289,4 @@ register struct super_block *sp; /* pointer to a superblock */
sp->s_dev = dev; /* restore device number */
return(OK);
}

View file

@ -15,59 +15,36 @@
PUBLIC _PROTOTYPE (int (*fs_call_vec[]), (void) ) = {
no_sys, /* 0 not used */
fs_getnode, /* 1 */
no_sys, /* 1 */ /* Was: fs_getnode */
fs_putnode, /* 2 */
fs_slink_s, /* 3 */
fs_pipe, /* 4 */
fs_readwrite_o, /* 5 */ /* read() */
fs_readwrite_o, /* 6 */ /* write() */
fs_clone_opcl, /* 7 */
fs_ftrunc, /* 8 */
fs_chown, /* 9 */
fs_chmod, /* 10 */
fs_access_o, /* 11 */
fs_mknod_o, /* 12 */
fs_mkdir_o, /* 13 */
fs_inhibread, /* 14 */ /* for lseek() */
fs_stat, /* 15 */
fs_create_o, /* 16 */
fs_unlink_o, /* 17 */ /* unlink() */
fs_unlink_o, /* 18 */ /* rmdir() */
fs_utime, /* 19 */
fs_rdlink_so, /* 20 */
fs_fstatfs, /* 21 */
fs_breadwrite_s, /* 22 */
fs_breadwrite_s, /* 23 */
fs_unlink_s, /* 24 */ /* unlink() */
fs_link_o, /* 25 */
fs_slink_o, /* 26 */
fs_rdlink_o, /* 27 */
fs_rename_o, /* 28 */
fs_unlink_s, /* 29 */ /* rmdir() */
fs_mountpoint_o, /* 30 */
fs_readsuper_o, /* 31 */
fs_unmount, /* 32 */
fs_trunc, /* 33 */
fs_sync, /* 34 */
lookup_o, /* 35 */
fs_stime, /* 36 */
fs_new_driver, /* 37 */
fs_breadwrite_o, /* 38 */
fs_breadwrite_o, /* 39 */
fs_getdents_o, /* 40 */
fs_flush, /* 41 */
fs_readwrite_s, /* 42 */
fs_readwrite_s, /* 43 */
fs_mknod_s, /* 44 */
fs_mkdir_s, /* 45 */
fs_create_s, /* 46 */
fs_link_s, /* 47 */
fs_rename_s, /* 48 */
fs_lookup_s, /* 49 */
fs_mountpoint_s, /* 50 */
fs_readsuper_s, /* 51 */
fs_newnode, /* 52 */
fs_rdlink_s, /* 53 */
fs_getdents, /* 54 */
fs_slink, /* 3 */
fs_ftrunc, /* 4 */
fs_chown, /* 5 */
fs_chmod, /* 6 */
fs_inhibread, /* 7 */
fs_stat, /* 8 */
fs_utime, /* 9 */
fs_fstatfs, /* 10 */
fs_breadwrite, /* 11 */
fs_breadwrite, /* 12 */
fs_unlink, /* 13 */
fs_unlink, /* 14 */
fs_unmount, /* 15 */
fs_sync, /* 16 */
fs_new_driver, /* 17 */
fs_flush, /* 18 */
fs_readwrite, /* 19 */
fs_readwrite, /* 20 */
fs_mknod, /* 21 */
fs_mkdir, /* 22 */
fs_create, /* 23 */
fs_link, /* 24 */
fs_rename, /* 25 */
fs_lookup, /* 26 */
fs_mountpoint, /* 27 */
fs_readsuper, /* 28 */
fs_newnode, /* 29 */
fs_rdlink, /* 30 */
fs_getdents, /* 31 */
};

View file

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

View file

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

View file

@ -1,14 +1,12 @@
/* This file is the counterpart of "read.c". It contains the code for writing
* insofar as this is not contained in read_write().
*
* The entry points into this file are
* do_write: call read_write to perform the WRITE system call
* write_map: write a new zone into an inode
* clear_zone: erase a zone in the middle of a file
* new_block: acquire a new block
* zero_block: overwrite a block with zeroes
*
* Updates:
* 2007-06-01: jfdsmit@gmail.com added i_zsearch optimalization
*/
#include "fs.h"
@ -181,6 +179,7 @@ int op; /* special actions */
return(OK);
}
/*===========================================================================*
* wr_indir *
*===========================================================================*/
@ -205,6 +204,7 @@ zone_t zone; /* zone to write */
bp->b_v2_ind[index] = (zone_t) conv4(sp->s_native, (long) zone);
}
/*===========================================================================*
* empty_indir *
*===========================================================================*/
@ -215,20 +215,21 @@ struct super_block *sb; /* superblock of device block resides on */
/* Return nonzero if the indirect block pointed to by bp contains
* only NO_ZONE entries.
*/
int i;
if(sb->s_version == V1) {
for(i = 0; i < V1_INDIRECTS; i++)
if(bp->b_v1_ind[i] != NO_ZONE)
return 0;
} else {
for(i = 0; i < V2_INDIRECTS(sb->s_block_size); i++)
if(bp->b_v2_ind[i] != NO_ZONE)
return 0;
}
int i;
if(sb->s_version == V1) {
for(i = 0; i < V1_INDIRECTS; i++)
if(bp->b_v1_ind[i] != NO_ZONE)
return(0);
} else {
for(i = 0; i < V2_INDIRECTS(sb->s_block_size); i++)
if(bp->b_v2_ind[i] != NO_ZONE)
return(0);
}
return 1;
return(1);
}
/*===========================================================================*
* clear_zone *
*===========================================================================*/
@ -269,6 +270,7 @@ int flag; /* 0 if called by read_write, 1 by new_block */
}
}
/*===========================================================================*
* new_block *
*===========================================================================*/
@ -323,6 +325,7 @@ off_t position; /* file pointer */
return(bp);
}
/*===========================================================================*
* zero_block *
*===========================================================================*/

View file

@ -7,6 +7,7 @@
#include "pm.h"
#include <minix/callnr.h>
#include <minix/endpoint.h>
#include <limits.h>
#include <minix/com.h>
#include <signal.h>
#include "mproc.h"
@ -22,8 +23,32 @@ PUBLIC int do_get()
register struct mproc *rmp = mp;
int r, proc;
int ngroups;
switch(call_nr) {
case GETGROUPS:
ngroups = m_in.grp_no;
if (ngroups > NGROUPS_MAX || ngroups < 0)
return(EINVAL);
if (ngroups == 0) {
r = rmp->mp_ngroups;
break;
}
if (ngroups < rmp->mp_ngroups)
/* Asking for less groups than available */
return(EINVAL);
r = sys_datacopy(SELF, (vir_bytes) rmp->mp_sgroups, who_e,
(vir_bytes) m_in.groupsp, ngroups * sizeof(gid_t));
if (r != OK)
return(r);
r = rmp->mp_ngroups;
break;
case GETUID:
r = rmp->mp_realuid;
rmp->mp_reply.reply_res2 = rmp->mp_effuid;
@ -60,7 +85,8 @@ PUBLIC int do_set()
*/
register struct mproc *rmp = mp;
message m;
int r;
int r, i;
int ngroups;
switch(call_nr) {
case SETUID:
@ -92,7 +118,34 @@ PUBLIC int do_set()
m.PM_RID = rmp->mp_realgid;
break;
case SETGROUPS:
if (rmp->mp_effuid != SUPER_USER)
return(EPERM);
ngroups = m_in.grp_no;
if (ngroups > NGROUPS_MAX || ngroups < 0)
return(EINVAL);
if (m_in.groupsp == NULL)
return(EFAULT);
r = sys_datacopy(who_e, (vir_bytes) m_in.groupsp, SELF,
(vir_bytes) rmp->mp_sgroups,
ngroups * sizeof(gid_t));
if (r != OK)
return(r);
for (i = ngroups; i < NGROUPS_MAX; i++)
rmp->mp_sgroups[i] = 0;
rmp->mp_ngroups = ngroups;
m.m_type = PM_SETGROUPS;
m.PM_PROC = rmp->mp_endpoint;
m.PM_GROUP_NO = rmp->mp_ngroups;
m.PM_GROUP_ADDR = rmp->mp_sgroups;
break;
case SETSID:
if (rmp->mp_procgrp == rmp->mp_pid) return(EPERM);
rmp->mp_procgrp = rmp->mp_pid;

View file

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

View file

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

View file

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

View file

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

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

View file

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

View file

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

View file

@ -11,11 +11,9 @@
#include <sys/select.h>
#include <minix/u64.h>
#include <assert.h>
#include "fs.h"
#include "file.h"
#include "fproc.h"
#include "vnode.h"
/*===========================================================================*
@ -64,6 +62,7 @@ PUBLIC int get_fd(int start, mode_t bits, int *k, struct filp **fpt)
return(ENFILE);
}
/*===========================================================================*
* get_filp *
*===========================================================================*/
@ -75,6 +74,7 @@ int fild; /* file descriptor */
return get_filp2(fp, fild);
}
/*===========================================================================*
* get_filp2 *
*===========================================================================*/
@ -86,16 +86,14 @@ int fild; /* file descriptor */
err_code = EBADF;
if (fild < 0 || fild >= OPEN_MAX ) return(NIL_FILP);
if (rfp->fp_filp[fild] == NIL_FILP && FD_ISSET(fild, &rfp->fp_filp_inuse))
{
printf("get_filp2: setting err_code to EIO for proc %d fd %d\n",
rfp->fp_endpoint, fild);
if (rfp->fp_filp[fild] == NIL_FILP && FD_ISSET(fild, &rfp->fp_filp_inuse))
err_code = EIO; /* The filedes is not there, but is not closed either.
*/
}
return(rfp->fp_filp[fild]); /* may also be NIL_FILP */
}
/*===========================================================================*
* find_filp *
*===========================================================================*/
@ -121,20 +119,23 @@ PUBLIC struct filp *find_filp(register struct vnode *vp, mode_t bits)
}
/*===========================================================================*
* inval_filp *
* invalidate *
*===========================================================================*/
PUBLIC int inval_filp(struct filp *fp)
PUBLIC int invalidate(struct filp *fp)
{
int f, fd, n = 0;
for(f = 0; f < NR_PROCS; f++) {
if(fproc[f].fp_pid == PID_FREE) continue;
for(fd = 0; fd < OPEN_MAX; fd++) {
if(fproc[f].fp_filp[fd] && fproc[f].fp_filp[fd] == fp) {
fproc[f].fp_filp[fd] = NIL_FILP;
n++;
}
}
}
/* Invalidate filp. fp_filp_inuse is not cleared, so filp can't be reused
until it is closed first. */
return n;
int f, fd, n = 0;
for(f = 0; f < NR_PROCS; f++) {
if(fproc[f].fp_pid == PID_FREE) continue;
for(fd = 0; fd < OPEN_MAX; fd++) {
if(fproc[f].fp_filp[fd] && fproc[f].fp_filp[fd] == fp) {
fproc[f].fp_filp[fd] = NIL_FILP;
n++;
}
}
}
return(n); /* Report back how often this filp has been invalidated. */
}

View file

@ -23,6 +23,8 @@ EXTERN struct fproc {
uid_t fp_effuid; /* effective user id */
gid_t fp_realgid; /* real group id */
gid_t fp_effgid; /* effective group id */
int fp_ngroups; /* number of supplemental groups */
gid_t fp_sgroups[NGROUPS_MAX];/* supplemental groups */
dev_t fp_tty; /* major/minor of controlling tty */
int fp_fd; /* place to save fd if rd/wr can't finish */
char *fp_buffer; /* place to save buffer if rd/wr can't finish*/

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,4 +1,3 @@
/* This file deals with protection in the file system. It contains the code
* for four system calls that relate to protection.
*
@ -7,9 +6,6 @@
* do_chown: perform the CHOWN and FCHOWN system calls
* do_umask: perform the UMASK system call
* do_access: perform the ACCESS system call
*
* Changes for VFS:
* Jul 2006 (Balazs Gerofi)
*/
#include "fs.h"
@ -18,47 +14,39 @@
#include "file.h"
#include "fproc.h"
#include "param.h"
#include <minix/vfsif.h>
#include "vnode.h"
#include "vmnt.h"
FORWARD _PROTOTYPE( in_group, (gid_t grp) );
/*===========================================================================*
* do_chmod *
*===========================================================================*/
PUBLIC int do_chmod()
{
/* Perform the chmod(name, mode) and fchmod(fd, mode) system calls. */
struct filp *flp;
struct vnode *vp;
int r;
uid_t uid;
gid_t gid;
mode_t new_mode;
if (call_nr == CHMOD) {
/* Perform the chmod(name, mode) system call. */
if (fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code);
/* Request lookup */
r = lookup_vp(0 /*flags*/, 0 /*!use_realuid*/, &vp);
if (r != OK) return r;
/* Temporarily open the file */
if(fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code);
if ((vp = eat_path(PATH_NOFLAGS)) == NIL_VNODE) return(err_code);
} else { /* call_nr == FCHMOD */
/* File is already opened; get a pointer to vnode from filp. */
if (!(flp = get_filp(m_in.fd))) return(err_code);
vp = flp->filp_vno;
dup_vnode(vp);
}
else if (call_nr == FCHMOD) {
if (!(flp = get_filp(m_in.m3_i1))) return err_code;
vp= flp->filp_vno;
dup_vnode(vp);
}
else panic(__FILE__, "do_chmod called with strange call_nr", call_nr);
uid= fp->fp_effuid;
gid= fp->fp_effgid;
/* Only the owner or the super_user may change the mode of a file.
* No one may change the mode of a file on a read-only file system.
*/
if (vp->v_uid != uid && uid != SU_UID)
if (vp->v_uid != fp->fp_effuid && fp->fp_effuid != SU_UID)
r = EPERM;
else
r = read_only(vp);
@ -70,24 +58,23 @@ PUBLIC int do_chmod()
}
/* Now make the change. Clear setgid bit if file is not in caller's grp */
if (uid != SU_UID && vp->v_gid != gid)
if (fp->fp_effuid != SU_UID && vp->v_gid != fp->fp_effgid)
m_in.mode &= ~I_SET_GID_BIT;
/* Issue request */
r = req_chmod(vp->v_fs_e, vp->v_inode_nr, m_in.mode, &new_mode);
if ((r = req_chmod(vp->v_fs_e, vp->v_inode_nr, m_in.mode, &new_mode)) == OK)
vp->v_mode = new_mode;
if (r == OK)
vp->v_mode = new_mode;
put_vnode(vp);
return OK;
return(OK);
}
/*===========================================================================*
* do_chown *
*===========================================================================*/
PUBLIC int do_chown()
{
/* Perform the chmod(name, mode) and fchmod(fd, mode) system calls. */
int inode_nr;
int fs_e;
struct filp *flp;
@ -98,56 +85,43 @@ PUBLIC int do_chown()
mode_t new_mode;
if (call_nr == CHOWN) {
/* Perform the chmod(name, mode) system call. */
if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
/* Request lookup */
r = lookup_vp(0 /*flags*/, 0 /*!use_realuid*/, &vp);
if (r != OK) return r;
}
else if (call_nr == FCHOWN) {
if (!(flp = get_filp(m_in.m1_i1))) return err_code;
vp= flp->filp_vno;
/* Temporarily open the file. */
if(fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
if ((vp = eat_path(PATH_NOFLAGS)) == NIL_VNODE) return(err_code);
} else { /* call_nr == FCHOWN */
/* File is already opened; get a pointer to the vnode from filp. */
if (!(flp = get_filp(m_in.fd))) return(err_code);
vp = flp->filp_vno;
dup_vnode(vp);
}
else panic(__FILE__, "do_chmod called with strange call_nr", call_nr);
uid= fp->fp_effuid;
gid= fp->fp_effgid;
r= OK;
if (uid == SU_UID) {
/* The super user can do anything. */
} else {
/* Regular users can only change groups of their own files. */
if (vp->v_uid != uid)
r = EPERM; /* File does not belong to the caller */
if (vp->v_uid != m_in.owner)
r = EPERM; /* no giving away */
if (gid != m_in.group)
r = EPERM; /* only change to the current gid */
r = read_only(vp);
if (r == OK) {
/* FS is R/W. Whether call is allowed depends on ownership, etc. */
/* The super user can do anything, so check permissions only if we're
a regular user. */
if (fp->fp_effuid != SU_UID) {
/* Regular users can only change groups of their own files. */
if (vp->v_uid != fp->fp_effuid) r = EPERM;
if (vp->v_uid != m_in.owner) r = EPERM; /* no giving away */
if (fp->fp_effgid != m_in.group) r = EPERM;
}
}
if (r == OK)
r = read_only(vp);
if (r != OK) {
put_vnode(vp);
return r;
}
/* Issue request */
r = req_chown(vp->v_fs_e, vp->v_inode_nr, m_in.owner, m_in.group, &new_mode);
if(r == OK) {
vp->v_uid = m_in.owner;
vp->v_gid = m_in.group;
vp->v_mode = new_mode;
if (r == OK) {
/* Do not change uid/gid if new uid/gid is -1. */
uid = (m_in.owner == (uid_t)-1 ? vp->v_uid : m_in.owner);
gid = (m_in.group == (gid_t)-1 ? vp->v_gid : m_in.group);
if ((r = req_chown(vp->v_fs_e, vp->v_inode_nr, uid, gid,
&new_mode)) == OK) {
vp->v_uid = uid;
vp->v_gid = gid;
vp->v_mode = new_mode;
}
}
put_vnode(vp);
return r;
return(r);
}
@ -178,24 +152,22 @@ PUBLIC int do_access()
if ( (m_in.mode & ~(R_OK | W_OK | X_OK)) != 0 && m_in.mode != F_OK)
return(EINVAL);
/* Temporarily open the file. */
if (fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code);
if ((vp = eat_path(PATH_NOFLAGS)) == NIL_VNODE) return(err_code);
/* Request lookup */
r = lookup_vp(0 /*flags*/, TRUE /*use_realuid*/, &vp);
if (r != OK) return r;
r= forbidden(vp, m_in.mode, 1 /*use_realuid*/);
r = forbidden(vp, m_in.mode);
put_vnode(vp);
return r;
return(r);
}
/*===========================================================================*
* forbidden *
*===========================================================================*/
PUBLIC int forbidden(struct vnode *vp, mode_t access_desired, int use_realuid)
PUBLIC int forbidden(struct vnode *vp, mode_t access_desired)
{
/* Given a pointer to an inode, 'rip', and the access desired, determine
/* Given a pointer to an vnode, 'vp', and the access desired, determine
* if the access is allowed, and if not why not. The routine looks up the
* caller's uid in the 'fproc' table. If access is allowed, OK is returned
* if it is forbidden, EACCES is returned.
@ -207,26 +179,13 @@ PUBLIC int forbidden(struct vnode *vp, mode_t access_desired, int use_realuid)
gid_t gid;
int r, shift, type;
if (vp->v_uid == (uid_t)-1 || vp->v_gid == (gid_t)-1)
{
printf("forbidden: bad uid/gid in vnode: inode %d on dev 0x%x\n",
vp->v_inode_nr, vp->v_dev);
printf("forbidden: last allocated at %s, %d\n", vp->v_file, vp->v_line);
return EACCES;
}
if (vp->v_uid == (uid_t) -1 || vp->v_gid == (gid_t) -1) return(EACCES);
/* Isolate the relevant rwx bits from the mode. */
bits = vp->v_mode;
if (use_realuid)
{
uid= fp->fp_realuid;
gid= fp->fp_realgid;
}
else
{
uid= fp->fp_effuid;
gid= fp->fp_effgid;
}
uid = (call_nr == ACCESS ? fp->fp_realuid : fp->fp_effuid);
gid = (call_nr == ACCESS ? fp->fp_realgid : fp->fp_effgid);
if (uid == SU_UID) {
/* Grant read and write permission. Grant search permission for
* directories. Grant execute permission (for non-directories) if
@ -238,17 +197,16 @@ PUBLIC int forbidden(struct vnode *vp, mode_t access_desired, int use_realuid)
else
perm_bits = R_BIT | W_BIT;
} else {
if (uid == vp->v_uid) shift = 6; /* owner */
else if (gid == vp->v_gid ) shift = 3; /* group */
if (uid == vp->v_uid) shift = 6; /* owner */
else if (gid == vp->v_gid) shift = 3; /* group */
else if (in_group(vp->v_gid) == OK) shift = 3; /* suppl. groups */
else shift = 0; /* other */
perm_bits = (bits >> shift) & (R_BIT | W_BIT | X_BIT);
}
/* If access desired is not a subset of what is allowed, it is refused. */
r = OK;
if ((perm_bits | access_desired) != perm_bits) {
r = EACCES;
}
if ((perm_bits | access_desired) != perm_bits) r = EACCES;
/* Check to see if someone is trying to write on a file system that is
* mounted read-only.
@ -261,6 +219,21 @@ PUBLIC int forbidden(struct vnode *vp, mode_t access_desired, int use_realuid)
}
/*===========================================================================*
* in_group *
*===========================================================================*/
PRIVATE int in_group(gid_t grp)
{
int i;
for (i = 0; i < fp->fp_ngroups; i++)
if (fp->fp_sgroups[i] == grp)
return(OK);
return(EINVAL);
}
/*===========================================================================*
* read_only *
*===========================================================================*/

View file

@ -51,10 +51,10 @@ _PROTOTYPE( int pm_exec, (int proc_e, char *path, vir_bytes path_len,
/* filedes.c */
_PROTOTYPE( struct filp *find_filp, (struct vnode *vp, mode_t bits) );
_PROTOTYPE( int get_fd, (int start, mode_t bits, int *k,
struct filp **fpt) );
struct filp **fpt) );
_PROTOTYPE( struct filp *get_filp, (int fild) );
_PROTOTYPE( struct filp *get_filp2, (struct fproc *rfp, int fild) );
_PROTOTYPE( int inval_filp, (struct filp *) );
_PROTOTYPE( int invalidate, (struct filp *) );
/* fscall.c */
_PROTOTYPE( void nested_fs_call, (message *m) );
@ -65,7 +65,7 @@ _PROTOTYPE( int do_unlink, (void) );
_PROTOTYPE( int do_rename, (void) );
_PROTOTYPE( int do_truncate, (void) );
_PROTOTYPE( int do_ftruncate, (void) );
_PROTOTYPE( int truncate_vn, (struct vnode *vp, off_t newsize) );
_PROTOTYPE( int truncate_vnode, (struct vnode *vp, off_t newsize) );
/* lock.c */
_PROTOTYPE( int lock_op, (struct filp *f, int req) );
@ -82,6 +82,7 @@ _PROTOTYPE( int do_fcntl, (void) );
_PROTOTYPE( void pm_fork, (int pproc, int cproc, int cpid) );
_PROTOTYPE( void pm_setgid, (int proc_e, int egid, int rgid) );
_PROTOTYPE( void pm_setuid, (int proc_e, int euid, int ruid) );
_PROTOTYPE( void pm_setgroups, (int proc_e, int ngroups, gid_t *addr) );
_PROTOTYPE( int do_sync, (void) );
_PROTOTYPE( int do_fsync, (void) );
_PROTOTYPE( void pm_reboot, (void) );
@ -114,18 +115,15 @@ _PROTOTYPE( int do_vm_open, (void) );
_PROTOTYPE( int do_vm_close, (void) );
/* path.c */
_PROTOTYPE( int lookup_rel_vp, (struct vnode *start_node, int flags,
int use_realuid, struct vnode **vpp) );
_PROTOTYPE( int lookup_vp, (int flags, int use_realuid,
struct vnode **vpp) );
_PROTOTYPE( int lookup_lastdir_rel, (struct vnode *start_node,
int use_realuid, struct vnode **vpp) );
_PROTOTYPE( int lookup_lastdir, (int use_realuid, struct vnode **vpp) );
_PROTOTYPE( struct vnode *advance, (struct vnode *dirp, int flags) );
_PROTOTYPE( struct vnode *eat_path, (int flags) );
_PROTOTYPE( struct vnode *last_dir, (void) );
/* pipe.c */
_PROTOTYPE( int do_pipe, (void) );
_PROTOTYPE( int map_vnode, (struct vnode *vp) );
_PROTOTYPE( void unpause, (int proc_nr_e) );
_PROTOTYPE( int Xpipe_check, (struct vnode *vp, int rw_flag,
_PROTOTYPE( int pipe_check, (struct vnode *vp, int rw_flag,
int oflags, int bytes, u64_t position, int notouch) );
_PROTOTYPE( void release, (struct vnode *vp, int call_nr, int count) );
_PROTOTYPE( void revive, (int proc_nr, int bytes) );
@ -147,8 +145,7 @@ _PROTOTYPE( int do_access, (void) );
_PROTOTYPE( int do_chmod, (void) );
_PROTOTYPE( int do_chown, (void) );
_PROTOTYPE( int do_umask, (void) );
_PROTOTYPE( int forbidden, (struct vnode *vp,
mode_t access_desired, int use_realuid) );
_PROTOTYPE( int forbidden, (struct vnode *vp, mode_t access_desired) );
_PROTOTYPE( int read_only, (struct vnode *vp) );
/* read.c */
@ -173,14 +170,14 @@ _PROTOTYPE( int req_flush, (endpoint_t fs_e, Dev_t dev) );
_PROTOTYPE( int req_fstatfs, (int fs_e, int who_e, char *buf) );
_PROTOTYPE( int req_ftrunc, (endpoint_t fs_e, ino_t inode_nr,
off_t start, off_t end) );
_PROTOTYPE( int req_getdents, (endpoint_t fs_e, ino_t inode_nr,
off_t pos, cp_grant_id_t gid, size_t size, off_t *pos_change) );
_PROTOTYPE( int req_getdents, (endpoint_t fs_e, ino_t inode_nr, u64_t pos,
char *buf, size_t size, u64_t *new_pos) );
_PROTOTYPE( int req_inhibread, (endpoint_t fs_e, ino_t inode_nr) );
_PROTOTYPE( int req_link, (endpoint_t fs_e, ino_t link_parent,
char *lastc, ino_t linked_file) );
_PROTOTYPE( int req_lookup, (endpoint_t fs_e, size_t path_off,
ino_t dir_ino, ino_t root_ino, _mnx_Uid_t uid,
_mnx_Gid_t gid, int flags, lookup_res_t *res) );
_PROTOTYPE( int req_lookup, (endpoint_t fs_e, ino_t dir_ino, ino_t root_ino,
_mnx_Uid_t uid, _mnx_Gid_t gid, int flags,
lookup_res_t *res) );
_PROTOTYPE( int req_mkdir, (endpoint_t fs_e, ino_t inode_nr,
char *lastc, _mnx_Uid_t uid, _mnx_Gid_t gid, _mnx_Mode_t dmode) );
_PROTOTYPE( int req_mknod, (endpoint_t fs_e, ino_t inode_nr,
@ -192,15 +189,15 @@ _PROTOTYPE( int req_newnode, (endpoint_t fs_e, _mnx_Uid_t uid,
Dev_t dev, struct node_details *res) );
_PROTOTYPE( int req_putnode, (int fs_e, ino_t inode_nr, int count) );
_PROTOTYPE( int req_rdlink, (endpoint_t fs_e, ino_t inode_nr,
endpoint_t who_e, vir_bytes buf, size_t len) );
endpoint_t who_e, char *buf, size_t len) );
_PROTOTYPE( int req_readsuper, (endpoint_t fs_e, char *driver_name,
Dev_t dev, int readonly, int isroot,
struct node_details *res_nodep) );
_PROTOTYPE( int req_readwrite, (endpoint_t fs_e, ino_t inode_nr,
int inode_index, u64_t pos, int rw_flag,
endpoint_t user_e, char *user_addr,
unsigned int num_of_bytes, u64_t *new_posp,
unsigned int *cum_iop) );
u64_t pos, int rw_flag,
endpoint_t user_e, char *user_addr,
unsigned int num_of_bytes, u64_t *new_posp,
unsigned int *cum_iop) );
_PROTOTYPE( int req_rename, (endpoint_t fs_e, ino_t old_dir,
char *old_name, ino_t new_dir, char *new_name) );
_PROTOTYPE( int req_rmdir, (endpoint_t fs_e, ino_t inode_nr,
@ -249,7 +246,7 @@ _PROTOTYPE( struct vmnt *get_free_vmnt, (short *index) );
_PROTOTYPE( struct vmnt *find_vmnt, (int fs_e) );
/* vnode.c */
_PROTOTYPE( struct vnode *get_free_vnode, (char *file, int line) );
_PROTOTYPE( struct vnode *get_free_vnode, (void) );
_PROTOTYPE( struct vnode *find_vnode, (int fs_e, int numb) );
_PROTOTYPE( void dup_vnode, (struct vnode *vp) );
_PROTOTYPE( void put_vnode, (struct vnode *vp) );

View file

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

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
* do_chdir: perform the CHDIR system call
* do_chroot: perform the CHROOT system call
* do_lstat: perform the LSTAT system call
* do_stat: perform the STAT system call
* do_fstat: perform the FSTAT system call
* do_fstatfs: perform the FSTATFS system call
* do_lstat: perform the LSTAT system call
*
* Changes for VFS:
* Jul 2006 (Balazs Gerofi)
*/
#include "fs.h"
@ -22,7 +19,6 @@
#include "file.h"
#include "fproc.h"
#include "param.h"
#include <minix/vfsif.h>
#include "vnode.h"
#include "vmnt.h"
@ -30,6 +26,7 @@
FORWARD _PROTOTYPE( int change, (struct vnode **iip, char *name_ptr, int len));
FORWARD _PROTOTYPE( int change_into, (struct vnode **iip, struct vnode *vp));
/*===========================================================================*
* do_fchdir *
*===========================================================================*/
@ -37,30 +34,13 @@ PUBLIC int do_fchdir()
{
/* Change directory on already-opened fd. */
struct filp *rfilp;
int r;
if(!fp->fp_wd || !fp->fp_rd) {
printf("VFS: do_fchdir: %d: no rd/wd\n",
fp->fp_endpoint);
return ENOENT;
}
/* Is the file descriptor valid? */
if ( (rfilp = get_filp(m_in.fd)) == NIL_FILP) return(err_code);
/* Is it a dir? */
if ((rfilp->filp_vno->v_mode & I_TYPE) != I_DIRECTORY)
return ENOTDIR;
/* Issue request and handle error */
r = forbidden(rfilp->filp_vno, X_BIT, 0 /*!use_realuid*/);
if (r != OK) return r;
rfilp->filp_vno->v_ref_count++; /* change_into expects a reference */
if ((rfilp = get_filp(m_in.fd)) == NIL_FILP) return(err_code);
return change_into(&fp->fp_wd, rfilp->filp_vno);
}
/*===========================================================================*
* do_chdir *
*===========================================================================*/
@ -73,23 +53,11 @@ PUBLIC int do_chdir()
int r;
register struct fproc *rfp;
if(!fp->fp_wd || !fp->fp_rd) {
printf("VFS: do_chdir: %d: no rd/wd\n",
fp->fp_endpoint);
return ENOENT;
}
if (who_e == PM_PROC_NR) {
int slot;
if(isokendpt(m_in.endpt1, &slot) != OK)
return EINVAL;
if(isokendpt(m_in.endpt1, &slot) != OK) return(EINVAL);
rfp = &fproc[slot];
if(!rfp->fp_wd || !rfp->fp_rd) {
printf("VFS: do_chdir: %d: no other rd/wd\n", fp->fp_endpoint);
return ENOENT;
}
put_vnode(fp->fp_rd);
dup_vnode(fp->fp_rd = rfp->fp_rd);
put_vnode(fp->fp_wd);
@ -109,10 +77,10 @@ PUBLIC int do_chdir()
}
/* Perform the chdir(name) system call. */
r = change(&fp->fp_wd, m_in.name, m_in.name_length);
return(r);
return change(&fp->fp_wd, m_in.name, m_in.name_length);
}
/*===========================================================================*
* do_chroot *
*===========================================================================*/
@ -120,18 +88,8 @@ PUBLIC int do_chroot()
{
/* Perform the chroot(name) system call. */
register int r;
if (!super_user) return(EPERM); /* only su may chroot() */
if(!fp->fp_wd || !fp->fp_rd) {
printf("VFS: do_chroot: %d: no rd/wd\n",
fp->fp_endpoint);
return ENOENT;
}
r = change(&fp->fp_rd, m_in.name, m_in.name_length);
return(r);
return change(&fp->fp_rd, m_in.name, m_in.name_length);
}
@ -147,25 +105,9 @@ int len; /* length of the directory name string */
struct vnode *vp;
int r;
/* Try to open the directory */
if (fetch_name(name_ptr, len, M3) != OK) return(err_code);
/* Request lookup */
if ((r = lookup_vp(0 /*flags*/, 0 /*!use_realuid*/, &vp)) != OK) return r;
/* Is it a dir? */
if ((vp->v_mode & I_TYPE) != I_DIRECTORY)
{
put_vnode(vp);
return ENOTDIR;
}
/* Access check */
r = forbidden(vp, X_BIT, 0 /*!use_realuid*/);
if (r != OK) {
put_vnode(vp);
return r;
}
if ((vp = eat_path(PATH_NOFLAGS)) == NIL_VNODE) return(err_code);
return change_into(iip, vp);
}
@ -177,10 +119,23 @@ PRIVATE int change_into(iip, vp)
struct vnode **iip; /* pointer to the inode pointer for the dir */
struct vnode *vp; /* this is what the inode has to become */
{
int r;
/* It must be a directory and also be searchable */
if ((vp->v_mode & I_TYPE) != I_DIRECTORY)
r = ENOTDIR;
else
r = forbidden(vp, X_BIT); /* Check if dir is searchable*/
/* If error, return vnode */
if (r != OK) {
put_vnode(vp);
return(r);
}
/* Everything is OK. Make the change. */
put_vnode(*iip); /* release the old directory */
*iip = vp; /* acquire the new one */
return(OK);
}
@ -195,19 +150,14 @@ PUBLIC int do_stat()
struct vnode *vp;
if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
/* Request lookup */
if ((r = lookup_vp(0 /*flags*/, 0 /*!use_realuid*/, &vp)) != OK)
return r;
if ((vp = eat_path(PATH_NOFLAGS)) == NIL_VNODE) return(err_code);
r = req_stat(vp->v_fs_e, vp->v_inode_nr, who_e, m_in.name2, 0);
/* Issue request */
r= req_stat(vp->v_fs_e, vp->v_inode_nr, who_e, m_in.name2, 0);
put_vnode(vp);
return r;
}
/*===========================================================================*
* do_fstat *
*===========================================================================*/
@ -218,46 +168,38 @@ PUBLIC int do_fstat()
int pipe_pos = 0;
/* Is the file descriptor valid? */
if ( (rfilp = get_filp(m_in.fd)) == NIL_FILP) {
return(err_code);
}
if ((rfilp = get_filp(m_in.fd)) == NIL_FILP) return(err_code);
/* If we read from a pipe, send position too */
pipe_pos= 0;
if (rfilp->filp_vno->v_pipe == I_PIPE) {
if (rfilp->filp_mode & R_BIT)
if (ex64hi(rfilp->filp_pos) != 0)
{
if (ex64hi(rfilp->filp_pos) != 0) {
panic(__FILE__, "do_fstat: bad position in pipe",
NO_NUM);
}
pipe_pos = ex64lo(rfilp->filp_pos);
pipe_pos = ex64lo(rfilp->filp_pos);
}
/* Issue request */
return req_stat(rfilp->filp_vno->v_fs_e, rfilp->filp_vno->v_inode_nr,
who_e, m_in.buffer, pipe_pos);
who_e, m_in.buffer, pipe_pos);
}
/*===========================================================================*
* do_fstatfs *
*===========================================================================*/
PUBLIC int do_fstatfs()
{
/* Perform the fstatfs(fd, buf) system call. */
register struct filp *rfilp;
/* Perform the fstatfs(fd, buf) system call. */
struct filp *rfilp;
/* Is the file descriptor valid? */
if ( (rfilp = get_filp(m_in.fd)) == NIL_FILP) return(err_code);
if( (rfilp = get_filp(m_in.fd)) == NIL_FILP) return(err_code);
/* Issue request */
return req_fstatfs(rfilp->filp_vno->v_fs_e, who_e, m_in.buffer);
}
/*===========================================================================*
* do_lstat *
*===========================================================================*/
@ -268,18 +210,11 @@ PUBLIC int do_lstat()
int r;
if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
/* Request lookup */
if ((r = lookup_vp(PATH_RET_SYMLINK, 0 /*!use_realuid*/, &vp)) != OK)
return r;
/* Issue request */
r= req_stat(vp->v_fs_e, vp->v_inode_nr, who_e, m_in.name2, 0);
if ((vp = eat_path(PATH_RET_SYMLINK)) == NIL_VNODE) return(err_code);
r = req_stat(vp->v_fs_e, vp->v_inode_nr, who_e, m_in.name2, 0);
put_vnode(vp);
return r;
return(r);
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,4 +1,3 @@
/* This file contains the routines related to vnodes.
* The entry points are:
*
@ -7,16 +6,13 @@
* find_vnode - find a vnode according to the FS endpoint and the inode num.
* dup_vnode - duplicate vnode (i.e. increase counter)
* put_vnode - drop vnode (i.e. decrease counter)
*
* Jul 2006 (Balazs Gerofi)
*/
#include "fs.h"
#include "vnode.h"
#include "vmnt.h"
#include "fproc.h"
#include "file.h"
#include <minix/vfsif.h>
/* Is vnode pointer reasonable? */
@ -37,30 +33,28 @@
/*===========================================================================*
* get_free_vnode *
*===========================================================================*/
PUBLIC struct vnode *get_free_vnode(file, line)
char *file;
int line;
PUBLIC struct vnode *get_free_vnode()
{
/* Find a free vnode slot in the vnode table */
/* Find a free vnode slot in the vnode table (it's not actually allocated) */
struct vnode *vp;
for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; ++vp)
if (vp->v_ref_count == 0)
{
vp->v_pipe= NO_PIPE;
vp->v_uid= -1;
vp->v_gid= -1;
vp->v_sdev= -1;
vp->v_file= file;
vp->v_line= line;
return vp;
for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; ++vp) {
if (vp->v_ref_count == 0) {
vp->v_pipe = NO_PIPE;
vp->v_uid = -1;
vp->v_gid = -1;
vp->v_sdev = NO_DEV;
vp->v_mapfs_e = 0;
vp->v_mapinode_nr = 0;
return(vp);
}
}
err_code = ENFILE;
return NIL_VNODE;
return(NIL_VNODE);
}
/*===========================================================================*
* find_vnode *
*===========================================================================*/
@ -71,10 +65,10 @@ PUBLIC struct vnode *find_vnode(int fs_e, int numb)
struct vnode *vp;
for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; ++vp)
if (vp->v_ref_count > 0 && vp->v_inode_nr == numb
&& vp->v_fs_e == fs_e) return vp;
if (vp->v_ref_count > 0 && vp->v_inode_nr == numb && vp->v_fs_e == fs_e)
return(vp);
return NIL_VNODE;
return(NIL_VNODE);
}
@ -97,39 +91,52 @@ PUBLIC void dup_vnode(struct vnode *vp)
PUBLIC void put_vnode(struct vnode *vp)
{
/* Decrease vnode's usage counter and decrease inode's usage counter in the
* corresponding FS process.
* corresponding FS process. Decreasing the fs_count each time we decrease the
* ref count would lead to poor performance. Instead, only decrease fs_count
* when the ref count hits zero. However, this could lead to fs_count to wrap.
* To prevent this, we drop the counter to 1 when the counter hits 256.
* We maintain fs_count as a sanity check to make sure VFS and the FS are in
* sync.
*/
ASSERTVP(vp);
if (vp->v_ref_count > 1)
{
if (vp->v_ref_count > 1) {
/* Decrease counter */
vp->v_ref_count--;
if (vp->v_fs_count > 256)
if (vp->v_fs_count > 256)
vnode_clean_refs(vp);
return;
}
if (vp->v_ref_count <= 0)
{
/* A vnode that's not in use can't be put. */
if (vp->v_ref_count <= 0) {
printf("put_vnode: bad v_ref_count %d\n", vp->v_ref_count);
panic(__FILE__, "put_vnode failed", NO_NUM);
}
if (vp->v_fs_count <= 0)
{
/* fs_count should indicate that the file is in use. */
if (vp->v_fs_count <= 0) {
printf("put_vnode: bad v_fs_count %d\n", vp->v_fs_count);
panic(__FILE__, "put_vnode failed", NO_NUM);
}
/* Send request */
if (req_putnode(vp->v_fs_e, vp->v_inode_nr, vp->v_fs_count) != OK)
printf("VFSput_vnode Warning: inode doesn't exist\n");
/* Tell FS we don't need this inode to be open anymore. */
req_putnode(vp->v_fs_e, vp->v_inode_nr, vp->v_fs_count);
vp->v_fs_count= 0;
vp->v_ref_count= 0;
/* This inode could've been mapped. If so, tell PFS to close it as well. */
if(vp->v_mapfs_e != 0 && vp->v_mapinode_nr != vp->v_inode_nr &&
vp->v_mapfs_e != vp->v_fs_e) {
req_putnode(vp->v_mapfs_e, vp->v_mapinode_nr, vp->v_mapfs_count);
}
vp->v_fs_count = 0;
vp->v_ref_count = 0;
vp->v_pipe = NO_PIPE;
vp->v_sdev = NO_DEV;
vp->v_index = 0;
vp->v_mapfs_e = 0;
vp->v_mapinode_nr = 0;
vp->v_fs_count = 0;
}
@ -139,34 +146,16 @@ PUBLIC void put_vnode(struct vnode *vp)
PUBLIC void vnode_clean_refs(struct vnode *vp)
{
/* Tell the underlying FS to drop all reference but one. */
if (vp == NIL_VNODE) {
return;
}
if (vp->v_fs_count <= 1)
return; /* Nothing to do */
if (req_putnode(vp->v_fs_e, vp->v_inode_nr, vp->v_fs_count-1) != OK)
printf("vnode_clean_refs: req_putnode failed\n");
vp->v_fs_count= 1;
if (vp == NIL_VNODE) return;
if (vp->v_fs_count <= 1) return; /* Nothing to do */
/* Drop all references except one */
req_putnode(vp->v_fs_e, vp->v_inode_nr, vp->v_fs_count - 1);
vp->v_fs_count = 1;
}
#if 0
/*===========================================================================*
* mark_vn *
*===========================================================================*/
PUBLIC void mark_vn(vp, file, line)
struct vnode *vp;
char *file;
int line;
{
if (!vp)
return;
vp->v_file= file;
vp->v_line= line;
}
#endif
#define REFVP(v) { vp = (v); CHECKVN(v); vp->v_ref_check++; }
#if DO_SANITYCHECKS

View file

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

View file

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

View file

@ -13,13 +13,13 @@ badones= # list of tests that failed
# Print test welcome message
clr
echo "Running POSIX compliance test suite. There are 48 tests in total."
echo "Running POSIX compliance test suite. There are 49 tests in total."
echo " "
# Run all the tests, keeping track of who failed.
for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 \
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 \
41 42 43 44 45 45-gcc sh1.sh sh2.sh
41 42 43 44 45 45-gcc 46 sh1.sh sh2.sh
do
if [ -x ./test$i ]
then

View file

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

View file

@ -25,7 +25,6 @@ _PROTOTYPE(void test2d, (void));
_PROTOTYPE(void test2e, (void));
_PROTOTYPE(void test2f, (void));
_PROTOTYPE(void test2g, (void));
_PROTOTYPE(void test2h, (void));
_PROTOTYPE(void sigpip, (int s));
_PROTOTYPE(void quit, (void));
_PROTOTYPE(void e, (int n));
@ -55,7 +54,6 @@ char *argv[];
if (m & 0020) test2e();
if (m & 0040) test2f();
if (m & 0100) test2g();
if (m & 0200) test2h();
}
subtest = 100;
if (cumsig != ITERATIONS) e(101);
@ -357,19 +355,6 @@ void test2g()
if (tmsbuf.tms_cstime < 0) e(11);
}
void test2h()
{
/* Test getgroups(). */
gid_t g[10];
subtest = 8;
errno = -8000;
if (getgroups(10, g) != 0) e(1);
if (getgroups(1, g) != 0) e(2);
if (getgroups(0, g) != 0) e(3);
}
void sigpip(s)
int s; /* for ANSI */
{

View file

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