// SPDX-License-Identifier: GPL-2.0/* * linux/arch/alpha/kernel/osf_sys.c * * Copyright (C) 1995 Linus Torvalds */ /* * This file handles some of the stranger OSF/1 system call interfaces. * Some of the system calls expect a non-C calling standard, others have * special parameter blocks.. */ #include <linux/errno.h>#include <linux/sched/signal.h>#include <linux/sched/mm.h>#include <linux/sched/task_stack.h>#include <linux/sched/cputime.h>#include <linux/kernel.h>#include <linux/mm.h>#include <linux/smp.h>#include <linux/stddef.h>#include <linux/syscalls.h>#include <linux/unistd.h>#include <linux/ptrace.h>#include <linux/user.h>#include <linux/utsname.h>#include <linux/time.h>#include <linux/timex.h>#include <linux/major.h>#include <linux/stat.h>#include <linux/mman.h>#include <linux/shm.h>#include <linux/poll.h>#include <linux/file.h>#include <linux/types.h>#include <linux/ipc.h>#include <linux/namei.h>#include <linux/uio.h>#include <linux/vfs.h>#include <linux/rcupdate.h>#include <linux/slab.h> #include <asm/fpu.h>#include <asm/io.h>#include <linux/uaccess.h>#include <asm/sysinfo.h>#include <asm/thread_info.h>#include <asm/hwrpb.h>#include <asm/processor.h> /* * Brk needs to return an error. Still support Linux's brk(0) query idiom, * which OSF programs just shouldn't be doing. We're still not quite * identical to OSF as we don't return 0 on success, but doing otherwise * would require changes to libc. Hopefully this is good enough. */SYSCALL_DEFINE1(osf_brk, unsigned long, brk){ unsigned long retval = sys_brk(brk); if (brk && brk != retval) retval = -ENOMEM; return retval;} /* * This is pure guess-work.. */SYSCALL_DEFINE4(osf_set_program_attributes, unsigned long, text_start, unsigned long, text_len, unsigned long, bss_start, unsigned long, bss_len){ struct mm_struct *mm; mm = current->mm; mm->end_code = bss_start + bss_len; mm->start_brk = bss_start + bss_len; mm->brk = bss_start + bss_len;#if 0 printk("set_program_attributes(%lx %lx %lx %lx)\n", text_start, text_len, bss_start, bss_len);#endif return 0;} /* * OSF/1 directory handling functions... * * The "getdents()" interface is much more sane: the "basep" stuff is * braindamage (it can't really handle filesystems where the directory * offset differences aren't the same as "d_reclen"). */#define NAME_OFFSET offsetof (struct osf_dirent, d_name) struct osf_dirent { unsigned int d_ino; unsigned short d_reclen; unsigned short d_namlen; char d_name[1];}; struct osf_dirent_callback { struct dir_context ctx; struct osf_dirent __user *dirent; long __user *basep; unsigned int count; int error;}; static intosf_filldir(struct dir_context *ctx, const char *name, int namlen, loff_t offset, u64 ino, unsigned int d_type){ struct osf_dirent __user *dirent; struct osf_dirent_callback *buf = container_of(ctx, struct osf_dirent_callback, ctx); unsigned int reclen = ALIGN(NAME_OFFSET + namlen + 1, sizeof(u32)); unsigned int d_ino; buf->error = -EINVAL; /* only used if we fail */ if (reclen > buf->count) return -EINVAL; d_ino = ino; if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) { buf->error = -EOVERFLOW; return -EOVERFLOW; } if (buf->basep) { if (put_user(offset, buf->basep)) goto Efault; buf->basep = NULL; } dirent = buf->dirent; if (put_user(d_ino, &dirent->d_ino) || put_user(namlen, &dirent->d_namlen) || put_user(reclen, &dirent->d_reclen) || copy_to_user(dirent->d_name, name, namlen) || put_user(0, dirent->d_name + namlen)) goto Efault; dirent = (void __user *)dirent + reclen; buf->dirent = dirent; buf->count -= reclen; return 0;Efault: buf->error = -EFAULT; return -EFAULT;} SYSCALL_DEFINE4(osf_getdirentries, unsigned int, fd, struct osf_dirent __user *, dirent, unsigned int, count, long __user *, basep){ int error; struct fd arg = fdget_pos(fd); struct osf_dirent_callback buf = { .ctx.actor = osf_filldir, .dirent = dirent, .basep = basep, .count = count }; if (!arg.file) return -EBADF; error = iterate_dir(arg.file, &buf.ctx); if (error >= 0) error = buf.error; if (count != buf.count) error = count - buf.count; fdput_pos(arg); return error;} #undef NAME_OFFSET SYSCALL_DEFINE6(osf_mmap, unsigned long, addr, unsigned long, len, unsigned long, prot, unsigned long, flags, unsigned long, fd, unsigned long, off){ unsigned long ret = -EINVAL; #if 0 if (flags & (_MAP_HASSEMAPHORE | _MAP_INHERIT | _MAP_UNALIGNED)) printk("%s: unimplemented OSF mmap flags %04lx\n", current->comm, flags);#endif if ((off + PAGE_ALIGN(len)) < off) goto out; if (off & ~PAGE_MASK) goto out; ret = ksys_mmap_pgoff(addr, len, prot, flags, fd, off >> PAGE_SHIFT); out: return ret;} struct osf_stat { int st_dev; int st_pad1; unsigned st_mode; unsigned short st_nlink; short st_nlink_reserved; unsigned st_uid; unsigned st_gid; int st_rdev; int st_ldev; long st_size; int st_pad2; int st_uatime; int st_pad3; int st_umtime; int st_pad4; int st_uctime; int st_pad5; int st_pad6; unsigned st_flags; unsigned st_gen; long st_spare[4]; unsigned st_ino; int st_ino_reserved; int st_atime; int st_atime_reserved; int st_mtime; int st_mtime_reserved; int st_ctime; int st_ctime_reserved; long st_blksize; long st_blocks;}; /* * The OSF/1 statfs structure is much larger, but this should * match the beginning, at least. */struct osf_statfs { short f_type; short f_flags; int f_fsize; int f_bsize; int f_blocks; int f_bfree; int f_bavail; int f_files; int f_ffree; __kernel_fsid_t f_fsid;}; struct osf_statfs64 { short f_type; short f_flags; int f_pad1; int f_pad2; int f_pad3; int f_pad4; int f_pad5; int f_pad6; int f_pad7; __kernel_fsid_t f_fsid; u_short f_namemax; short f_reserved1; int f_spare[8]; char f_pad8[90]; char f_pad9[90]; long mount_info[10]; u_long f_flags2; long f_spare2[14]; long f_fsize; long f_bsize; long f_blocks; long f_bfree; long f_bavail; long f_files; long f_ffree;}; static intlinux_to_osf_stat(struct kstat *lstat, struct osf_stat __user *osf_stat){ struct osf_stat tmp = { 0 }; tmp.st_dev = lstat->dev; tmp.st_mode = lstat->mode; tmp.st_nlink = lstat->nlink; tmp.st_uid = from_kuid_munged(current_user_ns(), lstat->uid); tmp.st_gid = from_kgid_munged(current_user_ns(), lstat->gid); tmp.st_rdev = lstat->rdev; tmp.st_ldev = lstat->rdev; tmp.st_size = lstat->size; tmp.st_uatime = lstat->atime.tv_nsec / 1000; tmp.st_umtime = lstat->mtime.tv_nsec / 1000; tmp.st_uctime = lstat->ctime.tv_nsec / 1000; tmp.st_ino = lstat->ino; tmp.st_atime = lstat->atime.tv_sec; tmp.st_mtime = lstat->mtime.tv_sec; tmp.st_ctime = lstat->ctime.tv_sec; tmp.st_blksize = lstat->blksize; tmp.st_blocks = lstat->blocks; return copy_to_user(osf_stat, &tmp, sizeof(tmp)) ? -EFAULT : 0;} static intlinux_to_osf_statfs(struct kstatfs *linux_stat, struct osf_statfs __user *osf_stat, unsigned long bufsiz){ struct osf_statfs tmp_stat; tmp_stat.f_type = linux_stat->f_type; tmp_stat.f_flags = 0; /* mount flags */ tmp_stat.f_fsize = linux_stat->f_frsize; tmp_stat.f_bsize = linux_stat->f_bsize; tmp_stat.f_blocks = linux_stat->f_blocks; tmp_stat.f_bfree = linux_stat->f_bfree; tmp_stat.f_bavail = linux_stat->f_bavail; tmp_stat.f_files = linux_stat->f_files; tmp_stat.f_ffree = linux_stat->f_ffree; tmp_stat.f_fsid = linux_stat->f_fsid; if (bufsiz > sizeof(tmp_stat)) bufsiz = sizeof(tmp_stat); return copy_to_user(osf_stat, &tmp_stat, bufsiz) ? -EFAULT : 0;} static intlinux_to_osf_statfs64(struct kstatfs *linux_stat, struct osf_statfs64 __user *osf_stat, unsigned long bufsiz){ struct osf_statfs64 tmp_stat = { 0 }; tmp_stat.f_type = linux_stat->f_type; tmp_stat.f_fsize = linux_stat->f_frsize; tmp_stat.f_bsize = linux_stat->f_bsize; tmp_stat.f_blocks = linux_stat->f_blocks; tmp_stat.f_bfree = linux_stat->f_bfree; tmp_stat.f_bavail = linux_stat->f_bavail; tmp_stat.f_files = linux_stat->f_files; tmp_stat.f_ffree = linux_stat->f_ffree; tmp_stat.f_fsid = linux_stat->f_fsid; if (bufsiz > sizeof(tmp_stat)) bufsiz = sizeof(tmp_stat); return copy_to_user(osf_stat, &tmp_stat, bufsiz) ? -EFAULT : 0;} SYSCALL_DEFINE3(osf_statfs, const char __user *, pathname, struct osf_statfs __user *, buffer, unsigned long, bufsiz){ struct kstatfs linux_stat; int error = user_statfs(pathname, &linux_stat); if (!error) error = linux_to_osf_statfs(&linux_stat, buffer, bufsiz); return error; } SYSCALL_DEFINE2(osf_stat, char __user *, name, struct osf_stat __user *, buf){ struct kstat stat; int error; error = vfs_stat(name, &stat); if (error) return error; return linux_to_osf_stat(&stat, buf);} SYSCALL_DEFINE2(osf_lstat, char __user *, name, struct osf_stat __user *, buf){ struct kstat stat; int error; error = vfs_lstat(name, &stat); if (error) return error; return linux_to_osf_stat(&stat, buf);} SYSCALL_DEFINE2(osf_fstat, int, fd, struct osf_stat __user *, buf){ struct kstat stat; int error; error = vfs_fstat(fd, &stat); if (error) return error; return linux_to_osf_stat(&stat, buf);} SYSCALL_DEFINE3(osf_fstatfs, unsigned long, fd, struct osf_statfs __user *, buffer, unsigned long, bufsiz){ struct kstatfs linux_stat; int error = fd_statfs(fd, &linux_stat); if (!error) error = linux_to_osf_statfs(&linux_stat, buffer, bufsiz); return error;} SYSCALL_DEFINE3(osf_statfs64, char __user *, pathname, struct osf_statfs64 __user *, buffer, unsigned long, bufsiz){ struct kstatfs linux_stat; int error = user_statfs(pathname, &linux_stat); if (!error) error = linux_to_osf_statfs64(&linux_stat, buffer, bufsiz); return error;} SYSCALL_DEFINE3(osf_fstatfs64, unsigned long, fd, struct osf_statfs64 __user *, buffer, unsigned long, bufsiz){ struct kstatfs linux_stat; int error = fd_statfs(fd, &linux_stat); if (!error) error = linux_to_osf_statfs64(&linux_stat, buffer, bufsiz); return error;} /* * Uhh.. OSF/1 mount parameters aren't exactly obvious.. * * Although to be frank, neither are the native Linux/i386 ones.. */struct ufs_args { char __user *devname; int flags; uid_t exroot;}; struct cdfs_args { char __user *devname; int flags; uid_t exroot; /* This has lots more here, which Linux handles with the option block but I'm too lazy to do the translation into ASCII. */}; struct procfs_args { char __user *devname; int flags; uid_t exroot;}; /* * We can't actually handle ufs yet, so we translate UFS mounts to * ext2fs mounts. I wouldn't mind a UFS filesystem, but the UFS * layout is so braindead it's a major headache doing it. * * Just how long ago was it written? OTOH our UFS driver may be still * unhappy with OSF UFS. [CHECKME] */static intosf_ufs_mount(const char __user *dirname, struct ufs_args __user *args, int flags){ int retval; struct cdfs_args tmp; struct filename *devname; retval = -EFAULT; if (copy_from_user(&tmp, args, sizeof(tmp))) goto out; devname = getname(tmp.devname); retval = PTR_ERR(devname); if (IS_ERR(devname)) goto out; retval = do_mount(devname->name, dirname, "ext2", flags, NULL); putname(devname); out: return retval;} static intosf_cdfs_mount(const char __user *dirname, struct cdfs_args __user *args, int flags){ int retval; struct cdfs_args tmp; struct filename *devname; retval = -EFAULT; if (copy_from_user(&tmp, args, sizeof(tmp))) goto out; devname = getname(tmp.devname); retval = PTR_ERR(devname); if (IS_ERR(devname)) goto out; retval = do_mount(devname->name, dirname, "iso9660", flags, NULL); putname(devname); out: return retval;} static intosf_procfs_mount(const char __user *dirname, struct procfs_args __user *args, int flags){ struct procfs_args tmp; Lines 1–500 of 1369. Load more
// SPDX-License-Identifier: GPL-2.0 /* * linux/arch/alpha/kernel/osf_sys.c * * Copyright (C) 1995 Linus Torvalds */ /* * This file handles some of the stranger OSF/1 system call interfaces. * Some of the system calls expect a non-C calling standard, others have * special parameter blocks.. */ #include <linux/errno.h> #include <linux/sched/signal.h> #include <linux/sched/mm.h> #include <linux/sched/task_stack.h> #include <linux/sched/cputime.h> #include <linux/kernel.h> #include <linux/mm.h> #include <linux/smp.h> #include <linux/stddef.h> #include <linux/syscalls.h> #include <linux/unistd.h> #include <linux/ptrace.h> #include <linux/user.h> #include <linux/utsname.h> #include <linux/time.h> #include <linux/timex.h> #include <linux/major.h> #include <linux/stat.h> #include <linux/mman.h> #include <linux/shm.h> #include <linux/poll.h> #include <linux/file.h> #include <linux/types.h> #include <linux/ipc.h> #include <linux/namei.h> #include <linux/uio.h> #include <linux/vfs.h> #include <linux/rcupdate.h> #include <linux/slab.h> #include <asm/fpu.h> #include <asm/io.h> #include <linux/uaccess.h> #include <asm/sysinfo.h> #include <asm/thread_info.h> #include <asm/hwrpb.h> #include <asm/processor.h> /* * Brk needs to return an error. Still support Linux's brk(0) query idiom, * which OSF programs just shouldn't be doing. We're still not quite * identical to OSF as we don't return 0 on success, but doing otherwise * would require changes to libc. Hopefully this is good enough. */ SYSCALL_DEFINE1(osf_brk, unsigned long, brk) { unsigned long retval = sys_brk(brk); if (brk && brk != retval) retval = -ENOMEM; return retval; } /* * This is pure guess-work.. */ SYSCALL_DEFINE4(osf_set_program_attributes, unsigned long, text_start, unsigned long, text_len, unsigned long, bss_start, unsigned long, bss_len) { struct mm_struct *mm; mm = current->mm; mm->end_code = bss_start + bss_len; mm->start_brk = bss_start + bss_len; mm->brk = bss_start + bss_len; #if 0 printk("set_program_attributes(%lx %lx %lx %lx)\n", text_start, text_len, bss_start, bss_len); #endif return 0; } /* * OSF/1 directory handling functions... * * The "getdents()" interface is much more sane: the "basep" stuff is * braindamage (it can't really handle filesystems where the directory * offset differences aren't the same as "d_reclen"). */ #define NAME_OFFSET offsetof (struct osf_dirent, d_name) struct osf_dirent { unsigned int d_ino; unsigned short d_reclen; unsigned short d_namlen; char d_name[1]; }; struct osf_dirent_callback { struct dir_context ctx; struct osf_dirent __user *dirent; long __user *basep; unsigned int count; int error; }; static int osf_filldir(struct dir_context *ctx, const char *name, int namlen, loff_t offset, u64 ino, unsigned int d_type) { struct osf_dirent __user *dirent; struct osf_dirent_callback *buf = container_of(ctx, struct osf_dirent_callback, ctx); unsigned int reclen = ALIGN(NAME_OFFSET + namlen + 1, sizeof(u32)); unsigned int d_ino; buf->error = -EINVAL; /* only used if we fail */ if (reclen > buf->count) return -EINVAL; d_ino = ino; if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) { buf->error = -EOVERFLOW; return -EOVERFLOW; } if (buf->basep) { if (put_user(offset, buf->basep)) goto Efault; buf->basep = NULL; } dirent = buf->dirent; if (put_user(d_ino, &dirent->d_ino) || put_user(namlen, &dirent->d_namlen) || put_user(reclen, &dirent->d_reclen) || copy_to_user(dirent->d_name, name, namlen) || put_user(0, dirent->d_name + namlen)) goto Efault; dirent = (void __user *)dirent + reclen; buf->dirent = dirent; buf->count -= reclen; return 0; Efault: buf->error = -EFAULT; return -EFAULT; } SYSCALL_DEFINE4(osf_getdirentries, unsigned int, fd, struct osf_dirent __user *, dirent, unsigned int, count, long __user *, basep) { int error; struct fd arg = fdget_pos(fd); struct osf_dirent_callback buf = { .ctx.actor = osf_filldir, .dirent = dirent, .basep = basep, .count = count }; if (!arg.file) return -EBADF; error = iterate_dir(arg.file, &buf.ctx); if (error >= 0) error = buf.error; if (count != buf.count) error = count - buf.count; fdput_pos(arg); return error; } #undef NAME_OFFSET SYSCALL_DEFINE6(osf_mmap, unsigned long, addr, unsigned long, len, unsigned long, prot, unsigned long, flags, unsigned long, fd, unsigned long, off) { unsigned long ret = -EINVAL; #if 0 if (flags & (_MAP_HASSEMAPHORE | _MAP_INHERIT | _MAP_UNALIGNED)) printk("%s: unimplemented OSF mmap flags %04lx\n", current->comm, flags); #endif if ((off + PAGE_ALIGN(len)) < off) goto out; if (off & ~PAGE_MASK) goto out; ret = ksys_mmap_pgoff(addr, len, prot, flags, fd, off >> PAGE_SHIFT); out: return ret; } struct osf_stat { int st_dev; int st_pad1; unsigned st_mode; unsigned short st_nlink; short st_nlink_reserved; unsigned st_uid; unsigned st_gid; int st_rdev; int st_ldev; long st_size; int st_pad2; int st_uatime; int st_pad3; int st_umtime; int st_pad4; int st_uctime; int st_pad5; int st_pad6; unsigned st_flags; unsigned st_gen; long st_spare[4]; unsigned st_ino; int st_ino_reserved; int st_atime; int st_atime_reserved; int st_mtime; int st_mtime_reserved; int st_ctime; int st_ctime_reserved; long st_blksize; long st_blocks; }; /* * The OSF/1 statfs structure is much larger, but this should * match the beginning, at least. */ struct osf_statfs { short f_type; short f_flags; int f_fsize; int f_bsize; int f_blocks; int f_bfree; int f_bavail; int f_files; int f_ffree; __kernel_fsid_t f_fsid; }; struct osf_statfs64 { short f_type; short f_flags; int f_pad1; int f_pad2; int f_pad3; int f_pad4; int f_pad5; int f_pad6; int f_pad7; __kernel_fsid_t f_fsid; u_short f_namemax; short f_reserved1; int f_spare[8]; char f_pad8[90]; char f_pad9[90]; long mount_info[10]; u_long f_flags2; long f_spare2[14]; long f_fsize; long f_bsize; long f_blocks; long f_bfree; long f_bavail; long f_files; long f_ffree; }; static int linux_to_osf_stat(struct kstat *lstat, struct osf_stat __user *osf_stat) { struct osf_stat tmp = { 0 }; tmp.st_dev = lstat->dev; tmp.st_mode = lstat->mode; tmp.st_nlink = lstat->nlink; tmp.st_uid = from_kuid_munged(current_user_ns(), lstat->uid); tmp.st_gid = from_kgid_munged(current_user_ns(), lstat->gid); tmp.st_rdev = lstat->rdev; tmp.st_ldev = lstat->rdev; tmp.st_size = lstat->size; tmp.st_uatime = lstat->atime.tv_nsec / 1000; tmp.st_umtime = lstat->mtime.tv_nsec / 1000; tmp.st_uctime = lstat->ctime.tv_nsec / 1000; tmp.st_ino = lstat->ino; tmp.st_atime = lstat->atime.tv_sec; tmp.st_mtime = lstat->mtime.tv_sec; tmp.st_ctime = lstat->ctime.tv_sec; tmp.st_blksize = lstat->blksize; tmp.st_blocks = lstat->blocks; return copy_to_user(osf_stat, &tmp, sizeof(tmp)) ? -EFAULT : 0; } static int linux_to_osf_statfs(struct kstatfs *linux_stat, struct osf_statfs __user *osf_stat, unsigned long bufsiz) { struct osf_statfs tmp_stat; tmp_stat.f_type = linux_stat->f_type; tmp_stat.f_flags = 0; /* mount flags */ tmp_stat.f_fsize = linux_stat->f_frsize; tmp_stat.f_bsize = linux_stat->f_bsize; tmp_stat.f_blocks = linux_stat->f_blocks; tmp_stat.f_bfree = linux_stat->f_bfree; tmp_stat.f_bavail = linux_stat->f_bavail; tmp_stat.f_files = linux_stat->f_files; tmp_stat.f_ffree = linux_stat->f_ffree; tmp_stat.f_fsid = linux_stat->f_fsid; if (bufsiz > sizeof(tmp_stat)) bufsiz = sizeof(tmp_stat); return copy_to_user(osf_stat, &tmp_stat, bufsiz) ? -EFAULT : 0; } static int linux_to_osf_statfs64(struct kstatfs *linux_stat, struct osf_statfs64 __user *osf_stat, unsigned long bufsiz) { struct osf_statfs64 tmp_stat = { 0 }; tmp_stat.f_type = linux_stat->f_type; tmp_stat.f_fsize = linux_stat->f_frsize; tmp_stat.f_bsize = linux_stat->f_bsize; tmp_stat.f_blocks = linux_stat->f_blocks; tmp_stat.f_bfree = linux_stat->f_bfree; tmp_stat.f_bavail = linux_stat->f_bavail; tmp_stat.f_files = linux_stat->f_files; tmp_stat.f_ffree = linux_stat->f_ffree; tmp_stat.f_fsid = linux_stat->f_fsid; if (bufsiz > sizeof(tmp_stat)) bufsiz = sizeof(tmp_stat); return copy_to_user(osf_stat, &tmp_stat, bufsiz) ? -EFAULT : 0; } SYSCALL_DEFINE3(osf_statfs, const char __user *, pathname, struct osf_statfs __user *, buffer, unsigned long, bufsiz) { struct kstatfs linux_stat; int error = user_statfs(pathname, &linux_stat); if (!error) error = linux_to_osf_statfs(&linux_stat, buffer, bufsiz); return error; } SYSCALL_DEFINE2(osf_stat, char __user *, name, struct osf_stat __user *, buf) { struct kstat stat; int error; error = vfs_stat(name, &stat); if (error) return error; return linux_to_osf_stat(&stat, buf); } SYSCALL_DEFINE2(osf_lstat, char __user *, name, struct osf_stat __user *, buf) { struct kstat stat; int error; error = vfs_lstat(name, &stat); if (error) return error; return linux_to_osf_stat(&stat, buf); } SYSCALL_DEFINE2(osf_fstat, int, fd, struct osf_stat __user *, buf) { struct kstat stat; int error; error = vfs_fstat(fd, &stat); if (error) return error; return linux_to_osf_stat(&stat, buf); } SYSCALL_DEFINE3(osf_fstatfs, unsigned long, fd, struct osf_statfs __user *, buffer, unsigned long, bufsiz) { struct kstatfs linux_stat; int error = fd_statfs(fd, &linux_stat); if (!error) error = linux_to_osf_statfs(&linux_stat, buffer, bufsiz); return error; } SYSCALL_DEFINE3(osf_statfs64, char __user *, pathname, struct osf_statfs64 __user *, buffer, unsigned long, bufsiz) { struct kstatfs linux_stat; int error = user_statfs(pathname, &linux_stat); if (!error) error = linux_to_osf_statfs64(&linux_stat, buffer, bufsiz); return error; } SYSCALL_DEFINE3(osf_fstatfs64, unsigned long, fd, struct osf_statfs64 __user *, buffer, unsigned long, bufsiz) { struct kstatfs linux_stat; int error = fd_statfs(fd, &linux_stat); if (!error) error = linux_to_osf_statfs64(&linux_stat, buffer, bufsiz); return error; } /* * Uhh.. OSF/1 mount parameters aren't exactly obvious.. * * Although to be frank, neither are the native Linux/i386 ones.. */ struct ufs_args { char __user *devname; int flags; uid_t exroot; }; struct cdfs_args { char __user *devname; int flags; uid_t exroot; /* This has lots more here, which Linux handles with the option block but I'm too lazy to do the translation into ASCII. */ }; struct procfs_args { char __user *devname; int flags; uid_t exroot; }; /* * We can't actually handle ufs yet, so we translate UFS mounts to * ext2fs mounts. I wouldn't mind a UFS filesystem, but the UFS * layout is so braindead it's a major headache doing it. * * Just how long ago was it written? OTOH our UFS driver may be still * unhappy with OSF UFS. [CHECKME] */ static int osf_ufs_mount(const char __user *dirname, struct ufs_args __user *args, int flags) { int retval; struct cdfs_args tmp; struct filename *devname; retval = -EFAULT; if (copy_from_user(&tmp, args, sizeof(tmp))) goto out; devname = getname(tmp.devname); retval = PTR_ERR(devname); if (IS_ERR(devname)) goto out; retval = do_mount(devname->name, dirname, "ext2", flags, NULL); putname(devname); out: return retval; } static int osf_cdfs_mount(const char __user *dirname, struct cdfs_args __user *args, int flags) { int retval; struct cdfs_args tmp; struct filename *devname; retval = -EFAULT; if (copy_from_user(&tmp, args, sizeof(tmp))) goto out; devname = getname(tmp.devname); retval = PTR_ERR(devname); if (IS_ERR(devname)) goto out; retval = do_mount(devname->name, dirname, "iso9660", flags, NULL); putname(devname); out: return retval; } static int osf_procfs_mount(const char __user *dirname, struct procfs_args __user *args, int flags) { struct procfs_args tmp;