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

   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 
  30 #include <asm/segment.h>
  31 #include <asm/system.h>
  32 #include <asm/io.h>
  33 
  34 extern int do_mount(dev_t, const char *, char *, int, void *);
  35 extern int do_pipe(int *);
  36 
  37 extern struct file_operations * get_blkfops(unsigned int);
  38 extern struct file_operations * get_chrfops(unsigned int);
  39 
  40 extern dev_t get_unnamed_dev(void);
  41 extern void put_unnamed_dev(dev_t);
  42 
  43 extern asmlinkage int sys_umount(char *);
  44 extern asmlinkage int sys_swapon(const char *specialfile);
  45 
  46 /*
  47  * OSF/1 directory handling functions...
  48  *
  49  * The "getdents()" interface is much more sane: the "basep" stuff is
  50  * braindamage (it can't really handle filesystems where the directory
  51  * offset differences aren't the same as "d_reclen").
  52  */
  53 #define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
  54 #define ROUND_UP(x) (((x)+7) & ~7)
  55 
  56 struct osf_dirent {
  57         unsigned int    d_ino;
  58         unsigned short  d_reclen;
  59         unsigned short  d_namlen;
  60         char            d_name[1];
  61 };
  62 
  63 struct osf_dirent_callback {
  64         struct osf_dirent * dirent;
  65         long *basep;
  66         int count;
  67         int error;
  68 };
  69 
  70 static int osf_filldir(void * __buf, char * name, int namlen, off_t offset, ino_t ino)
     /* [previous][next][first][last][top][bottom][index][help] */
  71 {
  72         struct osf_dirent * dirent;
  73         struct osf_dirent_callback * buf = (struct osf_dirent_callback *) __buf;
  74         int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);
  75 
  76         buf->error = -EINVAL;           /* unly used if we fail */
  77         if (reclen > buf->count)
  78                 return -EINVAL;
  79         if (buf->basep) {
  80                 put_user(offset, buf->basep);
  81                 buf->basep = NULL;
  82         }
  83         dirent = buf->dirent;
  84         put_user(ino, &dirent->d_ino);
  85         put_user(namlen, &dirent->d_namlen);
  86         put_user(reclen, &dirent->d_reclen);
  87         memcpy_tofs(dirent->d_name, name, namlen);
  88         put_fs_byte(0, dirent->d_name + namlen);
  89         ((char *) dirent) += reclen;
  90         buf->dirent = dirent;
  91         buf->count -= reclen;
  92         return 0;
  93 }
  94 
  95 asmlinkage int osf_getdirentries(unsigned int fd, struct osf_dirent * dirent,
     /* [previous][next][first][last][top][bottom][index][help] */
  96         unsigned int count, long *basep)
  97 {
  98         int error;
  99         struct file * file;
 100         struct osf_dirent_callback buf;
 101 
 102         if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
 103                 return -EBADF;
 104         if (!file->f_op || !file->f_op->readdir)
 105                 return -ENOTDIR;
 106         error = verify_area(VERIFY_WRITE, dirent, count);
 107         if (error)
 108                 return error;
 109         if (basep) {
 110                 error = verify_area(VERIFY_WRITE, basep, sizeof(long));
 111                 if (error)
 112                         return error;
 113         }
 114         buf.dirent = dirent;
 115         buf.basep = basep;
 116         buf.count = count;
 117         buf.error = 0;
 118         error = file->f_op->readdir(file->f_inode, file, dirent, osf_filldir);
 119         if (error < 0)
 120                 return error;
 121         if (count == buf.count)
 122                 return buf.error;
 123         return count - buf.count;
 124 }
 125 
 126 /*
 127  * Heh. As documented by DEC..
 128  */
 129 asmlinkage unsigned long sys_madvise(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 130 {
 131         return 0;
 132 }
 133 
 134 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] */
 135         struct pt_regs regs)
 136 {
 137         (&regs)->r20 = current->euid;
 138         return current->uid;
 139 }
 140 
 141 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] */
 142         struct pt_regs regs)
 143 {
 144         (&regs)->r20 = current->egid;
 145         return current->gid;
 146 }
 147 
 148 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] */
 149         struct pt_regs regs)
 150 {
 151         (&regs)->r20 = current->p_opptr->pid;
 152         return current->pid;
 153 }
 154 
 155 #define OSF_MAP_ANONYMOUS       0x0010
 156 #define OSF_MAP_FIXED           0x0100
 157 #define OSF_MAP_HASSEMAPHORE    0x0200
 158 #define OSF_MAP_INHERIT         0x0400
 159 #define OSF_MAP_UNALIGNED       0x0800
 160 
 161 asmlinkage unsigned long osf_mmap(unsigned long addr, unsigned long len,
     /* [previous][next][first][last][top][bottom][index][help] */
 162         unsigned long prot, unsigned long osf_flags, unsigned long fd,
 163         unsigned long off)
 164 {
 165         struct file * file = NULL;
 166         unsigned long flags = osf_flags & 0x0f;
 167 
 168         if (osf_flags & (OSF_MAP_HASSEMAPHORE | OSF_MAP_INHERIT | OSF_MAP_UNALIGNED))
 169                 printk("%s: unimplemented OSF mmap flags %04lx\n", current->comm, osf_flags);
 170         if (osf_flags & OSF_MAP_FIXED)
 171                 flags |= MAP_FIXED;
 172         if (osf_flags & OSF_MAP_ANONYMOUS)
 173                 flags |= MAP_ANONYMOUS;
 174         else {
 175                 if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
 176                         return -EBADF;
 177         }
 178         return do_mmap(file, addr, len, prot, flags, off);
 179 }
 180 
 181 asmlinkage int osf_statfs(char * path, struct statfs * buffer, unsigned long bufsiz)
     /* [previous][next][first][last][top][bottom][index][help] */
 182 {
 183         struct inode * inode;
 184         int retval;
 185 
 186         if (bufsiz > sizeof(struct statfs))
 187                 bufsiz = sizeof(struct statfs);
 188         retval = verify_area(VERIFY_WRITE, buffer, bufsiz);
 189         if (retval)
 190                 return retval;
 191         retval = namei(path, &inode);
 192         if (retval)
 193                 return retval;
 194         if (!inode->i_sb->s_op->statfs) {
 195                 iput(inode);
 196                 return -ENOSYS;
 197         }
 198         inode->i_sb->s_op->statfs(inode->i_sb, buffer, bufsiz);
 199         iput(inode);
 200         return 0;
 201 }
 202 
 203 asmlinkage int osf_fstatfs(unsigned long fd, struct statfs * buffer, unsigned long bufsiz)
     /* [previous][next][first][last][top][bottom][index][help] */
 204 {
 205         struct file * file;
 206         struct inode * inode;
 207         int retval;
 208 
 209         retval = verify_area(VERIFY_WRITE, buffer, bufsiz);
 210         if (retval)
 211                 return retval;
 212         if (bufsiz > sizeof(struct statfs))
 213                 bufsiz = sizeof(struct statfs);
 214         if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
 215                 return -EBADF;
 216         if (!(inode = file->f_inode))
 217                 return -ENOENT;
 218         if (!inode->i_sb->s_op->statfs)
 219                 return -ENOSYS;
 220         inode->i_sb->s_op->statfs(inode->i_sb, buffer, bufsiz);
 221         return 0;
 222 }
 223 
 224 /*
 225  * Uhh.. OSF/1 mount parameters aren't exactly obvious..
 226  *
 227  * Although to be frank, neither are the native Linux/i386 ones..
 228  */
 229 struct ufs_args {
 230         char * devname;
 231         int flags;
 232         uid_t exroot;
 233 };
 234 
 235 struct cdfs_args {
 236         char * devname;
 237         int flags;
 238         uid_t exroot;
 239 /*
 240  * this has lots more here, which linux handles with the option block
 241  * but I'm too lazy to do the translation into ascii..
 242  */
 243 };
 244 
 245 struct procfs_args {
 246         char * devname;
 247         int flags;
 248         uid_t exroot;
 249 };
 250 
 251 static int getdev(const char * name, int rdonly, struct inode ** ino)
     /* [previous][next][first][last][top][bottom][index][help] */
 252 {
 253         dev_t dev;
 254         struct inode * inode;
 255         struct file_operations * fops;
 256         int retval;
 257 
 258         retval = namei(name, &inode);
 259         if (retval)
 260                 return retval;
 261         if (!S_ISBLK(inode->i_mode)) {
 262                 iput(inode);
 263                 return -ENOTBLK;
 264         }
 265         if (IS_NODEV(inode)) {
 266                 iput(inode);
 267                 return -EACCES;
 268         }
 269         dev = inode->i_rdev;
 270         if (MAJOR(dev) >= MAX_BLKDEV) {
 271                 iput(inode);
 272                 return -ENXIO;
 273         }
 274         fops = get_blkfops(MAJOR(dev));
 275         if (!fops) {
 276                 iput(inode);
 277                 return -ENODEV;
 278         }
 279         if (fops->open) {
 280                 struct file dummy;
 281                 memset(&dummy, 0, sizeof(dummy));
 282                 dummy.f_inode = inode;
 283                 dummy.f_mode = rdonly ? 1 : 3;
 284                 retval = fops->open(inode, &dummy);
 285                 if (retval) {
 286                         iput(inode);
 287                         return retval;
 288                 }
 289         }
 290         *ino = inode;
 291         return 0;
 292 }
 293 
 294 static void putdev(struct inode * inode)
     /* [previous][next][first][last][top][bottom][index][help] */
 295 {
 296         struct file_operations * fops;
 297 
 298         fops = get_blkfops(MAJOR(inode->i_rdev));
 299         if (fops->release)
 300                 fops->release(inode, NULL);
 301 }
 302 
 303 /*
 304  * We can't actually handle ufs yet, so we translate UFS mounts to
 305  * ext2fs mounts... I wouldn't mind a USF filesystem, but the UFS
 306  * layout is so braindead it's a major headache doing it..
 307  */
 308 static int osf_ufs_mount(char * dirname, struct ufs_args * args, int flags)
     /* [previous][next][first][last][top][bottom][index][help] */
 309 {
 310         int retval;
 311         struct inode * inode;
 312         struct cdfs_args tmp;
 313 
 314         retval = verify_area(VERIFY_READ, args, sizeof(*args));
 315         if (retval)
 316                 return retval;
 317         memcpy_fromfs(&tmp, args, sizeof(tmp));
 318         retval = getdev(tmp.devname, 0, &inode);
 319         if (retval)
 320                 return retval;
 321         retval = do_mount(inode->i_rdev, dirname, "ext2", flags, NULL);
 322         if (retval)
 323                 putdev(inode);
 324         iput(inode);
 325         return retval;
 326 }
 327 
 328 static int osf_cdfs_mount(char * dirname, struct cdfs_args * args, int flags)
     /* [previous][next][first][last][top][bottom][index][help] */
 329 {
 330         int retval;
 331         struct inode * inode;
 332         struct cdfs_args tmp;
 333 
 334         retval = verify_area(VERIFY_READ, args, sizeof(*args));
 335         if (retval)
 336                 return retval;
 337         memcpy_fromfs(&tmp, args, sizeof(tmp));
 338         retval = getdev(tmp.devname, 1, &inode);
 339         if (retval)
 340                 return retval;
 341         retval = do_mount(inode->i_rdev, dirname, "iso9660", flags, NULL);
 342         if (retval)
 343                 putdev(inode);
 344         iput(inode);
 345         return retval;
 346 }
 347 
 348 static int osf_procfs_mount(char * dirname, struct procfs_args * args, int flags)
     /* [previous][next][first][last][top][bottom][index][help] */
 349 {
 350         dev_t dev;
 351         int retval;
 352         struct procfs_args tmp;
 353 
 354         retval = verify_area(VERIFY_READ, args, sizeof(*args));
 355         if (retval)
 356                 return retval;
 357         memcpy_fromfs(&tmp, args, sizeof(tmp));
 358         dev = get_unnamed_dev();
 359         if (!dev)
 360                 return -ENODEV;
 361         retval = do_mount(dev, dirname, "proc", flags, NULL);
 362         if (retval)
 363                 put_unnamed_dev(dev);
 364         return retval;
 365 }
 366 
 367 asmlinkage int osf_mount(unsigned long typenr, char * path, int flag, void * data)
     /* [previous][next][first][last][top][bottom][index][help] */
 368 {
 369         int retval;
 370 
 371         retval = -EINVAL;
 372         switch (typenr) {
 373                 case 1:
 374                         retval = osf_ufs_mount(path, (struct ufs_args *) data, flag);
 375                         break;
 376                 case 6:
 377                         retval = osf_cdfs_mount(path, (struct cdfs_args *) data, flag);
 378                         break;
 379                 case 9:
 380                         retval = osf_procfs_mount(path, (struct procfs_args *) data, flag);
 381                         break;
 382                 default:
 383                         printk("osf_mount(%ld, %x)\n", typenr, flag);
 384         }
 385         return retval;
 386 }
 387 
 388 asmlinkage int osf_umount(char * path, int flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 389 {
 390         return sys_umount(path);
 391 }
 392 
 393 /*
 394  * I don't know what the parameters are: the first one
 395  * seems to be a timeval pointer, and I suspect the second
 396  * one is the time remaining.. Ho humm.. No documentation.
 397  */
 398 asmlinkage int osf_usleep_thread(struct timeval * sleep, struct timeval * remain)
     /* [previous][next][first][last][top][bottom][index][help] */
 399 {
 400         struct timeval tmp;
 401         unsigned long ticks;
 402         int retval;
 403 
 404         retval = verify_area(VERIFY_READ, sleep, sizeof(*sleep));
 405         if (retval)
 406                 return retval;
 407         if (remain && (retval = verify_area(VERIFY_WRITE, remain, sizeof(*remain))))
 408                 return retval;
 409         memcpy_fromfs(&tmp, sleep, sizeof(*sleep));
 410         ticks = tmp.tv_usec;
 411         ticks = (ticks + (1000000 / HZ) - 1) / (1000000 / HZ);
 412         ticks += tmp.tv_sec * HZ;
 413         current->timeout = ticks + jiffies;
 414         current->state = TASK_INTERRUPTIBLE;
 415         schedule();
 416         if (!remain)
 417                 return 0;
 418         ticks = jiffies;
 419         if (ticks < current->timeout)
 420                 ticks = current->timeout - ticks;
 421         else
 422                 ticks = 0;
 423         current->timeout = 0;
 424         tmp.tv_sec = ticks / HZ;
 425         tmp.tv_usec = ticks % HZ;
 426         memcpy_tofs(remain, &tmp, sizeof(*remain));
 427         return 0;
 428 }
 429 
 430 asmlinkage int osf_utsname(char * name)
     /* [previous][next][first][last][top][bottom][index][help] */
 431 {
 432         int error = verify_area(VERIFY_WRITE, name, 5*32);
 433         if (error)
 434                 return error;
 435         memcpy_tofs(name +   0, system_utsname.sysname, 32);
 436         memcpy_tofs(name +  32, system_utsname.nodename, 32);
 437         memcpy_tofs(name +  64, system_utsname.release, 32);
 438         memcpy_tofs(name +  96, system_utsname.version, 32);
 439         memcpy_tofs(name + 128, system_utsname.machine, 32);
 440         return 0;
 441 }
 442 
 443 asmlinkage int osf_swapon(const char * path, int flags, int lowat, int hiwat)
     /* [previous][next][first][last][top][bottom][index][help] */
 444 {
 445         /* for now, simply ignore flags, lowat and hiwat... */
 446         return sys_swapon(path);
 447 }
 448 
 449 asmlinkage unsigned long sys_getpagesize(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 450 {
 451         return PAGE_SIZE;
 452 }
 453 
 454 asmlinkage unsigned long sys_getdtablesize(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 455 {
 456         return NR_OPEN;
 457 }
 458 
 459 asmlinkage int sys_pipe(int a0, int a1, int a2, int a3, int a4, int a5,
     /* [previous][next][first][last][top][bottom][index][help] */
 460         struct pt_regs regs)
 461 {
 462         int fd[2];
 463         int error;
 464 
 465         error = do_pipe(fd);
 466         if (error)
 467                 return error;
 468         (&regs)->r20 = fd[1];
 469         return fd[0];
 470 }
 471 
 472 /*
 473  * For compatibility with OSF/1 only.  Use utsname(2) instead.
 474  */
 475 asmlinkage int osf_getdomainname(char *name, int namelen)
     /* [previous][next][first][last][top][bottom][index][help] */
 476 {
 477         unsigned len;
 478         int i, error;
 479 
 480         error = verify_area(VERIFY_WRITE, name, namelen);
 481         if (error)
 482                 return error;
 483 
 484         len = namelen;
 485         if (namelen > 32)
 486           len = 32;
 487 
 488         for (i = 0; i < len; ++i) {
 489                 put_user(system_utsname.domainname[i], name + i);
 490                 if (system_utsname.domainname[i] == '\0')
 491                   break;
 492         }
 493         return 0;
 494 }

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