From ccaeedb267288a9eea9fd8cd1c553aa98bdef60d Mon Sep 17 00:00:00 2001 From: David van Moolenbroek Date: Sun, 24 Aug 2014 10:06:03 +0000 Subject: [PATCH] MFS: use libfsdriver Change-Id: Ib658c7dea47b81a417755b0554a75288117b431a --- minix/commands/fsck.mfs/fsck.c | 1 + minix/fs/mfs/Makefile | 4 +- minix/fs/mfs/const.h | 29 +-- minix/fs/mfs/fs.h | 4 +- minix/fs/mfs/glo.h | 25 +- minix/fs/mfs/inode.c | 20 +- minix/fs/mfs/link.c | 177 ++++--------- minix/fs/mfs/main.c | 112 +------- minix/fs/mfs/misc.c | 64 +---- minix/fs/mfs/mount.c | 92 +++---- minix/fs/mfs/open.c | 154 +++-------- minix/fs/mfs/path.c | 462 +++------------------------------ minix/fs/mfs/pipe.c | 1 - minix/fs/mfs/protect.c | 126 +-------- minix/fs/mfs/proto.h | 78 +++--- minix/fs/mfs/read.c | 411 +++++++++-------------------- minix/fs/mfs/stadir.c | 106 +++----- minix/fs/mfs/super.c | 1 - minix/fs/mfs/super.h | 1 - minix/fs/mfs/table.c | 72 +++-- minix/fs/mfs/time.c | 81 +++--- minix/fs/mfs/utility.c | 39 --- minix/fs/mfs/write.c | 4 +- minix/lib/libc/gen/fslib.c | 1 + 24 files changed, 464 insertions(+), 1601 deletions(-) delete mode 100644 minix/fs/mfs/pipe.c diff --git a/minix/commands/fsck.mfs/fsck.c b/minix/commands/fsck.mfs/fsck.c index 1a1bbd531..e68e5d98b 100644 --- a/minix/commands/fsck.mfs/fsck.c +++ b/minix/commands/fsck.mfs/fsck.c @@ -46,6 +46,7 @@ #include #include #include +#include #include "mfs/const.h" #include "mfs/inode.h" #include "mfs/type.h" diff --git a/minix/fs/mfs/Makefile b/minix/fs/mfs/Makefile index 7c0195bb2..f2d60b7e3 100644 --- a/minix/fs/mfs/Makefile +++ b/minix/fs/mfs/Makefile @@ -5,8 +5,8 @@ SRCS= cache.c link.c \ stadir.c stats.c table.c time.c utility.c \ write.c inode.c main.c path.c super.c -DPADD+= ${LIBMINIXFS} ${LIBBDEV} ${LIBSYS} -LDADD+= -lminixfs -lbdev -lsys +DPADD+= ${LIBMINIXFS} ${LIBFSDRIVER} ${LIBBDEV} ${LIBSYS} +LDADD+= -lminixfs -lfsdriver -lbdev -lsys CPPFLAGS+= -DDEFAULT_NR_BUFS=1024 diff --git a/minix/fs/mfs/const.h b/minix/fs/mfs/const.h index 5ea8e5eef..23b74719b 100644 --- a/minix/fs/mfs/const.h +++ b/minix/fs/mfs/const.h @@ -18,12 +18,6 @@ #define MFS_NAME_MAX MFS_DIRSIZ -/* The type of sizeof may be (unsigned) long. Use the following macro for - * taking the sizes of small objects so that there are no surprises like - * (small) long constants being passed to routines expecting an int. - */ -#define usizeof(t) ((unsigned) sizeof(t)) - /* File system types. */ #define SUPER_MAGIC 0x137F /* magic number contained in super-block */ #define SUPER_REV 0x7F13 /* magic # when 68000 disk read on PC or vv */ @@ -35,8 +29,6 @@ #define V3 3 /* version number of V3 file systems */ /* Miscellaneous constants */ -#define SU_UID ((uid_t) 0) /* super_user's uid_t */ - #define NO_BIT ((bit_t) 0) /* returned by alloc_bit() to signal failure */ #define LOOK_UP 0 /* tells search_dir to lookup string */ @@ -47,39 +39,30 @@ /* write_map() args */ #define WMAP_FREE (1 << 0) -#define IGN_PERM 0 -#define CHK_PERM 1 - #define IN_CLEAN 0 /* in-block inode and memory copies identical */ #define IN_DIRTY 1 /* in-block inode and memory copies differ */ #define ATIME 002 /* set if atime field needs updating */ #define CTIME 004 /* set if ctime field needs updating */ #define MTIME 010 /* set if mtime field needs updating */ -#define BYTE_SWAP 0 /* tells conv2/conv4 to swap bytes */ - -#define END_OF_FILE (-104) /* eof detected */ - #define ROOT_INODE ((ino_t) 1) /* inode number for root directory */ #define BOOT_BLOCK ((block_t) 0) /* block number of boot block */ #define SUPER_BLOCK_BYTES (1024) /* bytes offset */ #define START_BLOCK ((block_t) 2) /* first block of FS (not counting SB) */ -#define DIR_ENTRY_SIZE usizeof (struct direct) /* # bytes/dir entry */ +#define DIR_ENTRY_SIZE sizeof (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 SUPER_SIZE sizeof (struct super_block) /* super_block size */ -#define FS_BITMAP_CHUNKS(b) ((b)/usizeof (bitchunk_t))/* # map chunks/blk */ -#define FS_BITCHUNK_BITS (usizeof(bitchunk_t) * CHAR_BIT) +#define FS_BITMAP_CHUNKS(b) ((b)/sizeof (bitchunk_t))/* # map chunks/blk */ +#define FS_BITCHUNK_BITS (sizeof(bitchunk_t) * CHAR_BIT) #define FS_BITS_PER_BLOCK(b) (FS_BITMAP_CHUNKS(b) * FS_BITCHUNK_BITS) /* Derived sizes pertaining to the V2 file system. */ -#define V2_ZONE_NUM_SIZE usizeof (zone_t) /* # bytes in V2 zone */ -#define V2_INODE_SIZE usizeof (d2_inode) /* bytes in V2 dsk ino */ +#define V2_ZONE_NUM_SIZE sizeof (zone_t) /* # bytes in V2 zone */ +#define V2_INODE_SIZE sizeof (d2_inode) /* bytes in V2 dsk ino */ #define V2_INDIRECTS(b) ((b)/V2_ZONE_NUM_SIZE) /* # zones/indir block */ #define V2_INODES_PER_BLOCK(b) ((b)/V2_INODE_SIZE)/* # V2 dsk inodes/blk */ -#define NUL(str,l,m) mfs_nul_f(__FILE__,__LINE__,(str), (l), (m)) - #endif diff --git a/minix/fs/mfs/fs.h b/minix/fs/mfs/fs.h index 571dc03ed..75a4a6d8f 100644 --- a/minix/fs/mfs/fs.h +++ b/minix/fs/mfs/fs.h @@ -13,16 +13,16 @@ #include #include #include -#include #include #include #include -#include #include #include +#include + #include "mfsdir.h" #include "const.h" #include "type.h" diff --git a/minix/fs/mfs/glo.h b/minix/fs/mfs/glo.h index f6a7e99f1..8e50d387d 100644 --- a/minix/fs/mfs/glo.h +++ b/minix/fs/mfs/glo.h @@ -7,35 +7,14 @@ #define EXTERN #endif -#include - /* The following variables are used for returning results to the caller. */ EXTERN int err_code; /* temporary storage for error number */ EXTERN int cch[NR_INODES]; -extern char dot1[2]; /* dot1 (&dot1[0]) and dot2 (&dot2[0]) have a special */ -extern char dot2[3]; /* meaning to search_dir: no access permission check. */ - -extern int(*fs_call_vec[]) (void); - -EXTERN message fs_m_in; -EXTERN message fs_m_out; -EXTERN vfs_ucred_t credentials; - -EXTERN uid_t caller_uid; -EXTERN gid_t caller_gid; - -EXTERN int req_nr; - -EXTERN char user_path[PATH_MAX]; /* pathname to be processed */ - EXTERN dev_t fs_dev; /* The device that is handled by this FS proc. */ -EXTERN char fs_dev_label[16]; /* Name of the device driver that is handled - * by this FS proc. - */ -EXTERN int unmountdone; -EXTERN int exitsignaled; + +extern struct fsdriver mfs_table; #endif diff --git a/minix/fs/mfs/inode.c b/minix/fs/mfs/inode.c index 95a05e535..7c5a60c83 100644 --- a/minix/fs/mfs/inode.c +++ b/minix/fs/mfs/inode.c @@ -35,27 +35,21 @@ static void wipe_inode(struct inode *rip); /*===========================================================================* * fs_putnode * *===========================================================================*/ -int fs_putnode(void) +int fs_putnode(ino_t ino_nr, unsigned int count) { /* Find the inode specified by the request message and decrease its counter.*/ struct inode *rip; - int count; - rip = find_inode(fs_dev, fs_m_in.m_vfs_fs_putnode.inode); + rip = find_inode(fs_dev, ino_nr); if(!rip) { printf("%s:%d put_inode: inode #%llu dev: %llx not found\n", __FILE__, - __LINE__, fs_m_in.m_vfs_fs_putnode.inode, fs_dev); + __LINE__, ino_nr, fs_dev); panic("fs_putnode failed"); } - count = fs_m_in.m_vfs_fs_putnode.count; - if (count <= 0) { - printf("%s:%d put_inode: bad value for count: %d\n", __FILE__, - __LINE__, count); - panic("fs_putnode failed"); - } else if(count > rip->i_count) { + if (count > rip->i_count) { printf("%s:%d put_inode: count too high: %d > %d\n", __FILE__, __LINE__, count, rip->i_count); panic("fs_putnode failed"); @@ -255,7 +249,7 @@ register struct inode *rip; /* pointer to inode to be released */ /*===========================================================================* * alloc_inode * *===========================================================================*/ -struct inode *alloc_inode(dev_t dev, mode_t bits) +struct inode *alloc_inode(dev_t dev, mode_t bits, uid_t uid, gid_t gid) { /* Allocate a free inode on 'dev', and return a pointer to it. */ @@ -290,8 +284,8 @@ struct inode *alloc_inode(dev_t dev, mode_t bits) /* An inode slot is available. Put the inode just allocated into it. */ rip->i_mode = bits; /* set up RWX bits */ rip->i_nlinks = NO_LINK; /* initial no links */ - rip->i_uid = caller_uid; /* file's uid is owner's */ - rip->i_gid = caller_gid; /* ditto group id */ + rip->i_uid = uid; /* file's uid is owner's */ + rip->i_gid = gid; /* ditto group id */ rip->i_dev = dev; /* mark which device it is on */ rip->i_ndzones = sp->s_ndzones; /* number of direct zones */ rip->i_nindirs = sp->s_nindirs; /* number of indirect zones per blk*/ diff --git a/minix/fs/mfs/link.c b/minix/fs/mfs/link.c index b76356e13..a634e73da 100644 --- a/minix/fs/mfs/link.c +++ b/minix/fs/mfs/link.c @@ -29,25 +29,16 @@ static void zerozone_range(struct inode *rip, off_t pos, off_t len); /*===========================================================================* * fs_link * *===========================================================================*/ -int fs_link() +int fs_link(ino_t dir_nr, char *name, ino_t ino_nr) { /* Perform the link(name1, name2) system call. */ struct inode *ip, *rip; register int r; - char string[MFS_NAME_MAX]; struct inode *new_ip; - phys_bytes len; - len = min(fs_m_in.m_vfs_fs_link.path_len, sizeof(string)); - /* Copy the link name's last component */ - r = sys_safecopyfrom(VFS_PROC_NR, fs_m_in.m_vfs_fs_link.grant, - (vir_bytes) 0, (vir_bytes) string, (size_t) len); - if (r != OK) return r; - NUL(string, len, sizeof(string)); - /* Temporarily open the file. */ - if( (rip = get_inode(fs_dev, fs_m_in.m_vfs_fs_link.inode)) == NULL) + if( (rip = get_inode(fs_dev, ino_nr)) == NULL) return(EINVAL); /* Check to see if the file has maximum number of links already. */ @@ -55,9 +46,9 @@ int fs_link() if(rip->i_nlinks >= LINK_MAX) r = EMLINK; - /* Only super_user may link to directories. */ + /* Linking to directories is too dangerous to allow. */ if(r == OK) - if( (rip->i_mode & I_TYPE) == I_DIRECTORY && caller_uid != SU_UID) + if( (rip->i_mode & I_TYPE) == I_DIRECTORY) r = EPERM; /* If error with 'name', return the inode. */ @@ -67,7 +58,7 @@ int fs_link() } /* Temporarily open the last dir */ - if( (ip = get_inode(fs_dev, fs_m_in.m_vfs_fs_link.dir_ino)) == NULL) { + if( (ip = get_inode(fs_dev, dir_nr)) == NULL) { put_inode(rip); return(EINVAL); } @@ -79,7 +70,7 @@ int fs_link() } /* If 'name2' exists in full (even if no space) set 'r' to error. */ - if((new_ip = advance(ip, string, IGN_PERM)) == NULL) { + if((new_ip = advance(ip, name)) == NULL) { r = err_code; if(r == ENOENT) r = OK; @@ -90,7 +81,7 @@ int fs_link() /* Try to link. */ if(r == OK) - r = search_dir(ip, string, &rip->i_num, ENTER, IGN_PERM); + r = search_dir(ip, name, &rip->i_num, ENTER); /* If success, register the linking. */ if(r == OK) { @@ -109,56 +100,43 @@ int fs_link() /*===========================================================================* * fs_unlink * *===========================================================================*/ -int fs_unlink() +int fs_unlink(ino_t dir_nr, char *name, int call) { /* Perform the unlink(name) or rmdir(name) system call. The code for these two - * is almost the same. They differ only in some condition testing. Unlink() - * may be used by the superuser to do dangerous things; rmdir() may not. + * is almost the same. They differ only in some condition testing. */ register struct inode *rip; struct inode *rldirp; int r; - char string[MFS_NAME_MAX]; - phys_bytes len; - - /* Copy the last component */ - len = min(fs_m_in.m_vfs_fs_unlink.path_len, sizeof(string)); - r = sys_safecopyfrom(VFS_PROC_NR, fs_m_in.m_vfs_fs_unlink.grant, - (vir_bytes) 0, (vir_bytes) string, (size_t) len); - if (r != OK) return r; - NUL(string, len, sizeof(string)); /* Temporarily open the dir. */ - if((rldirp = get_inode(fs_dev, fs_m_in.m_vfs_fs_unlink.inode)) == NULL) + if((rldirp = get_inode(fs_dev, dir_nr)) == NULL) return(EINVAL); /* The last directory exists. Does the file also exist? */ - rip = advance(rldirp, string, IGN_PERM); + rip = advance(rldirp, name); r = err_code; /* If error, return inode. */ if(r != OK) { - /* Mount point? */ - if (r == EENTERMOUNT || r == ELEAVEMOUNT) { - put_inode(rip); - r = EBUSY; - } put_inode(rldirp); return(r); } + if (rip->i_mountpoint) { + put_inode(rip); + put_inode(rldirp); + return(EBUSY); + } if(rip->i_sp->s_rd_only) { r = EROFS; - } else if(fs_m_in.m_type == REQ_UNLINK) { - /* Now test if the call is allowed, separately for unlink() and rmdir(). */ - /* Only the su may unlink directories, but the su can unlink any - * dir.*/ + } else if (call == FSC_UNLINK) { if( (rip->i_mode & I_TYPE) == I_DIRECTORY) r = EPERM; /* Actually try to unlink the file; fails if parent is mode 0 etc. */ - if (r == OK) r = unlink_file(rldirp, rip, string); + if (r == OK) r = unlink_file(rldirp, rip, name); } else { - r = remove_dir(rldirp, rip, string); /* call is RMDIR */ + r = remove_dir(rldirp, rip, name); /* call is RMDIR */ } /* If unlink was possible, it has been done, otherwise it has not. */ @@ -171,17 +149,14 @@ int fs_unlink() /*===========================================================================* * fs_rdlink * *===========================================================================*/ -int fs_rdlink() +ssize_t fs_rdlink(ino_t ino_nr, struct fsdriver_data *data, size_t bytes) { struct buf *bp; /* buffer containing link text */ register struct inode *rip; /* target inode */ register int r; /* return value */ - size_t copylen; - copylen = min(fs_m_in.m_vfs_fs_rdlink.mem_size, UMAX_FILE_POS); - /* Temporarily open the file. */ - if( (rip = get_inode(fs_dev, fs_m_in.m_vfs_fs_rdlink.inode)) == NULL) + if( (rip = get_inode(fs_dev, ino_nr)) == NULL) return(EINVAL); if(!S_ISLNK(rip->i_mode)) @@ -190,15 +165,12 @@ int fs_rdlink() if(!(bp = get_block_map(rip, 0))) return EIO; /* Passed all checks */ - /* We can safely cast to unsigned, because copylen is guaranteed to be - below max file size */ - copylen = min( copylen, (unsigned) rip->i_size); - r = sys_safecopyto(VFS_PROC_NR, fs_m_in.m_vfs_fs_rdlink.grant, - (vir_bytes) 0, (vir_bytes) b_data(bp), - (size_t) copylen); + if (bytes > rip->i_size) + bytes = rip->i_size; + r = fsdriver_copyout(data, 0, b_data(bp), bytes); put_block(bp, DIRECTORY_BLOCK); if (r == OK) - fs_m_out.m_fs_vfs_rdlink.nbytes = copylen; + r = bytes; } put_inode(rip); @@ -224,10 +196,9 @@ char dir_name[MFS_NAME_MAX]; /* name of directory to be removed */ int r; /* search_dir checks that rip is a directory too. */ - if ((r = search_dir(rip, "", NULL, IS_EMPTY, IGN_PERM)) != OK) + if ((r = search_dir(rip, "", NULL, IS_EMPTY)) != OK) return(r); - if (strcmp(dir_name, ".") == 0 || strcmp(dir_name, "..") == 0)return(EINVAL); if (rip->i_num == ROOT_INODE) return(EBUSY); /* can't remove 'root' */ /* Actually try to unlink the file; fails if parent is mode 0 etc. */ @@ -236,8 +207,8 @@ char dir_name[MFS_NAME_MAX]; /* name of directory to be removed */ /* Unlink . and .. from the dir. The super user can link and unlink any dir, * so don't make too many assumptions about them. */ - (void) unlink_file(rip, NULL, dot1); - (void) unlink_file(rip, NULL, dot2); + (void) unlink_file(rip, NULL, "."); + (void) unlink_file(rip, NULL, ".."); return(OK); } @@ -258,14 +229,14 @@ char file_name[MFS_NAME_MAX]; /* name of file to be removed */ /* If rip is not NULL, it is used to get faster access to the inode. */ if (rip == NULL) { /* Search for file in directory and try to get its inode. */ - err_code = search_dir(dirp, file_name, &numb, LOOK_UP, IGN_PERM); + err_code = search_dir(dirp, file_name, &numb, LOOK_UP); if (err_code == OK) rip = get_inode(dirp->i_dev, (int) numb); if (err_code != OK || rip == NULL) return(err_code); } else { dup_inode(rip); /* inode will be returned with put_inode */ } - r = search_dir(dirp, file_name, NULL, DELETE, IGN_PERM); + r = search_dir(dirp, file_name, NULL, DELETE); if (r == OK) { rip->i_nlinks--; /* entry deleted from parent's dir */ @@ -281,7 +252,8 @@ char file_name[MFS_NAME_MAX]; /* name of file to be removed */ /*===========================================================================* * fs_rename * *===========================================================================*/ -int fs_rename() +int fs_rename(ino_t old_dir_nr, char *old_name, ino_t new_dir_nr, + char *new_name) { /* Perform the rename(name1, name2) system call. */ struct inode *old_dirp, *old_ip; /* ptrs to old dir, file inodes */ @@ -290,50 +262,33 @@ int fs_rename() int r = OK; /* error flag; initially no error */ int odir, ndir; /* TRUE iff {old|new} file is dir */ int same_pdir; /* TRUE iff parent dirs are the same */ - char old_name[MFS_NAME_MAX], new_name[MFS_NAME_MAX]; ino_t numb; - phys_bytes len; - /* Copy the last component of the old name */ - len = min( (unsigned) fs_m_in.m_vfs_fs_rename.len_old, sizeof(old_name)); - r = sys_safecopyfrom(VFS_PROC_NR, fs_m_in.m_vfs_fs_rename.grant_old, - (vir_bytes) 0, (vir_bytes) old_name, (size_t) len); - if (r != OK) return r; - NUL(old_name, len, sizeof(old_name)); - - /* Copy the last component of the new name */ - len = min( (unsigned) fs_m_in.m_vfs_fs_rename.len_new, sizeof(new_name)); - r = sys_safecopyfrom(VFS_PROC_NR, fs_m_in.m_vfs_fs_rename.grant_new, - (vir_bytes) 0, (vir_bytes) new_name, (size_t) len); - if (r != OK) return r; - NUL(new_name, len, sizeof(new_name)); - /* Get old dir inode */ - if ((old_dirp = get_inode(fs_dev, fs_m_in.m_vfs_fs_rename.dir_old)) == NULL) + if ((old_dirp = get_inode(fs_dev, old_dir_nr)) == NULL) return(err_code); - old_ip = advance(old_dirp, old_name, IGN_PERM); + old_ip = advance(old_dirp, old_name); r = err_code; - if (r == EENTERMOUNT || r == ELEAVEMOUNT) { - put_inode(old_ip); - old_ip = NULL; - if (r == EENTERMOUNT) r = EXDEV; /* should this fail at all? */ - else if (r == ELEAVEMOUNT) r = EINVAL; /* rename on dot-dot */ - } - if (old_ip == NULL) { put_inode(old_dirp); return(r); } + if (old_ip->i_mountpoint) { + put_inode(old_ip); + put_inode(old_dirp); + return(EBUSY); + } + /* Get new dir inode */ - if ((new_dirp = get_inode(fs_dev, fs_m_in.m_vfs_fs_rename.dir_new)) == NULL){ + if ((new_dirp = get_inode(fs_dev, new_dir_nr)) == NULL) { put_inode(old_ip); put_inode(old_dirp); return(err_code); } else { - if (new_dirp->i_nlinks == NO_LINK) { /* Dir does not actually exist */ + if (new_dirp->i_nlinks == NO_LINK) { /* Dir does not actually exist */ put_inode(old_ip); put_inode(old_dirp); put_inode(new_dirp); @@ -341,11 +296,10 @@ int fs_rename() } } - new_ip = advance(new_dirp, new_name, IGN_PERM); /* not required to exist */ + new_ip = advance(new_dirp, new_name); /* not required to exist */ - /* However, if the check failed because the file does exist, don't continue. - * Note that ELEAVEMOUNT is covered by the dot-dot check later. */ - if(err_code == EENTERMOUNT) { + /* If the node does exist, make sure it's not a mountpoint. */ + if (new_ip != NULL && new_ip->i_mountpoint) { put_inode(new_ip); new_ip = NULL; r = EBUSY; @@ -366,17 +320,14 @@ int fs_rename() r = EINVAL; break; } - next_new_superdirp = advance(new_superdirp, dot2, - IGN_PERM); + next_new_superdirp = advance(new_superdirp, ".."); put_inode(new_superdirp); if(next_new_superdirp == new_superdirp) { put_inode(new_superdirp); break; } - if(err_code == ELEAVEMOUNT) { - /* imitate that we are back at the root, - * cross device checked already on VFS */ + if(next_new_superdirp->i_num == ROOT_INODE) { put_inode(next_new_superdirp); err_code = OK; break; @@ -390,18 +341,8 @@ int fs_rename() } } - /* The old or new name must not be . or .. */ - if(strcmp(old_name, ".") == 0 || strcmp(old_name, "..") == 0 || - strcmp(new_name, ".") == 0 || strcmp(new_name, "..") == 0) { - r = EINVAL; - } - /* Both parent directories must be on the same device. - if(old_dirp->i_dev != new_dirp->i_dev) r = EXDEV; */ - /* Some tests apply only if the new path exists. */ if(new_ip == NULL) { - /* don't rename a file with a file system mounted on it. - if (old_ip->i_dev != old_dirp->i_dev) r = EXDEV;*/ if (odir && new_dirp->i_nlinks >= LINK_MAX && !same_pdir && r == OK) { r = EMLINK; @@ -448,16 +389,14 @@ int fs_rename() numb = old_ip->i_num; /* inode number of old file */ if(same_pdir) { - r = search_dir(old_dirp, old_name, NULL, DELETE, IGN_PERM); + r = search_dir(old_dirp, old_name, NULL, DELETE); /* shouldn't go wrong. */ if(r == OK) - (void) search_dir(old_dirp, new_name, &numb, ENTER, - IGN_PERM); + (void) search_dir(old_dirp, new_name, &numb, ENTER); } else { - r = search_dir(new_dirp, new_name, &numb, ENTER, IGN_PERM); + r = search_dir(new_dirp, new_name, &numb, ENTER); if(r == OK) - (void) search_dir(old_dirp, old_name, NULL, DELETE, - IGN_PERM); + (void) search_dir(old_dirp, old_name, NULL, DELETE); } } /* If r is OK, the ctime and mtime of old_dirp and new_dirp have been marked @@ -466,8 +405,8 @@ int fs_rename() if(r == OK && odir && !same_pdir) { /* Update the .. entry in the directory (still points to old_dirp).*/ numb = new_dirp->i_num; - (void) unlink_file(old_ip, NULL, dot2); - if(search_dir(old_ip, dot2, &numb, ENTER, IGN_PERM) == OK) { + (void) unlink_file(old_ip, NULL, ".."); + if(search_dir(old_ip, "..", &numb, ENTER) == OK) { /* New link created. */ new_dirp->i_nlinks++; IN_MARKDIRTY(new_dirp); @@ -484,23 +423,19 @@ int fs_rename() /*===========================================================================* - * fs_ftrunc * + * fs_trunc * *===========================================================================*/ -int fs_ftrunc(void) +int fs_trunc(ino_t ino_nr, off_t start, off_t end) { struct inode *rip; - off_t start, end; int r; - if( (rip = find_inode(fs_dev, fs_m_in.m_vfs_fs_ftrunc.inode)) == NULL) + if( (rip = find_inode(fs_dev, ino_nr)) == NULL) return(EINVAL); if(rip->i_sp->s_rd_only) { r = EROFS; } else { - start = fs_m_in.m_vfs_fs_ftrunc.trc_start; - end = fs_m_in.m_vfs_fs_ftrunc.trc_end; - if (end == 0) r = truncate_inode(rip, start); else diff --git a/minix/fs/mfs/main.c b/minix/fs/mfs/main.c index 43c881dd0..da34ba9e2 100644 --- a/minix/fs/mfs/main.c +++ b/minix/fs/mfs/main.c @@ -1,20 +1,8 @@ #include "fs.h" -#include -#include -#include -#include -#include -#include -#include -#include #include "buf.h" #include "inode.h" -/* Declare some local functions. */ -static void get_work(message *m_in); -static void reply(endpoint_t who, message *m_out); - /* SEF functions and variables. */ static void sef_local_startup(void); static int sef_cb_init_fresh(int type, sef_init_info_t *info); @@ -25,60 +13,16 @@ static void sef_cb_signal_handler(int signo); *===========================================================================*/ int main(int argc, char *argv[]) { -/* This is the main routine of this service. The main loop consists of - * three major activities: getting new work, processing the work, and - * sending the reply. The loop never terminates, unless a panic occurs. - */ - int error = OK, ind, transid; +/* This is the main routine of this service. */ /* SEF local startup. */ env_setargs(argc, argv); sef_local_startup(); - while(!unmountdone || !exitsignaled) { - endpoint_t src; + /* The fsdriver library does the actual work here. */ + fsdriver_task(&mfs_table); - /* Wait for request message. */ - get_work(&fs_m_in); - - transid = TRNS_GET_ID(fs_m_in.m_type); - fs_m_in.m_type = TRNS_DEL_ID(fs_m_in.m_type); - if (fs_m_in.m_type == 0) { - assert(!IS_VFS_FS_TRANSID(transid)); - fs_m_in.m_type = transid; /* Backwards compat. */ - transid = 0; - } else - assert(IS_VFS_FS_TRANSID(transid)); - - src = fs_m_in.m_source; - caller_uid = INVAL_UID; /* To trap errors */ - caller_gid = INVAL_GID; - req_nr = fs_m_in.m_type; - - if (req_nr < FS_BASE) { - fs_m_in.m_type += FS_BASE; - req_nr = fs_m_in.m_type; - } - ind = req_nr - FS_BASE; - - if (ind < 0 || ind >= NREQS) { - printf("MFS: bad request %d from %d\n", req_nr, src); - printf("ind = %d\n", ind); - error = EINVAL; - } else { - error = (*fs_call_vec[ind])(); - /*cch_check();*/ - } - - fs_m_out.m_type = error; - if (IS_VFS_FS_TRANSID(transid)) { - /* If a transaction ID was set, reset it */ - fs_m_out.m_type = TRNS_ADD_ID(fs_m_out.m_type, transid); - } - reply(src, &fs_m_out); - } - - return(OK); + return(0); } /*===========================================================================* @@ -130,53 +74,9 @@ static void sef_cb_signal_handler(int signo) /* Only check for termination signal, ignore anything else. */ if (signo != SIGTERM) return; - exitsignaled = 1; - (void) fs_sync(); + fs_sync(); - /* If unmounting has already been performed, exit immediately. - * We might not get another message. - */ - if (unmountdone) exit(0); -} - -/*===========================================================================* - * get_work * - *===========================================================================*/ -static void get_work(m_in) -message *m_in; /* pointer to message */ -{ - int r, srcok = 0; - endpoint_t src; - - do { - if ((r = sef_receive(ANY, m_in)) != OK) /* wait for message */ - panic("sef_receive failed: %d", r); - src = m_in->m_source; - - if(src == VFS_PROC_NR) { - if(unmountdone) - printf("MFS: unmounted: unexpected message from FS\n"); - else - srcok = 1; /* Normal FS request. */ - - } else - printf("MFS: unexpected source %d\n", src); - } while(!srcok); - - assert((src == VFS_PROC_NR && !unmountdone)); -} - - -/*===========================================================================* - * reply * - *===========================================================================*/ -static void reply( - endpoint_t who, - message *m_out /* report result */ -) -{ - if (OK != ipc_send(who, m_out)) /* send the message */ - printf("MFS(%d) was unable to send reply\n", sef_self()); + fsdriver_terminate(); } diff --git a/minix/fs/mfs/misc.c b/minix/fs/mfs/misc.c index e4bcbc31b..48d85ec49 100644 --- a/minix/fs/mfs/misc.c +++ b/minix/fs/mfs/misc.c @@ -1,14 +1,12 @@ #include "fs.h" -#include -#include -#include #include "inode.h" #include "clean.h" +#include /*===========================================================================* * fs_sync * *===========================================================================*/ -int fs_sync() +void fs_sync(void) { /* Perform the sync() system call. Flush all the tables. * The order in which the various tables are flushed is critical. The @@ -25,62 +23,4 @@ int fs_sync() /* Write all the dirty blocks to the disk. */ lmfs_flushall(); - - return(OK); /* sync() can't fail */ -} - - -/*===========================================================================* - * fs_flush * - *===========================================================================*/ -int fs_flush() -{ -/* Flush the blocks of a device from the cache after writing any dirty blocks - * to disk. - */ - dev_t dev = fs_m_in.m_vfs_fs_flush.device; - if(dev == fs_dev && lmfs_bufs_in_use() > 0) return(EBUSY); - - lmfs_flushall(); - lmfs_invalidate(dev); - - return(OK); -} - - -/*===========================================================================* - * fs_new_driver * - *===========================================================================*/ -int fs_new_driver(void) -{ -/* Set a new driver endpoint for this device. */ - dev_t dev; - cp_grant_id_t label_gid; - size_t label_len; - char label[sizeof(fs_dev_label)]; - int r; - - dev = fs_m_in.m_vfs_fs_new_driver.device; - label_gid = fs_m_in.m_vfs_fs_new_driver.grant; - label_len = fs_m_in.m_vfs_fs_new_driver.path_len; - - if (label_len > sizeof(label)) - return(EINVAL); - - r = sys_safecopyfrom(fs_m_in.m_source, label_gid, (vir_bytes) 0, - (vir_bytes) label, label_len); - - if (r != OK) { - printf("MFS: fs_new_driver safecopyfrom failed (%d)\n", r); - return(EINVAL); - } - - bdev_driver(dev, label); - - return(OK); -} - -int fs_bpeek(void) -{ - return lmfs_do_bpeek(&fs_m_in); } diff --git a/minix/fs/mfs/mount.c b/minix/fs/mfs/mount.c index 797b81854..544576f2c 100644 --- a/minix/fs/mfs/mount.c +++ b/minix/fs/mfs/mount.c @@ -4,44 +4,20 @@ #include #include -static int cleanmount = 1; - /*===========================================================================* - * fs_readsuper * + * fs_mount * *===========================================================================*/ -int fs_readsuper() +int fs_mount(dev_t dev, unsigned int flags, struct fsdriver_node *root_node, + unsigned int *res_flags) { /* 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. + * and sends back the details of them. */ struct inode *root_ip; - cp_grant_id_t label_gid; - size_t label_len; - int r; - int readonly, isroot; + int r, readonly; - fs_dev = fs_m_in.m_vfs_fs_readsuper.device; - label_gid = fs_m_in.m_vfs_fs_readsuper.grant; - label_len = fs_m_in.m_vfs_fs_readsuper.path_len; - readonly = (fs_m_in.m_vfs_fs_readsuper.flags & REQ_RDONLY) ? 1 : 0; - isroot = (fs_m_in.m_vfs_fs_readsuper.flags & REQ_ISROOT) ? 1 : 0; - - if (label_len > sizeof(fs_dev_label)) - return(EINVAL); - - r = sys_safecopyfrom(fs_m_in.m_source, label_gid, (vir_bytes) 0, - (vir_bytes) fs_dev_label, label_len); - if (r != OK) { - printf("MFS %s:%d safecopyfrom failed: %d\n", __FILE__, __LINE__, r); - return(EINVAL); - } - - /* Map the driver label for this major. */ - bdev_driver(fs_dev, fs_dev_label); + fs_dev = dev; + readonly = (flags & REQ_RDONLY) ? 1 : 0; /* Open the device the file system lives on. */ if (bdev_open(fs_dev, readonly ? BDEV_R_BIT : (BDEV_R_BIT|BDEV_W_BIT) ) != @@ -60,12 +36,6 @@ int fs_readsuper() return(r); } - /* Remember whether we were mounted cleanly so we know what to - * do at unmount time - */ - if(superblock.s_flags & MFSFLAG_CLEAN) - cleanmount = 1; - /* clean check: if rw and not clean, switch to readonly */ if(!(superblock.s_flags & MFSFLAG_CLEAN) && !readonly) { if(bdev_close(fs_dev) != OK) @@ -98,15 +68,16 @@ int fs_readsuper() } superblock.s_rd_only = readonly; - superblock.s_is_root = isroot; /* Root inode properties */ - fs_m_out.m_fs_vfs_readsuper.inode = root_ip->i_num; - fs_m_out.m_fs_vfs_readsuper.mode = root_ip->i_mode; - fs_m_out.m_fs_vfs_readsuper.file_size = root_ip->i_size; - fs_m_out.m_fs_vfs_readsuper.uid = root_ip->i_uid; - fs_m_out.m_fs_vfs_readsuper.gid = root_ip->i_gid; - fs_m_out.m_fs_vfs_readsuper.flags = RES_HASPEEK; + root_node->fn_ino_nr = root_ip->i_num; + root_node->fn_mode = root_ip->i_mode; + root_node->fn_size = root_ip->i_size; + root_node->fn_uid = root_ip->i_uid; + root_node->fn_gid = root_ip->i_gid; + root_node->fn_dev = NO_DEV; + + *res_flags = RES_NOFLAGS; /* Mark it dirty */ if(!superblock.s_rd_only) { @@ -120,9 +91,9 @@ int fs_readsuper() /*===========================================================================* - * fs_mountpoint * + * fs_mountpt * *===========================================================================*/ -int fs_mountpoint() +int fs_mountpt(ino_t ino_nr) { /* This function looks up the mount point, it checks the condition whether * the partition can be mounted on the inode or not. @@ -132,10 +103,9 @@ int fs_mountpoint() mode_t bits; /* Temporarily open the file. */ - if( (rip = get_inode(fs_dev, fs_m_in.m_vfs_fs_mountpoint.inode)) == NULL) + if( (rip = get_inode(fs_dev, ino_nr)) == NULL) return(EINVAL); - if(rip->i_mountpoint) r = EBUSY; /* It may not be special. */ @@ -153,33 +123,32 @@ int fs_mountpoint() /*===========================================================================* * fs_unmount * *===========================================================================*/ -int fs_unmount() +void fs_unmount(void) { -/* Unmount a file system by device number. */ +/* Unmount a file system. */ int count; 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. */ + * open --the root inode-- and that inode only 1 time. This is an integrity + * check only: VFS expects the unmount to succeed either way. + */ 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) + printf("MFS: file system has %d in-use inodes!\n", count); - if ((root_ip = find_inode(fs_dev, ROOT_INODE)) == NULL) { - panic("MFS: couldn't find root inode\n"); - return(EINVAL); - } + if ((root_ip = find_inode(fs_dev, ROOT_INODE)) == NULL) + panic("MFS: couldn't find root inode\n"); - 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(); + fs_sync(); /* Mark it clean if we're allowed to write _and_ it was clean originally. */ - if(cleanmount && !superblock.s_rd_only) { + if (!superblock.s_rd_only) { superblock.s_flags |= MFSFLAG_CLEAN; write_super(&superblock); } @@ -192,8 +161,5 @@ int fs_unmount() /* Finish off the unmount. */ superblock.s_dev = NO_DEV; - unmountdone = TRUE; - - return(OK); } diff --git a/minix/fs/mfs/open.c b/minix/fs/mfs/open.c index fba0d3094..67c8225ae 100644 --- a/minix/fs/mfs/open.c +++ b/minix/fs/mfs/open.c @@ -1,47 +1,31 @@ #include "fs.h" #include #include -#include #include "buf.h" #include "inode.h" #include "super.h" -#include static struct inode *new_node(struct inode *ldirp, char *string, mode_t - bits, zone_t z0); + bits, uid_t uid, gid_t gid, zone_t z0); /*===========================================================================* * fs_create * *===========================================================================*/ -int fs_create() +int fs_create(ino_t dir_nr, char *name, mode_t mode, uid_t uid, gid_t gid, + struct fsdriver_node *node) { - size_t len; int r; struct inode *ldirp; struct inode *rip; - mode_t omode; - char lastc[MFS_NAME_MAX]; - - /* Read request message */ - omode = fs_m_in.m_vfs_fs_create.mode; - caller_uid = fs_m_in.m_vfs_fs_create.uid; - caller_gid = fs_m_in.m_vfs_fs_create.gid; /* Try to make the file. */ - /* Copy the last component (i.e., file name) */ - len = min(fs_m_in.m_vfs_fs_create.path_len, sizeof(lastc)); - err_code = sys_safecopyfrom(VFS_PROC_NR, fs_m_in.m_vfs_fs_create.grant, - (vir_bytes) 0, (vir_bytes) lastc, len); - if (err_code != OK) return err_code; - NUL(lastc, len, sizeof(lastc)); - /* Get last directory inode (i.e., directory that will hold the new inode) */ - if ((ldirp = get_inode(fs_dev, fs_m_in.m_vfs_fs_create.inode)) == NULL) - return(ENOENT); + if ((ldirp = get_inode(fs_dev, dir_nr)) == NULL) + return(EINVAL); /* Create a new inode by calling new_node(). */ - rip = new_node(ldirp, lastc, omode, NO_ZONE); + rip = new_node(ldirp, name, mode, uid, gid, NO_ZONE); r = err_code; /* If an error occurred, release inode. */ @@ -52,13 +36,12 @@ int fs_create() } /* Reply message */ - fs_m_out.m_fs_vfs_create.inode = rip->i_num; - fs_m_out.m_fs_vfs_create.mode = rip->i_mode; - fs_m_out.m_fs_vfs_create.file_size = rip->i_size; - - /* These values are needed for the execution */ - fs_m_out.m_fs_vfs_create.uid = rip->i_uid; - fs_m_out.m_fs_vfs_create.gid = rip->i_gid; + node->fn_ino_nr = rip->i_num; + node->fn_mode = rip->i_mode; + node->fn_size = rip->i_size; + node->fn_uid = rip->i_uid; + node->fn_gid = rip->i_gid; + node->fn_dev = NO_DEV; /* Drop parent dir */ put_inode(ldirp); @@ -70,29 +53,17 @@ int fs_create() /*===========================================================================* * fs_mknod * *===========================================================================*/ -int fs_mknod() +int fs_mknod(ino_t dir_nr, char *name, mode_t mode, uid_t uid, gid_t gid, + dev_t dev) { struct inode *ip, *ldirp; - char lastc[MFS_NAME_MAX]; - phys_bytes len; - /* Copy the last component and set up caller's user and group id */ - len = min(fs_m_in.m_vfs_fs_mknod.path_len, sizeof(lastc)); - err_code = sys_safecopyfrom(VFS_PROC_NR, fs_m_in.m_vfs_fs_mknod.grant, - (vir_bytes) 0, (vir_bytes) lastc, (size_t) len); - if (err_code != OK) return err_code; - NUL(lastc, len, sizeof(lastc)); - - caller_uid = fs_m_in.m_vfs_fs_mknod.uid; - caller_gid = fs_m_in.m_vfs_fs_mknod.gid; - /* Get last directory inode */ - if((ldirp = get_inode(fs_dev, fs_m_in.m_vfs_fs_mknod.inode)) == NULL) - return(ENOENT); + if((ldirp = get_inode(fs_dev, dir_nr)) == NULL) + return(EINVAL); /* Try to create the new node */ - ip = new_node(ldirp, lastc, fs_m_in.m_vfs_fs_mknod.mode, - (zone_t) fs_m_in.m_vfs_fs_mknod.device); + ip = new_node(ldirp, name, mode, uid, gid, (zone_t) dev); put_inode(ip); put_inode(ldirp); @@ -103,30 +74,18 @@ int fs_mknod() /*===========================================================================* * fs_mkdir * *===========================================================================*/ -int fs_mkdir() +int fs_mkdir(ino_t dir_nr, char *name, mode_t mode, uid_t uid, gid_t gid) { int r1, r2; /* status codes */ ino_t dot, dotdot; /* inode numbers for . and .. */ struct inode *rip, *ldirp; - char lastc[MFS_NAME_MAX]; /* last component */ - phys_bytes len; - /* Copy the last component and set up caller's user and group id */ - len = min(fs_m_in.m_vfs_fs_mkdir.path_len, sizeof(lastc)); - err_code = sys_safecopyfrom(VFS_PROC_NR, fs_m_in.m_vfs_fs_mkdir.grant, - (vir_bytes) 0, (vir_bytes) lastc, (size_t) len); - if(err_code != OK) return(err_code); - NUL(lastc, len, sizeof(lastc)); - - caller_uid = fs_m_in.m_vfs_fs_mkdir.uid; - caller_gid = fs_m_in.m_vfs_fs_mkdir.gid; - /* Get last directory inode */ - if((ldirp = get_inode(fs_dev, fs_m_in.m_vfs_fs_mkdir.inode)) == NULL) - return(ENOENT); + if((ldirp = get_inode(fs_dev, dir_nr)) == NULL) + return(EINVAL); /* Next make the inode. If that fails, return error code. */ - rip = new_node(ldirp, lastc, fs_m_in.m_vfs_fs_mkdir.mode, (zone_t) 0); + rip = new_node(ldirp, name, mode, uid, gid, (zone_t) 0); if(rip == NULL || err_code == EEXIST) { put_inode(rip); /* can't make dir: it already exists */ @@ -139,11 +98,8 @@ int fs_mkdir() 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.m_vfs_fs_mkdir.mode; /* set mode */ - 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 */ + r1 = search_dir(rip, ".", &dot, ENTER); /* enter . in the new dir */ + r2 = search_dir(rip, "..", &dotdot, ENTER); /* enter .. in the new dir */ /* If both . and .. were successfully entered, increment the link counts. */ if (r1 == OK && r2 == OK) { @@ -154,7 +110,7 @@ int fs_mkdir() } else { /* It was not possible to enter . or .. probably disk was full - * links counts haven't been touched. */ - if(search_dir(ldirp, lastc, NULL, DELETE, IGN_PERM) != OK) + if(search_dir(ldirp, name, NULL, DELETE) != OK) panic("Dir disappeared: %llu", rip->i_num); rip->i_nlinks--; /* undo the increment done in new_node() */ } @@ -169,54 +125,39 @@ int fs_mkdir() /*===========================================================================* * fs_slink * *===========================================================================*/ -int fs_slink() +int fs_slink(ino_t dir_nr, char *name, uid_t uid, gid_t gid, + struct fsdriver_data *data, size_t bytes) { - phys_bytes len; struct inode *sip; /* inode containing symbolic link */ struct inode *ldirp; /* directory containing link */ register int r; /* error code */ - char string[MFS_NAME_MAX]; /* last component of the new dir's path name */ struct buf *bp; /* disk buffer for link */ - caller_uid = fs_m_in.m_vfs_fs_slink.uid; - caller_gid = fs_m_in.m_vfs_fs_slink.gid; - - /* Copy the link name's last component */ - len = min( (unsigned) fs_m_in.m_vfs_fs_slink.path_len, sizeof(string)); - r = sys_safecopyfrom(VFS_PROC_NR, fs_m_in.m_vfs_fs_slink.grant_path, - (vir_bytes) 0, (vir_bytes) string, (size_t) len); - if (r != OK) return(r); - NUL(string, len, sizeof(string)); - /* Temporarily open the dir. */ - if( (ldirp = get_inode(fs_dev, fs_m_in.m_vfs_fs_slink.inode)) == NULL) + if( (ldirp = get_inode(fs_dev, dir_nr)) == NULL) return(EINVAL); /* Create the inode for the symlink. */ - sip = new_node(ldirp, string, (I_SYMBOLIC_LINK | RWX_MODES), 0); + sip = new_node(ldirp, name, (I_SYMBOLIC_LINK | RWX_MODES), uid, gid, 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) { - size_t namelen = fs_m_in.m_vfs_fs_slink.mem_size; bp = new_block(sip, (off_t) 0); if (bp == NULL) r = err_code; else { - if(get_block_size(sip->i_dev) <= namelen) { + if(get_block_size(sip->i_dev) <= bytes) { r = ENAMETOOLONG; } else { - r = sys_safecopyfrom(VFS_PROC_NR, - fs_m_in.m_vfs_fs_slink.grant_target, - (vir_bytes) 0, (vir_bytes) b_data(bp), - namelen); - b_data(bp)[namelen] = '\0'; + r = fsdriver_copyin(data, 0, b_data(bp), bytes); + b_data(bp)[bytes] = '\0'; } } if(bp != NULL && r == OK) { sip->i_size = (off_t) strlen(b_data(bp)); - if(sip->i_size != fs_m_in.m_vfs_fs_slink.mem_size) { + if(sip->i_size != bytes) { /* 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 @@ -233,7 +174,7 @@ int fs_slink() if(r != OK) { sip->i_nlinks = NO_LINK; - if(search_dir(ldirp, string, NULL, DELETE, IGN_PERM) != OK) + if(search_dir(ldirp, name, NULL, DELETE) != OK) panic("Symbolic link vanished"); } } @@ -249,7 +190,7 @@ int fs_slink() * new_node * *===========================================================================*/ static struct inode *new_node(struct inode *ldirp, - char *string, mode_t bits, zone_t z0) + char *string, mode_t bits, uid_t uid, gid_t gid, 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 @@ -261,7 +202,6 @@ static struct inode *new_node(struct inode *ldirp, * The parsed path rest is returned in 'parsed' if parsed is nonzero. It * has to hold at least MFS_NAME_MAX bytes. */ - register struct inode *rip; register int r; @@ -270,19 +210,18 @@ static struct inode *new_node(struct inode *ldirp, return(NULL); } - /* Get final component of the path. */ - rip = advance(ldirp, string, IGN_PERM); - if (S_ISDIR(bits) && (ldirp->i_nlinks >= LINK_MAX)) { /* New entry is a directory, alas we can't give it a ".." */ - put_inode(rip); err_code = EMLINK; return(NULL); } + /* Get final component of the path. */ + rip = advance(ldirp, string); + if ( rip == NULL && err_code == ENOENT) { /* Last path component does not exist. Make new directory entry. */ - if ( (rip = alloc_inode((ldirp)->i_dev, bits)) == NULL) { + if ( (rip = alloc_inode((ldirp)->i_dev, bits, uid, gid)) == NULL) { /* Can't creat new inode: out of inodes. */ return(NULL); } @@ -296,7 +235,7 @@ static struct inode *new_node(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, IGN_PERM)) != OK) { + if((r=search_dir(ldirp, string, &rip->i_num, ENTER)) != OK) { rip->i_nlinks--; /* pity, have to free disk inode */ IN_MARKDIRTY(rip); /* dirty inodes are written out */ put_inode(rip); /* this call frees the inode */ @@ -304,8 +243,6 @@ static struct inode *new_node(struct inode *ldirp, return(NULL); } - } else if (err_code == EENTERMOUNT || err_code == ELEAVEMOUNT) { - r = EEXIST; } else { /* Either last component exists, or there is some problem. */ if (rip != NULL) @@ -321,18 +258,13 @@ static struct inode *new_node(struct inode *ldirp, /*===========================================================================* - * fs_inhibread * + * fs_seek * *===========================================================================*/ -int fs_inhibread() +void fs_seek(ino_t ino_nr) { struct inode *rip; - if((rip = find_inode(fs_dev, fs_m_in.m_vfs_fs_inhibread.inode)) == NULL) - return(EINVAL); - /* inhibit read ahead */ - rip->i_seek = ISEEK; - - return(OK); + if ((rip = find_inode(fs_dev, ino_nr)) != NULL) + rip->i_seek = ISEEK; } - diff --git a/minix/fs/mfs/path.c b/minix/fs/mfs/path.c index 14800a4e2..92328e748 100644 --- a/minix/fs/mfs/path.c +++ b/minix/fs/mfs/path.c @@ -1,355 +1,53 @@ /* This file contains the procedures that look up path names in the directory * system and determine the inode number that goes with a given path name. - * - * The entry points into this file are - * eat_path: the 'main' routine of the path-to-inode conversion mechanism - * last_dir: find the final directory on a given path - * advance: parse one component of a path name - * search_dir: search a directory for a string and return its inode number - * */ #include "fs.h" -#include "assert.h" +#include #include -#include -#include -#include #include "buf.h" #include "inode.h" #include "super.h" -#include -#include - - -char dot1[2] = "."; /* used for search_dir to bypass the access */ -char dot2[3] = ".."; /* permissions for . and .. */ - -static char *get_name(char *name, char string[MFS_NAME_MAX+1]); -static int ltraverse(struct inode *rip, char *suffix); -static int parse_path(ino_t dir_ino, ino_t root_ino, int flags, struct - inode **res_inop, size_t *offsetp, int *symlinkp); /*===========================================================================* * fs_lookup * *===========================================================================*/ -int fs_lookup() +int fs_lookup(ino_t dir_nr, char *name, struct fsdriver_node *node, + int *is_mountpt) { - cp_grant_id_t grant; - int r, r1, flags, symlinks; - unsigned int len; - size_t offset = 0, path_size; - ino_t dir_ino, root_ino; - struct inode *rip; + struct inode *dirp, *rip; - grant = fs_m_in.m_vfs_fs_lookup.grant_path; - path_size = fs_m_in.m_vfs_fs_lookup.path_size; /* Size of the buffer */ - len = fs_m_in.m_vfs_fs_lookup.path_len; /* including terminating nul */ - dir_ino = fs_m_in.m_vfs_fs_lookup.dir_ino; - root_ino = fs_m_in.m_vfs_fs_lookup.root_ino; - flags = fs_m_in.m_vfs_fs_lookup.flags; + /* Find the starting inode. */ + if ((dirp = find_inode(fs_dev, dir_nr)) == NULL) + return EINVAL; - /* Check length. */ - if(len > sizeof(user_path)) return(E2BIG); /* too big for buffer */ - if(len == 0) return(EINVAL); /* too small */ + /* Look up the directory entry. */ + if ((rip = advance(dirp, name)) == NULL) + return err_code; - /* Copy the pathname and set up caller's user and group id */ - r = sys_safecopyfrom(VFS_PROC_NR, grant, /*offset*/ (vir_bytes) 0, - (vir_bytes) user_path, (size_t) len); - if(r != OK) return(r); - - /* Verify this is a null-terminated path. */ - if(user_path[len - 1] != '\0') return(EINVAL); - - memset(&credentials, 0, sizeof(credentials)); - if(!(flags & PATH_GET_UCRED)) { /* Do we have to copy uid/gid credentials? */ - caller_uid = fs_m_in.m_vfs_fs_lookup.uid; - caller_gid = fs_m_in.m_vfs_fs_lookup.gid; - } else { - if((r=fs_lookup_credentials(&credentials, - &caller_uid, &caller_gid, - fs_m_in.m_vfs_fs_lookup.grant_ucred, - fs_m_in.m_vfs_fs_lookup.ucred_size)) != OK) - return r; - } - - /* Lookup inode */ - rip = NULL; - r = parse_path(dir_ino, root_ino, flags, &rip, &offset, &symlinks); - - if(symlinks != 0 && (r == ELEAVEMOUNT || r == EENTERMOUNT || r == ESYMLINK)){ - len = strlen(user_path)+1; - if(len > path_size) return(ENAMETOOLONG); - - r1 = sys_safecopyto(VFS_PROC_NR, grant, (vir_bytes) 0, - (vir_bytes) user_path, (size_t) len); - if(r1 != OK) return(r1); - } - - if(r == ELEAVEMOUNT || r == ESYMLINK) { - /* Report offset and the error */ - fs_m_out.m_fs_vfs_lookup.offset = offset; - fs_m_out.m_fs_vfs_lookup.symloop = symlinks; - - return(r); - } - - if (r != OK && r != EENTERMOUNT) return(r); - - fs_m_out.m_fs_vfs_lookup.inode = rip->i_num; - fs_m_out.m_fs_vfs_lookup.mode = rip->i_mode; - fs_m_out.m_fs_vfs_lookup.file_size = rip->i_size; - fs_m_out.m_fs_vfs_lookup.symloop = symlinks; - fs_m_out.m_fs_vfs_lookup.uid = rip->i_uid; - fs_m_out.m_fs_vfs_lookup.gid = rip->i_gid; - + /* On success, leave the resulting inode open and return its details. */ + node->fn_ino_nr = rip->i_num; + node->fn_mode = rip->i_mode; + node->fn_size = rip->i_size; + node->fn_uid = rip->i_uid; + node->fn_gid = rip->i_gid; /* This is only valid for block and character specials. But it doesn't * cause any harm to always set the device field. */ - fs_m_out.m_fs_vfs_lookup.device = (dev_t) rip->i_zone[0]; + node->fn_dev = (dev_t) rip->i_zone[0]; - if(r == EENTERMOUNT) { - fs_m_out.m_fs_vfs_lookup.offset = offset; - put_inode(rip); /* Only return a reference to the final object */ - } + *is_mountpt = rip->i_mountpoint; - return(r); -} - - -/*===========================================================================* - * parse_path * - *===========================================================================*/ -static int parse_path( -ino_t dir_ino, -ino_t root_ino, -int flags, -struct inode **res_inop, -size_t *offsetp, -int *symlinkp -) { - /* 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. - */ - int r, leaving_mount; - struct inode *rip, *dir_ip; - char *cp, *next_cp; /* component and next component */ - char component[MFS_NAME_MAX+1]; - - /* Start parsing path at the first component in user_path */ - cp = user_path; - - /* No symlinks encountered yet */ - *symlinkp = 0; - - /* Find starting inode inode according to the request message */ - if((rip = find_inode(fs_dev, dir_ino)) == NULL) - return(ENOENT); - - /* If dir has been removed return ENOENT. */ - if (rip->i_nlinks == NO_LINK) return(ENOENT); - - dup_inode(rip); - - /* If the given start inode is a mountpoint, we must be here because the file - * system mounted on top returned an ELEAVEMOUNT error. In this case, we must - * only accept ".." as the first path component. - */ - leaving_mount = rip->i_mountpoint; /* True iff rip is a mountpoint */ - - /* Scan the path component by component. */ - while (TRUE) { - if(cp[0] == '\0') { - /* We're done; either the path was empty or we've parsed all - components of the path */ - - *res_inop = rip; - *offsetp += cp - user_path; - - /* Return EENTERMOUNT if we are at a mount point */ - if (rip->i_mountpoint) return(EENTERMOUNT); - - return(OK); - } - - while(cp[0] == '/') cp++; - next_cp = get_name(cp, component); - - /* Special code for '..'. A process is not allowed to leave a chrooted - * environment. A lookup of '..' at the root of a mounted filesystem - * has to return ELEAVEMOUNT. In both cases, the caller needs search - * permission for the current inode, as it is used as directory. - */ - if(strcmp(component, "..") == 0) { - /* 'rip' is now accessed as directory */ - if ((r = forbidden(rip, X_BIT)) != OK) { - put_inode(rip); - return(r); - } - - if (rip->i_num == root_ino) { - cp = next_cp; - continue; /* Ignore the '..' at a process' root - and move on to the next component */ - } - - if (rip->i_num == ROOT_INODE && !rip->i_sp->s_is_root) { - /* Climbing up to parent FS */ - - put_inode(rip); - *offsetp += cp - user_path; - return(ELEAVEMOUNT); - } - } - - /* Only check for a mount point if we are not coming from one. */ - if (!leaving_mount && rip->i_mountpoint) { - /* Going to enter a child FS */ - - *res_inop = rip; - *offsetp += cp - user_path; - return(EENTERMOUNT); - } - - /* There is more path. Keep parsing. - * If we're leaving a mountpoint, skip directory permission checks. - */ - dir_ip = rip; - rip = advance(dir_ip, leaving_mount ? dot2 : component, CHK_PERM); - if(err_code == ELEAVEMOUNT || err_code == EENTERMOUNT) - err_code = OK; - - if (err_code != OK) { - put_inode(dir_ip); - return(err_code); - } - - leaving_mount = 0; - - /* The call to advance() succeeded. Fetch next component. */ - if (S_ISLNK(rip->i_mode)) { - - if (next_cp[0] == '\0' && (flags & PATH_RET_SYMLINK)) { - put_inode(dir_ip); - *res_inop = rip; - *offsetp += next_cp - user_path; - return(OK); - } - - /* Extract path name from the symlink file */ - r = ltraverse(rip, next_cp); - next_cp = user_path; - *offsetp = 0; - - /* Symloop limit reached? */ - if (++(*symlinkp) > _POSIX_SYMLOOP_MAX) - r = ELOOP; - - if (r != OK) { - put_inode(dir_ip); - put_inode(rip); - return(r); - } - - if (next_cp[0] == '/') { - put_inode(dir_ip); - put_inode(rip); - return(ESYMLINK); - } - - put_inode(rip); - dup_inode(dir_ip); - rip = dir_ip; - } - - put_inode(dir_ip); - cp = next_cp; /* Process subsequent component in next round */ - } -} - - -/*===========================================================================* - * ltraverse * - *===========================================================================*/ -static int ltraverse(rip, suffix) -register struct inode *rip; /* symbolic link */ -char *suffix; /* current remaining path. Has to point in the - * user_path buffer - */ -{ -/* Traverse a symbolic link. Copy the link text from the inode and insert - * the text into the path. Return error code or report success. Base - * directory has to be determined according to the first character of the - * new pathname. - */ - - size_t llen; /* length of link */ - size_t slen; /* length of suffix */ - struct buf *bp; /* buffer containing link text */ - char *sp; /* start of link text */ - - if(!(bp = get_block_map(rip, 0))) - return(EIO); - llen = (size_t) rip->i_size; - sp = b_data(bp); - slen = strlen(suffix); - - /* The path we're parsing looks like this: - * /already/processed/path/ or - * /already/processed/path//not/yet/processed/path - * After expanding the , the path will look like - * or - * /not/yet/processed - * In both cases user_path must have enough room to hold . - * However, in the latter case we have to move /not/yet/processed to the - * right place first, before we expand . When strlen() is - * smaller than strlen(/already/processes/path), we move the suffix to the - * left. Is strlen() greater then we move it to the right. Else - * we do nothing. - */ - - if (slen > 0) { /* Do we have path after the link? */ - /* For simplicity we require that suffix starts with a slash */ - if (suffix[0] != '/') { - panic("ltraverse: suffix does not start with a slash"); - } - - /* To be able to expand the , we have to move the 'suffix' - * to the right place. - */ - if (slen + llen + 1 > sizeof(user_path)) - return(ENAMETOOLONG);/* +suffix+\0 does not fit*/ - if ((unsigned) (suffix-user_path) != llen) { - /* Move suffix left or right */ - memmove(&user_path[llen], suffix, slen+1); - } - } else { - if (llen + 1 > sizeof(user_path)) - return(ENAMETOOLONG); /* + \0 does not fix */ - - /* Set terminating nul */ - user_path[llen]= '\0'; - } - - /* Everything is set, now copy the expanded link to user_path */ - memmove(user_path, sp, llen); - - put_block(bp, DIRECTORY_BLOCK); - return(OK); + return OK; } /*===========================================================================* * advance * *===========================================================================*/ -struct inode *advance(dirp, string, chk_perm) +struct inode *advance(dirp, string) struct inode *dirp; /* inode for directory to be searched */ -char string[MFS_NAME_MAX]; /* component name to look for */ -int chk_perm; /* check permissions when string is looked up*/ +const char *string; /* 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 @@ -358,114 +56,44 @@ int chk_perm; /* check permissions when string is looked up*/ ino_t numb; struct inode *rip; + assert(dirp != NULL); + /* If 'string' is empty, return an error. */ if (string[0] == '\0') { err_code = ENOENT; return(NULL); } - /* Check for NULL. */ - if (dirp == NULL) return(NULL); + /* If dir has been removed return ENOENT. */ + if (dirp->i_nlinks == NO_LINK) { + err_code = ENOENT; + return(NULL); + } /* If 'string' is not present in the directory, signal error. */ - if ( (err_code = search_dir(dirp, string, &numb, LOOK_UP, chk_perm)) != OK) { + if ( (err_code = search_dir(dirp, string, &numb, LOOK_UP)) != OK) { return(NULL); } /* The component has been found in the directory. Get inode. */ if ( (rip = get_inode(dirp->i_dev, (int) numb)) == NULL) { + assert(err_code != OK); return(NULL); } - /* The following test is for "mountpoint/.." where mountpoint is a - * mountpoint. ".." will refer to the root of the mounted filesystem, - * but has to become a reference to the parent of the 'mountpoint' - * directory. - * - * This case is recognized by the looked up name pointing to a - * root inode, and the directory in which it is held being a - * root inode, _and_ the name[1] being '.'. (This is a test for '..' - * and excludes '.'.) - */ - if (rip->i_num == ROOT_INODE) { - if (dirp->i_num == ROOT_INODE) { - if (string[1] == '.') { - if (!rip->i_sp->s_is_root) { - /* Climbing up mountpoint */ - err_code = ELEAVEMOUNT; - } - } - } - } - - /* See if the inode is mounted on. If so, switch to root directory of the - * mounted file system. The super_block provides the linkage between the - * inode mounted on and the root directory of the mounted file system. - */ - if (rip->i_mountpoint) { - /* Mountpoint encountered, report it */ - err_code = EENTERMOUNT; - } - + assert(err_code == OK); return(rip); } -/*===========================================================================* - * get_name * - *===========================================================================*/ -static char *get_name(path_name, string) -char *path_name; /* path name to parse */ -char string[MFS_NAME_MAX+1]; /* component extracted from 'old_name' */ -{ -/* Given a pointer to a path name in fs space, 'path_name', copy the first - * 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' = 'path_name' - 'string'. - * - * This routine follows the standard convention that /usr/ast, /usr//ast, - * //usr///ast and /usr/ast/ are all equivalent. - */ - size_t len; - char *cp, *ep; - - cp = path_name; - - /* Skip leading slashes */ - while (cp[0] == '/') cp++; - - /* Find the end of the first component */ - ep = cp; - while(ep[0] != '\0' && ep[0] != '/') - ep++; - - len = (size_t) (ep - cp); - - /* Truncate the amount to be copied if it exceeds MFS_NAME_MAX */ - if (len > MFS_NAME_MAX) len = MFS_NAME_MAX; - - /* Special case of the string at cp is empty */ - if (len == 0) - strlcpy(string, ".", MFS_NAME_MAX + 1); /* Return "." */ - else { - memcpy(string, cp, len); - string[len]= '\0'; - } - - return(ep); -} - - /*===========================================================================* * search_dir * *===========================================================================*/ -int search_dir(ldir_ptr, string, numb, flag, check_permissions) +int search_dir(ldir_ptr, string, numb, flag) register struct inode *ldir_ptr; /* ptr to inode for dir to search */ -char string[MFS_NAME_MAX]; /* component to search for */ +const char *string; /* component to search for */ ino_t *numb; /* pointer to inode number */ int flag; /* LOOK_UP, ENTER, DELETE or IS_EMPTY */ -int check_permissions; /* check permissions when flag is !IS_EMPTY */ { /* This function searches the directory whose inode is pointed to by 'ldip': * if (flag == ENTER) enter 'string' in the directory with inode # '*numb'; @@ -473,13 +101,12 @@ int check_permissions; /* check permissions when flag is !IS_EMPTY */ * if (flag == LOOK_UP) search for 'string' and return inode # in 'numb'; * if (flag == IS_EMPTY) return OK if only . and .. in dir else ENOTEMPTY; * - * if 'string' is dot1 or dot2, no access permissions are checked. + * This function, and this function alone, implements name truncation, + * by simply considering only the first MFS_NAME_MAX bytes from 'string'. */ - register struct direct *dp = NULL; register struct buf *bp = NULL; int i, r, e_hit, t, match; - mode_t bits; off_t pos; unsigned new_slots, old_slots; struct super_block *sp; @@ -493,20 +120,6 @@ int check_permissions; /* check permissions when flag is !IS_EMPTY */ if((flag == DELETE || flag == ENTER) && ldir_ptr->i_sp->s_rd_only) return EROFS; - r = OK; - - if (flag != IS_EMPTY) { - bits = (flag == LOOK_UP ? X_BIT : W_BIT | X_BIT); - - if (string == dot1 || string == dot2) { - if (flag != LOOK_UP) r = read_only(ldir_ptr); - /* only a writable device is required. */ - } else if(check_permissions) { - r = forbidden(ldir_ptr, bits); /* check access permissions */ - } - } - if (r != OK) return(r); - /* Step through the directory one block at a time. */ old_slots = (unsigned) (ldir_ptr->i_size/DIR_ENTRY_SIZE); new_slots = 0; @@ -543,7 +156,8 @@ int check_permissions; /* check permissions when flag is !IS_EMPTY */ if (flag == IS_EMPTY) { /* If this test succeeds, dir is not empty. */ if (strcmp(dp->mfs_d_name, "." ) != 0 && - strcmp(dp->mfs_d_name, "..") != 0) match = 1; + strcmp(dp->mfs_d_name, "..") != 0) + match = 1; } else { if (strncmp(dp->mfs_d_name, string, sizeof(dp->mfs_d_name)) == 0){ @@ -560,7 +174,7 @@ int check_permissions; /* check permissions when flag is !IS_EMPTY */ /* Save d_ino for recovery. */ t = MFS_NAME_MAX - sizeof(ino_t); *((ino_t *) &dp->mfs_d_name[t]) = dp->mfs_d_ino; - dp->mfs_d_ino = NO_ENTRY; /* erase entry */ + dp->mfs_d_ino = NO_ENTRY; /* erase entry */ MARKDIRTY(bp); ldir_ptr->i_update |= CTIME | MTIME; IN_MARKDIRTY(ldir_ptr); diff --git a/minix/fs/mfs/pipe.c b/minix/fs/mfs/pipe.c deleted file mode 100644 index 8b1378917..000000000 --- a/minix/fs/mfs/pipe.c +++ /dev/null @@ -1 +0,0 @@ - diff --git a/minix/fs/mfs/protect.c b/minix/fs/mfs/protect.c index ee069e26d..5deb7637b 100644 --- a/minix/fs/mfs/protect.c +++ b/minix/fs/mfs/protect.c @@ -1,25 +1,18 @@ #include "fs.h" #include "inode.h" #include "super.h" -#include - -static int in_group(gid_t grp); /*===========================================================================* * fs_chmod * *===========================================================================*/ -int fs_chmod() +int fs_chmod(ino_t ino_nr, mode_t *mode) { /* Perform the chmod(name, mode) system call. */ - register struct inode *rip; - mode_t mode; - mode = fs_m_in.m_vfs_fs_chmod.mode; - /* Temporarily open the file. */ - if( (rip = get_inode(fs_dev, fs_m_in.m_vfs_fs_chmod.inode)) == NULL) + if( (rip = get_inode(fs_dev, ino_nr)) == NULL) return(EINVAL); if(rip->i_sp->s_rd_only) { @@ -28,12 +21,12 @@ int fs_chmod() } /* Now make the change. Clear setgid bit if file is not in caller's grp */ - rip->i_mode = (rip->i_mode & ~ALL_MODES) | (mode & ALL_MODES); + rip->i_mode = (rip->i_mode & ~ALL_MODES) | (*mode & ALL_MODES); rip->i_update |= CTIME; IN_MARKDIRTY(rip); /* Return full new mode to caller. */ - fs_m_out.m_fs_vfs_chmod.mode = rip->i_mode; + *mode = rip->i_mode; put_inode(rip); return(OK); @@ -43,116 +36,23 @@ int fs_chmod() /*===========================================================================* * fs_chown * *===========================================================================*/ -int fs_chown() +int fs_chown(ino_t ino_nr, uid_t uid, gid_t gid, mode_t *mode) { register struct inode *rip; - register int r; /* Temporarily open the file. */ - if( (rip = get_inode(fs_dev, fs_m_in.m_vfs_fs_chown.inode)) == NULL) + if( (rip = get_inode(fs_dev, ino_nr)) == NULL) 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.m_vfs_fs_chown.uid; - rip->i_gid = fs_m_in.m_vfs_fs_chown.gid; - rip->i_mode &= ~(I_SET_UID_BIT | I_SET_GID_BIT); - rip->i_update |= CTIME; - IN_MARKDIRTY(rip); - } + rip->i_uid = uid; + rip->i_gid = gid; + rip->i_mode &= ~(I_SET_UID_BIT | I_SET_GID_BIT); + rip->i_update |= CTIME; + IN_MARKDIRTY(rip); /* Update caller on current mode, as it may have changed. */ - fs_m_out.m_fs_vfs_chown.mode = rip->i_mode; + *mode = rip->i_mode; put_inode(rip); - return(r); + return(OK); } - - -/*===========================================================================* - * forbidden * - *===========================================================================*/ -int forbidden(struct inode *rip, mode_t access_desired) -{ -/* Given a pointer to an inode, 'rip', 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. - */ - - register struct inode *old_rip = rip; - mode_t bits, perm_bits; - int r, shift; - - /* Isolate the relevant rwx bits from the mode. */ - bits = rip->i_mode; - if (caller_uid == SU_UID) { - /* Grant read and write permission. Grant search permission for - * directories. Grant execute permission (for non-directories) if - * and only if one of the 'X' bits is set. - */ - if ( (bits & I_TYPE) == I_DIRECTORY || - bits & ((X_BIT << 6) | (X_BIT << 3) | X_BIT)) - perm_bits = R_BIT | W_BIT | X_BIT; - else - 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 (in_group(rip->i_gid) == OK) shift = 3; /* other 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; - - /* Check to see if someone is trying to write on a file system that is - * mounted read-only. - */ - if (r == OK) - if (access_desired & W_BIT) - r = read_only(rip); - - if (rip != old_rip) put_inode(rip); - - return(r); -} - - -/*===========================================================================* - * in_group * - *===========================================================================*/ -static int in_group(gid_t grp) -{ - int i; - - if (credentials.vu_ngroups > NGROUPS_MAX) - return(EINVAL); - - for (i = 0; i < credentials.vu_ngroups; i++) - if (credentials.vu_sgroups[i] == grp) - return(OK); - - return(EINVAL); -} - - -/*===========================================================================* - * read_only * - *===========================================================================*/ -int read_only(ip) -struct inode *ip; /* ptr to inode whose file sys is to be cked */ -{ -/* Check to see if the file system on which the inode 'ip' resides is mounted - * read only. If so, return EROFS, else return OK. - */ - - register struct super_block *sp; - - sp = ip->i_sp; - return(sp->s_rd_only ? EROFS : OK); -} - diff --git a/minix/fs/mfs/proto.h b/minix/fs/mfs/proto.h index 3b16c3088..b19663817 100644 --- a/minix/fs/mfs/proto.h +++ b/minix/fs/mfs/proto.h @@ -13,16 +13,15 @@ struct filp; struct inode; struct super_block; - /* cache.c */ zone_t alloc_zone(dev_t dev, zone_t z); void free_zone(dev_t dev, zone_t numb); /* inode.c */ -struct inode *alloc_inode(dev_t dev, mode_t bits); +struct inode *alloc_inode(dev_t dev, mode_t bits, uid_t uid, gid_t gid); void dup_inode(struct inode *ip); struct inode *find_inode(dev_t dev, ino_t numb); -int fs_putnode(void); +int fs_putnode(ino_t ino_nr, unsigned int count); void init_inode_cache(void); struct inode *get_inode(dev_t dev, ino_t numb); void put_inode(struct inode *rip); @@ -30,57 +29,56 @@ void update_times(struct inode *rip); void rw_inode(struct inode *rip, int rw_flag); /* link.c */ -int fs_ftrunc(void); -int fs_link(void); -int fs_rdlink(void); -int fs_rename(void); -int fs_unlink(void); +int fs_trunc(ino_t ino_nr, off_t start, off_t end); +int fs_link(ino_t dir_nr, char *name, ino_t ino_nr); +ssize_t fs_rdlink(ino_t ino_nr, struct fsdriver_data *data, size_t bytes); +int fs_rename(ino_t old_dir_nr, char *old_name, ino_t new_dir_nr, + char *new_name); +int fs_unlink(ino_t dir_nr, char *name, int call); int truncate_inode(struct inode *rip, off_t len); /* misc.c */ -int fs_flush(void); -int fs_sync(void); -int fs_new_driver(void); -int fs_bpeek(void); +void fs_sync(void); /* mount.c */ -int fs_mountpoint(void); -int fs_readsuper(void); -int fs_unmount(void); +int fs_mount(dev_t dev, unsigned int flags, struct fsdriver_node *root_node, + unsigned int *res_flags); +void fs_unmount(void); +int fs_mountpt(ino_t ino_nr); /* open.c */ -int fs_create(void); -int fs_inhibread(void); -int fs_mkdir(void); -int fs_mknod(void); -int fs_slink(void); +int fs_create(ino_t dir_nr, char *name, mode_t mode, uid_t uid, gid_t gid, + struct fsdriver_node *node); +int fs_mkdir(ino_t dir_nr, char *name, mode_t mode, uid_t uid, gid_t gid); +int fs_mknod(ino_t dir_nr, char *name, mode_t mode, uid_t uid, gid_t gid, + dev_t dev); +int fs_slink(ino_t dir_nr, char *name, uid_t uid, gid_t gid, + struct fsdriver_data *data, size_t bytes); +void fs_seek(ino_t ino_nr); /* path.c */ -int fs_lookup(void); -struct inode *advance(struct inode *dirp, char string[MFS_NAME_MAX], int - chk_perm); -int search_dir(struct inode *ldir_ptr, char string [MFS_NAME_MAX], ino_t - *numb, int flag, int check_permissions); - +int fs_lookup(ino_t dir_nr, char *name, struct fsdriver_node *node, + int *is_mountpt); +struct inode *advance(struct inode *dirp, const char *string); +int search_dir(struct inode *ldir_ptr, const char *string, ino_t *numb, + int flag); /* protect.c */ -int fs_chmod(void); -int fs_chown(void); -int fs_getdents(void); -int forbidden(struct inode *rip, mode_t access_desired); -int read_only(struct inode *ip); +int fs_chmod(ino_t ino, mode_t *mode); +int fs_chown(ino_t ino, uid_t uid, gid_t gid, mode_t *mode); /* read.c */ -int fs_breadwrite(void); -int fs_readwrite(void); -void read_ahead(void); +ssize_t fs_readwrite(ino_t ino_nr, struct fsdriver_data *data, size_t bytes, + off_t pos, int call); block_t read_map(struct inode *rip, off_t pos, int opportunistic); struct buf *get_block_map(register struct inode *rip, u64_t position); zone_t rd_indir(struct buf *bp, int index); +ssize_t fs_getdents(ino_t ino_nr, struct fsdriver_data *data, size_t bytes, + off_t *posp); /* stadir.c */ -int fs_stat(void); -int fs_statvfs(void); +int fs_stat(ino_t ino_nr, struct stat *statbuf); +int fs_statvfs(struct statvfs *st); /* super.c */ bit_t alloc_bit(struct super_block *sp, int map, bit_t origin); @@ -95,17 +93,11 @@ u32_t get_used_blocks(struct super_block *sp); bit_t count_free_bits(struct super_block *sp, int map); /* time.c */ -int fs_utime(void); +int fs_utime(ino_t ino_t, struct timespec *atime, struct timespec *mtime); /* utility.c */ unsigned conv2(int norm, int w); long conv4(int norm, long x); -void mfs_nul_f(char *file, int line, char *str, unsigned int len, - unsigned int maxlen); -int min(unsigned int l, unsigned int r); -int no_sys(void); -void sanitycheck(char *file, int line); -#define SANITYCHECK sanitycheck(__FILE__, __LINE__) /* write.c */ void clear_zone(struct inode *rip, off_t pos, int flag); diff --git a/minix/fs/mfs/read.c b/minix/fs/mfs/read.c index 694e3caf7..86fc3a8c8 100644 --- a/minix/fs/mfs/read.c +++ b/minix/fs/mfs/read.c @@ -2,13 +2,9 @@ #include #include #include -#include -#include #include "buf.h" #include "inode.h" #include "super.h" -#include -#include #include #include @@ -16,59 +12,41 @@ static struct buf *rahead(struct inode *rip, block_t baseblock, u64_t position, unsigned bytes_ahead); static int rw_chunk(struct inode *rip, u64_t position, unsigned off, - size_t chunk, unsigned left, int rw_flag, cp_grant_id_t gid, unsigned - buf_off, unsigned int block_size, int *completed); + size_t chunk, unsigned left, int call, struct fsdriver_data *data, + unsigned buf_off, unsigned int block_size, int *completed); /*===========================================================================* * fs_readwrite * *===========================================================================*/ -int fs_readwrite(void) +ssize_t fs_readwrite(ino_t ino_nr, struct fsdriver_data *data, size_t nrbytes, + off_t position, int call) { - int r, rw_flag, block_spec; + int r; int regular; - cp_grant_id_t gid; - off_t position, f_size, bytes_left; - unsigned int off, cum_io, block_size, chunk; + off_t f_size, bytes_left; + size_t off, cum_io, block_size, chunk; mode_t mode_word; int completed; struct inode *rip; - size_t nrbytes; r = OK; /* Find the inode referred */ - if ((rip = find_inode(fs_dev, fs_m_in.m_vfs_fs_readwrite.inode)) == NULL) + if ((rip = find_inode(fs_dev, ino_nr)) == NULL) 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); + regular = (mode_word == I_REGULAR); /* Determine blocksize */ - if (block_spec) { - block_size = get_block_size( (dev_t) rip->i_zone[0]); - f_size = MAX_FILE_POS; - } else { - block_size = rip->i_sp->s_block_size; - f_size = rip->i_size; - } - - /* Get the values from the request message */ - switch(fs_m_in.m_type) { - case REQ_READ: rw_flag = READING; break; - case REQ_WRITE: rw_flag = WRITING; break; - case REQ_PEEK: rw_flag = PEEKING; break; - default: panic("odd request"); - } - gid = fs_m_in.m_vfs_fs_readwrite.grant; - position = fs_m_in.m_vfs_fs_readwrite.seek_pos; - nrbytes = fs_m_in.m_vfs_fs_readwrite.nbytes; + block_size = rip->i_sp->s_block_size; + f_size = rip->i_size; lmfs_reset_rdwt_err(); /* If this is file i/o, check we can write */ - if (rw_flag == WRITING && !block_spec) { + if (call == FSC_WRITE) { if(rip->i_sp->s_rd_only) return EROFS; @@ -83,18 +61,15 @@ int fs_readwrite(void) if(position > f_size) clear_zone(rip, f_size, 0); } - /* If this is block i/o, check we can write */ - if(block_spec && rw_flag == WRITING && - (dev_t) rip->i_zone[0] == superblock.s_dev && superblock.s_rd_only) - return EROFS; - 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); + chunk = block_size - off; + if (chunk > nrbytes) + chunk = nrbytes; - if (rw_flag == READING) { + if (call == FSC_READ) { bytes_left = f_size - position; if (position >= f_size) break; /* we are beyond EOF */ if (chunk > (unsigned int) bytes_left) chunk = bytes_left; @@ -102,7 +77,7 @@ int fs_readwrite(void) /* Read or write 'chunk' bytes. */ r = rw_chunk(rip, ((u64_t)((unsigned long)position)), off, chunk, - nrbytes, rw_flag, gid, cum_io, block_size, &completed); + nrbytes, call, data, cum_io, block_size, &completed); if (r != OK) break; /* EOF reached */ if (lmfs_rdwt_err() < 0) break; @@ -113,12 +88,8 @@ int fs_readwrite(void) position += (off_t) chunk; /* position within the file */ } - fs_m_out.m_fs_vfs_readwrite.seek_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 (call == FSC_WRITE) { if (regular || mode_word == I_DIRECTORY) { if (position > f_size) rip->i_size = position; } @@ -126,104 +97,38 @@ int fs_readwrite(void) rip->i_seek = NO_SEEK; - if (lmfs_rdwt_err() != OK) r = lmfs_rdwt_err(); /* check for disk error */ + if (lmfs_rdwt_err() != OK) r = lmfs_rdwt_err(); /* check for disk error */ if (lmfs_rdwt_err() == END_OF_FILE) r = OK; + if (r != OK) + return r; + /* even on a ROFS, writing to a device node on it is fine, * just don't update the inode stats for it. And dito for reading. */ - if (r == OK && !rip->i_sp->s_rd_only) { - if (rw_flag == READING) rip->i_update |= ATIME; - if (rw_flag == WRITING) rip->i_update |= CTIME | MTIME; + if (!rip->i_sp->s_rd_only) { + if (call == FSC_READ) rip->i_update |= ATIME; + if (call == FSC_WRITE) rip->i_update |= CTIME | MTIME; IN_MARKDIRTY(rip); /* inode is thus now dirty */ } - fs_m_out.m_fs_vfs_readwrite.nbytes = cum_io; - - return(r); -} - - -/*===========================================================================* - * fs_breadwrite * - *===========================================================================*/ -int fs_breadwrite(void) -{ - int r, rw_flag, completed; - cp_grant_id_t gid; - u64_t position; - unsigned int off, cum_io, chunk, block_size; - size_t nrbytes; - dev_t target_dev; - - /* Pseudo inode for rw_chunk */ - struct inode rip; - - r = OK; - - target_dev = fs_m_in.m_vfs_fs_breadwrite.device; - - /* Get the values from the request message */ - rw_flag = (fs_m_in.m_type == REQ_BREAD ? READING : WRITING); - gid = fs_m_in.m_vfs_fs_breadwrite.grant; - position = fs_m_in.m_vfs_fs_breadwrite.seek_pos; - nrbytes = fs_m_in.m_vfs_fs_breadwrite.nbytes; - - block_size = get_block_size(target_dev); - - /* Don't block-write to a RO-mounted filesystem. */ - if(superblock.s_dev == target_dev && superblock.s_rd_only) - return EROFS; - - rip.i_zone[0] = (zone_t) target_dev; - rip.i_mode = I_BLOCK_SPECIAL; - rip.i_size = 0; - - lmfs_reset_rdwt_err(); - - 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); - - /* Read or write 'chunk' bytes. */ - r = rw_chunk(&rip, position, off, chunk, nrbytes, rw_flag, gid, - cum_io, block_size, &completed); - - if (r != OK) break; /* EOF reached */ - if (lmfs_rdwt_err() < 0) break; - - /* Update counters and pointers. */ - nrbytes -= chunk; /* bytes yet to be read */ - cum_io += chunk; /* bytes read so far */ - position += chunk; /* position within the file */ - } - - fs_m_out.m_fs_vfs_breadwrite.seek_pos = position; - - if (lmfs_rdwt_err() != OK) r = lmfs_rdwt_err(); /* check for disk error */ - if (lmfs_rdwt_err() == END_OF_FILE) r = OK; - - fs_m_out.m_fs_vfs_breadwrite.nbytes = cum_io; - - return(r); + return cum_io; } /*===========================================================================* * rw_chunk * *===========================================================================*/ -static int rw_chunk(rip, position, off, chunk, left, rw_flag, gid, - buf_off, block_size, completed) +static int rw_chunk(rip, position, off, chunk, left, call, data, 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 */ unsigned off; /* off within the current block */ -unsigned int chunk; /* number of bytes to read or write */ +size_t chunk; /* number of bytes to read or write */ unsigned left; /* max number of bytes wanted after position */ -int rw_flag; /* READING, WRITING or PEEKING */ -cp_grant_id_t gid; /* grant */ -unsigned buf_off; /* offset in grant */ +int call; /* FSC_READ, FSC_WRITE, or FSC_PEEK */ +struct fsdriver_data *data; /* structure for (remote) user buffer */ +unsigned buf_off; /* offset in user buffer */ unsigned int block_size; /* block size of FS operating on */ int *completed; /* number of bytes copied */ { @@ -231,41 +136,27 @@ int *completed; /* number of bytes copied */ register struct buf *bp = NULL; register int r = OK; - int n, block_spec; + int n; block_t b; dev_t dev; ino_t ino = VMC_NO_INODE; u64_t ino_off = rounddown(position, block_size); - /* rw_flag: - * READING: read from FS, copy to user - * WRITING: copy from user, write to FS - * PEEKING: try to get all the blocks into the cache, no copying - */ - *completed = 0; - block_spec = (rip->i_mode & I_TYPE) == I_BLOCK_SPECIAL; + if (ex64hi(position) != 0) + panic("rw_chunk: position too high"); + b = read_map(rip, (off_t) ex64lo(position), 0); + dev = rip->i_dev; + ino = rip->i_num; + assert(ino != VMC_NO_INODE); - if (block_spec) { - b = (unsigned long)(position / block_size); - dev = (dev_t) rip->i_zone[0]; - } else { - if (ex64hi(position) != 0) - panic("rw_chunk: position too high"); - b = read_map(rip, (off_t) ex64lo(position), 0); - dev = rip->i_dev; - ino = rip->i_num; - assert(ino != VMC_NO_INODE); - } - - if (!block_spec && b == NO_BLOCK) { - if (rw_flag == READING) { + if (b == NO_BLOCK) { + if (call == FSC_READ) { /* Reading from a nonexistent block. Must read as all zeros.*/ - r = sys_safememset(VFS_PROC_NR, gid, (vir_bytes) buf_off, - 0, (size_t) chunk); + r = fsdriver_zero(data, buf_off, chunk); if(r != OK) { - printf("MFS: sys_safememset failed\n"); + printf("MFS: fsdriver_zero failed\n"); } return r; } else { @@ -275,7 +166,7 @@ int *completed; /* number of bytes copied */ if ((bp = new_block(rip, (off_t) ex64lo(position))) == NULL) return(err_code); } - } else if (rw_flag == READING || rw_flag == PEEKING) { + } else if (call != FSC_WRITE) { /* Read and read ahead if convenient. */ bp = rahead(rip, b, position, left); } else { @@ -284,34 +175,27 @@ int *completed; /* number of bytes copied */ * the cache, acquire it, otherwise just acquire a free buffer. */ n = (chunk == block_size ? NO_READ : NORMAL); - if (!block_spec && off == 0 && (off_t) ex64lo(position) >= rip->i_size) + if (off == 0 && (off_t) ex64lo(position) >= rip->i_size) n = NO_READ; - if(block_spec) { - assert(ino == VMC_NO_INODE); - bp = get_block(dev, b, n); - } else { - assert(ino != VMC_NO_INODE); - assert(!(ino_off % block_size)); - bp = lmfs_get_block_ino(dev, b, n, ino, ino_off); - } + assert(ino != VMC_NO_INODE); + assert(!(ino_off % block_size)); + bp = lmfs_get_block_ino(dev, b, n, ino, ino_off); } /* In all cases, bp now points to a valid buffer. */ assert(bp != NULL); - if (rw_flag == WRITING && chunk != block_size && !block_spec && + if (call == FSC_WRITE && chunk != block_size && (off_t) ex64lo(position) >= rip->i_size && off == 0) { zero_block(bp); } - if (rw_flag == READING) { + if (call == FSC_READ) { /* Copy a chunk from the block buffer to user space. */ - r = sys_safecopyto(VFS_PROC_NR, gid, (vir_bytes) buf_off, - (vir_bytes) (b_data(bp)+off), (size_t) chunk); - } else if(rw_flag == WRITING) { + r = fsdriver_copyout(data, buf_off, b_data(bp)+off, chunk); + } else if (call == FSC_WRITE) { /* Copy a chunk from user space to the block buffer. */ - r = sys_safecopyfrom(VFS_PROC_NR, gid, (vir_bytes) buf_off, - (vir_bytes) (b_data(bp)+off), (size_t) chunk); + r = fsdriver_copyin(data, buf_off, b_data(bp)+off, chunk); MARKDIRTY(bp); } @@ -461,7 +345,7 @@ unsigned bytes_ahead; /* bytes beyond position for immediate use */ /* Minimum number of blocks to prefetch. */ int nr_bufs = lmfs_nr_bufs(); # define BLOCKS_MINIMUM (nr_bufs < 50 ? 18 : 32) - int block_spec, scale, read_q_size; + int scale, read_q_size; unsigned int blocks_ahead, fragment, block_size; block_t block, blocks_left; off_t ind1_pos; @@ -482,12 +366,7 @@ unsigned bytes_ahead; /* bytes beyond position for immediate use */ readqsize = nr_bufs; } - block_spec = (rip->i_mode & I_TYPE) == I_BLOCK_SPECIAL; - if (block_spec) - dev = (dev_t) rip->i_zone[0]; - else - dev = rip->i_dev; - + dev = rip->i_dev; assert(dev != NO_DEV); block_size = get_block_size(dev); @@ -500,11 +379,7 @@ unsigned bytes_ahead; /* bytes beyond position for immediate use */ bytes_ahead += fragment; blocks_ahead = (bytes_ahead + block_size - 1) / block_size; - if(block_spec) - bp = get_block(dev, block, PREFETCH); - else - bp = lmfs_get_block_ino(dev, block, PREFETCH, rip->i_num, position); - + bp = lmfs_get_block_ino(dev, block, PREFETCH, rip->i_num, position); assert(bp != NULL); assert(bp->lmfs_count > 0); if (lmfs_dev(bp) != NO_DEV) return(bp); @@ -529,22 +404,15 @@ unsigned bytes_ahead; /* bytes beyond position for immediate use */ * indirect blocks (but don't call read_map!). */ - if (block_spec && rip->i_size == 0) { - blocks_left = (block_t) NR_IOREQS; - } else { - blocks_left = (block_t) (rip->i_size-ex64lo(position)+(block_size-1)) / + blocks_left = (block_t) (rip->i_size-ex64lo(position)+(block_size-1)) / block_size; - /* Go for the first indirect block if we are in its neighborhood. */ - if (!block_spec) { - scale = rip->i_sp->s_log_zone_size; - ind1_pos = (off_t) rip->i_ndzones * (block_size << scale); - if ((off_t) ex64lo(position) <= ind1_pos && - rip->i_size > ind1_pos) { - blocks_ahead++; - blocks_left++; - } - } + /* Go for the first indirect block if we are in its neighborhood. */ + scale = rip->i_sp->s_log_zone_size; + ind1_pos = (off_t) rip->i_ndzones * (block_size << scale); + if ((off_t) ex64lo(position) <= ind1_pos && rip->i_size > ind1_pos) { + blocks_ahead++; + blocks_left++; } /* No more than the maximum request. */ @@ -573,9 +441,10 @@ unsigned bytes_ahead; /* bytes beyond position for immediate use */ block++; position_running += block_size; - if(!block_spec && - (thisblock = read_map(rip, (off_t) ex64lo(position_running), 1)) != NO_BLOCK) { - bp = lmfs_get_block_ino(dev, thisblock, PREFETCH, rip->i_num, position_running); + thisblock = read_map(rip, (off_t) ex64lo(position_running), 1); + if (thisblock != NO_BLOCK) { + bp = lmfs_get_block_ino(dev, thisblock, PREFETCH, rip->i_num, + position_running); } else { bp = get_block(dev, block, PREFETCH); } @@ -591,8 +460,6 @@ unsigned bytes_ahead; /* bytes beyond position for immediate use */ assert(inuse_before == lmfs_bufs_in_use()); - if(block_spec) - return get_block(dev, baseblock, NORMAL); return(lmfs_get_block_ino(dev, baseblock, NORMAL, rip->i_num, position)); } @@ -600,33 +467,27 @@ unsigned bytes_ahead; /* bytes beyond position for immediate use */ /*===========================================================================* * fs_getdents * *===========================================================================*/ -int fs_getdents(void) +ssize_t fs_getdents(ino_t ino_nr, struct fsdriver_data *data, size_t bytes, + off_t *posp) { #define GETDENTS_BUFSIZE (sizeof(struct dirent) + MFS_NAME_MAX + 1) #define GETDENTS_ENTRIES 8 static char getdents_buf[GETDENTS_BUFSIZE * GETDENTS_ENTRIES]; - register struct inode *rip; - int o, r, done; - unsigned int block_size, len, reclen; - ino_t ino; - cp_grant_id_t gid; - size_t size, tmpbuf_off, userbuf_off; + struct fsdriver_dentry fsdentry; + struct inode *rip, *entrip; + int r, done; + unsigned int block_size, len, type; off_t pos, off, block_pos, new_pos, ent_pos; struct buf *bp; struct direct *dp; - struct dirent *dep; char *cp; - ino = fs_m_in.m_vfs_fs_getdents.inode; - gid = fs_m_in.m_vfs_fs_getdents.grant; - size = fs_m_in.m_vfs_fs_getdents.mem_size; - pos = fs_m_in.m_vfs_fs_getdents.seek_pos; - /* Check whether the position is properly aligned */ + pos = *posp; if( (unsigned int) pos % DIR_ENTRY_SIZE) return(ENOENT); - if( (rip = get_inode(fs_dev, ino)) == NULL) + if( (rip = get_inode(fs_dev, ino_nr)) == NULL) return(EINVAL); block_size = rip->i_sp->s_block_size; @@ -634,81 +495,63 @@ int fs_getdents(void) block_pos = pos - off; done = FALSE; /* Stop processing directory blocks when done is set */ - tmpbuf_off = 0; /* Offset in getdents_buf */ - memset(getdents_buf, '\0', sizeof(getdents_buf)); /* Avoid leaking any data */ - userbuf_off = 0; /* Offset in the user's buffer */ + fsdriver_dentry_init(&fsdentry, data, bytes, getdents_buf, + sizeof(getdents_buf)); /* 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; + r = 0; + for(; block_pos < rip->i_size; block_pos += block_size) { /* Since directories don't have holes, 'bp' cannot be NULL. */ bp = get_block_map(rip, block_pos); /* get a dir block */ assert(bp != NULL); - /* Search a directory block. */ - if (block_pos < pos) - dp = &b_dir(bp)[off / DIR_ENTRY_SIZE]; - else - dp = &b_dir(bp)[0]; - for (; dp < &b_dir(bp)[NR_DIR_ENTRIES(block_size)]; dp++) { - if (dp->mfs_d_ino == 0) - continue; /* Entry is not in use */ + /* Search a directory block. */ + if (block_pos < pos) + dp = &b_dir(bp)[off / DIR_ENTRY_SIZE]; + else + dp = &b_dir(bp)[0]; + for (; dp < &b_dir(bp)[NR_DIR_ENTRIES(block_size)]; dp++) { + if (dp->mfs_d_ino == 0) + continue; /* Entry is not in use */ - /* Compute the length of the name */ - cp = memchr(dp->mfs_d_name, '\0', sizeof(dp->mfs_d_name)); - if (cp == NULL) - len = sizeof(dp->mfs_d_name); - else - len = cp - (dp->mfs_d_name); - - /* Compute record length; also does alignment. */ - reclen = _DIRENT_RECLEN(dep, len); + /* Compute the length of the name */ + cp = memchr(dp->mfs_d_name, '\0', sizeof(dp->mfs_d_name)); + if (cp == NULL) + len = sizeof(dp->mfs_d_name); + else + len = cp - (dp->mfs_d_name); - /* Need the position of this entry in the directory */ - ent_pos = block_pos + ((char *) dp - (char *) bp->data); + /* Need the position of this entry in the directory */ + ent_pos = block_pos + ((char *) dp - (char *) bp->data); - if (userbuf_off + tmpbuf_off + reclen >= size) { - /* The user has no space for one more record */ - done = TRUE; + /* We also need(?) the file type of the target inode. */ + if (!(entrip = get_inode(fs_dev, (ino_t) dp->mfs_d_ino))) + panic("unexpected get_inode failure"); + type = IFTODT(entrip->i_mode); + put_inode(entrip); - /* Record the position of this entry, it is the - * starting point of the next request (unless the - * postion is modified with lseek). - */ - new_pos = ent_pos; - break; + /* MFS does not store file types in its directory entries, and + * fetching the mode from the inode is seriously expensive. + * Userland should always be prepared to receive DT_UNKNOWN. + */ + r = fsdriver_dentry_add(&fsdentry, (ino_t) dp->mfs_d_ino, + dp->mfs_d_name, len, type); + + /* If the user buffer is full, or an error occurred, stop. */ + if (r <= 0) { + done = TRUE; + + /* Record the position 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 (tmpbuf_off + reclen >= GETDENTS_BUFSIZE*GETDENTS_ENTRIES) { - r = sys_safecopyto(VFS_PROC_NR, gid, - (vir_bytes) userbuf_off, - (vir_bytes) getdents_buf, - (size_t) tmpbuf_off); - if (r != OK) { - put_inode(rip); - return(r); - } - - userbuf_off += tmpbuf_off; - tmpbuf_off = 0; - } - - dep = (struct dirent *) &getdents_buf[tmpbuf_off]; - dep->d_fileno = (ino_t) dp->mfs_d_ino; - dep->d_reclen = (unsigned short) reclen; - dep->d_namlen = len; - memcpy(dep->d_name, dp->mfs_d_name, len); - { - struct inode *entrip; - if(!(entrip = get_inode(fs_dev, dep->d_fileno))) - panic("unexpected get_inode failure"); - dep->d_type = fs_mode_to_type(entrip->i_mode); - put_inode(entrip); - } - dep->d_name[len] = '\0'; - tmpbuf_off += reclen; } put_block(bp, DIRECTORY_BLOCK); @@ -716,30 +559,14 @@ int fs_getdents(void) break; } - if (tmpbuf_off != 0) { - r = sys_safecopyto(VFS_PROC_NR, gid, (vir_bytes) userbuf_off, - (vir_bytes) getdents_buf, (size_t) tmpbuf_off); - if (r != OK) { - put_inode(rip); - return(r); - } - - userbuf_off += tmpbuf_off; - } - - if (done && userbuf_off == 0) - r = EINVAL; /* The user's buffer is too small */ - else { - fs_m_out.m_fs_vfs_getdents.nbytes = userbuf_off; - fs_m_out.m_fs_vfs_getdents.seek_pos = new_pos; + if (r >= 0 && (r = fsdriver_dentry_finish(&fsdentry)) >= 0) { + *posp = new_pos; if(!rip->i_sp->s_rd_only) { rip->i_update |= ATIME; IN_MARKDIRTY(rip); } - r = OK; } put_inode(rip); /* release the inode */ return(r); } - diff --git a/minix/fs/mfs/stadir.c b/minix/fs/mfs/stadir.c index 446697e53..91be2280a 100644 --- a/minix/fs/mfs/stadir.c +++ b/minix/fs/mfs/stadir.c @@ -5,7 +5,6 @@ #include #include "inode.h" #include "super.h" -#include /*===========================================================================* * estimate_blocks * @@ -38,20 +37,18 @@ static blkcnt_t estimate_blocks(struct inode *rip) return (zones + sindirs + dindirs) * (blkcnt_t) (zone_size / 512); } -/*===========================================================================* - * stat_inode * - *===========================================================================*/ -static int stat_inode( - register struct inode *rip, /* pointer to inode to stat */ - endpoint_t who_e, /* Caller endpoint */ - cp_grant_id_t gid /* grant for the stat buf */ -) -{ -/* Common code for stat and fstat system calls. */ - struct stat statbuf; +/*===========================================================================* + * fs_stat * + *===========================================================================*/ +int fs_stat(ino_t ino_nr, struct stat *statbuf) +{ + struct inode *rip; mode_t mo; - int r, s; + int s; + + if ((rip = get_inode(fs_dev, ino_nr)) == NULL) + return(EINVAL); /* Update the atime, ctime, and mtime fields in the inode, if need be. */ if (rip->i_update) update_times(rip); @@ -62,76 +59,49 @@ static int stat_inode( /* true iff special */ s = (mo == I_CHAR_SPECIAL || mo == I_BLOCK_SPECIAL); - memset(&statbuf, 0, sizeof(struct stat)); + statbuf->st_dev = rip->i_dev; + statbuf->st_ino = (ino_t) rip->i_num; + statbuf->st_mode = (mode_t) rip->i_mode; + statbuf->st_nlink = (nlink_t) rip->i_nlinks; + statbuf->st_uid = rip->i_uid; + statbuf->st_gid = rip->i_gid; + statbuf->st_rdev = (s ? (dev_t)rip->i_zone[0] : NO_DEV); + statbuf->st_size = rip->i_size; + statbuf->st_atime = rip->i_atime; + statbuf->st_mtime = rip->i_mtime; + statbuf->st_ctime = rip->i_ctime; + statbuf->st_blksize = lmfs_fs_block_size(); + statbuf->st_blocks = estimate_blocks(rip); - statbuf.st_dev = rip->i_dev; - statbuf.st_ino = (ino_t) rip->i_num; - statbuf.st_mode = (mode_t) rip->i_mode; - statbuf.st_nlink = (nlink_t) rip->i_nlinks; - statbuf.st_uid = rip->i_uid; - statbuf.st_gid = rip->i_gid; - statbuf.st_rdev = (s ? (dev_t)rip->i_zone[0] : NO_DEV); - statbuf.st_size = rip->i_size; - statbuf.st_atime = rip->i_atime; - statbuf.st_mtime = rip->i_mtime; - statbuf.st_ctime = rip->i_ctime; - statbuf.st_blksize = lmfs_fs_block_size(); - statbuf.st_blocks = estimate_blocks(rip); + put_inode(rip); /* release the inode */ - /* Copy the struct to user space. */ - r = sys_safecopyto(who_e, gid, (vir_bytes) 0, (vir_bytes) &statbuf, - (size_t) sizeof(statbuf)); - - return(r); + return(OK); } + /*===========================================================================* * fs_statvfs * *===========================================================================*/ -int fs_statvfs() +int fs_statvfs(struct statvfs *st) { - struct statvfs st; struct super_block *sp; - int r, scale; + int scale; u64_t used; sp = get_super(fs_dev); scale = sp->s_log_zone_size; - memset(&st, 0, sizeof(st)); + fs_blockstats(&st->f_blocks, &st->f_bfree, &used); + st->f_bavail = st->f_bfree; - fs_blockstats(&st.f_blocks, &st.f_bfree, &used); - st.f_bavail = st.f_bfree; + st->f_bsize = sp->s_block_size << scale; + st->f_frsize = sp->s_block_size; + st->f_iosize = st->f_frsize; + st->f_files = sp->s_ninodes; + st->f_ffree = count_free_bits(sp, IMAP); + st->f_favail = st->f_ffree; + st->f_namemax = MFS_DIRSIZ; - st.f_bsize = sp->s_block_size << scale; - st.f_frsize = sp->s_block_size; - st.f_iosize = st.f_frsize; - st.f_files = sp->s_ninodes; - st.f_ffree = count_free_bits(sp, IMAP); - st.f_favail = st.f_ffree; - st.f_namemax = MFS_DIRSIZ; - - /* Copy the struct to user space. */ - r = sys_safecopyto(fs_m_in.m_source, fs_m_in.m_vfs_fs_statvfs.grant, 0, - (vir_bytes) &st, (phys_bytes) sizeof(st)); - - return(r); + return(OK); } - -/*===========================================================================* - * fs_stat * - *===========================================================================*/ -int fs_stat() -{ - register int r; /* return value */ - register struct inode *rip; /* target inode */ - - if ((rip = get_inode(fs_dev, fs_m_in.m_vfs_fs_stat.inode)) == NULL) - return(EINVAL); - - r = stat_inode(rip, fs_m_in.m_source, fs_m_in.m_vfs_fs_stat.grant); - put_inode(rip); /* release the inode */ - return(r); -} - diff --git a/minix/fs/mfs/super.c b/minix/fs/mfs/super.c index b31edb2c7..68543a4b3 100644 --- a/minix/fs/mfs/super.c +++ b/minix/fs/mfs/super.c @@ -193,7 +193,6 @@ unsigned int get_block_size(dev_t dev) static int rw_super(struct super_block *sp, int writing) { /* Read/write a superblock. */ - int r; dev_t save_dev = sp->s_dev; struct buf *bp; char *sbbuf; diff --git a/minix/fs/mfs/super.h b/minix/fs/mfs/super.h index 5b142515b..27ceec492 100644 --- a/minix/fs/mfs/super.h +++ b/minix/fs/mfs/super.h @@ -57,7 +57,6 @@ EXTERN struct super_block { int s_nindirs; /* # indirect zones per indirect block */ bit_t s_isearch; /* inodes below this bit number are in use */ bit_t s_zsearch; /* all zones below this bit number are in use*/ - char s_is_root; } superblock; #define IMAP 0 /* operating on the inode bit map */ diff --git a/minix/fs/mfs/table.c b/minix/fs/mfs/table.c index 058aa23d8..077595c63 100644 --- a/minix/fs/mfs/table.c +++ b/minix/fs/mfs/table.c @@ -1,10 +1,8 @@ -/* This file contains the table used to map system call numbers onto the +/* This file contains the table used to map file system calls onto the * routines that perform them. */ -#include - #define _TABLE #include "fs.h" @@ -12,40 +10,36 @@ #include "buf.h" #include "super.h" -int (*fs_call_vec[])(void) = { - no_sys, /* 0 not used */ - no_sys, /* 1 */ /* Was: fs_getnode */ - fs_putnode, /* 2 */ - fs_slink, /* 3 */ - fs_ftrunc, /* 4 */ - fs_chown, /* 5 */ - fs_chmod, /* 6 */ - fs_inhibread, /* 7 */ - fs_stat, /* 8 */ - fs_utime, /* 9 */ - fs_statvfs, /* 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 */ - no_sys, /* 29 */ /* Was: fs_newnode */ - fs_rdlink, /* 30 */ - fs_getdents, /* 31 */ - fs_readwrite, /* 32 */ - fs_bpeek, /* 33 */ +struct fsdriver mfs_table = { + .fdr_mount = fs_mount, + .fdr_unmount = fs_unmount, + .fdr_lookup = fs_lookup, + .fdr_putnode = fs_putnode, + .fdr_read = fs_readwrite, + .fdr_write = fs_readwrite, + .fdr_peek = fs_readwrite, + .fdr_getdents = fs_getdents, + .fdr_trunc = fs_trunc, + .fdr_seek = fs_seek, + .fdr_create = fs_create, + .fdr_mkdir = fs_mkdir, + .fdr_mknod = fs_mknod, + .fdr_link = fs_link, + .fdr_unlink = fs_unlink, + .fdr_rmdir = fs_unlink, + .fdr_rename = fs_rename, + .fdr_slink = fs_slink, + .fdr_rdlink = fs_rdlink, + .fdr_stat = fs_stat, + .fdr_chown = fs_chown, + .fdr_chmod = fs_chmod, + .fdr_utime = fs_utime, + .fdr_mountpt = fs_mountpt, + .fdr_statvfs = fs_statvfs, + .fdr_sync = fs_sync, + .fdr_driver = lmfs_driver, + .fdr_bread = lmfs_bio, + .fdr_bwrite = lmfs_bio, + .fdr_bpeek = lmfs_bio, + .fdr_bflush = lmfs_bflush }; - diff --git a/minix/fs/mfs/time.c b/minix/fs/mfs/time.c index d70e4b578..a52b57710 100644 --- a/minix/fs/mfs/time.c +++ b/minix/fs/mfs/time.c @@ -1,72 +1,49 @@ #include "fs.h" #include "inode.h" +#include #include -#include /*===========================================================================* * fs_utime * *===========================================================================*/ -int fs_utime() +int fs_utime(ino_t ino_nr, struct timespec *atime, struct timespec *mtime) { register struct inode *rip; - register int r; /* Temporarily open the file. */ - if( (rip = get_inode(fs_dev, fs_m_in.m_vfs_fs_utime.inode)) == NULL) + if( (rip = get_inode(fs_dev, ino_nr)) == NULL) return(EINVAL); - /* - * Only the owner of a file or the super_user can change the timestamps. - * Here we assume VFS did that check before. - */ + rip->i_update = CTIME; /* discard any stale ATIME and MTIME flags */ - r = OK; - if(read_only(rip) != OK) r = EROFS; /* not even su can touch if R/O */ - if(r == OK) { - rip->i_update = CTIME; /* discard any stale ATIME and MTIME flags */ - switch(fs_m_in.m_vfs_fs_utime.acnsec) { - case UTIME_NOW: - rip->i_update |= ATIME; - break; - case UTIME_OMIT: /* do not touch */ - break; - default: - /* - * cases fs_m_in.m_vfs_fs_utime.acnsec < 0 || fs_m_in.m_vfs_fs_utime.acnsec >= 1E9 - * are caught by VFS to cooperate with old instances of MFS - */ - rip->i_atime = fs_m_in.m_vfs_fs_utime.actime; - /* - * MFS does not support better than second resolution, - * so we discard ACNSEC to round down - */ - break; - } - - switch(fs_m_in.m_vfs_fs_utime.modnsec) { - case UTIME_NOW: - rip->i_update |= MTIME; - break; - case UTIME_OMIT: /* do not touch */ - break; - default: - /* - * cases fs_m_in.m_vfs_fs_utime.modnsec < 0 || fs_m_in.m_vfs_fs_utime.modnsec >= 1E9 - * are caught by VFS to cooperate with old instances of MFS - */ - rip->i_mtime = fs_m_in.m_vfs_fs_utime.modtime; - /* - * MFS does not support better than second resolution, - * so we discard MODNSEC to round down - */ - break; - } - - IN_MARKDIRTY(rip); + switch (atime->tv_nsec) { + case UTIME_NOW: + rip->i_update |= ATIME; + break; + case UTIME_OMIT: /* do not touch */ + break; + default: + /* MFS does not support subsecond resolution, so we round down. */ + rip->i_atime = atime->tv_sec; + break; } + switch (mtime->tv_nsec) { + case UTIME_NOW: + rip->i_update |= MTIME; + break; + case UTIME_OMIT: /* do not touch */ + break; + default: + /* MFS does not support subsecond resolution, so we round down. */ + rip->i_mtime = mtime->tv_sec; + break; + } + + IN_MARKDIRTY(rip); + put_inode(rip); - return(r); + return(OK); } diff --git a/minix/fs/mfs/utility.c b/minix/fs/mfs/utility.c index 31b68f989..b4c96b68a 100644 --- a/minix/fs/mfs/utility.c +++ b/minix/fs/mfs/utility.c @@ -4,17 +4,6 @@ #include "super.h" -/*===========================================================================* - * no_sys * - *===========================================================================*/ -int no_sys() -{ -/* Somebody has used an illegal system call number */ - printf("no_sys: invalid call %d\n", req_nr); - return(EINVAL); -} - - /*===========================================================================* * conv2 * *===========================================================================*/ @@ -45,31 +34,3 @@ long x; /* 32-bit long to be byte swapped */ l = ( (long) lo <<16) | hi; return(l); } - - -/*===========================================================================* - * mfs_min * - *===========================================================================*/ -int min(unsigned int l, unsigned int r) -{ - if(r >= l) return(l); - - return(r); -} - - -/*===========================================================================* - * mfs_nul * - *===========================================================================*/ -void mfs_nul_f(char *file, int line, char *str, unsigned int len, -unsigned int maxlen) -{ - if(len < maxlen && str[len-1] != '\0') { - printf("MFS %s:%d string (length %d, maxlen %d) not null-terminated\n", - file, line, len, maxlen); - } -} - -#define MYASSERT(c) if(!(c)) { printf("MFS:%s:%d: sanity check: %s failed\n", \ - file, line, #c); panic("sanity check " #c " failed: %d", __LINE__); } - diff --git a/minix/fs/mfs/write.c b/minix/fs/mfs/write.c index d6cd91a15..3015b8b3d 100644 --- a/minix/fs/mfs/write.c +++ b/minix/fs/mfs/write.c @@ -233,8 +233,8 @@ struct super_block *sb; /* superblock of device block resides on */ *===========================================================================*/ void clear_zone(rip, pos, flag) register struct inode *rip; /* inode to clear */ -off_t pos; /* points to block to clear */ -int flag; /* 1 if called by new_block, 0 otherwise */ +off_t __unused pos; /* points to block to clear */ +int __unused flag; /* 1 if called by new_block, 0 otherwise */ { /* Zero a zone, possibly starting in the middle. The parameter 'pos' gives * a byte in the first block to be zeroed. Clearzone() is called from diff --git a/minix/lib/libc/gen/fslib.c b/minix/lib/libc/gen/fslib.c index dcc99815e..4e54cae16 100644 --- a/minix/lib/libc/gen/fslib.c +++ b/minix/lib/libc/gen/fslib.c @@ -10,6 +10,7 @@ #include /* for unshort :-( */ #include #include +#include #include "mfs/const.h" /* depends of -I flag in Makefile */ #include "mfs/type.h" /* ditto */ #include "mfs/inode.h" /* ditto */