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(kdev_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 kdev_t get_unnamed_dev(void);
  42 extern void put_unnamed_dev(kdev_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 asmlinkage unsigned long osf_mmap(unsigned long addr, unsigned long len,
     /* [previous][next][first][last][top][bottom][index][help] */
 157         unsigned long prot, unsigned long flags, unsigned long fd,
 158         unsigned long off)
 159 {
 160         struct file * file = NULL;
 161 
 162         if (flags & (MAP_HASSEMAPHORE | MAP_INHERIT | MAP_UNALIGNED))
 163                 printk("%s: unimplemented OSF mmap flags %04lx\n", current->comm, flags);
 164         if (!(flags & MAP_ANONYMOUS)) {
 165                 if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
 166                         return -EBADF;
 167         }
 168         return do_mmap(file, addr, len, prot, flags, off);
 169 }
 170 
 171 asmlinkage int osf_statfs(char * path, struct statfs * buffer, unsigned long bufsiz)
     /* [previous][next][first][last][top][bottom][index][help] */
 172 {
 173         struct inode * inode;
 174         int retval;
 175 
 176         if (bufsiz > sizeof(struct statfs))
 177                 bufsiz = sizeof(struct statfs);
 178         retval = verify_area(VERIFY_WRITE, buffer, bufsiz);
 179         if (retval)
 180                 return retval;
 181         retval = namei(path, &inode);
 182         if (retval)
 183                 return retval;
 184         if (!inode->i_sb->s_op->statfs) {
 185                 iput(inode);
 186                 return -ENOSYS;
 187         }
 188         inode->i_sb->s_op->statfs(inode->i_sb, buffer, bufsiz);
 189         iput(inode);
 190         return 0;
 191 }
 192 
 193 asmlinkage int osf_fstatfs(unsigned long fd, struct statfs * buffer, unsigned long bufsiz)
     /* [previous][next][first][last][top][bottom][index][help] */
 194 {
 195         struct file * file;
 196         struct inode * inode;
 197         int retval;
 198 
 199         retval = verify_area(VERIFY_WRITE, buffer, bufsiz);
 200         if (retval)
 201                 return retval;
 202         if (bufsiz > sizeof(struct statfs))
 203                 bufsiz = sizeof(struct statfs);
 204         if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
 205                 return -EBADF;
 206         if (!(inode = file->f_inode))
 207                 return -ENOENT;
 208         if (!inode->i_sb->s_op->statfs)
 209                 return -ENOSYS;
 210         inode->i_sb->s_op->statfs(inode->i_sb, buffer, bufsiz);
 211         return 0;
 212 }
 213 
 214 /*
 215  * Uhh.. OSF/1 mount parameters aren't exactly obvious..
 216  *
 217  * Although to be frank, neither are the native Linux/i386 ones..
 218  */
 219 struct ufs_args {
 220         char * devname;
 221         int flags;
 222         uid_t exroot;
 223 };
 224 
 225 struct cdfs_args {
 226         char * devname;
 227         int flags;
 228         uid_t exroot;
 229 /*
 230  * this has lots more here, which linux handles with the option block
 231  * but I'm too lazy to do the translation into ascii..
 232  */
 233 };
 234 
 235 struct procfs_args {
 236         char * devname;
 237         int flags;
 238         uid_t exroot;
 239 };
 240 
 241 static int getdev(const char * name, int rdonly, struct inode ** ino)
     /* [previous][next][first][last][top][bottom][index][help] */
 242 {
 243         kdev_t dev;
 244         struct inode * inode;
 245         struct file_operations * fops;
 246         int retval;
 247 
 248         retval = namei(name, &inode);
 249         if (retval)
 250                 return retval;
 251         if (!S_ISBLK(inode->i_mode)) {
 252                 iput(inode);
 253                 return -ENOTBLK;
 254         }
 255         if (IS_NODEV(inode)) {
 256                 iput(inode);
 257                 return -EACCES;
 258         }
 259         dev = inode->i_rdev;
 260         if (MAJOR(dev) >= MAX_BLKDEV) {
 261                 iput(inode);
 262                 return -ENXIO;
 263         }
 264         fops = get_blkfops(MAJOR(dev));
 265         if (!fops) {
 266                 iput(inode);
 267                 return -ENODEV;
 268         }
 269         if (fops->open) {
 270                 struct file dummy;
 271                 memset(&dummy, 0, sizeof(dummy));
 272                 dummy.f_inode = inode;
 273                 dummy.f_mode = rdonly ? 1 : 3;
 274                 retval = fops->open(inode, &dummy);
 275                 if (retval) {
 276                         iput(inode);
 277                         return retval;
 278                 }
 279         }
 280         *ino = inode;
 281         return 0;
 282 }
 283 
 284 static void putdev(struct inode * inode)
     /* [previous][next][first][last][top][bottom][index][help] */
 285 {
 286         struct file_operations * fops;
 287 
 288         fops = get_blkfops(MAJOR(inode->i_rdev));
 289         if (fops->release)
 290                 fops->release(inode, NULL);
 291 }
 292 
 293 /*
 294  * We can't actually handle ufs yet, so we translate UFS mounts to
 295  * ext2fs mounts... I wouldn't mind a USF filesystem, but the UFS
 296  * layout is so braindead it's a major headache doing it..
 297  */
 298 static int osf_ufs_mount(char * dirname, struct ufs_args * args, int flags)
     /* [previous][next][first][last][top][bottom][index][help] */
 299 {
 300         int retval;
 301         struct inode * inode;
 302         struct cdfs_args tmp;
 303 
 304         retval = verify_area(VERIFY_READ, args, sizeof(*args));
 305         if (retval)
 306                 return retval;
 307         memcpy_fromfs(&tmp, args, sizeof(tmp));
 308         retval = getdev(tmp.devname, 0, &inode);
 309         if (retval)
 310                 return retval;
 311         retval = do_mount(inode->i_rdev, dirname, "ext2", flags, NULL);
 312         if (retval)
 313                 putdev(inode);
 314         iput(inode);
 315         return retval;
 316 }
 317 
 318 static int osf_cdfs_mount(char * dirname, struct cdfs_args * args, int flags)
     /* [previous][next][first][last][top][bottom][index][help] */
 319 {
 320         int retval;
 321         struct inode * inode;
 322         struct cdfs_args tmp;
 323 
 324         retval = verify_area(VERIFY_READ, args, sizeof(*args));
 325         if (retval)
 326                 return retval;
 327         memcpy_fromfs(&tmp, args, sizeof(tmp));
 328         retval = getdev(tmp.devname, 1, &inode);
 329         if (retval)
 330                 return retval;
 331         retval = do_mount(inode->i_rdev, dirname, "iso9660", flags, NULL);
 332         if (retval)
 333                 putdev(inode);
 334         iput(inode);
 335         return retval;
 336 }
 337 
 338 static int osf_procfs_mount(char * dirname, struct procfs_args * args, int flags)
     /* [previous][next][first][last][top][bottom][index][help] */
 339 {
 340         kdev_t dev;
 341         int retval;
 342         struct procfs_args tmp;
 343 
 344         retval = verify_area(VERIFY_READ, args, sizeof(*args));
 345         if (retval)
 346                 return retval;
 347         memcpy_fromfs(&tmp, args, sizeof(tmp));
 348         dev = get_unnamed_dev();
 349         if (!dev)
 350                 return -ENODEV;
 351         retval = do_mount(dev, dirname, "proc", flags, NULL);
 352         if (retval)
 353                 put_unnamed_dev(dev);
 354         return retval;
 355 }
 356 
 357 asmlinkage int osf_mount(unsigned long typenr, char * path, int flag, void * data)
     /* [previous][next][first][last][top][bottom][index][help] */
 358 {
 359         int retval;
 360 
 361         retval = -EINVAL;
 362         switch (typenr) {
 363                 case 1:
 364                         retval = osf_ufs_mount(path, (struct ufs_args *) data, flag);
 365                         break;
 366                 case 6:
 367                         retval = osf_cdfs_mount(path, (struct cdfs_args *) data, flag);
 368                         break;
 369                 case 9:
 370                         retval = osf_procfs_mount(path, (struct procfs_args *) data, flag);
 371                         break;
 372                 default:
 373                         printk("osf_mount(%ld, %x)\n", typenr, flag);
 374         }
 375         return retval;
 376 }
 377 
 378 asmlinkage int osf_umount(char * path, int flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 379 {
 380         return sys_umount(path);
 381 }
 382 
 383 /*
 384  * I don't know what the parameters are: the first one
 385  * seems to be a timeval pointer, and I suspect the second
 386  * one is the time remaining.. Ho humm.. No documentation.
 387  */
 388 asmlinkage int osf_usleep_thread(struct timeval * sleep, struct timeval * remain)
     /* [previous][next][first][last][top][bottom][index][help] */
 389 {
 390         struct timeval tmp;
 391         unsigned long ticks;
 392         int retval;
 393 
 394         retval = verify_area(VERIFY_READ, sleep, sizeof(*sleep));
 395         if (retval)
 396                 return retval;
 397         if (remain && (retval = verify_area(VERIFY_WRITE, remain, sizeof(*remain))))
 398                 return retval;
 399         memcpy_fromfs(&tmp, sleep, sizeof(*sleep));
 400         ticks = tmp.tv_usec;
 401         ticks = (ticks + (1000000 / HZ) - 1) / (1000000 / HZ);
 402         ticks += tmp.tv_sec * HZ;
 403         current->timeout = ticks + jiffies;
 404         current->state = TASK_INTERRUPTIBLE;
 405         schedule();
 406         if (!remain)
 407                 return 0;
 408         ticks = jiffies;
 409         if (ticks < current->timeout)
 410                 ticks = current->timeout - ticks;
 411         else
 412                 ticks = 0;
 413         current->timeout = 0;
 414         tmp.tv_sec = ticks / HZ;
 415         tmp.tv_usec = ticks % HZ;
 416         memcpy_tofs(remain, &tmp, sizeof(*remain));
 417         return 0;
 418 }
 419 
 420 asmlinkage int osf_utsname(char * name)
     /* [previous][next][first][last][top][bottom][index][help] */
 421 {
 422         int error = verify_area(VERIFY_WRITE, name, 5*32);
 423         if (error)
 424                 return error;
 425         memcpy_tofs(name +   0, system_utsname.sysname, 32);
 426         memcpy_tofs(name +  32, system_utsname.nodename, 32);
 427         memcpy_tofs(name +  64, system_utsname.release, 32);
 428         memcpy_tofs(name +  96, system_utsname.version, 32);
 429         memcpy_tofs(name + 128, system_utsname.machine, 32);
 430         return 0;
 431 }
 432 
 433 asmlinkage int osf_swapon(const char * path, int flags, int lowat, int hiwat)
     /* [previous][next][first][last][top][bottom][index][help] */
 434 {
 435         /* for now, simply ignore lowat and hiwat... */
 436         return sys_swapon(path, flags);
 437 }
 438 
 439 asmlinkage unsigned long sys_getpagesize(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 440 {
 441         return PAGE_SIZE;
 442 }
 443 
 444 asmlinkage unsigned long sys_getdtablesize(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 445 {
 446         return NR_OPEN;
 447 }
 448 
 449 asmlinkage int sys_pipe(int a0, int a1, int a2, int a3, int a4, int a5,
     /* [previous][next][first][last][top][bottom][index][help] */
 450         struct pt_regs regs)
 451 {
 452         int fd[2];
 453         int error;
 454 
 455         error = do_pipe(fd);
 456         if (error)
 457                 return error;
 458         (&regs)->r20 = fd[1];
 459         return fd[0];
 460 }
 461 
 462 /*
 463  * For compatibility with OSF/1 only.  Use utsname(2) instead.
 464  */
 465 asmlinkage int osf_getdomainname(char *name, int namelen)
     /* [previous][next][first][last][top][bottom][index][help] */
 466 {
 467         unsigned len;
 468         int i, error;
 469 
 470         error = verify_area(VERIFY_WRITE, name, namelen);
 471         if (error)
 472                 return error;
 473 
 474         len = namelen;
 475         if (namelen > 32)
 476           len = 32;
 477 
 478         for (i = 0; i < len; ++i) {
 479                 put_user(system_utsname.domainname[i], name + i);
 480                 if (system_utsname.domainname[i] == '\0')
 481                   break;
 482         }
 483         return 0;
 484 }
 485 
 486 
 487 asmlinkage long osf_shmat(int shmid, void *shmaddr, int shmflg)
     /* [previous][next][first][last][top][bottom][index][help] */
 488 {
 489         unsigned long raddr;
 490         int err;
 491 
 492         err = sys_shmat(shmid, shmaddr, shmflg, &raddr);
 493         if (err)
 494                 return err;
 495         /*
 496          * This works because all user-level addresses are
 497          * non-negative longs!
 498          */
 499         return raddr;
 500 }
 501 
 502 
 503 /*
 504  * The following stuff should move into a header file should it ever
 505  * be labeled "officially supported."  Right now, there is just enough
 506  * support to avoid applications (such as tar) printing error
 507  * messages.  The attributes are not really implemented.
 508  */
 509 
 510 /*
 511  * Values for Property list entry flag
 512  */
 513 #define PLE_PROPAGATE_ON_COPY           0x1     /* cp(1) will copy entry
 514                                                    by default */
 515 #define PLE_FLAG_MASK                   0x1     /* Valid flag values */
 516 #define PLE_FLAG_ALL                    -1      /* All flag value */
 517 
 518 struct proplistname_args {
 519         unsigned int    pl_mask;
 520         unsigned int    pl_numnames;
 521         char            **pl_names;
 522 };
 523 
 524 union pl_args {
 525         struct setargs {
 526                 char *path;
 527                 long follow;
 528                 long nbytes;
 529                 char *buf;
 530         } set;
 531         struct fsetargs {
 532                 long fd;
 533                 long nbytes;
 534                 char *buf;
 535         } fset;
 536         struct getargs {
 537                 char *path;
 538                 long follow;
 539                 struct proplistname_args *name_args;
 540                 long nbytes;
 541                 char *buf;
 542                 int *min_buf_size;
 543         } get;
 544         struct fgetargs {
 545                 long fd;
 546                 struct proplistname_args *name_args;
 547                 long nbytes;
 548                 char *buf;
 549                 int *min_buf_size;
 550         } fget;
 551         struct delargs {
 552                 char *path;
 553                 long follow;
 554                 struct proplistname_args *name_args;
 555         } del;
 556         struct fdelargs {
 557                 long fd;
 558                 struct proplistname_args *name_args;
 559         } fdel;
 560 };
 561 
 562 enum pl_code {
 563         PL_SET  = 1,    PL_FSET = 2,
 564         PL_GET  = 3,    PL_FGET = 4,
 565         PL_DEL  = 5,    PL_FDEL = 6
 566 };
 567 
 568 asmlinkage long osf_proplist_syscall (enum pl_code code, union pl_args *args)
     /* [previous][next][first][last][top][bottom][index][help] */
 569 {
 570         long error;
 571         int *min_buf_size_ptr;
 572 
 573         switch (code) {
 574               case PL_SET:
 575                 error = verify_area(VERIFY_READ, &args->set.nbytes,
 576                                     sizeof(args->set.nbytes));
 577                 if (error)
 578                   return error;
 579                 return args->set.nbytes;
 580 
 581               case PL_FSET:
 582                 error = verify_area(VERIFY_READ, &args->fset.nbytes,
 583                                     sizeof(args->fset.nbytes));
 584                 if (error)
 585                   return error;
 586                 return args->fset.nbytes;
 587 
 588               case PL_GET:
 589                 error = verify_area(VERIFY_READ, &args->get.min_buf_size,
 590                                     sizeof(args->get.min_buf_size));
 591                 if (error)
 592                   return error;
 593                 min_buf_size_ptr = get_user(&args->get.min_buf_size);
 594                 error = verify_area(VERIFY_WRITE, min_buf_size_ptr,
 595                                     sizeof(*min_buf_size_ptr));
 596                 if (error)
 597                   return error;
 598                 put_user(0, min_buf_size_ptr);
 599                 return 0;
 600 
 601               case PL_FGET:
 602                 error = verify_area(VERIFY_READ, &args->fget.min_buf_size,
 603                                     sizeof(args->fget.min_buf_size));
 604                 if (error)
 605                   return error;
 606                 min_buf_size_ptr = get_user(&args->fget.min_buf_size);
 607                 error = verify_area(VERIFY_WRITE, min_buf_size_ptr,
 608                                     sizeof(*min_buf_size_ptr));
 609                 if (error)
 610                   return error;
 611                 put_user(0, min_buf_size_ptr);
 612                 return 0;
 613 
 614               case PL_DEL:
 615               case PL_FDEL:
 616                 return 0;
 617 
 618               default:
 619                 return -EOPNOTSUPP;
 620         }
 621 }

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