/* mimic cpio's block count first */
if (frmt && strcmp(NM_CPIO, argv0) == 0) {
-#ifdef __minix
- (void)fprintf(listf, "%d blocks\n",
- (rdcnt ? rdcnt : wrcnt) / 5120);
-#else
(void)fprintf(listf, OFFT_F " blocks\n",
(rdcnt ? rdcnt : wrcnt) / 5120);
-#endif
}
ar_summary(0);
#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
#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
#define ITIMER 64
#define GETMCONTEXT 67
#define SETMCONTEXT 68
+#define GETDENTS 69
+#define FTRUNCATE 70
/* Posix signal handling. */
#define SIGACTION 71
#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 */
#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 ISSETUGID 106 /* to PM: ask if process is tainted */
#define GETEPINFO_O 107 /* to PM: get pid/uid/gid of an endpoint */
#define UTIMENS 108 /* to FS: [f]utimens(); also [fl]utimes */
+#define FCNTL 109 /* to VFS */
+#define TRUNCATE 110 /* 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 */
#define OS_RELEASE "3"
#define OS_VERSION "2.1"
+/* 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
#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
#include <sys/types.h>
struct statfs {
- off_t f_bsize; /* file system block size */
+ int f_bsize; /* file system block size */
};
int fstatfs(int fd, struct statfs *st);
struct mapreqvm
{
int flags; /* reserved, must be 0 */
- off_t phys_offset;
+ phys_bytes phys_offset;
size_t size;
int readonly;
char reserved[36]; /* reserved, must be 0 */
pg_info(&vm->p_seg.p_ttbr, &vm->p_seg.p_ttbr_v);
}
-int libexec_pg_alloc(struct exec_info *execi, off_t vaddr, size_t len)
+static int libexec_pg_alloc(struct exec_info *execi, vir_bytes vaddr, size_t len)
{
pg_map(PG_ALLOCATEME, vaddr, vaddr+len, &kinfo);
pg_load();
pg_info(&vm->p_seg.p_cr3, &vm->p_seg.p_cr3_v);
}
-int libexec_pg_alloc(struct exec_info *execi, off_t vaddr, size_t len)
+static int libexec_pg_alloc(struct exec_info *execi, vir_bytes vaddr, size_t len)
{
pg_map(PG_ALLOCATEME, vaddr, vaddr+len, &kinfo);
pg_load();
#include "namespace.h"
#include <lib.h>
+#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
__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.
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;
}
#include "namespace.h"
#include <lib.h>
+#include <minix/u64.h>
+#include <errno.h>
#include <string.h>
#include <unistd.h>
__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;
}
#include <lib.h>
#include <dirent.h>
+#include <errno.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+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)
#include "namespace.h"
#include <lib.h>
+#include <minix/u64.h>
+#include <errno.h>
#include <unistd.h>
#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));
}
__weak_alias(truncate, _truncate)
#endif
+#include <minix/u64.h>
+#include <errno.h>
#include <string.h>
#include <unistd.h>
+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;
}
#include <sys/mman.h>
#include <machine/elf.h>
-int libexec_alloc_mmap_prealloc_junk(struct exec_info *execi, off_t vaddr, size_t len)
+int libexec_alloc_mmap_prealloc_junk(struct exec_info *execi, vir_bytes vaddr, size_t len)
{
if(minix_mmap_for(execi->proc_e, (void *) vaddr, len,
PROT_READ|PROT_WRITE|PROT_EXEC,
return OK;
}
-int libexec_alloc_mmap_prealloc_cleared(struct exec_info *execi, off_t vaddr, size_t len)
+int libexec_alloc_mmap_prealloc_cleared(struct exec_info *execi, vir_bytes vaddr, size_t len)
{
if(minix_mmap_for(execi->proc_e, (void *) vaddr, len,
PROT_READ|PROT_WRITE|PROT_EXEC,
return OK;
}
-int libexec_alloc_mmap_ondemand(struct exec_info *execi, off_t vaddr, size_t len)
+int libexec_alloc_mmap_ondemand(struct exec_info *execi, vir_bytes vaddr, size_t len)
{
if(minix_mmap_for(execi->proc_e, (void *) vaddr, len,
PROT_READ|PROT_WRITE|PROT_EXEC,
return vm_procctl(execi->proc_e, VMPPARAM_CLEAR);
}
-int libexec_clear_sys_memset(struct exec_info *execi, off_t vaddr, size_t len)
+int libexec_clear_sys_memset(struct exec_info *execi, vir_bytes vaddr, size_t len)
{
return sys_memset(execi->proc_e, 0, vaddr, len);
}
int libexec_copy_memcpy(struct exec_info *execi,
- off_t off, off_t vaddr, size_t len)
+ off_t off, vir_bytes vaddr, size_t len)
{
assert(off + len <= execi->hdr_len);
memcpy((char *) vaddr, (char *) execi->hdr + off, len);
return OK;
}
-int libexec_clear_memset(struct exec_info *execi, off_t vaddr, size_t len)
+int libexec_clear_memset(struct exec_info *execi, vir_bytes vaddr, size_t len)
{
memset((char *) vaddr, 0, len);
return OK;
struct exec_info;
typedef int (*libexec_loadfunc_t)(struct exec_info *execi,
- off_t offset, off_t vaddr, size_t len);
+ off_t offset, vir_bytes vaddr, size_t len);
typedef int (*libexec_clearfunc_t)(struct exec_info *execi,
- off_t vaddr, size_t len);
+ vir_bytes vaddr, size_t len);
typedef int (*libexec_allocfunc_t)(struct exec_info *execi,
- off_t vaddr, size_t len);
+ vir_bytes vaddr, size_t len);
typedef int (*libexec_procclearfunc_t)(struct exec_info *execi);
typedef int (*libexec_exec_loadfunc_t)(struct exec_info *execi);
int libexec_load_elf(struct exec_info *execi);
-int libexec_copy_memcpy(struct exec_info *execi, off_t offset, off_t vaddr, size_t len);
-int libexec_clear_memset(struct exec_info *execi, off_t vaddr, size_t len);
-int libexec_alloc_mmap_prealloc_cleared(struct exec_info *execi, off_t vaddr, size_t len);
-int libexec_alloc_mmap_prealloc_junk(struct exec_info *execi, off_t vaddr, size_t len);
-int libexec_alloc_mmap_ondemand(struct exec_info *execi, off_t vaddr, size_t len);
+/* Default callbacks for kernel. */
+int libexec_copy_memcpy(struct exec_info *execi, off_t offset, vir_bytes vaddr, size_t len);
+int libexec_clear_memset(struct exec_info *execi, vir_bytes vaddr, size_t len);
+
+/* Default callbacks. */
+int libexec_alloc_mmap_prealloc_cleared(struct exec_info *execi, vir_bytes vaddr, size_t len);
+int libexec_alloc_mmap_prealloc_junk(struct exec_info *execi, vir_bytes vaddr, size_t len);
+int libexec_alloc_mmap_ondemand(struct exec_info *execi, vir_bytes vaddr, size_t len);
int libexec_clearproc_vm_procctl(struct exec_info *execi);
-int libexec_clear_sys_memset(struct exec_info *execi, off_t vaddr, size_t len);
+int libexec_clear_sys_memset(struct exec_info *execi, vir_bytes vaddr, size_t len);
#endif /* !_LIBEXEC_H_ */
EXTERN struct fs_hooks *vtreefs_hooks;
+EXTERN int proto_version;
EXTERN message fs_m_in;
EXTERN message fs_m_out;
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);
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 *
*===========================================================================*/
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;
/* 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);
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;
panic("zeroblock_range: no block");
offset = pos % rip->i_sp->s_block_size;
if (offset + len > rip->i_sp->s_block_size)
- panic("zeroblock_range: len too long: %d", len);
+ panic("zeroblock_range: len too long: %lld", len);
memset(b_data(bp) + offset, 0, len);
lmfs_markdirty(bp);
put_block(bp, FULL_DATA_BLOCK);
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);
}
+/*===========================================================================*
+ * fs_getdents_321 *
+ *===========================================================================*/
+static 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, 0); /* 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 0 /* d_nam_len is a uint8_t, so the test is always false. */
+ 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;
+ }
+#endif
+ 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 *
*===========================================================================*/
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;
}
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';
-#define GETDENTS_BUFSIZ 257
+#define GETDENTS_BUFSIZ 261
#define ISO9660_STANDARD_ID "CD001" /* Standard code for ISO9660 filesystems */
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 */
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);
}
+/*===========================================================================*
+ * fs_getdents_321 *
+ *===========================================================================*/
+int fs_getdents_321(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];
+
+ /* 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_pos<dir->d_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 = (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 *
*===========================================================================*/
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);
/* 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_ino = (u32_t)(b_data(bp) + (size_t)block_pos);
dirp->d_off= cur_pos;
dirp->d_reclen= reclen;
memcpy(dirp->d_name, name, len);
EXTERN gid_t caller_gid;
EXTERN int req_nr;
+EXTERN int proto_version;
EXTERN endpoint_t SELF_E;
/* 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 */
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);
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);
}
+/*===========================================================================*
+ * 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, 0); /* 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 *
*===========================================================================*/
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;
}
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';
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);
*/
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 */
char *frame, int frame_len);
static int exec_restart(int proc_e, int result, vir_bytes pc);
static int read_seg(struct exec_info *execi, off_t off,
- off_t seg_addr, size_t seg_bytes);
+ vir_bytes seg_addr, size_t seg_bytes);
static int exec_restart(int proc_e, int result, vir_bytes pc);
/* Array of loaders for different object formats */
static int read_seg(
struct exec_info *execi, /* various data needed for exec */
off_t off, /* offset in file */
-off_t seg_addr, /* address to load segment */
+vir_bytes seg_addr, /* address to load segment */
size_t seg_bytes /* how much is to be transferred? */
)
{
static int stack_prepare_elf(struct vfs_exec_info *execi,
char *curstack, size_t *frame_len, vir_bytes *vsp, int *extrabase);
static int map_header(struct vfs_exec_info *execi);
-static int read_seg(struct exec_info *execi, off_t off, off_t seg_addr, size_t seg_bytes);
+static int read_seg(struct exec_info *execi, off_t off, vir_bytes seg_addr, size_t seg_bytes);
#define PTRSIZE sizeof(char *) /* Size of pointers in argv[] and envp[]. */
/* Issue request */
r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, ((u64_t)(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;
/*===========================================================================*
* read_seg *
*===========================================================================*/
-static int read_seg(struct exec_info *execi, off_t off, off_t seg_addr, size_t seg_bytes)
+static int read_seg(struct exec_info *execi, off_t off, vir_bytes seg_addr, size_t seg_bytes)
{
/*
* The byte count on read is usually smaller than the segment count, because
if ((unsigned long) vp->v_size < off+seg_bytes) return(EIO);
if ((r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, ((u64_t)(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);
execi->args.hdr = hdr;
r = req_readwrite(execi->vp->v_fs_e, execi->vp->v_inode_nr,
- ((u64_t)(pos)), READING, VFS_PROC_NR, hdr,
+ ((u64_t)(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");
#include <string.h>
#include <minix/com.h>
#include <minix/callnr.h>
+#include <minix/config.h> /* Remove with version check in do_truncate */
#include <minix/vfsif.h>
#include <dirent.h>
#include <assert.h>
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);
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)
*/
#include "fs.h"
+#include <minix/callnr.h>
#include <minix/com.h>
#include <minix/u64.h>
#include <fcntl.h>
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. */
}
/* 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);
}
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) {
return(r);
}
+/*===========================================================================*
+ * actual_lseek *
+ *===========================================================================*/
int actual_lseek(message *m_out, int seekfd, int seekwhence, off_t offset)
{
/* Perform the lseek(ls_fd, offset, whence) system call. */
default: unlock_filp(rfilp); return(EINVAL);
}
- if (offset >= 0)
- newpos = pos + offset;
- else
- newpos = sub64ul(pos, -offset);
-
- /* Check for overflow. */
- if (ex64hi(newpos) != 0) {
- r = EOVERFLOW;
- } else if ((off_t) ex64lo(newpos) < 0) { /* no negative file size */
+ 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;
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 */
int common_open(char path[PATH_MAX], int oflags, mode_t omode);
int do_creat(void);
int do_lseek(message *m_out);
+int do_lseek321(message *m_out);
int do_llseek(message *m_out);
int do_mknod(message *m_out);
int do_mkdir(message *m_out);
/* 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);
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);
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_bpeek(endpoint_t fs_e, dev_t dev, u64_t pos, unsigned int num_of_bytes);
int req_peek(endpoint_t fs_e, ino_t inode_nr, u64_t pos, unsigned int bytes);
if(rw_flag == PEEKING) {
r = req_bpeek(vp->v_bfs_e, vp->v_sdev, position, size);
} else {
- r = req_breadwrite(vp->v_bfs_e, for_e, vp->v_sdev,
- position, size, buf, rw_flag, &res_pos, &res_cum_io);
+ r = req_breadwrite(vp->v_bfs_e, for_e, vp->v_sdev, position,
+ size, (vir_bytes) buf, rw_flag, &res_pos, &res_cum_io);
if (r == OK) {
position = res_pos;
cum_io += res_cum_io;
} else {
u64_t new_pos;
r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, position,
- rw_flag, for_e, buf, size, &new_pos, &cum_io_incr);
+ rw_flag, for_e, (vir_bytes) buf, size, &new_pos,
+ &cum_io_incr);
if (r >= 0) {
if (ex64hi(new_pos))
int do_getdents(message *UNUSED(m_out))
{
/* 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;
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;
}
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);
*/
#include "fs.h"
-#include <string.h>
-#include <assert.h>
-#include <sys/stat.h>
-#include <sys/statfs.h>
-#include <sys/statvfs.h>
-#include <minix/vfsif.h>
#include <minix/com.h>
#include <minix/const.h>
#include <minix/endpoint.h>
#include <minix/u64.h>
+#include <minix/vfsif.h>
+#include <sys/dirent.h>
+#include <sys/stat.h>
+#include <sys/statfs.h>
+#include <sys/statvfs.h>
+#include <assert.h>
+#include <stddef.h>
+#include <string.h>
#include <unistd.h>
#include <time.h>
#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 *
*===========================================================================*/
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
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");
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)
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 = ((u64_t)(m.RES_SEEK_POS_LO));
- r = m.RES_NBYTES;
+ *new_pos = ((u64_t)(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 *
*===========================================================================*/
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;
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;
if (ex64hi(pos) != 0)
panic("req_readwrite: pos too large");
- 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_readwrite: cpf_grant_magic failed");
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 */
do_chown, /* 16 = chown */
no_sys, /* 17 = break */
no_sys, /* 18 = unused (was old stat)*/
- do_lseek, /* 19 = lseek */
+ no_sys, /* 19 = unused (was lseek_321)*/
no_sys, /* 20 = getpid */
do_mount, /* 21 = mount */
do_umount, /* 22 = umount */
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) */
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) */
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 */
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) */
no_sys, /* 106 = unused */
no_sys, /* 107 = (getepinfo) */
do_utimens, /* 108 = utimens */
- no_sys, /* 109 = unused */
- no_sys, /* 110 = unused */
+ do_fcntl, /* 109 = fcntl */
+ do_truncate, /* 110 = unused */
no_sys, /* 111 = (srv_kill) */
do_gcov_flush, /* 112 = gcov_flush */
no_sys, /* 113 = (getsid) */
};
static int libexec_copy_physcopy(struct exec_info *execi,
- off_t off, off_t vaddr, size_t len)
+ off_t off, vir_bytes vaddr, size_t len)
{
vir_bytes end;
struct vm_exec_info *ei = execi->opaque;
}
static int libexec_alloc_vm_prealloc(struct exec_info *execi,
- off_t vaddr, size_t len)
+ vir_bytes vaddr, size_t len)
{
boot_alloc(execi, vaddr, len, MF_PREALLOC);
return OK;
}
static int libexec_alloc_vm_ondemand(struct exec_info *execi,
- off_t vaddr, size_t len)
+ vir_bytes vaddr, size_t len)
{
boot_alloc(execi, vaddr, len, 0);
return OK;
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 */
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
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 */
#endif
struct stat {
-# ifdef AVOID_USING_BIG_TYPES
dev_t st_dev; /* inode's device */
mode_t st_mode; /* inode protection mode */
ino_t st_ino; /* inode's number */
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 */
-# else /* !AVOID_USING_BIG_TYPES */
-/* XXX For now MINIX is still using big_xxx_t types; just cut this when the day finally comes! */
- 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 */
-# endif /* AVOID_USING_BIG_TYPES */
#if (_POSIX_C_SOURCE - 0) >= 200809L || (_XOPEN_SOURCE - 0) >= 700 || \
defined(_NETBSD_SOURCE)
struct timespec st_atim; /* time of last access */
off_t st_size; /* file size, in off_t bytes */
off_t st_size_rest;
#else
-# ifdef AVOID_USING_BIG_TYPES
off_t st_size; /* file size, in bytes */
-# else /* !AVOID_USING_BIG_TYPES */ /* XXX also cut here */
- big_off_t st_size; /* file size, in bytes */
-# endif /* AVOID_USING_BIG_TYPES */
#endif
blkcnt_t st_blocks; /* blocks allocated for file */
blksize_t st_blksize; /* optimal blocksize for I/O */
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 */
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
#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 */
#include <time.h>
#ifndef PRIdOFF
-#define PRIdOFF PRId32
+#define PRIdOFF PRId64
#endif
/* what type of file are we dealing with */
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;
}
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;