linux-old/arch/sparc64/solaris/fs.c
<<
>>
Prefs
   1/* $Id: fs.c,v 1.25 2001/09/19 00:04:30 davem Exp $
   2 * fs.c: fs related syscall emulation for Solaris
   3 *
   4 * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
   5 *
   6 * 1999-08-19 Implemented solaris F_FREESP (truncate)
   7 *            fcntl, by Jason Rappleye (rappleye@ccr.buffalo.edu)
   8 */
   9
  10#include <linux/types.h>
  11#include <linux/sched.h>
  12#include <linux/slab.h>
  13#include <linux/fs.h>
  14#include <linux/mm.h>
  15#include <linux/file.h>
  16#include <linux/stat.h>
  17#include <linux/smp_lock.h>
  18#include <linux/limits.h>
  19#include <linux/resource.h>
  20#include <linux/quotaops.h>
  21
  22#include <asm/uaccess.h>
  23#include <asm/string.h>
  24#include <asm/ptrace.h>
  25
  26#include "conv.h"
  27
  28#define R4_DEV(DEV) ((DEV & 0xff) | ((DEV & 0xff00) << 10))
  29#define R4_MAJOR(DEV) (((DEV) >> 18) & 0x3fff)
  30#define R4_MINOR(DEV) ((DEV) & 0x3ffff)
  31#define R3_VERSION      1
  32#define R4_VERSION      2
  33
  34typedef struct {
  35        s32     tv_sec;
  36        s32     tv_nsec;
  37} timestruct_t;
  38
  39struct sol_stat {
  40        u32             st_dev;
  41        s32             st_pad1[3];     /* network id */
  42        u32             st_ino;
  43        u32             st_mode;
  44        u32             st_nlink;
  45        u32             st_uid;
  46        u32             st_gid;
  47        u32             st_rdev;
  48        s32             st_pad2[2];
  49        s32             st_size;
  50        s32             st_pad3;        /* st_size, off_t expansion */
  51        timestruct_t    st_atime;
  52        timestruct_t    st_mtime;
  53        timestruct_t    st_ctime;
  54        s32             st_blksize;
  55        s32             st_blocks;
  56        char            st_fstype[16];
  57        s32             st_pad4[8];     /* expansion area */
  58};
  59
  60struct sol_stat64 {
  61        u32             st_dev;
  62        s32             st_pad1[3];     /* network id */
  63        u64             st_ino;
  64        u32             st_mode;
  65        u32             st_nlink;
  66        u32             st_uid;
  67        u32             st_gid;
  68        u32             st_rdev;
  69        s32             st_pad2[2];
  70        s64             st_size;
  71        timestruct_t    st_atime;
  72        timestruct_t    st_mtime;
  73        timestruct_t    st_ctime;
  74        s64             st_blksize;
  75        s32             st_blocks;
  76        char            st_fstype[16];
  77        s32             st_pad4[4];     /* expansion area */
  78};
  79
  80#define UFSMAGIC (((unsigned)'u'<<24)||((unsigned)'f'<<16)||((unsigned)'s'<<8))
  81
  82static inline int putstat(struct sol_stat *ubuf, struct stat *kbuf)
  83{
  84        if (put_user (R4_DEV(kbuf->st_dev), &ubuf->st_dev)      ||
  85            __put_user (kbuf->st_ino, &ubuf->st_ino)            ||
  86            __put_user (kbuf->st_mode, &ubuf->st_mode)          ||
  87            __put_user (kbuf->st_nlink, &ubuf->st_nlink)        ||
  88            __put_user (kbuf->st_uid, &ubuf->st_uid)            ||
  89            __put_user (kbuf->st_gid, &ubuf->st_gid)            ||
  90            __put_user (R4_DEV(kbuf->st_rdev), &ubuf->st_rdev)  ||
  91            __put_user (kbuf->st_size, &ubuf->st_size)          ||
  92            __put_user (kbuf->st_atime, &ubuf->st_atime.tv_sec) ||
  93            __put_user (0, &ubuf->st_atime.tv_nsec)             ||
  94            __put_user (kbuf->st_mtime, &ubuf->st_mtime.tv_sec) ||
  95            __put_user (0, &ubuf->st_mtime.tv_nsec)             ||
  96            __put_user (kbuf->st_ctime, &ubuf->st_ctime.tv_sec) ||
  97            __put_user (0, &ubuf->st_ctime.tv_nsec)             ||
  98            __put_user (kbuf->st_blksize, &ubuf->st_blksize)    ||
  99            __put_user (kbuf->st_blocks, &ubuf->st_blocks)      ||
 100            __put_user (UFSMAGIC, (unsigned *)ubuf->st_fstype))
 101                return -EFAULT;
 102        return 0;
 103}
 104
 105static inline int putstat64(struct sol_stat64 *ubuf, struct stat *kbuf)
 106{
 107        if (put_user (R4_DEV(kbuf->st_dev), &ubuf->st_dev)      ||
 108            __put_user (kbuf->st_ino, &ubuf->st_ino)            ||
 109            __put_user (kbuf->st_mode, &ubuf->st_mode)          ||
 110            __put_user (kbuf->st_nlink, &ubuf->st_nlink)        ||
 111            __put_user (kbuf->st_uid, &ubuf->st_uid)            ||
 112            __put_user (kbuf->st_gid, &ubuf->st_gid)            ||
 113            __put_user (R4_DEV(kbuf->st_rdev), &ubuf->st_rdev)  ||
 114            __put_user (kbuf->st_size, &ubuf->st_size)          ||
 115            __put_user (kbuf->st_atime, &ubuf->st_atime.tv_sec) ||
 116            __put_user (0, &ubuf->st_atime.tv_nsec)             ||
 117            __put_user (kbuf->st_mtime, &ubuf->st_mtime.tv_sec) ||
 118            __put_user (0, &ubuf->st_mtime.tv_nsec)             ||
 119            __put_user (kbuf->st_ctime, &ubuf->st_ctime.tv_sec) ||
 120            __put_user (0, &ubuf->st_ctime.tv_nsec)             ||
 121            __put_user (kbuf->st_blksize, &ubuf->st_blksize)    ||
 122            __put_user (kbuf->st_blocks, &ubuf->st_blocks)      ||
 123            __put_user (UFSMAGIC, (unsigned *)ubuf->st_fstype))
 124                return -EFAULT;
 125        return 0;
 126}
 127
 128asmlinkage int solaris_stat(u32 filename, u32 statbuf)
 129{
 130        int ret;
 131        struct stat s;
 132        char *filenam;
 133        mm_segment_t old_fs = get_fs();
 134        int (*sys_newstat)(char *,struct stat *) = 
 135                (int (*)(char *,struct stat *))SYS(stat);
 136        
 137        filenam = getname ((char *)A(filename));
 138        ret = PTR_ERR(filenam);
 139        if (!IS_ERR(filenam)) {
 140                set_fs (KERNEL_DS);
 141                ret = sys_newstat(filenam, &s);
 142                set_fs (old_fs);
 143                putname (filenam);
 144                if (putstat ((struct sol_stat *)A(statbuf), &s))
 145                        return -EFAULT;
 146        }
 147        return ret;
 148}
 149
 150asmlinkage int solaris_xstat(int vers, u32 filename, u32 statbuf)
 151{
 152        /* Solaris doesn't bother with looking at vers, so we do neither */
 153        return solaris_stat(filename, statbuf);
 154}
 155
 156asmlinkage int solaris_stat64(u32 filename, u32 statbuf)
 157{
 158        int ret;
 159        struct stat s;
 160        char *filenam;
 161        mm_segment_t old_fs = get_fs();
 162        int (*sys_newstat)(char *,struct stat *) = 
 163                (int (*)(char *,struct stat *))SYS(stat);
 164        
 165        filenam = getname ((char *)A(filename));
 166        ret = PTR_ERR(filenam);
 167        if (!IS_ERR(filenam)) {
 168                set_fs (KERNEL_DS);
 169                ret = sys_newstat(filenam, &s);
 170                set_fs (old_fs);
 171                putname (filenam);
 172                if (putstat64 ((struct sol_stat64 *)A(statbuf), &s))
 173                        return -EFAULT;
 174        }
 175        return ret;
 176}
 177
 178asmlinkage int solaris_lstat(u32 filename, u32 statbuf)
 179{
 180        int ret;
 181        struct stat s;
 182        char *filenam;
 183        mm_segment_t old_fs = get_fs();
 184        int (*sys_newlstat)(char *,struct stat *) = 
 185                (int (*)(char *,struct stat *))SYS(lstat);
 186        
 187        filenam = getname ((char *)A(filename));
 188        ret = PTR_ERR(filenam);
 189        if (!IS_ERR(filenam)) {
 190                set_fs (KERNEL_DS);
 191                ret = sys_newlstat(filenam, &s);
 192                set_fs (old_fs);
 193                putname (filenam);
 194                if (putstat ((struct sol_stat *)A(statbuf), &s))
 195                        return -EFAULT;
 196        }
 197        return ret;
 198}
 199
 200asmlinkage int solaris_lxstat(int vers, u32 filename, u32 statbuf)
 201{
 202        return solaris_lstat(filename, statbuf);
 203}
 204
 205asmlinkage int solaris_lstat64(u32 filename, u32 statbuf)
 206{
 207        int ret;
 208        struct stat s;
 209        char *filenam;
 210        mm_segment_t old_fs = get_fs();
 211        int (*sys_newlstat)(char *,struct stat *) = 
 212                (int (*)(char *,struct stat *))SYS(lstat);
 213        
 214        filenam = getname ((char *)A(filename));
 215        ret = PTR_ERR(filenam);
 216        if (!IS_ERR(filenam)) {
 217                set_fs (KERNEL_DS);
 218                ret = sys_newlstat(filenam, &s);
 219                set_fs (old_fs);
 220                putname (filenam);
 221                if (putstat64 ((struct sol_stat64 *)A(statbuf), &s))
 222                        return -EFAULT;
 223        }
 224        return ret;
 225}
 226
 227asmlinkage int solaris_fstat(unsigned int fd, u32 statbuf)
 228{
 229        int ret;
 230        struct stat s;
 231        mm_segment_t old_fs = get_fs();
 232        int (*sys_newfstat)(unsigned,struct stat *) = 
 233                (int (*)(unsigned,struct stat *))SYS(fstat);
 234        
 235        set_fs (KERNEL_DS);
 236        ret = sys_newfstat(fd, &s);
 237        set_fs (old_fs);
 238        if (putstat ((struct sol_stat *)A(statbuf), &s))
 239                return -EFAULT;
 240        return ret;
 241}
 242
 243asmlinkage int solaris_fxstat(int vers, u32 fd, u32 statbuf)
 244{
 245        return solaris_fstat(fd, statbuf);
 246}
 247
 248asmlinkage int solaris_fstat64(unsigned int fd, u32 statbuf)
 249{
 250        int ret;
 251        struct stat s;
 252        mm_segment_t old_fs = get_fs();
 253        int (*sys_newfstat)(unsigned,struct stat *) = 
 254                (int (*)(unsigned,struct stat *))SYS(fstat);
 255        
 256        set_fs (KERNEL_DS);
 257        ret = sys_newfstat(fd, &s);
 258        set_fs (old_fs);
 259        if (putstat64 ((struct sol_stat64 *)A(statbuf), &s))
 260                return -EFAULT;
 261        return ret;
 262}
 263
 264asmlinkage int solaris_mknod(u32 path, u32 mode, s32 dev)
 265{
 266        int (*sys_mknod)(const char *,int,dev_t) = 
 267                (int (*)(const char *,int,dev_t))SYS(mknod);
 268        int major, minor;
 269
 270        if ((major = R4_MAJOR(dev)) > 255 || 
 271            (minor = R4_MINOR(dev)) > 255) return -EINVAL;
 272        return sys_mknod((const char *)A(path), mode, MKDEV(major,minor));
 273}
 274
 275asmlinkage int solaris_xmknod(int vers, u32 path, u32 mode, s32 dev)
 276{
 277        return solaris_mknod(path, mode, dev);
 278}
 279
 280asmlinkage int solaris_getdents64(unsigned int fd, void *dirent, unsigned int count)
 281{
 282        int (*sys_getdents)(unsigned int, void *, unsigned int) =
 283                (int (*)(unsigned int, void *, unsigned int))SYS(getdents);
 284                
 285        return sys_getdents(fd, dirent, count);
 286}
 287
 288/* This statfs thingie probably will go in the near future, but... */
 289
 290struct sol_statfs {
 291        short   f_type;
 292        s32     f_bsize;
 293        s32     f_frsize;
 294        s32     f_blocks;
 295        s32     f_bfree;
 296        u32     f_files;
 297        u32     f_ffree;
 298        char    f_fname[6];
 299        char    f_fpack[6];
 300};
 301
 302asmlinkage int solaris_statfs(u32 path, u32 buf, int len, int fstype)
 303{
 304        int ret;
 305        struct statfs s;
 306        mm_segment_t old_fs = get_fs();
 307        int (*sys_statfs)(const char *,struct statfs *) = 
 308                (int (*)(const char *,struct statfs *))SYS(statfs);
 309        struct sol_statfs *ss = (struct sol_statfs *)A(buf);
 310        
 311        if (len != sizeof(struct sol_statfs)) return -EINVAL;
 312        if (!fstype) {
 313                set_fs (KERNEL_DS);
 314                ret = sys_statfs((const char *)A(path), &s);
 315                set_fs (old_fs);
 316                if (!ret) {
 317                        if (put_user (s.f_type, &ss->f_type)            ||
 318                            __put_user (s.f_bsize, &ss->f_bsize)        ||
 319                            __put_user (0, &ss->f_frsize)               ||
 320                            __put_user (s.f_blocks, &ss->f_blocks)      ||
 321                            __put_user (s.f_bfree, &ss->f_bfree)        ||
 322                            __put_user (s.f_files, &ss->f_files)        ||
 323                            __put_user (s.f_ffree, &ss->f_ffree)        ||
 324                            __clear_user (&ss->f_fname, 12))
 325                                return -EFAULT;
 326                }
 327                return ret;
 328        }
 329/* Linux can't stat unmounted filesystems so we
 330 * simply lie and claim 100MB of 1GB is free. Sorry.
 331 */
 332        if (put_user (fstype, &ss->f_type)              ||
 333            __put_user (1024, &ss->f_bsize)             ||
 334            __put_user (0, &ss->f_frsize)               ||
 335            __put_user (1024*1024, &ss->f_blocks)       ||
 336            __put_user (100*1024, &ss->f_bfree)         ||
 337            __put_user (60000, &ss->f_files)            ||
 338            __put_user (50000, &ss->f_ffree)            ||
 339            __clear_user (&ss->f_fname, 12))
 340                return -EFAULT;
 341        return 0;
 342}
 343
 344asmlinkage int solaris_fstatfs(u32 fd, u32 buf, int len, int fstype)
 345{
 346        int ret;
 347        struct statfs s;
 348        mm_segment_t old_fs = get_fs();
 349        int (*sys_fstatfs)(unsigned,struct statfs *) = 
 350                (int (*)(unsigned,struct statfs *))SYS(fstatfs);
 351        struct sol_statfs *ss = (struct sol_statfs *)A(buf);
 352        
 353        if (len != sizeof(struct sol_statfs)) return -EINVAL;
 354        if (!fstype) {
 355                set_fs (KERNEL_DS);
 356                ret = sys_fstatfs(fd, &s);
 357                set_fs (old_fs);
 358                if (!ret) {
 359                        if (put_user (s.f_type, &ss->f_type)            ||
 360                            __put_user (s.f_bsize, &ss->f_bsize)        ||
 361                            __put_user (0, &ss->f_frsize)               ||
 362                            __put_user (s.f_blocks, &ss->f_blocks)      ||
 363                            __put_user (s.f_bfree, &ss->f_bfree)        ||
 364                            __put_user (s.f_files, &ss->f_files)        ||
 365                            __put_user (s.f_ffree, &ss->f_ffree)        ||
 366                            __clear_user (&ss->f_fname, 12))
 367                                return -EFAULT;
 368                }
 369                return ret;
 370        }
 371        /* Otherwise fstatfs is the same as statfs */
 372        return solaris_statfs(0, buf, len, fstype);
 373}
 374
 375struct sol_statvfs {
 376        u32     f_bsize;
 377        u32     f_frsize;
 378        u32     f_blocks;
 379        u32     f_bfree;
 380        u32     f_bavail;
 381        u32     f_files;
 382        u32     f_ffree;
 383        u32     f_favail;
 384        u32     f_fsid;
 385        char    f_basetype[16];
 386        u32     f_flag;
 387        u32     f_namemax;
 388        char    f_fstr[32];
 389        u32     f_filler[16];
 390};
 391
 392struct sol_statvfs64 {
 393        u32     f_bsize;
 394        u32     f_frsize;
 395        u64     f_blocks;
 396        u64     f_bfree;
 397        u64     f_bavail;
 398        u64     f_files;
 399        u64     f_ffree;
 400        u64     f_favail;
 401        u32     f_fsid;
 402        char    f_basetype[16];
 403        u32     f_flag;
 404        u32     f_namemax;
 405        char    f_fstr[32];
 406        u32     f_filler[16];
 407};
 408
 409static int report_statvfs(struct vfsmount *mnt, struct inode *inode, u32 buf)
 410{
 411        struct statfs s;
 412        int error;
 413        struct sol_statvfs *ss = (struct sol_statvfs *)A(buf);
 414
 415        error = vfs_statfs(mnt->mnt_sb, &s);
 416        if (!error) {
 417                const char *p = mnt->mnt_sb->s_type->name;
 418                int i = 0;
 419                int j = strlen (p);
 420                
 421                if (j > 15) j = 15;
 422                if (IS_RDONLY(inode)) i = 1;
 423                if (mnt->mnt_flags & MNT_NOSUID) i |= 2;
 424                if (put_user (s.f_bsize, &ss->f_bsize)          ||
 425                    __put_user (0, &ss->f_frsize)               ||
 426                    __put_user (s.f_blocks, &ss->f_blocks)      ||
 427                    __put_user (s.f_bfree, &ss->f_bfree)        ||
 428                    __put_user (s.f_bavail, &ss->f_bavail)      ||
 429                    __put_user (s.f_files, &ss->f_files)        ||
 430                    __put_user (s.f_ffree, &ss->f_ffree)        ||
 431                    __put_user (s.f_ffree, &ss->f_favail)       ||
 432                    __put_user (R4_DEV(inode->i_sb->s_dev), &ss->f_fsid) ||
 433                    __copy_to_user (ss->f_basetype,p,j)         ||
 434                    __put_user (0, (char *)&ss->f_basetype[j])  ||
 435                    __put_user (s.f_namelen, &ss->f_namemax)    ||
 436                    __put_user (i, &ss->f_flag)                 ||                  
 437                    __clear_user (&ss->f_fstr, 32))
 438                        return -EFAULT;
 439        }
 440        return error;
 441}
 442
 443static int report_statvfs64(struct vfsmount *mnt, struct inode *inode, u32 buf)
 444{
 445        struct statfs s;
 446        int error;
 447        struct sol_statvfs64 *ss = (struct sol_statvfs64 *)A(buf);
 448                        
 449        error = vfs_statfs(mnt->mnt_sb, &s);
 450        if (!error) {
 451                const char *p = mnt->mnt_sb->s_type->name;
 452                int i = 0;
 453                int j = strlen (p);
 454                
 455                if (j > 15) j = 15;
 456                if (IS_RDONLY(inode)) i = 1;
 457                if (mnt->mnt_flags & MNT_NOSUID) i |= 2;
 458                if (put_user (s.f_bsize, &ss->f_bsize)          ||
 459                    __put_user (0, &ss->f_frsize)               ||
 460                    __put_user (s.f_blocks, &ss->f_blocks)      ||
 461                    __put_user (s.f_bfree, &ss->f_bfree)        ||
 462                    __put_user (s.f_bavail, &ss->f_bavail)      ||
 463                    __put_user (s.f_files, &ss->f_files)        ||
 464                    __put_user (s.f_ffree, &ss->f_ffree)        ||
 465                    __put_user (s.f_ffree, &ss->f_favail)       ||
 466                    __put_user (R4_DEV(inode->i_sb->s_dev), &ss->f_fsid) ||
 467                    __copy_to_user (ss->f_basetype,p,j)         ||
 468                    __put_user (0, (char *)&ss->f_basetype[j])  ||
 469                    __put_user (s.f_namelen, &ss->f_namemax)    ||
 470                    __put_user (i, &ss->f_flag)                 ||                  
 471                    __clear_user (&ss->f_fstr, 32))
 472                        return -EFAULT;
 473        }
 474        return error;
 475}
 476
 477asmlinkage int solaris_statvfs(u32 path, u32 buf)
 478{
 479        struct nameidata nd;
 480        int error;
 481
 482        error = user_path_walk((const char *)A(path),&nd);
 483        if (!error) {
 484                struct inode * inode = nd.dentry->d_inode;
 485                error = report_statvfs(nd.mnt, inode, buf);
 486                path_release(&nd);
 487        }
 488        return error;
 489}
 490
 491asmlinkage int solaris_fstatvfs(unsigned int fd, u32 buf)
 492{
 493        struct file * file;
 494        int error;
 495
 496        error = -EBADF;
 497        file = fget(fd);
 498        if (file) {
 499                error = report_statvfs(file->f_vfsmnt, file->f_dentry->d_inode, buf);
 500                fput(file);
 501        }
 502
 503        return error;
 504}
 505
 506asmlinkage int solaris_statvfs64(u32 path, u32 buf)
 507{
 508        struct nameidata nd;
 509        int error;
 510
 511        lock_kernel();
 512        error = user_path_walk((const char *)A(path), &nd);
 513        if (!error) {
 514                struct inode * inode = nd.dentry->d_inode;
 515                error = report_statvfs64(nd.mnt, inode, buf);
 516                path_release(&nd);
 517        }
 518        unlock_kernel();
 519        return error;
 520}
 521
 522asmlinkage int solaris_fstatvfs64(unsigned int fd, u32 buf)
 523{
 524        struct file * file;
 525        int error;
 526
 527        error = -EBADF;
 528        file = fget(fd);
 529        if (file) {
 530                lock_kernel();
 531                error = report_statvfs64(file->f_vfsmnt, file->f_dentry->d_inode, buf);
 532                unlock_kernel();
 533                fput(file);
 534        }
 535        return error;
 536}
 537
 538extern asmlinkage long sparc32_open(const char * filename, int flags, int mode);
 539
 540asmlinkage int solaris_open(u32 fname, int flags, u32 mode)
 541{
 542        const char *filename = (const char *)(long)fname;
 543        int fl = flags & 0xf;
 544
 545        /* Translate flags first. */
 546        if (flags & 0x2000) fl |= O_LARGEFILE;
 547        if (flags & 0x8050) fl |= O_SYNC;
 548        if (flags & 0x80) fl |= O_NONBLOCK;
 549        if (flags & 0x100) fl |= O_CREAT;
 550        if (flags & 0x200) fl |= O_TRUNC;
 551        if (flags & 0x400) fl |= O_EXCL;
 552        if (flags & 0x800) fl |= O_NOCTTY;
 553        flags = fl;
 554
 555        return sparc32_open(filename, flags, mode);
 556}
 557
 558#define SOL_F_SETLK     6
 559#define SOL_F_SETLKW    7
 560#define SOL_F_FREESP    11
 561#define SOL_F_ISSTREAM  13
 562#define SOL_F_GETLK     14
 563#define SOL_F_PRIV      15
 564#define SOL_F_NPRIV     16
 565#define SOL_F_QUOTACTL  17
 566#define SOL_F_BLOCKS    18
 567#define SOL_F_BLKSIZE   19
 568#define SOL_F_GETOWN    23
 569#define SOL_F_SETOWN    24
 570
 571struct sol_flock {
 572        short   l_type;
 573        short   l_whence;
 574        u32     l_start;
 575        u32     l_len;
 576        s32     l_sysid;
 577        s32     l_pid;
 578        s32     l_pad[4];
 579};
 580
 581asmlinkage int solaris_fcntl(unsigned fd, unsigned cmd, u32 arg)
 582{
 583        int (*sys_fcntl)(unsigned,unsigned,unsigned long) = 
 584                (int (*)(unsigned,unsigned,unsigned long))SYS(fcntl);
 585        int ret, flags;
 586
 587        switch (cmd) {
 588        case F_DUPFD:
 589        case F_GETFD:
 590        case F_SETFD: return sys_fcntl(fd, cmd, (unsigned long)arg);
 591        case F_GETFL:
 592                flags = sys_fcntl(fd, cmd, 0);
 593                ret = flags & 0xf;
 594                if (flags & O_SYNC) ret |= 0x8050;
 595                if (flags & O_NONBLOCK) ret |= 0x80;
 596                return ret;
 597        case F_SETFL:
 598                flags = arg & 0xf;
 599                if (arg & 0x8050) flags |= O_SYNC;
 600                if (arg & 0x80) flags |= O_NONBLOCK;
 601                return sys_fcntl(fd, cmd, (long)flags);
 602        case SOL_F_GETLK:
 603        case SOL_F_SETLK:
 604        case SOL_F_SETLKW:
 605                {
 606                        struct flock f;
 607                        mm_segment_t old_fs = get_fs();
 608
 609                        switch (cmd) {
 610                        case SOL_F_GETLK: cmd = F_GETLK; break;
 611                        case SOL_F_SETLK: cmd = F_SETLK; break;
 612                        case SOL_F_SETLKW: cmd = F_SETLKW; break;
 613                        }
 614
 615                        if (get_user (f.l_type, &((struct sol_flock *)A(arg))->l_type) ||
 616                            __get_user (f.l_whence, &((struct sol_flock *)A(arg))->l_whence) ||
 617                            __get_user (f.l_start, &((struct sol_flock *)A(arg))->l_start) ||
 618                            __get_user (f.l_len, &((struct sol_flock *)A(arg))->l_len) ||
 619                            __get_user (f.l_pid, &((struct sol_flock *)A(arg))->l_sysid))
 620                                return -EFAULT;
 621
 622                        set_fs(KERNEL_DS);
 623                        ret = sys_fcntl(fd, cmd, (unsigned long)&f);
 624                        set_fs(old_fs);
 625
 626                        if (__put_user (f.l_type, &((struct sol_flock *)A(arg))->l_type) ||
 627                            __put_user (f.l_whence, &((struct sol_flock *)A(arg))->l_whence) ||
 628                            __put_user (f.l_start, &((struct sol_flock *)A(arg))->l_start) ||
 629                            __put_user (f.l_len, &((struct sol_flock *)A(arg))->l_len) ||
 630                            __put_user (f.l_pid, &((struct sol_flock *)A(arg))->l_pid) ||
 631                            __put_user (0, &((struct sol_flock *)A(arg))->l_sysid))
 632                                return -EFAULT;
 633
 634                        return ret;
 635                }
 636        case SOL_F_FREESP:
 637                { 
 638                    int length;
 639                    int (*sys_newftruncate)(unsigned int, unsigned long)=
 640                            (int (*)(unsigned int, unsigned long))SYS(ftruncate);
 641
 642                    if (get_user(length, &((struct sol_flock*)A(arg))->l_start))
 643                            return -EFAULT;
 644
 645                    return sys_newftruncate(fd, length);
 646                }
 647        };
 648        return -EINVAL;
 649}
 650
 651asmlinkage int solaris_ulimit(int cmd, int val)
 652{
 653        switch (cmd) {
 654        case 1: /* UL_GETFSIZE - in 512B chunks */
 655                return current->rlim[RLIMIT_FSIZE].rlim_cur >> 9;
 656        case 2: /* UL_SETFSIZE */
 657                if ((unsigned long)val > (LONG_MAX>>9)) return -ERANGE;
 658                val <<= 9;
 659                lock_kernel();
 660                if (val > current->rlim[RLIMIT_FSIZE].rlim_max) {
 661                        if (!capable(CAP_SYS_RESOURCE)) {
 662                                unlock_kernel();
 663                                return -EPERM;
 664                        }
 665                        current->rlim[RLIMIT_FSIZE].rlim_max = val;
 666                }
 667                current->rlim[RLIMIT_FSIZE].rlim_cur = val;
 668                unlock_kernel();
 669                return 0;
 670        case 3: /* UL_GMEMLIM */
 671                return current->rlim[RLIMIT_DATA].rlim_cur;
 672        case 4: /* UL_GDESLIM */
 673                return NR_OPEN;
 674        }
 675        return -EINVAL;
 676}
 677
 678/* At least at the time I'm writing this, Linux doesn't have ACLs, so we
 679   just fake this */
 680asmlinkage int solaris_acl(u32 filename, int cmd, int nentries, u32 aclbufp)
 681{
 682        return -ENOSYS;
 683}
 684
 685asmlinkage int solaris_facl(unsigned int fd, int cmd, int nentries, u32 aclbufp)
 686{
 687        return -ENOSYS;
 688}
 689
 690asmlinkage int solaris_pread(unsigned int fd, char *buf, u32 count, u32 pos)
 691{
 692        ssize_t (*sys_pread)(unsigned int, char *, size_t, loff_t) =
 693                (ssize_t (*)(unsigned int, char *, size_t, loff_t))SYS(pread);
 694                
 695        return sys_pread(fd, buf, count, (loff_t)pos);
 696}
 697
 698asmlinkage int solaris_pwrite(unsigned int fd, char *buf, u32 count, u32 pos)
 699{
 700        ssize_t (*sys_pwrite)(unsigned int, char *, size_t, loff_t) =
 701                (ssize_t (*)(unsigned int, char *, size_t, loff_t))SYS(pwrite);
 702                
 703        return sys_pwrite(fd, buf, count, (loff_t)pos);
 704}
 705
 706/* POSIX.1 names */
 707#define _PC_LINK_MAX    1
 708#define _PC_MAX_CANON   2
 709#define _PC_MAX_INPUT   3
 710#define _PC_NAME_MAX    4
 711#define _PC_PATH_MAX    5
 712#define _PC_PIPE_BUF    6
 713#define _PC_NO_TRUNC    7
 714#define _PC_VDISABLE    8
 715#define _PC_CHOWN_RESTRICTED    9
 716/* POSIX.4 names */
 717#define _PC_ASYNC_IO    10
 718#define _PC_PRIO_IO     11
 719#define _PC_SYNC_IO     12
 720#define _PC_LAST        12
 721
 722/* This is not a real and complete implementation yet, just to keep
 723 * the easy Solaris binaries happy.
 724 */
 725asmlinkage int solaris_fpathconf(int fd, int name)
 726{
 727        int ret;
 728
 729        switch(name) {
 730        case _PC_LINK_MAX:
 731                ret = LINK_MAX;
 732                break;
 733        case _PC_MAX_CANON:
 734                ret = MAX_CANON;
 735                break;
 736        case _PC_MAX_INPUT:
 737                ret = MAX_INPUT;
 738                break;
 739        case _PC_NAME_MAX:
 740                ret = NAME_MAX;
 741                break;
 742        case _PC_PATH_MAX:
 743                ret = PATH_MAX;
 744                break;
 745        case _PC_PIPE_BUF:
 746                ret = PIPE_BUF;
 747                break;
 748        case _PC_CHOWN_RESTRICTED:
 749                ret = 1;
 750                break;
 751        case _PC_NO_TRUNC:
 752        case _PC_VDISABLE:
 753                ret = 0;
 754                break;
 755        default:
 756                ret = -EINVAL;
 757                break;
 758        }
 759        return ret;
 760}
 761
 762asmlinkage int solaris_pathconf(u32 path, int name)
 763{
 764        return solaris_fpathconf(0, name);
 765}
 766
 767/* solaris_llseek returns long long - quite difficult */
 768asmlinkage long solaris_llseek(struct pt_regs *regs, u32 off_hi, u32 off_lo, int whence)
 769{
 770        int (*sys_llseek)(unsigned int, unsigned long, unsigned long, loff_t *, unsigned int) =
 771                (int (*)(unsigned int, unsigned long, unsigned long, loff_t *, unsigned int))SYS(_llseek);
 772        int ret;
 773        mm_segment_t old_fs = get_fs();
 774        loff_t retval;
 775        
 776        set_fs(KERNEL_DS);
 777        ret = sys_llseek((unsigned int)regs->u_regs[UREG_I0], off_hi, off_lo, &retval, whence);
 778        set_fs(old_fs);
 779        if (ret < 0) return ret;
 780        regs->u_regs[UREG_I1] = (u32)retval;
 781        return (retval >> 32);
 782}
 783
 784/* Have to mask out all but lower 3 bits */
 785asmlinkage int solaris_access(u32 filename, long mode)
 786{
 787        int (*sys_access)(const char *, int) = 
 788                (int (*)(const char *, int))SYS(access);
 789                
 790        return sys_access((const char *)A(filename), mode & 7);
 791}
 792
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.