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;