From eea93434119555079c56688a1c516f6c49977105 Mon Sep 17 00:00:00 2001 From: Thomas Veerman Date: Thu, 7 Mar 2013 15:55:22 +0000 Subject: [PATCH] stat.h: replace big_ with native types This patch will make mode_t 16-bits->32-bits, off_t 32-bits->64-bits, ino_t 32-bits->64-bits, and nlink_t 16-bits->32-bits. As uid_t and gid_t were already 32-bits we can drop the big_{mode,off,ino,uid, gid,nlink}_t types from struct stat. This has huge consequences: . lseek now has to accept a 64-bit argument and returns a 64-bit result. Therefore we need a new lseek and return proper results based on the used version (i.e., translate). . some fcntl functions take and return a struct flock which holds 2 off_t fields. Like lseek, we need to distinguish between old and new versions. . getdents uses struct dirent which has among other fields an ino_t and off_t field. Consequently we need a new getdents system call and have to translate when we encounter an old call. . truncate and ftruncate also take off_t arguments and therefore require a new version. To add insult to injury VFS itself uses getdents. This has as consequence that we have 2^3 combinations of version for getdents; old and new version of libc (new system calls), new and old version of VFS (when booting an old image), old and new version of an FS. We can distinguish between these cases as follows; libc will use new system call numbers that have not yet been in use. When using a new number, VFS knows libc is new, otherwise it's an old libc. Vice versa, libc first tries the new number and if that fails due to ENOSYS (unknown system call number) it knows it's dealing with an old VFS. Finally, since we now have VFS-FS protocol versioning and by bumping the version to 1, VFS knows an FS is old when it reports version 0 and an FS knows VFS is old when VFS reports it's using version 0. 0 = old version, 1 = new version libc | VFS | FS | approach ---------------------------- 0 | 0 | 0 | Nothing to do ---------------------------- 0 | 0 | 1 | VFS reports protocol version 0, FS falls back | to using the old getdents function ---------------------------- 0 | 1 | 0 | VFS reports protocol version 1, FS version 0. | libc requires old getdents so there is nothing | to do. VFS itself needs new getdents and will | translate. ---------------------------- 0 | 1 | 1 | VFS reports protocol version 1, FS version 1. | VFS intercepts getdents results and translates | them on the fly before returning results to libc ---------------------------- 1 | 0 | 0 | libc first tries new system call number and | then fall back to the old number. libc first | translates the results to the new getdents before | returning. ---------------------------- 1 | 0 | 1 | VFS reports protocol version 0, so FS uses fall | back. libc translates. ---------------------------- 1 | 1 | 0 | VFS reports protocol version 1, FS version 0. VFS | will intercept all results and translate on the | fly. ---------------------------- 1 | 1 | 1 | Nothing to do. As VFS can distinguish between old and new system calls of (f)truncate, lseek, and fcntl, it will translate the arguments and results if necessary. Likewise libc falls back to using the old calls and translating the results to the new version if necessary. Change-Id: Id5bc819e6ef90f317dbddb21020e0a65028225ce --- include/minix/callnr.h | 16 ++-- include/minix/config.h | 3 + include/minix/vfsif.h | 2 +- include/sys/statfs.h | 2 +- lib/libc/sys-minix/fcntl.c | 81 ++++++++++++++++- lib/libc/sys-minix/ftruncate.c | 33 ++++++- lib/libc/sys-minix/getdents.c | 70 +++++++++++++- lib/libc/sys-minix/lseek.c | 43 +++++++-- lib/libc/sys-minix/truncate.c | 34 ++++++- lib/libvtreefs/glo.h | 1 + lib/libvtreefs/mount.c | 7 ++ lib/libvtreefs/read.c | 154 ++++++++++++++++++++++++++++++- servers/ext2/glo.h | 2 + servers/ext2/mount.c | 6 ++ servers/ext2/read.c | 158 +++++++++++++++++++++++++++++++- servers/iso9660fs/const.h | 2 +- servers/iso9660fs/glo.h | 1 + servers/iso9660fs/mount.c | 6 ++ servers/iso9660fs/read.c | 159 +++++++++++++++++++++++++++++++- servers/mfs/glo.h | 1 + servers/mfs/inode.h | 2 +- servers/mfs/mount.c | 6 ++ servers/mfs/proto.h | 1 + servers/mfs/read.c | 157 +++++++++++++++++++++++++++++++- servers/mfs/stadir.c | 6 +- servers/mfs/super.h | 4 +- servers/vfs/exec.c | 6 +- servers/vfs/link.c | 30 +++++- servers/vfs/lock.c | 39 +++++++- servers/vfs/misc.c | 29 ++++-- servers/vfs/open.c | 62 ++++++++++++- servers/vfs/path.c | 2 +- servers/vfs/proto.h | 7 +- servers/vfs/read.c | 11 ++- servers/vfs/request.c | 161 ++++++++++++++++++++++++++++----- servers/vfs/table.c | 26 +++--- sys/sys/ansi.h | 4 +- sys/sys/dirent.h | 7 ++ sys/sys/fcntl.h | 8 ++ sys/sys/stat.h | 16 ++-- sys/sys/types.h | 13 +-- usr.bin/gzip/gzip.c | 8 -- 42 files changed, 1253 insertions(+), 133 deletions(-) diff --git a/include/minix/callnr.h b/include/minix/callnr.h index aedf3d3df..38be5bcaa 100644 --- a/include/minix/callnr.h +++ b/include/minix/callnr.h @@ -17,7 +17,7 @@ #define CHMOD 15 #define CHOWN 16 #define BRK 17 -#define LSEEK 19 +#define LSEEK_321 19 #define MINIX_GETPID 20 #define MOUNT 21 #define UMOUNT 22 @@ -48,7 +48,7 @@ #define FSTAT 52 #define LSTAT 53 #define IOCTL 54 -#define FCNTL 55 +#define FCNTL_321 55 #define FS_READY 57 #define PIPE2 58 #define EXEC 59 @@ -59,6 +59,8 @@ #define ITIMER 64 #define GETMCONTEXT 67 #define SETMCONTEXT 68 +#define GETDENTS 69 +#define FTRUNCATE 70 /* Posix signal handling. */ #define SIGACTION 71 @@ -70,7 +72,7 @@ #define REBOOT 76 #define SVRCTL 77 #define SYSUNAME 78 -#define GETDENTS 80 /* to VFS */ +#define GETDENTS_321 80 /* to VFS */ #define LLSEEK 81 /* to VFS */ #define FSTATFS 82 /* to VFS */ #define STATVFS 83 /* to VFS */ @@ -83,20 +85,22 @@ #define GETTIMEOFDAY 90 /* to PM */ #define SETEUID 91 /* to PM */ #define SETEGID 92 /* to PM */ -#define TRUNCATE 93 /* to VFS */ -#define FTRUNCATE 94 /* to VFS */ +#define TRUNCATE_321 93 /* to VFS */ +#define FTRUNCATE_321 94 /* to VFS */ #define FCHMOD 95 /* to VFS */ #define FCHOWN 96 /* to VFS */ +#define LSEEK 97 #define SPROF 98 /* to PM */ #define CPROF 99 /* to PM */ -/* Calls provided by PM and FS that are not part of the API */ #define PM_NEWEXEC 100 /* from VFS or RS to PM: new exec */ #define SRV_FORK 101 /* to PM: special fork call for RS */ #define EXEC_RESTART 102 /* to PM: final part of exec for RS */ #define GETPROCNR 104 /* to PM */ #define ISSETUGID 106 /* to PM: ask if process is tainted */ #define GETEPINFO_O 107 /* to PM: get pid/uid/gid of an endpoint */ +#define TRUNCATE 108 /* to VFS */ +#define FCNTL 109 /* to VFS */ #define SRV_KILL 111 /* to PM: special kill call for RS */ #define GCOV_FLUSH 112 /* flush gcov data from server to gcov files */ diff --git a/include/minix/config.h b/include/minix/config.h index 79d91b835..9a004aa1c 100644 --- a/include/minix/config.h +++ b/include/minix/config.h @@ -5,6 +5,9 @@ #define OS_RELEASE "3" #define OS_VERSION "3.0" +/* Keep these in sync with os_version above for temp version check in VFS */ +#define OS_VMAJOR 2 +#define OS_VMINOR 1 /* This file sets configuration parameters for the MINIX kernel, FS, and PM. * It is divided up into two main sections. The first section contains * user-settable parameters. In the second section, various internal system diff --git a/include/minix/vfsif.h b/include/minix/vfsif.h index f42a6923c..b4950c6bc 100644 --- a/include/minix/vfsif.h +++ b/include/minix/vfsif.h @@ -73,7 +73,7 @@ #define VFS_FS_PROTO_VERSION(b) (((b) & RES_PROTO_V_MASK) >> RES_PROTO_V_SHIFT) #define VFS_FS_PROTO_PUT_VERSION(b,v) \ ((b) |= (((v) << RES_PROTO_V_SHIFT) & RES_PROTO_V_MASK)) -#define VFS_FS_CURRENT_VERSION 0 /* Current version */ +#define VFS_FS_CURRENT_VERSION 1 /* Current version */ /* VFS/FS flags */ #define REQ_RDONLY 001 diff --git a/include/sys/statfs.h b/include/sys/statfs.h index 064f0eb56..a80eef121 100644 --- a/include/sys/statfs.h +++ b/include/sys/statfs.h @@ -7,7 +7,7 @@ #include struct statfs { - off_t f_bsize; /* file system block size */ + int f_bsize; /* file system block size */ }; int fstatfs(int fd, struct statfs *st); diff --git a/lib/libc/sys-minix/fcntl.c b/lib/libc/sys-minix/fcntl.c index 59c37a652..1c6a29f45 100644 --- a/lib/libc/sys-minix/fcntl.c +++ b/lib/libc/sys-minix/fcntl.c @@ -2,6 +2,7 @@ #include "namespace.h" #include +#include #include #include @@ -9,12 +10,78 @@ __weak_alias(fcntl, _fcntl) #endif +static int __fcntl_321(int fd, int cmd, va_list argp); + +int __fcntl_321(int fd, int cmd, va_list argp) +{ + message m; + struct flock_321 f_321; + struct flock *flock; + int r; + + /* Set up for the sensible case where there is no variable parameter. This + * covers F_GETFD, F_GETFL and invalid commands. + */ + m.m1_i3 = 0; + m.m1_p1 = NULL; + + /* Adjust for the stupid cases. */ + switch(cmd) { + case F_DUPFD: + case F_SETFD: + case F_SETFL: + m.m1_i3 = va_arg(argp, int); + break; + case F_GETLK: + case F_SETLK: + case F_SETLKW: + case F_FREESP: + /* VFS expects old format, so translate */ + flock = (struct flock *) va_arg(argp, struct flock *); + f_321.l_type = flock->l_type; + f_321.l_whence = flock->l_whence; + f_321.l_start = flock->l_start; + f_321.l_len = flock->l_len; + f_321.l_pid = flock->l_pid; + m.m1_p1 = (char *) &f_321; + break; + } + + /* Clean up and make the system call. */ + m.m1_i1 = fd; + m.m1_i2 = cmd; + + r = _syscall(VFS_PROC_NR, FCNTL_321, &m); + + if (r == 0) { + /* Maybe we need to convert back */ + + switch(cmd) { + case F_GETLK: + case F_SETLK: + case F_SETLKW: + case F_FREESP: + /* VFS expected old format but libc new format, so translate */ + flock->l_type = f_321.l_type; + flock->l_whence = f_321.l_whence; + flock->l_start = f_321.l_start; + flock->l_len = f_321.l_len; + flock->l_pid = f_321.l_pid; + break; + } + } + + return r; +} + int fcntl(int fd, int cmd, ...) { - va_list argp; + va_list argp, argp_321; message m; + int r, org_errno; va_start(argp, cmd); + va_start(argp_321, cmd); /* Set up for the sensible case where there is no variable parameter. This * covers F_GETFD, F_GETFL and invalid commands. @@ -41,5 +108,15 @@ int fcntl(int fd, int cmd, ...) va_end(argp); m.m1_i1 = fd; m.m1_i2 = cmd; - return(_syscall(VFS_PROC_NR, FCNTL, &m)); + org_errno = errno; + r = _syscall(VFS_PROC_NR, FCNTL, &m); + + if (r == -1 && errno == ENOSYS) { + errno = org_errno; + r = __fcntl_321(fd, cmd, argp_321); + } + + va_end(argp_321); + + return r; } diff --git a/lib/libc/sys-minix/ftruncate.c b/lib/libc/sys-minix/ftruncate.c index e95e258e4..4437dfea8 100644 --- a/lib/libc/sys-minix/ftruncate.c +++ b/lib/libc/sys-minix/ftruncate.c @@ -2,6 +2,8 @@ #include "namespace.h" #include +#include +#include #include #include @@ -9,11 +11,38 @@ __weak_alias(ftruncate, _ftruncate) #endif -int ftruncate(int _fd, off_t _length) +static int __ftruncate_321(int _fd, int _length); + +static int __ftruncate_321(int _fd, int _length) { message m; m.m2_l1 = _length; m.m2_i1 = _fd; - return(_syscall(VFS_PROC_NR, FTRUNCATE, &m)); + return(_syscall(VFS_PROC_NR, FTRUNCATE_321, &m)); +} + +int ftruncate(int _fd, off_t _length) +{ + message m; + int orig_errno, r; + + m.m2_l1 = ex64lo(_length); + m.m2_l2 = ex64hi(_length); + m.m2_i1 = _fd; + + orig_errno = errno; + r = _syscall(VFS_PROC_NR, FTRUNCATE, &m); + if (r == -1 && errno == ENOSYS) { + /* Old VFS, no support for new ftruncate */ + if (_length >= INT_MIN && _length <= INT_MAX) { + errno = orig_errno; + return __ftruncate_321(_fd, (int) _length); + } + + /* Not going to fit */ + errno = EOVERFLOW; + } + + return r; } diff --git a/lib/libc/sys-minix/getdents.c b/lib/libc/sys-minix/getdents.c index ef17e5440..1cb2d715f 100644 --- a/lib/libc/sys-minix/getdents.c +++ b/lib/libc/sys-minix/getdents.c @@ -3,15 +3,83 @@ #include #include +#include +#include +#include +#include + +static ssize_t __getdents321(int fd, char *buffer, size_t nbytes); ssize_t getdents(int fd, char *buffer, size_t nbytes) { message m; + int r, orig_errno; + orig_errno = errno; m.m1_i1 = fd; m.m1_i2 = nbytes; m.m1_p1 = (char *) buffer; - return _syscall(VFS_PROC_NR, GETDENTS, &m); + r = _syscall(VFS_PROC_NR, GETDENTS, &m); + if (r == -1 && errno == ENOSYS) { + errno = orig_errno;/* Restore old value so world is still as expected*/ + r = __getdents321(fd, buffer, nbytes); + } + + return r; +} + +ssize_t __getdents321(int fd, char *buffer, size_t nbytes) +{ + message m; + int r, consumed = 0, newconsumed = 0; + char *intermediate = NULL; + struct dirent *dent; + struct dirent_321 *dent_321; +#define DWORD_ALIGN(d) if((d) % sizeof(long)) (d)+=sizeof(long)-(d)%sizeof(long) + + intermediate = malloc(nbytes); + if (intermediate == NULL) return EINVAL; + + m.m1_i1 = fd; + /* Pretend the buffer is smaller so we know the converted/expanded version + * will fit. + */ + nbytes = nbytes / 2; + if (nbytes < (sizeof(struct dirent) + NAME_MAX + 1)) { + free(intermediate); + return EINVAL; /* This might not fit. Sorry */ + } + + m.m1_i2 = nbytes; + m.m1_p1 = (char *) intermediate; + r = _syscall(VFS_PROC_NR, GETDENTS_321, &m); + + if (r <= 0) { + free(intermediate); + return r; + } + + /* Provided format is struct dirent_321 and has to be translated to + * struct dirent */ + dent_321 = (struct dirent_321 *) intermediate; + dent = (struct dirent *) buffer; + + while (consumed < r && dent_321->d_reclen > 0) { + dent->d_ino = (ino_t) dent_321->d_ino; + dent->d_off = (off_t) dent_321->d_off; + dent->d_reclen = offsetof(struct dirent, d_name) + + strlen(dent_321->d_name) + 1; + DWORD_ALIGN(dent->d_reclen); + strcpy(dent->d_name, dent_321->d_name); + consumed += dent_321->d_reclen; + newconsumed += dent->d_reclen; + dent_321 = (struct dirent_321 *) &intermediate[consumed]; + dent = (struct dirent *) &buffer[newconsumed]; + } + + free(intermediate); + + return newconsumed; } #if defined(__minix) && defined(__weak_alias) diff --git a/lib/libc/sys-minix/lseek.c b/lib/libc/sys-minix/lseek.c index fbcfb09aa..73d8414f0 100644 --- a/lib/libc/sys-minix/lseek.c +++ b/lib/libc/sys-minix/lseek.c @@ -2,22 +2,53 @@ #include "namespace.h" #include +#include +#include #include #ifdef __weak_alias __weak_alias(lseek, _lseek) #endif -off_t lseek(fd, offset, whence) -int fd; -off_t offset; -int whence; +i32_t __lseek_321(int fd, i32_t offset, int whence); + +i32_t __lseek_321(int fd, i32_t offset, int whence) { message m; m.m2_i1 = fd; m.m2_l1 = offset; m.m2_i2 = whence; - if (_syscall(VFS_PROC_NR, LSEEK, &m) < 0) return( (off_t) -1); - return( (off_t) m.m2_l1); + if (_syscall(VFS_PROC_NR, LSEEK_321, &m) < 0) return(-1); + return( (i32_t) m.m2_l1); +} + +off_t +lseek(int fd, off_t offset, int whence) +{ + message m; + int orig_errno; + + m.m2_i1 = fd; + m.m2_l1 = ex64lo(offset); + m.m2_l2 = ex64hi(offset); + m.m2_i2 = whence; + + orig_errno = errno; + if (_syscall(VFS_PROC_NR, LSEEK, &m) < 0) { + if (errno == ENOSYS) { + /* Old VFS, no support for new lseek */ + if (offset >= INT_MIN && offset <= INT_MAX) { + /* offset fits in old range, retry */ + errno = orig_errno; + return (off_t) __lseek_321(fd, (i32_t) offset, whence); + } + + /* Not going to fit */ + errno = EOVERFLOW; + } + + return( (off_t) -1); + } + return( (off_t) make64(m.m2_l1, m.m2_l2)); } diff --git a/lib/libc/sys-minix/truncate.c b/lib/libc/sys-minix/truncate.c index e72ca9da4..1d20db861 100644 --- a/lib/libc/sys-minix/truncate.c +++ b/lib/libc/sys-minix/truncate.c @@ -6,16 +6,46 @@ __weak_alias(truncate, _truncate) #endif +#include +#include #include #include +static int __truncate_321(const char *_path, int _length); -int truncate(const char *_path, off_t _length) +static int __truncate_321(const char *_path, int _length) { message m; m.m2_p1 = (char *) __UNCONST(_path); m.m2_i1 = strlen(_path)+1; m.m2_l1 = _length; - return(_syscall(VFS_PROC_NR, TRUNCATE, &m)); + return(_syscall(VFS_PROC_NR, TRUNCATE_321, &m)); +} + +int truncate(const char *_path, off_t _length) +{ + message m; + int orig_errno, r; + + m.m2_p1 = (char *) __UNCONST(_path); + m.m2_i1 = strlen(_path)+1; + m.m2_l1 = ex64lo(_length); + m.m2_l2 = ex64hi(_length); + + orig_errno = errno; + r = _syscall(VFS_PROC_NR, TRUNCATE, &m); + + if (r == -1 && errno == ENOSYS) { + /* Old VFS, no support for new truncate */ + if (_length >= INT_MIN && _length <= INT_MAX) { + errno = orig_errno; + return __truncate_321(_path, (int) _length); + } + + /* Not going to fit */ + errno = EOVERFLOW; + } + + return r; } diff --git a/lib/libvtreefs/glo.h b/lib/libvtreefs/glo.h index c770ae5d0..f57983c37 100644 --- a/lib/libvtreefs/glo.h +++ b/lib/libvtreefs/glo.h @@ -8,6 +8,7 @@ EXTERN struct fs_hooks *vtreefs_hooks; +EXTERN int proto_version; EXTERN message fs_m_in; EXTERN message fs_m_out; diff --git a/lib/libvtreefs/mount.c b/lib/libvtreefs/mount.c index 06c7a05f6..6006c6034 100644 --- a/lib/libvtreefs/mount.c +++ b/lib/libvtreefs/mount.c @@ -18,6 +18,13 @@ int fs_readsuper(void) if (fs_m_in.REQ_FLAGS & REQ_ISROOT) return EINVAL; + /* Get VFS-FS protocol version */ + if (!(fs_m_in.REQ_FLAGS & REQ_HASPROTO)) { + proto_version = 0; + } else { + proto_version = VFS_FS_PROTO_VERSION(fs_m_in.REQ_PROTO); + } + /* Get the root inode and increase its reference count. */ root = get_root_inode(); ref_inode(root); diff --git a/lib/libvtreefs/read.c b/lib/libvtreefs/read.c index d5357622e..9947536f3 100644 --- a/lib/libvtreefs/read.c +++ b/lib/libvtreefs/read.c @@ -67,6 +67,153 @@ int fs_read(void) return r; } +/*===========================================================================* + * fs_getdents_321 * + *===========================================================================*/ +int fs_getdents_321(void) +{ + /* Retrieve directory entries. + */ + struct inode *node, *child = NULL; + struct dirent_321 *dent; + char *name; + size_t len, off, user_off, user_left; + off_t pos; + int r, skip, get_next, indexed; + static char buf[GETDENTS_BUFSIZ]; + + if (fs_m_in.REQ_SEEK_POS_HI != 0) + return EIO; + + if ((node = find_inode(fs_m_in.REQ_INODE_NR)) == NULL) + return EINVAL; + + off = 0; + user_off = 0; + user_left = fs_m_in.REQ_MEM_SIZE; + indexed = node->i_indexed; + get_next = FALSE; + child = NULL; + + /* Call the getdents hook, if any, to "refresh" the directory. */ + if (!is_inode_deleted(node) && vtreefs_hooks->getdents_hook != NULL) { + r = vtreefs_hooks->getdents_hook(node, get_inode_cbdata(node)); + if (r != OK) return r; + } + + for (pos = fs_m_in.REQ_SEEK_POS_LO; ; pos++) { + /* Determine which inode and name to use for this entry. */ + if (pos == 0) { + /* The "." entry. */ + child = node; + name = "."; + } + else if (pos == 1) { + /* The ".." entry. */ + child = get_parent_inode(node); + if (child == NULL) + child = node; + name = ".."; + } + else if (pos - 2 < indexed) { + /* All indexed entries. */ + child = get_inode_by_index(node, pos - 2); + + /* If there is no inode with this particular index, + * continue with the next index number. + */ + if (child == NULL) continue; + + name = child->i_name; + } + else { + /* All non-indexed entries. */ + + /* If this is the first loop iteration, first get to + * the non-indexed child identified by the current + * position. + */ + if (get_next == FALSE) { + skip = pos - indexed - 2; + child = get_first_inode(node); + + /* Skip indexed children. */ + while (child != NULL && + child->i_index != NO_INDEX) + child = get_next_inode(child); + + /* Skip to the right position. */ + while (child != NULL && skip-- > 0) + child = get_next_inode(child); + + get_next = TRUE; + } + else { + child = get_next_inode(child); + } + + /* No more children? Then stop. */ + if (child == NULL) + break; + + assert(!is_inode_deleted(child)); + + name = child->i_name; + } + + len = DWORD_ALIGN(sizeof(struct dirent_321) + strlen(name)); + + /* Is the user buffer too small to store another record? */ + if (user_off + off + len > user_left) { + /* Is the user buffer too small for even a single + * record? + */ + if (user_off == 0 && off == 0) + return EINVAL; + + break; + } + + /* If our own buffer cannot contain the new record, copy out + * first. + */ + if (off + len > sizeof(buf)) { + r = sys_safecopyto(fs_m_in.m_source, fs_m_in.REQ_GRANT, + user_off, (vir_bytes) buf, off); + if (r != OK) return r; + + user_off += off; + user_left -= off; + off = 0; + } + + /* Fill in the actual directory entry. */ + dent = (struct dirent_321 *) &buf[off]; + dent->d_ino = (u32_t) get_inode_number(child); + dent->d_off = (i32_t) pos; + dent->d_reclen = len; + strcpy(dent->d_name, name); + + off += len; + } + + /* If there is anything left in our own buffer, copy that out now. */ + if (off > 0) { + r = sys_safecopyto(fs_m_in.m_source, fs_m_in.REQ_GRANT, + user_off, (vir_bytes) buf, off); + if (r != OK) + return r; + + user_off += off; + } + + fs_m_out.RES_SEEK_POS_HI = 0; + fs_m_out.RES_SEEK_POS_LO = pos; + fs_m_out.RES_NBYTES = user_off; + + return OK; +} + /*===========================================================================* * fs_getdents * *===========================================================================*/ @@ -82,6 +229,9 @@ int fs_getdents(void) int r, skip, get_next, indexed; static char buf[GETDENTS_BUFSIZ]; + if (proto_version == 0) + return fs_getdents_321(); + if (fs_m_in.REQ_SEEK_POS_HI != 0) return EIO; @@ -189,8 +339,8 @@ int fs_getdents(void) /* Fill in the actual directory entry. */ dent = (struct dirent *) &buf[off]; - dent->d_ino = get_inode_number(child); - dent->d_off = pos; + dent->d_ino = (ino_t) get_inode_number(child); + dent->d_off = (off_t) pos; dent->d_reclen = len; strcpy(dent->d_name, name); diff --git a/servers/ext2/glo.h b/servers/ext2/glo.h index 2f20f8c8d..f79e03be5 100644 --- a/servers/ext2/glo.h +++ b/servers/ext2/glo.h @@ -21,6 +21,8 @@ extern char dot2[3]; /* meaning to search_dir: no access permission check. */ extern int(*fs_call_vec[]) (void); +EXTERN int proto_version; + EXTERN message fs_m_in; EXTERN message fs_m_out; EXTERN vfs_ucred_t credentials; diff --git a/servers/ext2/mount.c b/servers/ext2/mount.c index fbd4f754a..07186dc84 100644 --- a/servers/ext2/mount.c +++ b/servers/ext2/mount.c @@ -39,6 +39,12 @@ int fs_readsuper() readonly = (fs_m_in.REQ_FLAGS & REQ_RDONLY) ? 1 : 0; isroot = (fs_m_in.REQ_FLAGS & REQ_ISROOT) ? 1 : 0; + if (!(fs_m_in.REQ_FLAGS & REQ_HASPROTO)) { + proto_version = 0; + } else { + proto_version = VFS_FS_PROTO_VERSION(fs_m_in.REQ_PROTO); + } + if (label_len > sizeof(fs_dev_label)) return(EINVAL); diff --git a/servers/ext2/read.c b/servers/ext2/read.c index 48d7ff6ca..34285f3bf 100644 --- a/servers/ext2/read.c +++ b/servers/ext2/read.c @@ -557,6 +557,156 @@ unsigned bytes_ahead; /* bytes beyond position for immediate use */ } +/*===========================================================================* + * fs_getdents_321 * + *===========================================================================*/ +int fs_getdents_321(void) +{ +#define GETDENTS_321_BUFSIZE (sizeof(struct dirent_321) + EXT2_NAME_MAX + 1) +#define GETDENTS_321_ENTRIES 8 + static char getdents_buf[GETDENTS_321_BUFSIZE * GETDENTS_321_ENTRIES]; + struct inode *rip; + int o, r, done; + unsigned int block_size, len, reclen; + pino_t ino; + block_t b; + cp_grant_id_t gid; + size_t size, tmpbuf_off, userbuf_off; + off_t pos, off, block_pos, new_pos, ent_pos; + struct buf *bp; + struct ext2_disk_dir_desc *d_desc; + struct dirent *dep; + + ino = (pino_t) fs_m_in.REQ_INODE_NR; + gid = (cp_grant_id_t) fs_m_in.REQ_GRANT; + size = (size_t) fs_m_in.REQ_MEM_SIZE; + pos = (off_t) fs_m_in.REQ_SEEK_POS_LO; + + /* Check whether the position is properly aligned */ + if ((unsigned int) pos % DIR_ENTRY_ALIGN) + return(ENOENT); + + if ((rip = get_inode(fs_dev, ino)) == NULL) + return(EINVAL); + + block_size = rip->i_sp->s_block_size; + off = (pos % block_size); /* Offset in block */ + block_pos = pos - off; + done = FALSE; /* Stop processing directory blocks when done is set */ + + memset(getdents_buf, '\0', sizeof(getdents_buf)); /* Avoid leaking any data */ + tmpbuf_off = 0; /* Offset in getdents_buf */ + userbuf_off = 0; /* Offset in the user's buffer */ + + /* The default position for the next request is EOF. If the user's buffer + * fills up before EOF, new_pos will be modified. */ + new_pos = rip->i_size; + + for (; block_pos < rip->i_size; block_pos += block_size) { + off_t temp_pos = block_pos; + b = read_map(rip, block_pos); /* get block number */ + /* Since directories don't have holes, 'b' cannot be NO_BLOCK. */ + bp = get_block(rip->i_dev, b, NORMAL); /* get a dir block */ + assert(bp != NULL); + + /* Search a directory block. */ + d_desc = (struct ext2_disk_dir_desc*) &b_data(bp); + + /* we need to seek to entry at off bytes. + * when NEXT_DISC_DIR_POS == block_size it's last dentry. + */ + for (; temp_pos + conv2(le_CPU, d_desc->d_rec_len) <= pos + && NEXT_DISC_DIR_POS(d_desc, &b_data(bp)) < block_size; + d_desc = NEXT_DISC_DIR_DESC(d_desc)) { + temp_pos += conv2(le_CPU, d_desc->d_rec_len); + } + + for (; CUR_DISC_DIR_POS(d_desc, &b_data(bp)) < block_size; + d_desc = NEXT_DISC_DIR_DESC(d_desc)) { + if (d_desc->d_ino == 0) + continue; /* Entry is not in use */ + + if (d_desc->d_name_len > NAME_MAX || + d_desc->d_name_len > EXT2_NAME_MAX) { + len = min(NAME_MAX, EXT2_NAME_MAX); + } else { + len = d_desc->d_name_len; + } + + /* Compute record length */ + reclen = offsetof(struct dirent_321, d_name) + len + 1; + o = (reclen % sizeof(long)); + if (o != 0) + reclen += sizeof(long) - o; + + /* Need the position of this entry in the directory */ + ent_pos = block_pos + ((char *)d_desc - b_data(bp)); + + if (userbuf_off + tmpbuf_off + reclen >= size) { + /* The user has no space for one more record */ + done = TRUE; + + /* Record the position of this entry, it is the + * starting point of the next request (unless the + * position is modified with lseek). + */ + new_pos = ent_pos; + break; + } + + if (tmpbuf_off + reclen >= + GETDENTS_321_BUFSIZE * GETDENTS_321_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_ino = (u32_t) conv4(le_CPU, d_desc->d_ino); + dep->d_off = (i32_t) ent_pos; + dep->d_reclen = (unsigned short) reclen; + memcpy(dep->d_name, d_desc->d_name, len); + dep->d_name[len] = '\0'; + tmpbuf_off += reclen; + } + + put_block(bp, DIRECTORY_BLOCK); + if (done) + break; + } + + if (tmpbuf_off != 0) { + r = sys_safecopyto(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.RES_NBYTES = userbuf_off; + fs_m_out.RES_SEEK_POS_LO = new_pos; + rip->i_update |= ATIME; + rip->i_dirt = IN_DIRTY; + r = OK; + } + + put_inode(rip); /* release the inode */ + return(r); +} + /*===========================================================================* * fs_getdents * *===========================================================================*/ @@ -577,6 +727,10 @@ int fs_getdents(void) struct ext2_disk_dir_desc *d_desc; struct dirent *dep; + if (proto_version == 0) { + return fs_getdents_321(); + } + ino = (pino_t) fs_m_in.REQ_INODE_NR; gid = (cp_grant_id_t) fs_m_in.REQ_GRANT; size = (size_t) fs_m_in.REQ_MEM_SIZE; @@ -668,8 +822,8 @@ int fs_getdents(void) } dep = (struct dirent *) &getdents_buf[tmpbuf_off]; - dep->d_ino = conv4(le_CPU, d_desc->d_ino); - dep->d_off = ent_pos; + dep->d_ino = (ino_t) conv4(le_CPU, d_desc->d_ino); + dep->d_off = (off_t) ent_pos; dep->d_reclen = (unsigned short) reclen; memcpy(dep->d_name, d_desc->d_name, len); dep->d_name[len] = '\0'; diff --git a/servers/iso9660fs/const.h b/servers/iso9660fs/const.h index 3dfd35317..3174947f1 100644 --- a/servers/iso9660fs/const.h +++ b/servers/iso9660fs/const.h @@ -1,5 +1,5 @@ -#define GETDENTS_BUFSIZ 257 +#define GETDENTS_BUFSIZ 261 #define ISO9660_STANDARD_ID "CD001" /* Standard code for ISO9660 filesystems */ diff --git a/servers/iso9660fs/glo.h b/servers/iso9660fs/glo.h index bb84c902a..fc59cb00e 100644 --- a/servers/iso9660fs/glo.h +++ b/servers/iso9660fs/glo.h @@ -19,6 +19,7 @@ EXTERN int FS_STATE; EXTERN uid_t caller_uid; EXTERN gid_t caller_gid; +EXTERN int proto_version; EXTERN int req_nr; /* request number to the server */ EXTERN int SELF_E; /* process number */ diff --git a/servers/iso9660fs/mount.c b/servers/iso9660fs/mount.c index 62e2fa952..021c7ab6e 100644 --- a/servers/iso9660fs/mount.c +++ b/servers/iso9660fs/mount.c @@ -18,6 +18,12 @@ int fs_readsuper() { label_gid = fs_m_in.REQ_GRANT; label_len = fs_m_in.REQ_PATH_LEN; + if (!(fs_m_in.REQ_FLAGS & REQ_HASPROTO)) { + proto_version = 0; + } else { + proto_version = VFS_FS_PROTO_VERSION(fs_m_in.REQ_PROTO); + } + if (label_len > sizeof(fs_dev_label)) return(EINVAL); diff --git a/servers/iso9660fs/read.c b/servers/iso9660fs/read.c index 34dc8a686..88fb196b9 100644 --- a/servers/iso9660fs/read.c +++ b/servers/iso9660fs/read.c @@ -137,9 +137,9 @@ int fs_bread(void) /*===========================================================================* - * fs_getdents * + * fs_getdents_321 * *===========================================================================*/ -int fs_getdents(void) { +int fs_getdents_321(void) { struct dir_record *dir; pino_t ino; cp_grant_id_t gid; @@ -246,8 +246,159 @@ int fs_getdents(void) { /* The standard data structure is created using the * data in the buffer. */ dirp = (struct dirent *) &getdents_buf[tmpbuf_offset]; - dirp->d_ino = (pino_t)(b_data(bp) + block_pos); - dirp->d_off= cur_pos; + dirp->d_ino = (u32_t) (b_data(bp) + block_pos); + dirp->d_off= (i32_t) cur_pos; + dirp->d_reclen= reclen; + memcpy(dirp->d_name, name, len); + dirp->d_name[len]= '\0'; + tmpbuf_offset += reclen; + + cur_pos += dir_tmp->length; + release_dir_record(dir_tmp); + } + + block_pos += dir_tmp->length; + } + + put_block(bp); /* release the block */ + if (done == TRUE) break; + + cur_pos += block_size - cur_pos; + block++; /* read the next one */ + } + + if (tmpbuf_offset != 0) { + r = sys_safecopyto(VFS_PROC_NR, gid, userbuf_off, + (vir_bytes) getdents_buf, tmpbuf_offset); + if (r != OK) + panic("fs_getdents: sys_safecopyto failed: %d", r); + + userbuf_off += tmpbuf_offset; + } + + fs_m_out.RES_NBYTES = userbuf_off; + fs_m_out.RES_SEEK_POS_LO = cur_pos; + + release_dir_record(dir); /* release the inode */ + return(OK); +} + +/*===========================================================================* + * fs_getdents * + *===========================================================================*/ +int fs_getdents(void) { + struct dir_record *dir; + pino_t ino; + cp_grant_id_t gid; + size_t block_size; + off_t pos, block_pos, block, cur_pos, tmpbuf_offset, userbuf_off; + struct buf *bp; + struct dir_record *dir_tmp; + struct dirent *dirp; + int r,done,o,len,reclen; + char *cp; + char name[NAME_MAX + 1]; + char name_old[NAME_MAX + 1]; + + if (proto_version == 0) { + return fs_getdents_321(); + } + + /* Initialize the tmp arrays */ + memset(name,'\0',NAME_MAX); + memset(name_old,'\0',NAME_MAX); + + /* Get input parameters */ + ino = fs_m_in.REQ_INODE_NR; + gid = fs_m_in.REQ_GRANT; + pos = fs_m_in.REQ_SEEK_POS_LO; + + block_size = v_pri.logical_block_size_l; + cur_pos = pos; /* The current position */ + tmpbuf_offset = 0; + userbuf_off = 0; + memset(getdents_buf, '\0', GETDENTS_BUFSIZ); /* Avoid leaking any data */ + + if ((dir = get_dir_record(ino)) == NULL) return(EINVAL); + + block = dir->loc_extent_l; /* First block of the directory */ + block += pos / block_size; /* Shift to the block where start to read */ + done = FALSE; + + while (cur_posd_file_size) { + bp = get_block(block); /* Get physical block */ + + if (bp == NULL) { + release_dir_record(dir); + return(EINVAL); + } + + block_pos = cur_pos % block_size; /* Position where to start read */ + + while (block_pos < block_size) { + dir_tmp = get_free_dir_record(); + create_dir_record(dir_tmp,b_data(bp) + block_pos, + block*block_size + block_pos); + if (dir_tmp->length == 0) { /* EOF. I exit and return 0s */ + block_pos = block_size; + done = TRUE; + release_dir_record(dir_tmp); + } else { /* The dir record is valid. Copy data... */ + if (dir_tmp->file_id[0] == 0) + strlcpy(name, ".", NAME_MAX + 1); + else if (dir_tmp->file_id[0] == 1) + strlcpy(name, "..", NAME_MAX + 1); + else { + /* Extract the name from the field file_id */ + strncpy(name, dir_tmp->file_id, + dir_tmp->length_file_id); + name[dir_tmp->length_file_id] = 0; + + /* Tidy up file name */ + cp = memchr(name, ';', NAME_MAX); + if (cp != NULL) name[cp - name] = 0; + + /*If no file extension, then remove final '.'*/ + if (name[strlen(name) - 1] == '.') + name[strlen(name) - 1] = '\0'; + } + + if (strcmp(name_old, name) == 0) { + cur_pos += dir_tmp->length; + release_dir_record(dir_tmp); + continue; + } + + strlcpy(name_old, name, NAME_MAX + 1); + + /* Compute the length of the name */ + cp = memchr(name, '\0', NAME_MAX); + if (cp == NULL) len = NAME_MAX; + else len= cp - name; + + /* Compute record length */ + reclen = offsetof(struct dirent, d_name) + len + 1; + o = (reclen % sizeof(long)); + if (o != 0) + reclen += sizeof(long) - o; + + /* If the new record does not fit, then copy the buffer + * and start from the beginning. */ + if (tmpbuf_offset + reclen > GETDENTS_BUFSIZ) { + r = sys_safecopyto(VFS_PROC_NR, gid, userbuf_off, + (vir_bytes)getdents_buf, tmpbuf_offset); + + if (r != OK) + panic("fs_getdents: sys_safecopyto failed: %d", r); + userbuf_off += tmpbuf_offset; + tmpbuf_offset= 0; + } + + /* The standard data structure is created using the + * data in the buffer. */ + dirp = (struct dirent *) &getdents_buf[tmpbuf_offset]; + dirp->d_ino = (ino_t)(b_data(bp) + block_pos); + dirp->d_off= (off_t) cur_pos; dirp->d_reclen= reclen; memcpy(dirp->d_name, name, len); dirp->d_name[len]= '\0'; diff --git a/servers/mfs/glo.h b/servers/mfs/glo.h index 09d30d986..15792f571 100644 --- a/servers/mfs/glo.h +++ b/servers/mfs/glo.h @@ -27,6 +27,7 @@ EXTERN uid_t caller_uid; EXTERN gid_t caller_gid; EXTERN int req_nr; +EXTERN int proto_version; EXTERN endpoint_t SELF_E; diff --git a/servers/mfs/inode.h b/servers/mfs/inode.h index dfacdf303..3035595e0 100644 --- a/servers/mfs/inode.h +++ b/servers/mfs/inode.h @@ -32,7 +32,7 @@ EXTERN struct inode { /* The following items are not present on the disk. */ dev_t i_dev; /* which device is the inode on */ - ino_t i_num; /* inode number on its (minor) device */ + pino_t i_num; /* inode number on its (minor) device */ int i_count; /* # times inode used; 0 means slot is free */ unsigned int i_ndzones; /* # direct zones (Vx_NR_DZONES) */ unsigned int i_nindirs; /* # indirect zones per indirect block */ diff --git a/servers/mfs/mount.c b/servers/mfs/mount.c index 7b32de5da..b4042ceb2 100644 --- a/servers/mfs/mount.c +++ b/servers/mfs/mount.c @@ -30,6 +30,12 @@ int fs_readsuper() readonly = (fs_m_in.REQ_FLAGS & REQ_RDONLY) ? 1 : 0; isroot = (fs_m_in.REQ_FLAGS & REQ_ISROOT) ? 1 : 0; + if (!(fs_m_in.REQ_FLAGS & REQ_HASPROTO)) { + proto_version = 0; + } else { + proto_version = VFS_FS_PROTO_VERSION(fs_m_in.REQ_PROTO); + } + if (label_len > sizeof(fs_dev_label)) return(EINVAL); diff --git a/servers/mfs/proto.h b/servers/mfs/proto.h index 83677736d..d41037438 100644 --- a/servers/mfs/proto.h +++ b/servers/mfs/proto.h @@ -66,6 +66,7 @@ int search_dir(struct inode *ldir_ptr, char string [MFS_NAME_MAX], pino_t int fs_chmod(void); int fs_chown(void); int fs_getdents(void); +int fs_getdents_321(void); int forbidden(struct inode *rip, pmode_t access_desired); int read_only(struct inode *ip); diff --git a/servers/mfs/read.c b/servers/mfs/read.c index 208b9dc7f..2ad474b13 100644 --- a/servers/mfs/read.c +++ b/servers/mfs/read.c @@ -545,6 +545,153 @@ unsigned bytes_ahead; /* bytes beyond position for immediate use */ } +/*===========================================================================* + * fs_getdents_321 * + *===========================================================================*/ +int fs_getdents_321(void) +{ +#define GETDENTS_321_BUFSIZE (sizeof(struct dirent_321) + MFS_NAME_MAX + 1) +#define GETDENTS_321_ENTRIES 8 + static char getdents_buf[GETDENTS_321_BUFSIZE * GETDENTS_321_ENTRIES]; + register struct inode *rip; + int o, r, done; + unsigned int block_size, len, reclen; + pino_t ino; + block_t b; + cp_grant_id_t gid; + size_t size, tmpbuf_off, userbuf_off; + off_t pos, off, block_pos, new_pos, ent_pos; + struct buf *bp; + struct direct *dp; + struct dirent_321 *dep; + char *cp; + + ino = (pino_t) fs_m_in.REQ_INODE_NR; + gid = (cp_grant_id_t) fs_m_in.REQ_GRANT; + size = (size_t) fs_m_in.REQ_MEM_SIZE; + pos = (off_t) fs_m_in.REQ_SEEK_POS_LO; + + /* Check whether the position is properly aligned */ + if ((unsigned int) pos % DIR_ENTRY_SIZE) + return(ENOENT); + + if ((rip = get_inode(fs_dev, ino)) == NULL) + return(EINVAL); + + block_size = rip->i_sp->s_block_size; + off = (pos % block_size); /* Offset in block */ + block_pos = pos - off; + done = FALSE; /* Stop processing directory blocks when done is set */ + + 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 */ + + /* The default position for the next request is EOF. If the user's buffer + * fills up before EOF, new_pos will be modified. */ + new_pos = rip->i_size; + + for(; block_pos < rip->i_size; block_pos += block_size) { + b = read_map(rip, block_pos); /* get block number */ + + /* Since directories don't have holes, 'b' cannot be NO_BLOCK. */ + bp = get_block(rip->i_dev, b, NORMAL); /* get a dir block */ + + 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 */ + + /* 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 */ + reclen = offsetof(struct dirent_321, d_name) + len + 1; + o = (reclen % sizeof(long)); + if (o != 0) + reclen += sizeof(long) - o; + + /* 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; + + /* 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_321_BUFSIZE * GETDENTS_321_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_321 *) &getdents_buf[tmpbuf_off]; + dep->d_ino = (u32_t) dp->mfs_d_ino; + dep->d_off = (i32_t) ent_pos; + dep->d_reclen = (unsigned short) reclen; + memcpy(dep->d_name, dp->mfs_d_name, len); + dep->d_name[len] = '\0'; + tmpbuf_off += reclen; + } + + put_block(bp, DIRECTORY_BLOCK); + if (done) + break; + } + + if (tmpbuf_off != 0) { + r = sys_safecopyto(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.RES_NBYTES = userbuf_off; + fs_m_out.RES_SEEK_POS_LO = 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); +} + /*===========================================================================* * fs_getdents * *===========================================================================*/ @@ -566,6 +713,12 @@ int fs_getdents(void) struct dirent *dep; char *cp; + if (proto_version == 0) { + /* VFS-FS protocol version 0 uses 32-bits ino_t and off_t. We need to + * use the binary compatible version of this routine */ + return fs_getdents_321(); + } + ino = (pino_t) fs_m_in.REQ_INODE_NR; gid = (cp_grant_id_t) fs_m_in.REQ_GRANT; size = (size_t) fs_m_in.REQ_MEM_SIZE; @@ -651,8 +804,8 @@ int fs_getdents(void) } dep = (struct dirent *) &getdents_buf[tmpbuf_off]; - dep->d_ino = dp->mfs_d_ino; - dep->d_off = ent_pos; + dep->d_ino = (ino_t) dp->mfs_d_ino; + dep->d_off = (off_t) ent_pos; dep->d_reclen = (unsigned short) reclen; memcpy(dep->d_name, dp->mfs_d_name, len); dep->d_name[len] = '\0'; diff --git a/servers/mfs/stadir.c b/servers/mfs/stadir.c index 362306298..e721a73ae 100644 --- a/servers/mfs/stadir.c +++ b/servers/mfs/stadir.c @@ -66,9 +66,9 @@ static int stat_inode( memset(&statbuf, 0, sizeof(struct stat)); statbuf.st_dev = rip->i_dev; - statbuf.st_ino = rip->i_num; - statbuf.st_mode = rip->i_mode; - statbuf.st_nlink = rip->i_nlinks; + 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); diff --git a/servers/mfs/super.h b/servers/mfs/super.h index d932fa3d5..c8e2e887c 100644 --- a/servers/mfs/super.h +++ b/servers/mfs/super.h @@ -22,14 +22,14 @@ */ EXTERN struct super_block { - pino_t s_ninodes; /* # usable inodes on the minor device */ + u32_t s_ninodes; /* # usable inodes on the minor device */ zone1_t s_nzones; /* total device size, including bit maps etc */ short s_imap_blocks; /* # of blocks used by inode bit map */ short s_zmap_blocks; /* # of blocks used by zone bit map */ zone1_t s_firstdatazone_old; /* number of first data zone (small) */ short s_log_zone_size; /* log2 of blocks/zone */ unsigned short s_flags; /* FS state flags */ - off_t s_max_size; /* maximum file size on this device */ + i32_t s_max_size; /* maximum file size on this device */ zone_t s_zones; /* number of zones (replaces s_nzones in V2) */ short s_magic; /* magic number to recognize super-blocks */ diff --git a/servers/vfs/exec.c b/servers/vfs/exec.c index daad6a2fb..4f8d0ac11 100644 --- a/servers/vfs/exec.c +++ b/servers/vfs/exec.c @@ -500,7 +500,7 @@ char path[PATH_MAX]; /* path to script file */ /* Issue request */ r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, cvul64(pos), READING, - VFS_PROC_NR, buf, _MAX_BLOCK_SIZE, &new_pos, &cum_io); + VFS_PROC_NR, (vir_bytes) buf, _MAX_BLOCK_SIZE, &new_pos, &cum_io); if (r != OK) return(r); n = vp->v_size; @@ -625,7 +625,7 @@ static int read_seg(struct exec_info *execi, off_t off, off_t seg_addr, size_t s if ((unsigned long) vp->v_size < off+seg_bytes) return(EIO); if ((r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, cvul64(off), READING, - execi->proc_e, (char*)seg_addr, seg_bytes, + execi->proc_e, (vir_bytes) seg_addr, seg_bytes, &new_pos, &cum_io)) != OK) { printf("VFS: read_seg: req_readwrite failed (data)\n"); return(r); @@ -671,7 +671,7 @@ static int map_header(struct vfs_exec_info *execi) execi->args.hdr = hdr; r = req_readwrite(execi->vp->v_fs_e, execi->vp->v_inode_nr, - cvul64(pos), READING, VFS_PROC_NR, hdr, + cvul64(pos), READING, VFS_PROC_NR, (vir_bytes) hdr, execi->args.hdr_len, &new_pos, &cum_io); if (r != OK) { printf("VFS: exec: map_header: req_readwrite failed\n"); diff --git a/servers/vfs/link.c b/servers/vfs/link.c index 0b68f4d2a..87b604dcf 100644 --- a/servers/vfs/link.c +++ b/servers/vfs/link.c @@ -16,6 +16,7 @@ #include #include #include +#include /* Remove with version check in do_truncate */ #include #include #include @@ -306,8 +307,18 @@ int do_truncate() resolve.l_vmnt_lock = VMNT_READ; resolve.l_vnode_lock = VNODE_WRITE; - length = (off_t) job_m_in.flength; - if (length < 0) return(EINVAL); + if (job_call_nr == TRUNCATE_321) { + length = (off_t) job_m_in.m2_l1; + if ((int) job_m_in.flength < 0) return(EINVAL); + } else { +#if OS_VMAJOR == 2 && OS_VMINOR == 1 + length = (off_t) make64(job_m_in.m2_l1, 0); /* Ignore higher bits */ +#else +#error "Please remove this version check. Recompile dynamic packages first." + length = (off_t) make64(job_m_in.m2_l1, job_m_in.m2_l2); +#endif + if (length < 0) return(EINVAL); + } /* Temporarily open file */ if (fetch_name(vname, vname_length, fullpath) != OK) return(err_code); @@ -343,9 +354,20 @@ int do_ftruncate() off_t length; scratch(fp).file.fd_nr = job_m_in.fd; - length = (off_t) job_m_in.flength; - if (length < 0) return(EINVAL); + if (job_call_nr == FTRUNCATE_321) { + length = (off_t) job_m_in.m2_l1; + if ((int) job_m_in.flength < 0) return(EINVAL); + } else { +#if OS_VMAJOR == 2 && OS_VMINOR == 1 + length = (off_t) make64(job_m_in.m2_l1, 0); /* Ignore higher bits */ +#else +#error "Please remove this version check. Recompile dynamic packages first." + length = (off_t) make64(job_m_in.m2_l1, job_m_in.m2_l2); +#endif + if (length < 0) return(EINVAL); + } + /* File is already opened; get a vnode pointer from filp */ if ((rfilp = get_filp(scratch(fp).file.fd_nr, VNODE_WRITE)) == NULL) diff --git a/servers/vfs/lock.c b/servers/vfs/lock.c index 0551a8401..d113faa93 100644 --- a/servers/vfs/lock.c +++ b/servers/vfs/lock.c @@ -6,6 +6,7 @@ */ #include "fs.h" +#include #include #include #include @@ -30,11 +31,26 @@ int req; /* either F_SETLK or F_SETLKW */ mode_t mo; off_t first, last; struct flock flock; + struct flock_321 fa_321; struct file_lock *flp, *flp2, *empty; /* Fetch the flock structure from user space. */ - r = sys_datacopy(who_e, (vir_bytes) scratch(fp).io.io_buffer, VFS_PROC_NR, - (vir_bytes) &flock, sizeof(flock)); + if (job_call_nr == FCNTL_321) { + r = sys_datacopy(who_e, (vir_bytes) scratch(fp).io.io_buffer, + VFS_PROC_NR, (vir_bytes) &fa_321, sizeof(fa_321)); + + /* Convert old values to new structure */ + if (r == OK) { + flock.l_type = fa_321.l_type; + flock.l_whence = fa_321.l_whence; + flock.l_start = (off_t) fa_321.l_start; + flock.l_len = (off_t) fa_321.l_len; + flock.l_pid = fa_321.l_pid; + } + } else { + r = sys_datacopy(who_e, (vir_bytes) scratch(fp).io.io_buffer, + VFS_PROC_NR, (vir_bytes) &flock, sizeof(flock)); + } if (r != OK) return(EINVAL); /* Make some error checks. */ @@ -147,8 +163,23 @@ int req; /* either F_SETLK or F_SETLKW */ } /* Copy the flock structure back to the caller. */ - r = sys_datacopy(VFS_PROC_NR, (vir_bytes) &flock, - who_e, (vir_bytes) scratch(fp).io.io_buffer, sizeof(flock)); + if (job_call_nr == FCNTL_321) { + /* Convert new values to old structure */ + if (r == OK) { + fa_321.l_type = flock.l_type; + fa_321.l_whence = flock.l_whence; + fa_321.l_start = (i32_t) flock.l_start; + fa_321.l_len = (i32_t) flock.l_len; + fa_321.l_pid = flock.l_pid; + } + r = sys_datacopy(VFS_PROC_NR, (vir_bytes) &fa_321, + who_e, (vir_bytes) scratch(fp).io.io_buffer, + sizeof(fa_321)); + } else { + r = sys_datacopy(VFS_PROC_NR, (vir_bytes) &flock, + who_e, (vir_bytes) scratch(fp).io.io_buffer, + sizeof(flock)); + } return(r); } diff --git a/servers/vfs/misc.c b/servers/vfs/misc.c index dd1083792..e3bb2719b 100644 --- a/servers/vfs/misc.c +++ b/servers/vfs/misc.c @@ -176,23 +176,38 @@ int do_fcntl() case F_FREESP: { /* Free a section of a file */ - off_t start, end; + off_t start, end, offset; struct flock flock_arg; - signed long offset; /* Check if it's a regular file. */ if (!S_ISREG(f->filp_vno->v_mode)) r = EINVAL; else if (!(f->filp_mode & W_BIT)) r = EBADF; - else + else { /* Copy flock data from userspace. */ - r = sys_datacopy(who_e, (vir_bytes) scratch(fp).io.io_buffer, - SELF, (vir_bytes) &flock_arg, - sizeof(flock_arg)); + if (job_call_nr == FCNTL_321) { + struct flock_321 fa_321; + r = sys_datacopy(who_e, + (vir_bytes) scratch(fp).io.io_buffer, SELF, + (vir_bytes) &fa_321, sizeof(fa_321)); + /* Let's convert the values to the new structure */ + if (r == OK) { + flock_arg.l_type = fa_321.l_type; + flock_arg.l_whence = fa_321.l_whence; + flock_arg.l_start = (off_t) fa_321.l_start; + flock_arg.l_len = (off_t) fa_321.l_len; + flock_arg.l_pid = fa_321.l_pid; + } + } else { + r = sys_datacopy(who_e, + (vir_bytes) scratch(fp).io.io_buffer, SELF, + (vir_bytes) &flock_arg, sizeof(flock_arg)); + } + } if (r != OK) break; /* Convert starting offset to signed. */ - offset = (signed long) flock_arg.l_start; + offset = (off_t) flock_arg.l_start; /* Figure out starting position base. */ switch(flock_arg.l_whence) { diff --git a/servers/vfs/open.c b/servers/vfs/open.c index cd86331f2..ddbebe3f5 100644 --- a/servers/vfs/open.c +++ b/servers/vfs/open.c @@ -590,17 +590,17 @@ int do_mkdir() /*===========================================================================* * do_lseek * *===========================================================================*/ -int do_lseek() +int do_lseek_321() { /* Perform the lseek(ls_fd, offset, whence) system call. */ register struct filp *rfilp; int r = OK, seekfd, seekwhence; - off_t offset; + i32_t offset; u64_t pos, newpos; seekfd = job_m_in.ls_fd; seekwhence = job_m_in.whence; - offset = (off_t) job_m_in.offset_lo; + offset = (i32_t) job_m_in.offset_lo; /* Check to see if the file descriptor is valid. */ if ( (rfilp = get_filp(seekfd, VNODE_READ)) == NULL) return(err_code); @@ -627,7 +627,7 @@ int do_lseek() /* Check for overflow. */ if (ex64hi(newpos) != 0) { r = EOVERFLOW; - } else if ((off_t) ex64lo(newpos) < 0) { /* no negative file size */ + } else if ((i32_t) ex64lo(newpos) < 0) { /* no negative file size */ r = EOVERFLOW; } else { /* insert the new position into the output message */ @@ -646,6 +646,60 @@ int do_lseek() return(r); } +/*===========================================================================* + * do_lseek * + *===========================================================================*/ +int do_lseek() +{ +/* Perform the lseek(ls_fd, offset, whence) system call. */ + register struct filp *rfilp; + int r = OK, seekfd, seekwhence; + off_t offset; + u64_t pos, newpos; + + seekfd = job_m_in.ls_fd; + seekwhence = job_m_in.whence; + offset = (off_t) make64(job_m_in.offset_lo, job_m_in.offset_high); + + /* Check to see if the file descriptor is valid. */ + if ( (rfilp = get_filp(seekfd, VNODE_READ)) == NULL) return(err_code); + + /* No lseek on pipes. */ + if (S_ISFIFO(rfilp->filp_vno->v_mode)) { + unlock_filp(rfilp); + return(ESPIPE); + } + + /* The value of 'whence' determines the start position to use. */ + switch(seekwhence) { + case SEEK_SET: pos = cvu64(0); break; + case SEEK_CUR: pos = rfilp->filp_pos; break; + case SEEK_END: pos = cvul64(rfilp->filp_vno->v_size); break; + default: unlock_filp(rfilp); return(EINVAL); + } + + if (offset < 0 && -offset > pos) { /* no negative file size */ + r = EOVERFLOW; + } else { + newpos = pos + offset; + + /* insert the new position into the output message */ + m_out.reply_l1 = ex64lo(newpos); + m_out.reply_l2 = ex64hi(newpos); + + if (cmp64(newpos, rfilp->filp_pos) != 0) { + rfilp->filp_pos = newpos; + + /* Inhibit read ahead request */ + r = req_inhibread(rfilp->filp_vno->v_fs_e, + rfilp->filp_vno->v_inode_nr); + } + } + + unlock_filp(rfilp); + return(r); +} + /*===========================================================================* * do_llseek * *===========================================================================*/ diff --git a/servers/vfs/path.c b/servers/vfs/path.c index 6c0d2bbdf..26eb9c041 100644 --- a/servers/vfs/path.c +++ b/servers/vfs/path.c @@ -626,7 +626,7 @@ char ename[NAME_MAX + 1]; do { r = req_getdents(dirp->v_fs_e, dirp->v_inode_nr, pos, buf, sizeof(buf), - &new_pos, 1); + &new_pos, 1, 0 /* Not MINIX 3.2.1 format */); if (r == 0) { return(ENOENT); /* end of entries -- matching inode !found */ diff --git a/servers/vfs/proto.h b/servers/vfs/proto.h index c47a13fd2..9f750cfbf 100644 --- a/servers/vfs/proto.h +++ b/servers/vfs/proto.h @@ -162,6 +162,7 @@ void close_reply(void); int common_open(char path[PATH_MAX], int oflags, mode_t omode); int do_creat(void); int do_lseek(void); +int do_lseek_321(void); int do_llseek(void); int do_mknod(void); int do_mkdir(void); @@ -218,7 +219,7 @@ int rw_pipe(int rw_flag, endpoint_t usr, struct filp *f, char *buf, /* request.c */ int req_breadwrite(endpoint_t fs_e, endpoint_t user_e, dev_t dev, u64_t pos, - unsigned int num_of_bytes, char *user_addr, int rw_flag, + unsigned int num_of_bytes, vir_bytes user_addr, int rw_flag, u64_t *new_posp, unsigned int *cum_iop); int req_chmod(endpoint_t fs_e, ino_t inode_nr, mode_t rmode, mode_t *new_modep); @@ -231,7 +232,7 @@ int req_fstatfs(endpoint_t fs_e, endpoint_t proc_e, vir_bytes buf); int req_statvfs(endpoint_t fs_e, endpoint_t proc_e, vir_bytes buf); int req_ftrunc(endpoint_t fs_e, ino_t inode_nr, off_t start, off_t end); int req_getdents(endpoint_t fs_e, ino_t inode_nr, u64_t pos, char *buf, - size_t size, u64_t *new_pos, int direct); + size_t size, u64_t *new_pos, int direct, int getdents_321); int req_inhibread(endpoint_t fs_e, ino_t inode_nr); int req_link(endpoint_t fs_e, ino_t link_parent, char *lastc, ino_t linked_file); @@ -251,7 +252,7 @@ int req_rdlink(endpoint_t fs_e, ino_t inode_nr, endpoint_t proc_e, int req_readsuper(struct vmnt *vmp, char *driver_name, dev_t dev, int readonly, int isroot, struct node_details *res_nodep); int req_readwrite(endpoint_t fs_e, ino_t inode_nr, u64_t pos, int rw_flag, - endpoint_t user_e, char *user_addr, unsigned int num_of_bytes, + endpoint_t user_e, vir_bytes user_addr, unsigned int num_of_bytes, u64_t *new_posp, unsigned int *cum_iop); int req_rename(endpoint_t fs_e, ino_t old_dir, char *old_name, ino_t new_dir, char *new_name); diff --git a/servers/vfs/read.c b/servers/vfs/read.c index b8e982da9..b97ec50f3 100644 --- a/servers/vfs/read.c +++ b/servers/vfs/read.c @@ -176,7 +176,7 @@ int read_write(int rw_flag, struct filp *f, char *buf, size_t size, lock_bsf(); r = req_breadwrite(vp->v_bfs_e, for_e, vp->v_sdev, position, size, - buf, rw_flag, &res_pos, &res_cum_io); + (vir_bytes) buf, rw_flag, &res_pos, &res_cum_io); if (r == OK) { position = res_pos; cum_io += res_cum_io; @@ -191,7 +191,7 @@ int read_write(int rw_flag, struct filp *f, char *buf, size_t size, /* Issue request */ r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, position, rw_flag, for_e, - buf, size, &new_pos, &cum_io_incr); + (vir_bytes) buf, size, &new_pos, &cum_io_incr); if (r >= 0) { if (ex64hi(new_pos)) @@ -237,10 +237,11 @@ int read_write(int rw_flag, struct filp *f, char *buf, size_t size, int do_getdents() { /* Perform the getdents(fd, buf, size) system call. */ - int r = OK; + int r = OK, getdents_321 = 0; u64_t new_pos; register struct filp *rfilp; + if (job_call_nr == GETDENTS_321) getdents_321 = 1; scratch(fp).file.fd_nr = job_m_in.fd; scratch(fp).io.io_buffer = job_m_in.buffer; scratch(fp).io.io_nbytes = (size_t) job_m_in.nbytes; @@ -260,7 +261,7 @@ int do_getdents() r = req_getdents(rfilp->filp_vno->v_fs_e, rfilp->filp_vno->v_inode_nr, rfilp->filp_pos, scratch(fp).io.io_buffer, - scratch(fp).io.io_nbytes, &new_pos,0); + scratch(fp).io.io_nbytes, &new_pos, 0, getdents_321); if (r > 0) rfilp->filp_pos = new_pos; } @@ -314,7 +315,7 @@ size_t req_size; panic("unmapped pipe"); r = req_readwrite(vp->v_mapfs_e, vp->v_mapinode_nr, position, rw_flag, usr_e, - buf, size, &new_pos, &cum_io_incr); + (vir_bytes) buf, size, &new_pos, &cum_io_incr); if (r != OK) { return(r); diff --git a/servers/vfs/request.c b/servers/vfs/request.c index 98e06a79c..e8bda6f1f 100644 --- a/servers/vfs/request.c +++ b/servers/vfs/request.c @@ -6,25 +6,28 @@ */ #include "fs.h" -#include -#include -#include -#include -#include -#include #include #include #include #include -#include #include +#include +#include +#include +#include +#include +#include +#include +#include #include "fproc.h" +#include "param.h" +#include "path.h" #include "vmnt.h" #include "vnode.h" -#include "path.h" -#include "param.h" +static size_t translate_dents(char *src, size_t size, char *dst, int direction); + /*===========================================================================* * req_breadwrite * *===========================================================================*/ @@ -34,7 +37,7 @@ int req_breadwrite( dev_t dev, u64_t pos, unsigned int num_of_bytes, - char *user_addr, + vir_bytes user_addr, int rw_flag, u64_t *new_posp, unsigned int *cum_iop @@ -44,7 +47,7 @@ int req_breadwrite( cp_grant_id_t grant_id; message m; - grant_id = cpf_grant_magic(fs_e, user_e, (vir_bytes) user_addr, num_of_bytes, + grant_id = cpf_grant_magic(fs_e, user_e, user_addr, num_of_bytes, (rw_flag == READING ? CPF_WRITE : CPF_READ)); if(grant_id == -1) panic("req_breadwrite: cpf_grant_magic failed"); @@ -279,19 +282,65 @@ int req_getdents( char *buf, size_t size, u64_t *new_pos, - int direct + int direct, + int getdents_321 /* Set to 1 if user land expects old format */ ) { int r; + int fs_getdents_321 = 0, do_translation = 0; message m; cp_grant_id_t grant_id; + struct vmnt *vmp; + char *indir_buf_src = NULL; + char *indir_buf_dst = NULL; - if (direct) { - grant_id = cpf_grant_direct(fs_e, (vir_bytes) buf, size, - CPF_WRITE); + vmp = find_vmnt(fs_e); + assert(vmp != NULL); + + if (VFS_FS_PROTO_VERSION(vmp->m_proto) == 0) { + fs_getdents_321 = 1; + } + + /* When we have to translate new struct dirent to the old format or vice + * versa, we're going to have to ignore the user provided buffer and do only + * one entry at a time. We have to do the translation here and allocate + * space on the stack. This is a limited resource. Besides, we don't want to + * be dependent on crazy buffer sizes provided by user space (i.e., we'd have + * to allocate a similarly sized buffer here). + * + * We need to translate iff: + * 1. userland expects old format and FS provides new format + * 2. userland expects new format and FS provides old format + * We don't need to translate iff + * 3. userland expects old format and FS provides old format + * 4. userland expects new format and FS provides new format + * + * Note: VFS expects new format (when doing 'direct'), covered by case 2. + */ + if (getdents_321 && !fs_getdents_321) { /* case 1 */ + do_translation = 1; + } else if (fs_getdents_321 && !getdents_321) {/* case 2 */ + do_translation = 1; + } + + if (do_translation) { + /* We're cutting down the buffer size in two so it's guaranteed we + * have enough space for the translation (data structure has become + * larger). + */ + size = size / 2; + indir_buf_src = malloc(size); + indir_buf_dst = malloc(size * 2); /* dst buffer keeps original size */ + if (indir_buf_src == NULL || indir_buf_dst == NULL) + panic("Couldn't allocate temp buf space\n"); + + grant_id = cpf_grant_direct(fs_e, (vir_bytes) indir_buf_src, size, + CPF_WRITE); + } else if (direct) { + grant_id = cpf_grant_direct(fs_e, (vir_bytes) buf, size, CPF_WRITE); } else { grant_id = cpf_grant_magic(fs_e, who_e, (vir_bytes) buf, size, - CPF_WRITE); + CPF_WRITE); } if (grant_id < 0) @@ -308,14 +357,84 @@ int req_getdents( r = fs_sendrec(fs_e, &m); cpf_revoke(grant_id); + if (do_translation) { + if (r == OK) { + m.RES_NBYTES = translate_dents(indir_buf_src, m.RES_NBYTES, + indir_buf_dst, getdents_321); + if (direct) { + memcpy(buf, indir_buf_dst, m.RES_NBYTES); + } else { + r = sys_vircopy(SELF, (vir_bytes) indir_buf_dst, who_e, + (vir_bytes) buf, m.RES_NBYTES); + } + } + free(indir_buf_src); + free(indir_buf_dst); + } + if (r == OK) { - *new_pos = cvul64(m.RES_SEEK_POS_LO); - r = m.RES_NBYTES; + *new_pos = cvul64(m.RES_SEEK_POS_LO); + r = m.RES_NBYTES; } return(r); } +/*===========================================================================* + * translate_dents * + *===========================================================================*/ +static size_t +translate_dents(char *src, size_t size, char *dst, int to_getdents_321) +{ +/* Convert between 'struct dirent' and 'struct dirent_321' both ways and + * return the size of the new buffer. + */ + int consumed = 0, newconsumed = 0; + struct dirent *dent; + struct dirent_321 *dent_321; +#define DWORD_ALIGN(d) if((d) % sizeof(long)) (d)+=sizeof(long)-(d)%sizeof(long) + + if (to_getdents_321) { + /* Provided format is struct dirent and has to be translated + * to struct dirent_321 */ + dent_321 = (struct dirent_321 *) dst; + dent = (struct dirent *) src; + + while (consumed < size && dent->d_reclen > 0) { + dent_321->d_ino = (u32_t) dent->d_ino; + dent_321->d_off = (i32_t) dent->d_off; + dent_321->d_reclen = offsetof(struct dirent_321,d_name)+ + strlen(dent->d_name) + 1; + DWORD_ALIGN(dent_321->d_reclen); + strcpy(dent_321->d_name, dent->d_name); + consumed += dent->d_reclen; + newconsumed += dent_321->d_reclen; + dent = (struct dirent *) &src[consumed]; + dent_321 = (struct dirent_321 *) &dst[newconsumed]; + } + } else { + /* Provided format is struct dirent_321 and has to be + * translated to struct dirent */ + dent_321 = (struct dirent_321 *) src; + dent = (struct dirent *) dst; + + while (consumed < size && dent_321->d_reclen > 0) { + dent->d_ino = (ino_t) dent_321->d_ino; + dent->d_off = (off_t) dent_321->d_off; + dent->d_reclen = offsetof(struct dirent, d_name) + + strlen(dent_321->d_name) + 1; + DWORD_ALIGN(dent->d_reclen); + strcpy(dent->d_name, dent_321->d_name); + consumed += dent_321->d_reclen; + newconsumed += dent->d_reclen; + dent_321 = (struct dirent_321 *) &src[consumed]; + dent = (struct dirent *) &dst[newconsumed]; + } + } + + return newconsumed; +} + /*===========================================================================* * req_inhibread * *===========================================================================*/ @@ -741,8 +860,6 @@ int req_readsuper( res_nodep->fs_e = m.m_source; res_nodep->inode_nr = (ino_t) m.RES_INODE_NR; vmp->m_proto = m.RES_PROTO; - printf("%d: proto = 0x%x, version=%d conreqs=%d\n", fs_e, vmp->m_proto, - VFS_FS_PROTO_VERSION(vmp->m_proto), VFS_FS_PROTO_CONREQS(vmp->m_proto)); res_nodep->fmode = (mode_t) m.RES_MODE; res_nodep->fsize = m.RES_FILE_SIZE_LO; res_nodep->uid = (uid_t) m.RES_UID; @@ -763,7 +880,7 @@ ino_t inode_nr; u64_t pos; int rw_flag; endpoint_t user_e; -char *user_addr; +vir_bytes user_addr; unsigned int num_of_bytes; u64_t *new_posp; unsigned int *cum_iop; @@ -792,7 +909,7 @@ unsigned int *cum_iop; /* fallthrough */ case WRITING: if(type < 0) { type = REQ_WRITE; grantflag = CPF_READ; } - grant_id = cpf_grant_magic(fs_e, user_e, (vir_bytes) user_addr, + grant_id = cpf_grant_magic(fs_e, user_e, user_addr, num_of_bytes, grantflag); if (grant_id == -1) panic("req_readwrite: cpf_grant_magic failed"); diff --git a/servers/vfs/table.c b/servers/vfs/table.c index 61bd517dc..81b20c6f6 100644 --- a/servers/vfs/table.c +++ b/servers/vfs/table.c @@ -23,7 +23,7 @@ int (*call_vec[])(void) = { do_open, /* 5 = open */ do_close, /* 6 = close */ no_sys, /* 7 = wait */ - no_sys, /* 8 = unused (was creat) */ + no_sys, /* 8 = unused */ do_link, /* 9 = link */ do_unlink, /* 10 = unlink */ no_sys, /* 11 = waitpid */ @@ -34,7 +34,7 @@ int (*call_vec[])(void) = { do_chown, /* 16 = chown */ no_sys, /* 17 = break */ no_sys, /* 18 = unused (was old stat)*/ - do_lseek, /* 19 = lseek */ + do_lseek_321, /* 19 = lseek_321 (to be phased out) */ no_sys, /* 20 = getpid */ do_mount, /* 21 = mount */ do_umount, /* 22 = umount */ @@ -56,7 +56,7 @@ int (*call_vec[])(void) = { do_rename, /* 38 = rename */ do_mkdir, /* 39 = mkdir */ do_unlink, /* 40 = rmdir */ - no_sys, /* 41 = unused (was dup) */ + no_sys, /* 41 = unused */ do_pipe, /* 42 = pipe */ no_sys, /* 43 = times */ no_sys, /* 44 = (prof) */ @@ -84,8 +84,8 @@ int (*call_vec[])(void) = { do_fstat, /* 66 = fstat - badly numbered, being phased out */ do_lstat, /* 67 = lstat - badly numbered, being phased out */ no_sys, /* 68 = (setmcontext) */ - no_sys, /* 69 = unused */ - no_sys, /* 70 = unused */ + do_getdents, /* 69 = getdents */ + do_ftruncate, /* 70 = ftruncate */ no_sys, /* 71 = (sigaction) */ no_sys, /* 72 = (sigsuspend) */ no_sys, /* 73 = (sigpending) */ @@ -95,11 +95,11 @@ int (*call_vec[])(void) = { do_svrctl, /* 77 = svrctl */ no_sys, /* 78 = (sysuname) */ no_sys, /* 79 = unused */ - do_getdents, /* 80 = getdents */ + do_getdents, /* 80 = getdents_321 (to be phased out) */ do_llseek, /* 81 = llseek */ do_fstatfs, /* 82 = fstatfs */ - do_statvfs, /* 83 = fstatvfs */ - do_fstatvfs, /* 84 = statvfs */ + do_statvfs, /* 83 = fstatvfs */ + do_fstatvfs, /* 84 = statvfs */ do_select, /* 85 = select */ do_fchdir, /* 86 = fchdir */ do_fsync, /* 87 = fsync */ @@ -108,11 +108,11 @@ int (*call_vec[])(void) = { no_sys, /* 90 = (gettimeofday) */ no_sys, /* 91 = (seteuid) */ no_sys, /* 92 = (setegid) */ - do_truncate, /* 93 = truncate */ - do_ftruncate, /* 94 = truncate */ + do_truncate, /* 93 = truncate_321 (to be phased out) */ + do_ftruncate, /* 94 = ftruncate_321 (to be phased out) */ do_chmod, /* 95 = fchmod */ do_chown, /* 96 = fchown */ - no_sys, /* 97 = unused */ + do_lseek, /* 97 = lseek */ no_sys, /* 98 = (sprofile) */ no_sys, /* 99 = (cprofile) */ no_sys, /* 100 = (newexec) */ @@ -123,8 +123,8 @@ int (*call_vec[])(void) = { no_sys, /* 105 = unused */ no_sys, /* 106 = unused */ no_sys, /* 107 = (getepinfo) */ - no_sys, /* 108 = unused */ - no_sys, /* 109 = unused */ + do_truncate, /* 108 = unused */ + do_fcntl, /* 109 = fcntl */ no_sys, /* 110 = unused */ no_sys, /* 111 = (srv_kill) */ do_gcov_flush, /* 112 = gcov_flush */ diff --git a/sys/sys/ansi.h b/sys/sys/ansi.h index d96dcf123..50909a83c 100644 --- a/sys/sys/ansi.h +++ b/sys/sys/ansi.h @@ -38,8 +38,8 @@ typedef char * __caddr_t; /* core address */ typedef __uint32_t __gid_t; /* group id */ typedef __uint32_t __in_addr_t; /* IP(v4) address */ typedef __uint16_t __in_port_t; /* "Internet" port number */ -typedef __uint16_t __mode_t; /* file permissions */ -typedef __int32_t __off_t; /* file offset */ +typedef __uint32_t __mode_t; /* file permissions */ +typedef __int64_t __off_t; /* file offset */ typedef __int32_t __pid_t; /* process id */ typedef __uint8_t __sa_family_t; /* socket address family */ typedef __int32_t __socklen_t; /* socket-related datum length */ diff --git a/sys/sys/dirent.h b/sys/sys/dirent.h index 3bdc05006..d09ce8b29 100644 --- a/sys/sys/dirent.h +++ b/sys/sys/dirent.h @@ -17,6 +17,13 @@ struct dirent { /* Largest entry (8 slots) */ char d_name[1]; /* Null terminated name */ }; +struct dirent_321 { /* Largest entry (8 slots) */ + u32_t d_ino; /* I-node number */ + i32_t d_off; /* Offset in directory */ + unsigned short d_reclen; /* Length of this record */ + char d_name[1]; /* Null terminated name */ +}; + #if defined(_NETBSD_SOURCE) #define MAXNAMLEN 511 #define d_fileno d_ino diff --git a/sys/sys/fcntl.h b/sys/sys/fcntl.h index 15b4a0c21..420aea0c9 100644 --- a/sys/sys/fcntl.h +++ b/sys/sys/fcntl.h @@ -153,6 +153,14 @@ struct flock { pid_t l_pid; /* process id of the locks' owner */ }; +struct flock_321 { + short l_type; /* type: F_RDLCK, F_WRLCK, or F_UNLCK */ + short l_whence; /* flag for starting offset */ + i32_t l_start; /* relative offset in bytes */ + i32_t l_len; /* size; if 0, then until EOF */ + pid_t l_pid; /* process id of the locks' owner */ +}; + #if defined(_NETBSD_SOURCE) /* lock operations for flock(2) */ #define LOCK_SH F_RDLCK /* Shared lock */ diff --git a/sys/sys/stat.h b/sys/sys/stat.h index 06a5a347e..76ebf2257 100644 --- a/sys/sys/stat.h +++ b/sys/sys/stat.h @@ -47,13 +47,13 @@ #endif struct stat { - big_dev_t st_dev; /* inode's device */ - big_mode_t st_mode; /* inode protection mode */ - big_ino_t st_ino; /* inode's number */ - big_nlink_t st_nlink; /* number of hard links */ - big_uid_t st_uid; /* user ID of the file's owner */ - big_gid_t st_gid; /* group ID of the file's group */ - big_dev_t st_rdev; /* device type */ + dev_t st_dev; /* inode's device */ + mode_t st_mode; /* inode protection mode */ + ino_t st_ino; /* inode's number */ + nlink_t st_nlink; /* number of hard links */ + uid_t st_uid; /* user ID of the file's owner */ + gid_t st_gid; /* group ID of the file's group */ + dev_t st_rdev; /* device type */ #if defined(_NETBSD_SOURCE) struct timespec st_atimespec;/* time of last access */ struct timespec st_mtimespec;/* time of last data modification */ @@ -73,7 +73,7 @@ struct stat { off_t st_size; /* file size, in off_t bytes */ off_t st_size_rest; #else - big_off_t st_size; /* file size, in bytes */ + off_t st_size; /* file size, in bytes */ #endif blkcnt_t st_blocks; /* blocks allocated for file */ blksize_t st_blksize; /* optimal blocksize for I/O */ diff --git a/sys/sys/types.h b/sys/sys/types.h index acc33f114..00cabd7d9 100644 --- a/sys/sys/types.h +++ b/sys/sys/types.h @@ -106,15 +106,6 @@ typedef int16_t i16_t; typedef int32_t i32_t; typedef int64_t i64_t; -typedef uint64_t big_ino_t; -typedef int64_t big_off_t; -typedef u32_t big_dev_t; -typedef u32_t big_gid_t; -typedef u32_t big_mode_t; -typedef u32_t big_nlink_t; -typedef u32_t big_uid_t; - - #ifdef _NETBSD_SOURCE /* some Minix specific types that do not conflict with posix */ typedef uint32_t zone_t; /* zone number */ @@ -204,7 +195,7 @@ typedef __gid_t gid_t; /* group id */ typedef int idtype_t; /* type of the id */ typedef uint32_t id_t; /* group id, process id or user id */ -typedef uint32_t ino_t; /* inode number */ +typedef uint64_t ino_t; /* inode number */ typedef long key_t; /* IPC key (for Sys V IPC) */ #ifndef mode_t @@ -212,7 +203,7 @@ typedef __mode_t mode_t; /* permissions */ #define mode_t __mode_t #endif -typedef int16_t nlink_t; /* link count */ +typedef uint32_t nlink_t; /* link count */ #ifndef off_t typedef __off_t off_t; /* file offset */ diff --git a/usr.bin/gzip/gzip.c b/usr.bin/gzip/gzip.c index fdbdbc537..0bd9a0005 100644 --- a/usr.bin/gzip/gzip.c +++ b/usr.bin/gzip/gzip.c @@ -1278,11 +1278,7 @@ file_compress(char *file, char *outfile, size_t outsize) if (osb.st_size != size) { maybe_warnx("output file: %s wrong size (%" PRIdOFF " != %" PRIdOFF "), deleting", -#ifndef __minix outfile, osb.st_size, size); -#else - outfile, osb.st_size, (big_off_t)size); -#endif goto bad_outfile; } @@ -1561,11 +1557,7 @@ file_uncompress(char *file, char *outfile, size_t outsize) if (osb.st_size != size) { maybe_warnx("stat gave different size: %" PRIdOFF " != %" PRIdOFF " (leaving original)", -#ifndef __minix size, osb.st_size); -#else - (big_off_t)size, osb.st_size); -#endif close(ofd); unlink(outfile); return -1;