root/arch/alpha/kernel/osf_sys.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. osf_filldir
  2. osf_getdirentries
  3. sys_madvise
  4. sys_getxuid
  5. sys_getxgid
  6. sys_getxpid
  7. osf_mmap
  8. osf_statfs
  9. osf_fstatfs
  10. getdev
  11. putdev
  12. osf_ufs_mount
  13. osf_cdfs_mount
  14. osf_procfs_mount
  15. osf_mount
  16. osf_umount
  17. osf_usleep_thread
  18. osf_utsname
  19. osf_swapon
  20. sys_getpagesize
  21. sys_getdtablesize
  22. sys_pipe
  23. osf_getdomainname
  24. osf_shmat
  25. osf_proplist_syscall

   1 /*
   2  *  linux/arch/alpha/kernel/osf_sys.c
   3  *
   4  *  Copyright (C) 1995  Linus Torvalds
   5  */
   6 
   7 /*
   8  * This file handles some of the stranger OSF/1 system call interfaces.
   9  * Some of the system calls expect a non-C calling standard, others have
  10  * special parameter blocks..
  11  */
  12 
  13 #include <linux/errno.h>
  14 #include <linux/sched.h>
  15 #include <linux/kernel.h>
  16 #include <linux/mm.h>
  17 #include <linux/stddef.h>
  18 #include <linux/unistd.h>
  19 #include <linux/ptrace.h>
  20 #include <linux/malloc.h>
  21 #include <linux/ldt.h>
  22 #include <linux/user.h>
  23 #include <linux/a.out.h>
  24 #include <linux/utsname.h>
  25 #include <linux/time.h>
  26 #include <linux/major.h>
  27 #include <linux/stat.h>
  28 #include <linux/mman.h>
  29 #include <linux/shm.h>
  30 
  31 #include <asm/segment.h>
  32 #include <asm/system.h>
  33 #include <asm/io.h>
  34 
  35 extern int do_mount(dev_t, const char *, char *, int, void *);
  36 extern int do_pipe(int *);
  37 
  38 extern struct file_operations * get_blkfops(unsigned int);
  39 extern struct file_operations * get_chrfops(unsigned int);
  40 
  41 extern dev_t get_unnamed_dev(void);
  42 extern void put_unnamed_dev(dev_t);
  43 
  44 extern asmlinkage int sys_umount(char *);
  45 extern asmlinkage int sys_swapon(const char *specialfile, int swap_flags);
  46 
  47 /*
  48  * OSF/1 directory handling functions...
  49  *
  50  * The "getdents()" interface is much more sane: the "basep" stuff is
  51  * braindamage (it can't really handle filesystems where the directory
  52  * offset differences aren't the same as "d_reclen").
  53  */
  54 #define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
  55 #define ROUND_UP(x) (((x)+3) & ~3)
  56 
  57 struct osf_dirent {
  58         unsigned int    d_ino;
  59         unsigned short  d_reclen;
  60         unsigned short  d_namlen;
  61         char            d_name[1];
  62 };
  63 
  64 struct osf_dirent_callback {
  65         struct osf_dirent * dirent;
  66         long *basep;
  67         int count;
  68         int error;
  69 };
  70 
  71 static int osf_filldir(void * __buf, const char * name, int namlen, off_t offset, ino_t ino)
     /* [previous][next][first][last][top][bottom][index][help] */
  72 {
  73         struct osf_dirent * dirent;
  74         struct osf_dirent_callback * buf = (struct osf_dirent_callback *) __buf;
  75         int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);
  76 
  77         buf->error = -EINVAL;           /* unly used if we fail */
  78         if (reclen > buf->count)
  79                 return -EINVAL;
  80         if (buf->basep) {
  81                 put_user(offset, buf->basep);
  82                 buf->basep = NULL;
  83         }
  84         dirent = buf->dirent;
  85         put_user(ino, &dirent->d_ino);
  86         put_user(namlen, &dirent->d_namlen);
  87         put_user(reclen, &dirent->d_reclen);
  88         memcpy_tofs(dirent->d_name, name, namlen);
  89         put_fs_byte(0, dirent->d_name + namlen);
  90         ((char *) dirent) += reclen;
  91         buf->dirent = dirent;
  92         buf->count -= reclen;
  93         return 0;
  94 }
  95 
  96 asmlinkage int osf_getdirentries(unsigned int fd, struct osf_dirent * dirent,
     /* [previous][next][first][last][top][bottom][index][help] */
  97         unsigned int count, long *basep)
  98 {
  99         int error;
 100         struct file * file;
 101         struct osf_dirent_callback buf;
 102 
 103         if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
 104                 return -EBADF;
 105         if (!file->f_op || !file->f_op->readdir)
 106                 return -ENOTDIR;
 107         error = verify_area(VERIFY_WRITE, dirent, count);
 108         if (error)
 109                 return error;
 110         if (basep) {
 111                 error = verify_area(VERIFY_WRITE, basep, sizeof(long));
 112                 if (error)
 113                         return error;
 114         }
 115         buf.dirent = dirent;
 116         buf.basep = basep;
 117         buf.count = count;
 118         buf.error = 0;
 119         error = file->f_op->readdir(file->f_inode, file, &buf, osf_filldir);
 120         if (error < 0)
 121                 return error;
 122         if (count == buf.count)
 123                 return buf.error;
 124         return count - buf.count;
 125 }
 126 
 127 /*
 128  * Heh. As documented by DEC..
 129  */
 130 asmlinkage unsigned long sys_madvise(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 131 {
 132         return 0;
 133 }
 134 
 135 asmlinkage unsigned long sys_getxuid(int a0, int a1, int a2, int a3, int a4, int a5,
     /* [previous][next][first][last][top][bottom][index][help] */
 136         struct pt_regs regs)
 137 {
 138         (&regs)->r20 = current->euid;
 139         return current->uid;
 140 }
 141 
 142 asmlinkage unsigned long sys_getxgid(int a0, int a1, int a2, int a3, int a4, int a5,
     /* [previous][next][first][last][top][bottom][index][help] */
 143         struct pt_regs regs)
 144 {
 145         (&regs)->r20 = current->egid;
 146         return current->gid;
 147 }
 148 
 149 asmlinkage unsigned long sys_getxpid(int a0, int a1, int a2, int a3, int a4, int a5,
     /* [previous][next][first][last][top][bottom][index][help] */
 150         struct pt_regs regs)
 151 {
 152         (&regs)->r20 = current->p_opptr->pid;
 153         return current->pid;
 154 }
 155 
 156 #define OSF_MAP_ANONYMOUS       0x0010
 157 #define OSF_MAP_FIXED           0x0100
 158 #define OSF_MAP_HASSEMAPHORE    0x0200
 159 #define OSF_MAP_INHERIT         0x0400
 160 #define OSF_MAP_UNALIGNED       0x0800
 161 
 162 asmlinkage unsigned long osf_mmap(unsigned long addr, unsigned long len,
     /* [previous][next][first][last][top][bottom][index][help] */
 163         unsigned long prot, unsigned long osf_flags, unsigned long fd,
 164         unsigned long off)
 165 {
 166         struct file * file = NULL;
 167         unsigned long flags = osf_flags & 0x0f;
 168 
 169         if (osf_flags & (OSF_MAP_HASSEMAPHORE | OSF_MAP_INHERIT | OSF_MAP_UNALIGNED))
 170                 printk("%s: unimplemented OSF mmap flags %04lx\n", current->comm, osf_flags);
 171         if (osf_flags & OSF_MAP_FIXED)
 172                 flags |= MAP_FIXED;
 173         if (osf_flags & OSF_MAP_ANONYMOUS)
 174                 flags |= MAP_ANONYMOUS;
 175         else {
 176                 if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
 177                         return -EBADF;
 178         }
 179         return do_mmap(file, addr, len, prot, flags, off);
 180 }
 181 
 182 asmlinkage int osf_statfs(char * path, struct statfs * buffer, unsigned long bufsiz)
     /* [previous][next][first][last][top][bottom][index][help] */
 183 {
 184         struct inode * inode;
 185         int retval;
 186 
 187         if (bufsiz > sizeof(struct statfs))
 188                 bufsiz = sizeof(struct statfs);
 189         retval = verify_area(VERIFY_WRITE, buffer, bufsiz);
 190         if (retval)
 191                 return retval;
 192         retval = namei(path, &inode);
 193         if (retval)
 194                 return retval;
 195         if (!inode->i_sb->s_op->statfs) {
 196                 iput(inode);
 197                 return -ENOSYS;
 198         }
 199         inode->i_sb->s_op->statfs(inode->i_sb, buffer, bufsiz);
 200         iput(inode);
 201         return 0;
 202 }
 203 
 204 asmlinkage int osf_fstatfs(unsigned long fd, struct statfs * buffer, unsigned long bufsiz)
     /* [previous][next][first][last][top][bottom][index][help] */
 205 {
 206         struct file * file;
 207         struct inode * inode;
 208         int retval;
 209 
 210         retval = verify_area(VERIFY_WRITE, buffer, bufsiz);
 211         if (retval)
 212                 return retval;
 213         if (bufsiz > sizeof(struct statfs))
 214                 bufsiz = sizeof(struct statfs);
 215         if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
 216                 return -EBADF;
 217         if (!(inode = file->f_inode))
 218                 return -ENOENT;
 219         if (!inode->i_sb->s_op->statfs)
 220                 return -ENOSYS;
 221         inode->i_sb->s_op->statfs(inode->i_sb, buffer, bufsiz);
 222         return 0;
 223 }
 224 
 225 /*
 226  * Uhh.. OSF/1 mount parameters aren't exactly obvious..
 227  *
 228  * Although to be frank, neither are the native Linux/i386 ones..
 229  */
 230 struct ufs_args {
 231         char * devname;
 232         int flags;
 233         uid_t exroot;
 234 };
 235 
 236 struct cdfs_args {
 237         char * devname;
 238         int flags;
 239         uid_t exroot;
 240 /*
 241  * this has lots more here, which linux handles with the option block
 242  * but I'm too lazy to do the translation into ascii..
 243  */
 244 };
 245 
 246 struct procfs_args {
 247         char * devname;
 248         int flags;
 249         uid_t exroot;
 250 };
 251 
 252 static int getdev(const char * name, int rdonly, struct inode ** ino)
     /* [previous][next][first][last][top][bottom][index][help] */
 253 {
 254         dev_t dev;
 255         struct inode * inode;
 256         struct file_operations * fops;
 257         int retval;
 258 
 259         retval = namei(name, &inode);
 260         if (retval)
 261                 return retval;
 262         if (!S_ISBLK(inode->i_mode)) {
 263                 iput(inode);
 264                 return -ENOTBLK;
 265         }
 266         if (IS_NODEV(inode)) {
 267                 iput(inode);
 268                 return -EACCES;
 269         }
 270         dev = inode->i_rdev;
 271         if (MAJOR(dev) >= MAX_BLKDEV) {
 272                 iput(inode);
 273                 return -ENXIO;
 274         }
 275         fops = get_blkfops(MAJOR(dev));
 276         if (!fops) {
 277                 iput(inode);
 278                 return -ENODEV;
 279         }
 280         if (fops->open) {
 281                 struct file dummy;
 282                 memset(&dummy, 0, sizeof(dummy));
 283                 dummy.f_inode = inode;
 284                 dummy.f_mode = rdonly ? 1 : 3;
 285                 retval = fops->open(inode, &dummy);
 286                 if (retval) {
 287                         iput(inode);
 288                         return retval;
 289                 }
 290         }
 291         *ino = inode;
 292         return 0;
 293 }
 294 
 295 static void putdev(struct inode * inode)
     /* [previous][next][first][last][top][bottom][index][help] */
 296 {
 297         struct file_operations * fops;
 298 
 299         fops = get_blkfops(MAJOR(inode->i_rdev));
 300         if (fops->release)
 301                 fops->release(inode, NULL);
 302 }
 303 
 304 /*
 305  * We can't actually handle ufs yet, so we translate UFS mounts to
 306  * ext2fs mounts... I wouldn't mind a USF filesystem, but the UFS
 307  * layout is so braindead it's a major headache doing it..
 308  */
 309 static int osf_ufs_mount(char * dirname, struct ufs_args * args, int flags)
     /* [previous][next][first][last][top][bottom][index][help] */
 310 {
 311         int retval;
 312         struct inode * inode;
 313         struct cdfs_args tmp;
 314 
 315         retval = verify_area(VERIFY_READ, args, sizeof(*args));
 316         if (retval)
 317                 return retval;
 318         memcpy_fromfs(&tmp, args, sizeof(tmp));
 319         retval = getdev(tmp.devname, 0, &inode);
 320         if (retval)
 321                 return retval;
 322         retval = do_mount(inode->i_rdev, dirname, "ext2", flags, NULL);
 323         if (retval)
 324                 putdev(inode);
 325         iput(inode);
 326         return retval;
 327 }
 328 
 329 static int osf_cdfs_mount(char * dirname, struct cdfs_args * args, int flags)
     /* [previous][next][first][last][top][bottom][index][help] */
 330 {
 331         int retval;
 332         struct inode * inode;
 333         struct cdfs_args tmp;
 334 
 335         retval = verify_area(VERIFY_READ, args, sizeof(*args));
 336         if (retval)
 337                 return retval;
 338         memcpy_fromfs(&tmp, args, sizeof(tmp));
 339         retval = getdev(tmp.devname, 1, &inode);
 340         if (retval)
 341                 return retval;
 342         retval = do_mount(inode->i_rdev, dirname, "iso9660", flags, NULL);
 343         if (retval)
 344                 putdev(inode);
 345         iput(inode);
 346         return retval;
 347 }
 348 
 349 static int osf_procfs_mount(char * dirname, struct procfs_args * args, int flags)
     /* [previous][next][first][last][top][bottom][index][help] */
 350 {
 351         dev_t dev;
 352         int retval;
 353         struct procfs_args tmp;
 354 
 355         retval = verify_area(VERIFY_READ, args, sizeof(*args));
 356         if (retval)
 357                 return retval;
 358         memcpy_fromfs(&tmp, args, sizeof(tmp));
 359         dev = get_unnamed_dev();
 360         if (!dev)
 361                 return -ENODEV;
 362         retval = do_mount(dev, dirname, "proc", flags, NULL);
 363         if (retval)
 364                 put_unnamed_dev(dev);
 365         return retval;
 366 }
 367 
 368 asmlinkage int osf_mount(unsigned long typenr, char * path, int flag, void * data)
     /* [previous][next][first][last][top][bottom][index][help] */
 369 {
 370         int retval;
 371 
 372         retval = -EINVAL;
 373         switch (typenr) {
 374                 case 1:
 375                         retval = osf_ufs_mount(path, (struct ufs_args *) data, flag);
 376                         break;
 377                 case 6:
 378                         retval = osf_cdfs_mount(path, (struct cdfs_args *) data, flag);
 379                         break;
 380                 case 9:
 381                         retval = osf_procfs_mount(path, (struct procfs_args *) data, flag);
 382                         break;
 383                 default:
 384                         printk("osf_mount(%ld, %x)\n", typenr, flag);
 385         }
 386         return retval;
 387 }
 388 
 389 asmlinkage int osf_umount(char * path, int flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 390 {
 391         return sys_umount(path);
 392 }
 393 
 394 /*
 395  * I don't know what the parameters are: the first one
 396  * seems to be a timeval pointer, and I suspect the second
 397  * one is the time remaining.. Ho humm.. No documentation.
 398  */
 399 asmlinkage int osf_usleep_thread(struct timeval * sleep, struct timeval * remain)
     /* [previous][next][first][last][top][bottom][index][help] */
 400 {
 401         struct timeval tmp;
 402         unsigned long ticks;
 403         int retval;
 404 
 405         retval = verify_area(VERIFY_READ, sleep, sizeof(*sleep));
 406         if (retval)
 407                 return retval;
 408         if (remain && (retval = verify_area(VERIFY_WRITE, remain, sizeof(*remain))))
 409                 return retval;
 410         memcpy_fromfs(&tmp, sleep, sizeof(*sleep));
 411         ticks = tmp.tv_usec;
 412         ticks = (ticks + (1000000 / HZ) - 1) / (1000000 / HZ);
 413         ticks += tmp.tv_sec * HZ;
 414         current->timeout = ticks + jiffies;
 415         current->state = TASK_INTERRUPTIBLE;
 416         schedule();
 417         if (!remain)
 418                 return 0;
 419         ticks = jiffies;
 420         if (ticks < current->timeout)
 421                 ticks = current->timeout - ticks;
 422         else
 423                 ticks = 0;
 424         current->timeout = 0;
 425         tmp.tv_sec = ticks / HZ;
 426         tmp.tv_usec = ticks % HZ;
 427         memcpy_tofs(remain, &tmp, sizeof(*remain));
 428         return 0;
 429 }
 430 
 431 asmlinkage int osf_utsname(char * name)
     /* [previous][next][first][last][top][bottom][index][help] */
 432 {
 433         int error = verify_area(VERIFY_WRITE, name, 5*32);
 434         if (error)
 435                 return error;
 436         memcpy_tofs(name +   0, system_utsname.sysname, 32);
 437         memcpy_tofs(name +  32, system_utsname.nodename, 32);
 438         memcpy_tofs(name +  64, system_utsname.release, 32);
 439         memcpy_tofs(name +  96, system_utsname.version, 32);
 440         memcpy_tofs(name + 128, system_utsname.machine, 32);
 441         return 0;
 442 }
 443 
 444 asmlinkage int osf_swapon(const char * path, int flags, int lowat, int hiwat)
     /* [previous][next][first][last][top][bottom][index][help] */
 445 {
 446         /* for now, simply ignore lowat and hiwat... */
 447         return sys_swapon(path, flags);
 448 }
 449 
 450 asmlinkage unsigned long sys_getpagesize(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 451 {
 452         return PAGE_SIZE;
 453 }
 454 
 455 asmlinkage unsigned long sys_getdtablesize(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 456 {
 457         return NR_OPEN;
 458 }
 459 
 460 asmlinkage int sys_pipe(int a0, int a1, int a2, int a3, int a4, int a5,
     /* [previous][next][first][last][top][bottom][index][help] */
 461         struct pt_regs regs)
 462 {
 463         int fd[2];
 464         int error;
 465 
 466         error = do_pipe(fd);
 467         if (error)
 468                 return error;
 469         (&regs)->r20 = fd[1];
 470         return fd[0];
 471 }
 472 
 473 /*
 474  * For compatibility with OSF/1 only.  Use utsname(2) instead.
 475  */
 476 asmlinkage int osf_getdomainname(char *name, int namelen)
     /* [previous][next][first][last][top][bottom][index][help] */
 477 {
 478         unsigned len;
 479         int i, error;
 480 
 481         error = verify_area(VERIFY_WRITE, name, namelen);
 482         if (error)
 483                 return error;
 484 
 485         len = namelen;
 486         if (namelen > 32)
 487           len = 32;
 488 
 489         for (i = 0; i < len; ++i) {
 490                 put_user(system_utsname.domainname[i], name + i);
 491                 if (system_utsname.domainname[i] == '\0')
 492                   break;
 493         }
 494         return 0;
 495 }
 496 
 497 
 498 asmlinkage long osf_shmat(int shmid, void *shmaddr, int shmflg)
     /* [previous][next][first][last][top][bottom][index][help] */
 499 {
 500         unsigned long raddr;
 501         int err;
 502 
 503         err = sys_shmat(shmid, shmaddr, shmflg, &raddr);
 504         if (err)
 505                 return err;
 506         /*
 507          * This works because all user-level addresses are
 508          * non-negative longs!
 509          */
 510         return raddr;
 511 }
 512 
 513 
 514 /*
 515  * The following stuff should move into a header file should it ever
 516  * be labeled "officially supported."  Right now, there is just enough
 517  * support to avoid applications (such as tar) printing error
 518  * messages.  The attributes are not really implemented.
 519  */
 520 
 521 /*
 522  * Values for Property list entry flag
 523  */
 524 #define PLE_PROPAGATE_ON_COPY           0x1     /* cp(1) will copy entry
 525                                                    by default */
 526 #define PLE_FLAG_MASK                   0x1     /* Valid flag values */
 527 #define PLE_FLAG_ALL                    -1      /* All flag value */
 528 
 529 struct proplistname_args {
 530         unsigned int    pl_mask;
 531         unsigned int    pl_numnames;
 532         char            **pl_names;
 533 };
 534 
 535 union pl_args {
 536         struct setargs {
 537                 char *path;
 538                 long follow;
 539                 long nbytes;
 540                 char *buf;
 541         } set;
 542         struct fsetargs {
 543                 long fd;
 544                 long nbytes;
 545                 char *buf;
 546         } fset;
 547         struct getargs {
 548                 char *path;
 549                 long follow;
 550                 struct proplistname_args *name_args;
 551                 long nbytes;
 552                 char *buf;
 553                 int *min_buf_size;
 554         } get;
 555         struct fgetargs {
 556                 long fd;
 557                 struct proplistname_args *name_args;
 558                 long nbytes;
 559                 char *buf;
 560                 int *min_buf_size;
 561         } fget;
 562         struct delargs {
 563                 char *path;
 564                 long follow;
 565                 struct proplistname_args *name_args;
 566         } del;
 567         struct fdelargs {
 568                 long fd;
 569                 struct proplistname_args *name_args;
 570         } fdel;
 571 };
 572 
 573 enum pl_code {
 574         PL_SET  = 1,    PL_FSET = 2,
 575         PL_GET  = 3,    PL_FGET = 4,
 576         PL_DEL  = 5,    PL_FDEL = 6
 577 };
 578 
 579 asmlinkage long osf_proplist_syscall (enum pl_code code, union pl_args *args)
     /* [previous][next][first][last][top][bottom][index][help] */
 580 {
 581         long error;
 582         int *min_buf_size_ptr;
 583 
 584         switch (code) {
 585               case PL_SET:
 586                 error = verify_area(VERIFY_READ, &args->set.nbytes,
 587                                     sizeof(args->set.nbytes));
 588                 if (error)
 589                   return error;
 590                 return args->set.nbytes;
 591 
 592               case PL_FSET:
 593                 error = verify_area(VERIFY_READ, &args->fset.nbytes,
 594                                     sizeof(args->fset.nbytes));
 595                 if (error)
 596                   return error;
 597                 return args->fset.nbytes;
 598 
 599               case PL_GET:
 600                 error = verify_area(VERIFY_READ, &args->get.min_buf_size,
 601                                     sizeof(args->get.min_buf_size));
 602                 if (error)
 603                   return error;
 604                 min_buf_size_ptr = get_user(&args->get.min_buf_size);
 605                 error = verify_area(VERIFY_WRITE, min_buf_size_ptr,
 606                                     sizeof(*min_buf_size_ptr));
 607                 if (error)
 608                   return error;
 609                 put_user(0, min_buf_size_ptr);
 610                 return 0;
 611 
 612               case PL_FGET:
 613                 error = verify_area(VERIFY_READ, &args->fget.min_buf_size,
 614                                     sizeof(args->fget.min_buf_size));
 615                 if (error)
 616                   return error;
 617                 min_buf_size_ptr = get_user(&args->fget.min_buf_size);
 618                 error = verify_area(VERIFY_WRITE, min_buf_size_ptr,
 619                                     sizeof(*min_buf_size_ptr));
 620                 if (error)
 621                   return error;
 622                 put_user(0, min_buf_size_ptr);
 623                 return 0;
 624 
 625               case PL_DEL:
 626               case PL_FDEL:
 627                 return 0;
 628 
 629               default:
 630                 return -EOPNOTSUPP;
 631         }
 632 }

/* [previous][next][first][last][top][bottom][index][help] */