home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / CPM / UZI / UZI.ARK / SCALL1.C < prev    next >
C/C++ Source or Header  |  1988-11-29  |  27KB  |  1,463 lines

  1. /**************************************************
  2. UZI (Unix Z80 Implementation) Kernel:  scall1.c
  3. ***************************************************/
  4.  
  5.  
  6. /*LINTLIBRARY*/
  7. #include "unix.h"
  8. #include "extern.h"
  9.  
  10.  
  11. /*******************************************
  12. open(name, flag)
  13. char *name;
  14. register int16 flag;
  15. *********************************************/
  16.  
  17. #define name (char *)udata.u_argn1
  18. #define flag (int16)udata.u_argn
  19.  
  20. _open()
  21. {
  22.     int16 uindex;
  23.     register int16 oftindex;
  24.     register inoptr ino;
  25.     register int16 perm;
  26.     inoptr n_open();
  27.  
  28.     if (flag < 0 || flag > 2)
  29.     {
  30.     udata.u_error = EINVAL;
  31.     return (-1);
  32.     }
  33.     if ((uindex = uf_alloc()) == -1)
  34.     return (-1);
  35.  
  36.     if ((oftindex = oft_alloc()) == -1)
  37.     goto nooft;
  38.  
  39.     ifnot (ino = n_open(name,NULLINOPTR))
  40.     goto cantopen;
  41.  
  42.     of_tab[oftindex].o_inode = ino;
  43.  
  44.     perm = getperm(ino);
  45.     if (((flag == O_RDONLY || flag == O_RDWR) && !(perm & OTH_RD)) ||
  46.     ((flag == O_WRONLY || flag == O_RDWR) && !(perm & OTH_WR)))
  47.     {
  48.     udata.u_error = EPERM;
  49.     goto cantopen;
  50.     }
  51.  
  52.     if (getmode(ino) == F_DIR &&
  53.     (flag == O_WRONLY || flag == O_RDWR))
  54.     {
  55.     udata.u_error = EISDIR;
  56.     goto cantopen;
  57.     }
  58.  
  59.     if (isdevice(ino) && d_open((int)ino->c_node.i_addr[0]) != 0)
  60.     {
  61.     udata.u_error = ENXIO;
  62.     goto cantopen;
  63.     }
  64.  
  65.     udata.u_files[uindex] = oftindex;
  66.  
  67.     of_tab[oftindex].o_ptr.o_offset = 0;
  68.     of_tab[oftindex].o_ptr.o_blkno = 0;
  69.     of_tab[oftindex].o_access = flag;
  70.  
  71.     return (uindex);
  72.  
  73. cantopen:
  74.     oft_deref(oftindex);  /* This will call i_deref() */
  75. nooft:
  76.     udata.u_files[uindex] = -1;
  77.     return (-1);
  78. }
  79.  
  80. #undef name
  81. #undef flag
  82.  
  83.  
  84.  
  85. /*********************************************
  86. close(uindex)
  87. int16 uindex;
  88. **********************************************/
  89.  
  90. #define uindex (int16)udata.u_argn
  91.  
  92. _close()
  93. {
  94.     return(doclose(uindex));
  95. }
  96.  
  97. #undef uindex
  98.  
  99.  
  100. doclose(uindex)
  101. int16 uindex;
  102. {
  103.     register int16 oftindex;
  104.     inoptr ino;
  105.     inoptr getinode();
  106.  
  107.     ifnot(ino = getinode(uindex))
  108.     return(-1);
  109.     oftindex = udata.u_files[uindex];
  110.  
  111.     if (isdevice(ino)
  112.     /* && ino->c_refs == 1 && of_tab[oftindex].o_refs == 1 */ )
  113.     d_close((int)(ino->c_node.i_addr[0]));
  114.  
  115.     udata.u_files[uindex] = -1;
  116.     oft_deref(oftindex);
  117.  
  118.     return(0);
  119. }
  120.  
  121.  
  122.  
  123. /****************************************
  124. creat(name, mode)
  125. char *name;
  126. int16 mode;
  127. *****************************************/
  128.  
  129. #define name (char *)udata.u_argn1
  130. #define mode (int16)udata.u_argn
  131.  
  132. _creat()
  133. {
  134.     register inoptr ino;
  135.     register int16 uindex;
  136.     register int16 oftindex;
  137.     inoptr parent;
  138.     register int16 j;
  139.     inoptr n_open();
  140.     inoptr newfile();
  141.  
  142.     parent = NULLINODE;
  143.  
  144.     if ((uindex = uf_alloc()) == -1)
  145.     return (-1);
  146.     if ((oftindex = oft_alloc()) == -1)
  147.     return (-1);
  148.  
  149.     if (ino = n_open(name,&parent))  /* The file exists */
  150.     {
  151.     i_deref(parent);
  152.     if (getmode(ino) == F_DIR)
  153.     {
  154.         i_deref(ino);
  155.         udata.u_error = EISDIR;
  156.         goto nogood;
  157.     }
  158.     ifnot (getperm(ino) & OTH_WR)
  159.     {
  160.         i_deref(ino);
  161.         udata.u_error = EACCES;
  162.         goto nogood;
  163.     }
  164.     if (getmode(ino) == F_REG)
  165.     {
  166.         /* Truncate the file to zero length */
  167.         f_trunc(ino);
  168.         /* Reset any oft pointers */
  169.         for (j=0; j < OFTSIZE; ++j)
  170.             if (of_tab[j].o_inode == ino)
  171.                 of_tab[j].o_ptr.o_blkno = of_tab[j].o_ptr.o_offset = 0;
  172.     }
  173.  
  174.     }
  175.     else
  176.     {
  177.     if (parent && (ino = newfile(parent,name)))
  178.              /* Parent was derefed in newfile */
  179.     {
  180.         ino->c_node.i_mode = (F_REG | (mode & MODE_MASK & ~udata.u_mask));
  181.         setftime(ino, A_TIME|M_TIME|C_TIME);
  182.         /* The rest of the inode is initialized in newfile() */
  183.         wr_inode(ino);
  184.     }
  185.     else
  186.     {
  187.         /* Doesn't exist and can't make it */
  188.         if (parent)
  189.             i_deref(parent);
  190.         goto nogood;
  191.     }
  192.     }
  193.  
  194.     udata.u_files[uindex] = oftindex;
  195.  
  196.     of_tab[oftindex].o_ptr.o_offset = 0;
  197.     of_tab[oftindex].o_ptr.o_blkno = 0;
  198.     of_tab[oftindex].o_inode = ino;
  199.     of_tab[oftindex].o_access = O_WRONLY;
  200.  
  201.     return (uindex);
  202.  
  203. nogood:
  204.     oft_deref(oftindex);
  205.     return (-1);
  206.  
  207. }
  208.  
  209. #undef name
  210. #undef mode
  211.  
  212.  
  213.  
  214. /********************************************
  215. pipe(fildes)
  216. int fildes[];
  217. *******************************************/
  218.  
  219. #define fildes (int *)udata.u_argn
  220.  
  221. _pipe()
  222. {
  223.     register int16 u1, u2, oft1, oft2;
  224.     register inoptr ino;
  225.     inoptr i_open();
  226.  
  227.     if ((u1 = uf_alloc()) == -1)
  228.     goto nogood2;
  229.     if ((oft1 = oft_alloc()) == -1)
  230.     goto nogood2;
  231.     udata.u_files[u1] = oft1;
  232.  
  233.     if ((u2 = uf_alloc()) == -1)
  234.     goto nogood;
  235.     if ((oft2 = oft_alloc()) == -1)
  236.     {
  237.     oft_deref(oft1);
  238.     goto nogood;
  239.     }
  240.  
  241.     ifnot (ino = i_open(ROOTDEV, 0))
  242.     {
  243.     oft_deref(oft1);
  244.     oft_deref(oft2);
  245.     goto nogood;
  246.     }
  247.  
  248.     udata.u_files[u2] = oft2;
  249.  
  250.     of_tab[oft1].o_ptr.o_offset = 0;
  251.     of_tab[oft1].o_ptr.o_blkno = 0;
  252.     of_tab[oft1].o_inode = ino;
  253.     of_tab[oft1].o_access = O_RDONLY;
  254.  
  255.     of_tab[oft2].o_ptr.o_offset = 0;
  256.     of_tab[oft2].o_ptr.o_blkno = 0;
  257.     of_tab[oft2].o_inode = ino;
  258.     of_tab[oft2].o_access = O_WRONLY;
  259.  
  260.     ++ino->c_refs;
  261.     ino->c_node.i_mode = F_PIPE | 0777; /* No permissions necessary on pipes */
  262.     ino->c_node.i_nlink = 0;            /* a pipe is not in any directory */
  263.  
  264.     *fildes = u1;
  265.     *(fildes+1) = u2;
  266.     return (0);
  267.  
  268. nogood:
  269.     udata.u_files[u1] = -1;
  270. nogood2:
  271.     return(-1);
  272.  
  273. }
  274.  
  275. #undef fildes
  276.  
  277.  
  278.  
  279. /********************************************
  280. link(name1, name2)
  281. char *name1;
  282. char *name2;
  283. *********************************************/
  284.  
  285. #define name1 (char *)udata.u_argn1
  286. #define name2 (char *)udata.u_argn
  287.  
  288. _link()
  289. {
  290.     register inoptr ino;
  291.     register inoptr ino2;
  292.     inoptr parent2;
  293.     char *filename();
  294.     inoptr n_open();
  295.  
  296.     ifnot (ino = n_open(name1,NULLINOPTR))
  297.     return(-1);
  298.  
  299.     if (getmode(ino) == F_DIR && !super())
  300.     {
  301.     udata.u_error = EPERM;
  302.     goto nogood;
  303.     }
  304.  
  305.     /* Make sure file2 doesn't exist, and get its parent */
  306.     if (ino2 = n_open(name2,&parent2))
  307.     {
  308.     i_deref(ino2);
  309.     i_deref(parent2);
  310.     udata.u_error = EEXIST;
  311.     goto nogood;
  312.     }
  313.  
  314.     ifnot (parent2)
  315.     goto nogood;
  316.  
  317.     if (ino->c_dev != parent2->c_dev)
  318.     {
  319.     i_deref(parent2);
  320.     udata.u_error = EXDEV;
  321.     goto nogood;
  322.     }
  323.  
  324.     if (ch_link(parent2,"",filename(name2),ino) == 0)
  325.     goto nogood;
  326.  
  327.  
  328.     /* Update the link count. */
  329.     ++ino->c_node.i_nlink;
  330.     wr_inode(ino);
  331.     setftime(ino, C_TIME);
  332.  
  333.     i_deref(parent2);
  334.     i_deref(ino);
  335.     return(0);
  336.  
  337. nogood:
  338.     i_deref(ino);
  339.     return(-1);
  340.  
  341. }
  342.  
  343. #undef name1
  344. #undef name2
  345.  
  346.  
  347.  
  348. /**********************************************************
  349. unlink(path)
  350. char *path;
  351. **************************************************/
  352.  
  353. #define path (char *)udata.u_argn
  354.  
  355. _unlink()
  356. {
  357.     register inoptr ino;
  358.     inoptr pino;
  359.     char *filename();
  360.     inoptr i_open();
  361.     inoptr n_open();
  362.  
  363.     ino = n_open(path,&pino);
  364.  
  365.     ifnot (pino && ino)
  366.     {
  367.     udata.u_error = ENOENT;
  368.     return (-1);
  369.     }
  370.  
  371.     if (getmode(ino) == F_DIR && !super())
  372.     {
  373.     udata.u_error = EPERM;
  374.     goto nogood;
  375.     }
  376.  
  377.     /* Remove the directory entry */
  378.  
  379.     if (ch_link(pino,filename(path),"",NULLINODE) == 0)
  380.     goto nogood;
  381.  
  382.     /* Decrease the link count of the inode */
  383.  
  384.     ifnot (ino->c_node.i_nlink--)
  385.     {
  386.     ino->c_node.i_nlink += 2;
  387.     warning("_unlink: bad nlink");
  388.     }
  389.     setftime(ino, C_TIME);
  390.     i_deref(pino);
  391.     i_deref(ino);
  392.     return(0);
  393.  
  394. nogood:
  395.     i_deref(pino);
  396.     i_deref(ino);
  397.     return(-1);
  398. }
  399.  
  400. #undef path
  401.  
  402.  
  403.  
  404. /*****************************************************
  405. read(d, buf, nbytes)
  406. int16 d;
  407. char *buf;
  408. uint16 nbytes;
  409. **********************************************/
  410.  
  411. #define d (int16)udata.u_argn2
  412. #define buf (char *)udata.u_argn1
  413. #define nbytes (uint16)udata.u_argn
  414.  
  415. _read()
  416. {
  417.     register inoptr ino;
  418.     inoptr rwsetup();
  419.  
  420.     /* Set up u_base, u_offset, ino; check permissions, file num. */
  421.     if ((ino = rwsetup(1)) == NULLINODE)
  422.     return (-1);   /* bomb out if error */
  423.  
  424.     readi(ino);
  425.     updoff();
  426.  
  427.     return (udata.u_count);
  428. }
  429.  
  430. #undef d
  431. #undef buf
  432. #undef nbytes
  433.  
  434.  
  435. /***********************************
  436. write(d, buf, nbytes)
  437. int16 d;
  438. char *buf;
  439. uint16 nbytes;
  440. ***********************************/
  441.  
  442. #define d (int16)udata.u_argn2
  443. #define buf (char *)udata.u_argn1
  444. #define nbytes (uint16)udata.u_argn
  445.  
  446. _write()
  447. {
  448.     register inoptr ino;
  449.     off_t *offp;
  450.     inoptr rwsetup();
  451.  
  452.     /* Set up u_base, u_offset, ino; check permissions, file num. */
  453.     if ((ino = rwsetup(0)) == NULLINODE)
  454.     return (-1);   /* bomb out if error */
  455.  
  456.     writei(ino);
  457.     updoff();
  458.  
  459.     return (udata.u_count);
  460. }
  461.  
  462. #undef d
  463. #undef buf
  464. #undef nbytes
  465.  
  466.  
  467.  
  468. inoptr
  469. rwsetup(rwflag)
  470. int rwflag;
  471. {
  472.     register inoptr ino;
  473.     register struct oft *oftp;
  474.     inoptr getinode();
  475.  
  476.     udata.u_base = (char *)udata.u_argn1;  /* buf */
  477.     udata.u_count = (uint16)udata.u_argn;  /* nbytes */
  478.  
  479.     if ((ino = getinode(udata.u_argn2)) == NULLINODE)
  480.     return (NULLINODE);
  481.  
  482.     oftp = of_tab + udata.u_files[udata.u_argn2];
  483.     if (oftp->o_access == (rwflag ? O_WRONLY : O_RDONLY))
  484.     {
  485.     udata.u_error = EBADF;
  486.     return (NULLINODE);
  487.     }
  488.  
  489.     setftime(ino, rwflag ? A_TIME : (A_TIME | M_TIME | C_TIME));
  490.  
  491.     /* Initialize u_offset from file pointer */
  492.     udata.u_offset.o_blkno = oftp->o_ptr.o_blkno;
  493.     udata.u_offset.o_offset = oftp->o_ptr.o_offset;
  494.  
  495.     return (ino);
  496. }
  497.  
  498.  
  499.  
  500. readi(ino)
  501. register inoptr ino;
  502. {
  503.     register uint16 amount;
  504.     register uint16 toread;
  505.     register blkno_t pblk;
  506.     register char *bp;
  507.     int dev;
  508.     int ispipe;
  509.     char *bread();
  510.     char *zerobuf();
  511.     blkno_t bmap();
  512.  
  513.     dev = ino->c_dev;
  514.     ispipe = 0;
  515.     switch (getmode(ino))
  516.     {
  517.  
  518.     case F_DIR:
  519.     case F_REG:
  520.  
  521.     /* See of end of file will limit read */
  522.     toread = udata.u_count =
  523.         ino->c_node.i_size.o_blkno-udata.u_offset.o_blkno >= 64 ?
  524.             udata.u_count :
  525.             min(udata.u_count,
  526.              512*(ino->c_node.i_size.o_blkno-udata.u_offset.o_blkno) +
  527.              (ino->c_node.i_size.o_offset-udata.u_offset.o_offset));
  528.     goto loop;
  529.  
  530.     case F_PIPE:
  531.     ispipe = 1;
  532.     while (psize(ino) == 0)
  533.     {
  534.         if (ino->c_refs == 1) /* No writers */
  535.             break;
  536.         /* Sleep if empty pipe */
  537.         psleep(ino);
  538.     }
  539.     toread = udata.u_count = min(udata.u_count, psize(ino));
  540.     goto loop;
  541.  
  542.     case F_BDEV:
  543.     toread = udata.u_count;
  544.     dev = *(ino->c_node.i_addr);
  545.  
  546.     loop:
  547.     while (toread)
  548.     {
  549.         if ((pblk = bmap(ino, udata.u_offset.o_blkno, 1)) != NULLBLK)
  550.             bp = bread(dev, pblk, 0);
  551.         else
  552.             bp = zerobuf();
  553.  
  554.         bcopy(bp+udata.u_offset.o_offset, udata.u_base,
  555.                 (amount = min(toread, 512 - udata.u_offset.o_offset)));
  556.         brelse(bp);
  557.  
  558.         udata.u_base += amount;
  559.         addoff(&udata.u_offset, amount);
  560.         if (ispipe && udata.u_offset.o_blkno >= 18)
  561.             udata.u_offset.o_blkno = 0;
  562.         toread -= amount;
  563.         if (ispipe)
  564.         {
  565.             addoff(&(ino->c_node.i_size), -amount);
  566.             wakeup(ino);
  567.         }
  568.     }
  569.  
  570.     break;
  571.  
  572.     case F_CDEV:
  573.     udata.u_count = cdread(ino->c_node.i_addr[0]);
  574.  
  575.     if (udata.u_count != -1)
  576.         addoff(&udata.u_offset, udata.u_count);
  577.     break;
  578.  
  579.     default:
  580.     udata.u_error = ENODEV;
  581.     }
  582. }
  583.  
  584.  
  585.  
  586. /* Writei (and readi) need more i/o error handling */
  587.  
  588. writei(ino)
  589. register inoptr ino;
  590. {
  591.     register uint16 amount;
  592.     register uint16 towrite;
  593.     register char *bp;
  594.     int ispipe;
  595.     blkno_t pblk;
  596.     int created;        /* Set by bmap if newly allocated block used */
  597.     int dev;
  598.     char *zerobuf();
  599.     char *bread();
  600.     blkno_t bmap();
  601.  
  602.     dev = ino->c_dev;
  603.  
  604.     switch (getmode(ino))
  605.     {
  606.  
  607.     case F_BDEV:
  608.     dev = *(ino->c_node.i_addr);
  609.     case F_DIR:
  610.     case F_REG:
  611.     ispipe = 0;
  612.     towrite = udata.u_count;
  613.     goto loop;
  614.  
  615.     case F_PIPE:
  616.     ispipe = 1;
  617.     while ((towrite = udata.u_count) > (16*512) - psize(ino))
  618.     {
  619.         if (ino->c_refs == 1) /* No readers */
  620.         {
  621.             udata.u_count = -1;
  622.             udata.u_error = EPIPE;
  623.             ssig(udata.u_ptab, SIGPIPE);
  624.             return;
  625.         }
  626.         /* Sleep if empty pipe */
  627.         psleep(ino);
  628.     }
  629.  
  630.     /* Sleep if empty pipe */
  631.     goto loop;
  632.  
  633.     loop:
  634.  
  635.     while (towrite)
  636.     {
  637.         amount = min(towrite, 512 - udata.u_offset.o_offset);
  638.  
  639.  
  640.         if ((pblk = bmap(ino, udata.u_offset.o_blkno, 0)) == NULLBLK)
  641.             break;    /* No space to make more blocks */
  642.  
  643.         /* If we are writing an entire block, we don't care
  644.         about its previous contents */
  645.         bp = bread(dev, pblk, (amount == 512));
  646.  
  647.         bcopy(udata.u_base, bp+udata.u_offset.o_offset, amount);
  648.         bawrite(bp);
  649.  
  650.         udata.u_base += amount;
  651.         addoff(&udata.u_offset, amount);
  652.         if(ispipe)
  653.         {
  654.             if (udata.u_offset.o_blkno >= 18)
  655.                 udata.u_offset.o_blkno = 0;
  656.             addoff(&(ino->c_node.i_size), amount);
  657.             /* Wake up any readers */
  658.             wakeup(ino);
  659.         }
  660.         towrite -= amount;
  661.     }
  662.  
  663.     /* Update size if file grew */
  664.     ifnot (ispipe)
  665.     {
  666.         if ( udata.u_offset.o_blkno > ino->c_node.i_size.o_blkno ||
  667.             (udata.u_offset.o_blkno == ino->c_node.i_size.o_blkno &&
  668.                 udata.u_offset.o_offset > ino->c_node.i_size.o_offset))
  669.         {
  670.             ino->c_node.i_size.o_blkno = udata.u_offset.o_blkno;
  671.             ino->c_node.i_size.o_offset = udata.u_offset.o_offset;
  672.             ino->c_dirty = 1;
  673.         }
  674.     }
  675.  
  676.     break;
  677.  
  678.     case F_CDEV:
  679.     udata.u_count = cdwrite(ino->c_node.i_addr[0]);
  680.  
  681.     if (udata.u_count != -1)
  682.         addoff(&udata.u_offset, udata.u_count);
  683.     break;
  684.  
  685.     default:
  686.     udata.u_error = ENODEV;
  687.     }
  688.  
  689. }
  690.  
  691.  
  692. min(a, b)
  693. int a, b;
  694. {
  695.     return ( a < b ? a : b);
  696. }
  697.  
  698.  
  699. psize(ino)
  700. inoptr ino;
  701. {
  702.     return (512*ino->c_node.i_size.o_blkno+ino->c_node.i_size.o_offset);
  703. }
  704.  
  705.  
  706.  
  707. addoff(ofptr, amount)
  708. off_t *ofptr;
  709. int amount;
  710. {
  711.     if (amount >= 0)
  712.     {
  713.     ofptr->o_offset += amount % 512;
  714.     if (ofptr->o_offset >= 512)
  715.     {
  716.     ofptr->o_offset -= 512;
  717.     ++ofptr->o_blkno;
  718.     }
  719.     ofptr->o_blkno += amount/512;
  720.     }
  721.     else
  722.     {
  723.     ofptr->o_offset -= (-amount) % 512;
  724.     if (ofptr->o_offset < 0)
  725.     {
  726.         ofptr->o_offset += 512;
  727.         --ofptr->o_blkno;
  728.     }
  729.     ofptr->o_blkno -= (-amount)/512;
  730.     }
  731. }
  732.  
  733.  
  734. updoff()
  735. {
  736.     register off_t *offp;
  737.  
  738.     /* Update current file pointer */
  739.     offp = &of_tab[udata.u_files[udata.u_argn2]].o_ptr;
  740.     offp->o_blkno = udata.u_offset.o_blkno;
  741.     offp->o_offset = udata.u_offset.o_offset;
  742. }
  743.  
  744.  
  745.  
  746. /****************************************
  747. seek(file,offset,flag)
  748. int16 file;
  749. uint16 offset;
  750. int16 flag;
  751. *****************************************/
  752.  
  753. #define file (int16)udata.u_argn2
  754. #define offset (uint16)udata.u_argn1
  755. #define flag (int16)udata.u_argn
  756.  
  757. _seek()
  758. {
  759.     register inoptr ino;
  760.     register int16 oftno;
  761.     register uint16 retval;
  762.     inoptr getinode();
  763.  
  764.     if ((ino = getinode(file)) == NULLINODE)
  765.     return(-1);
  766.  
  767.     if (getmode(ino) == F_PIPE)
  768.     {
  769.     udata.u_error = ESPIPE;
  770.     return(-1);
  771.     }
  772.  
  773.     oftno = udata.u_files[file];
  774.  
  775.  
  776.     if (flag <= 2)
  777.     retval = of_tab[oftno].o_ptr.o_offset;
  778.     else
  779.     retval = of_tab[oftno].o_ptr.o_blkno;
  780.  
  781.     switch(flag)
  782.     {
  783.     case 0:
  784.     of_tab[oftno].o_ptr.o_blkno = 0;
  785.     of_tab[oftno].o_ptr.o_offset = offset;
  786.     break;
  787.     case 1:
  788.     of_tab[oftno].o_ptr.o_offset += offset;
  789.     break;
  790.     case 2:
  791.     of_tab[oftno].o_ptr.o_blkno = ino->c_node.i_size.o_blkno;
  792.     of_tab[oftno].o_ptr.o_offset = ino->c_node.i_size.o_offset + offset;
  793.     break;
  794.     case 3:
  795.     of_tab[oftno].o_ptr.o_blkno = offset;
  796.     break;
  797.     case 4:
  798.     of_tab[oftno].o_ptr.o_blkno += offset;
  799.     break;
  800.     case 5:
  801.     of_tab[oftno].o_ptr.o_blkno = ino->c_node.i_size.o_blkno + offset;
  802.     break;
  803.     default:
  804.     udata.u_error = EINVAL;
  805.     return(-1);
  806.     }
  807.  
  808.     while ((unsigned)of_tab[oftno].o_ptr.o_offset >= 512)
  809.     {
  810.     of_tab[oftno].o_ptr.o_offset -= 512;
  811.     ++of_tab[oftno].o_ptr.o_blkno;
  812.     }
  813.  
  814.     return((int16)retval);
  815. }
  816.  
  817. #undef file
  818. #undef offset
  819. #undef flag
  820.  
  821.  
  822.  
  823. /************************************
  824. chdir(dir)
  825. char *dir;
  826. ************************************/
  827.  
  828. #define dir (char *)udata.u_argn
  829.  
  830. _chdir()
  831. {
  832.     register inoptr newcwd;
  833.     inoptr n_open();
  834.  
  835.     ifnot (newcwd = n_open(dir,NULLINOPTR))
  836.     return(-1);
  837.  
  838.     if (getmode(newcwd) != F_DIR)
  839.     {
  840.     udata.u_error = ENOTDIR;
  841.     i_deref(newcwd);
  842.     return(-1);
  843.     }
  844.     i_deref(udata.u_cwd);
  845.     udata.u_cwd = newcwd;
  846.     return(0);
  847. }
  848.  
  849. #undef dir
  850.  
  851.  
  852.  
  853. /*************************************
  854. mknod(name,mode,dev)
  855. char *name;
  856. int16 mode;
  857. int16 dev;
  858. ***************************************/
  859.  
  860. #define name (char *)udata.u_argn2
  861. #define mode (int16)udata.u_argn1
  862. #define dev (int16)udata.u_argn
  863.  
  864. _mknod()
  865. {
  866.     register inoptr ino;
  867.     inoptr parent;
  868.     inoptr n_open();
  869.     inoptr newfile();
  870.  
  871.     udata.u_error = 0;
  872.     ifnot (super())
  873.     {
  874.     udata.u_error = EPERM;
  875.     return(-1);
  876.     }
  877.  
  878.     if (ino = n_open(name,&parent))
  879.     {
  880.     udata.u_error = EEXIST;
  881.     goto nogood;
  882.     }
  883.  
  884.     ifnot (parent)
  885.     {
  886.     udata.u_error = ENOENT;
  887.     goto nogood3;
  888.     }
  889.  
  890.     ifnot (ino = newfile(parent,name))
  891.     goto nogood2;
  892.  
  893.     /* Initialize mode and dev */
  894.     ino->c_node.i_mode = mode & ~udata.u_mask;
  895.     ino->c_node.i_addr[0] = isdevice(ino) ? dev : 0;
  896.     setftime(ino, A_TIME|M_TIME|C_TIME);
  897.     wr_inode(ino);
  898.  
  899.     i_deref(ino);
  900.     return (0);
  901.  
  902. nogood:
  903.     i_deref(ino);
  904. nogood2:
  905.     i_deref(parent);
  906. nogood3:
  907.     return (-1);
  908. }
  909.  
  910. #undef name
  911. #undef mode
  912. #undef dev
  913.  
  914.  
  915.  
  916. /****************************************
  917. sync()
  918. ***************************************/
  919.  
  920. _sync()
  921. {
  922.     register j;
  923.     register inoptr ino;
  924.     register char *buf;
  925.     char *bread();
  926.  
  927.     /* Write out modified inodes */
  928.  
  929.     for (ino=i_tab; ino < i_tab+ITABSIZE; ++ino)
  930.     if ((ino->c_refs) > 0 && ino->c_dirty != 0)
  931.     {
  932.         wr_inode(ino);
  933.         ino->c_dirty = 0;
  934.     }
  935.  
  936.     /* Write out modified super blocks */
  937.     /* This fills the rest of the super block with garbage. */
  938.  
  939.     for (j=0; j < NDEVS; ++j)
  940.     {
  941.     if (fs_tab[j].s_mounted == SMOUNTED && fs_tab[j].s_fmod)
  942.     {
  943.         fs_tab[j].s_fmod = 0;
  944.         buf = bread(j, 1, 1);
  945.         bcopy((char *)&fs_tab[j], buf, 512);
  946.         bfree(buf, 2);
  947.     }
  948.     }
  949.  
  950.     bufsync();   /* Clear buffer pool */
  951. }
  952.  
  953.  
  954. /****************************************
  955. access(path,mode)
  956. char *path;
  957. int16 mode;
  958. ****************************************/
  959.  
  960. #define path (char *)udata.u_argn1
  961. #define mode (int16)udata.u_argn
  962.  
  963. _access()
  964. {
  965.     register inoptr ino;
  966.     register int16 euid;
  967.     register int16 egid;
  968.     register int16 retval;
  969.     inoptr n_open();
  970.  
  971.     if ((mode & 07) && !*(path))
  972.     {
  973.     udata.u_error = ENOENT;
  974.     return (-1);
  975.     }
  976.  
  977.     /* Temporarily make eff. id real id. */
  978.     euid = udata.u_euid;
  979.     egid = udata.u_egid;
  980.     udata.u_euid = udata.u_ptab->p_uid;
  981.     udata.u_egid = udata.u_gid;
  982.  
  983.     ifnot (ino = n_open(path,NULLINOPTR))
  984.     {
  985.     retval = -1;
  986.     goto nogood;
  987.     }
  988.  
  989.     retval = 0;
  990.     if (~getperm(ino) & (mode&07))
  991.     {
  992.     udata.u_error = EPERM;
  993.     retval = -1;
  994.     }
  995.  
  996.     i_deref(ino);
  997. nogood:
  998.     udata.u_euid = euid;
  999.     udata.u_egid = egid;
  1000.  
  1001.     return(retval);
  1002. }
  1003.  
  1004. #undef path
  1005. #undef mode
  1006.  
  1007.  
  1008.  
  1009. /*******************************************
  1010. chmod(path,mode)
  1011. char *path;
  1012. int16 mode;
  1013. *******************************************/
  1014.  
  1015. #define path (char *)udata.u_argn1
  1016. #define mode (int16)udata.u_argn
  1017.  
  1018. _chmod()
  1019. {
  1020.  
  1021.     inoptr ino;
  1022.     inoptr n_open();
  1023.  
  1024.     ifnot (ino = n_open(path,NULLINOPTR))
  1025.     return (-1);
  1026.  
  1027.     if (ino->c_node.i_uid != udata.u_euid && !super())
  1028.     {
  1029.     i_deref(ino);
  1030.     udata.u_error = EPERM;
  1031.     return(-1);
  1032.     }
  1033.  
  1034.     ino->c_node.i_mode = (mode & MODE_MASK) | (ino->c_node.i_mode & F_MASK);
  1035.     setftime(ino, C_TIME);
  1036.     i_deref(ino);
  1037.     return(0);
  1038. }
  1039.  
  1040. #undef path
  1041. #undef mode
  1042.  
  1043.  
  1044.  
  1045. /***********************************************
  1046. chown(path, owner, group)
  1047. char *path;
  1048. int owner;
  1049. int group;
  1050. **********************************************/
  1051.  
  1052. #define path (char *)udata.u_argn2
  1053. #define owner (int16)udata.u_argn1
  1054. #define group (int16)udata.u_argn
  1055.  
  1056. _chown()
  1057. {
  1058.     register inoptr ino;
  1059.     inoptr n_open();
  1060.  
  1061.     ifnot (ino = n_open(path,NULLINOPTR))
  1062.     return (-1);
  1063.  
  1064.     if (ino->c_node.i_uid != udata.u_euid && !super())
  1065.     {
  1066.     i_deref(ino);
  1067.     udata.u_error = EPERM;
  1068.     return(-1);
  1069.     }
  1070.  
  1071.     ino->c_node.i_uid = owner;
  1072.     ino->c_node.i_gid = group;
  1073.     setftime(ino, C_TIME);
  1074.     i_deref(ino);
  1075.     return(0);
  1076. }
  1077.  
  1078. #undef path
  1079. #undef owner
  1080. #undef group
  1081.  
  1082.  
  1083.  
  1084. /**************************************
  1085. stat(path,buf)
  1086. char *path;
  1087. char *buf;
  1088. ****************************************/
  1089.  
  1090. #define path (char *)udata.u_argn1
  1091. #define buf (char *)udata.u_argn
  1092.  
  1093. _stat()
  1094. {
  1095.  
  1096.     register inoptr ino;
  1097.     inoptr n_open();
  1098.  
  1099.     ifnot (valadr(buf,sizeof(struct stat)) && (ino = n_open(path,NULLINOPTR)))
  1100.     {
  1101.     return (-1);
  1102.     }
  1103.  
  1104.     stcpy(ino,buf);
  1105.     i_deref(ino);
  1106.     return(0);
  1107. }
  1108.  
  1109. #undef path
  1110. #undef buf
  1111.  
  1112.  
  1113.  
  1114. /********************************************
  1115. fstat(fd, buf)
  1116. int16 fd;
  1117. char *buf;
  1118. ********************************************/
  1119.  
  1120. #define fd (int16)udata.u_argn1
  1121. #define buf (char *)udata.u_argn
  1122.  
  1123. _fstat()
  1124. {
  1125.     register inoptr ino;
  1126.     inoptr getinode();
  1127.  
  1128.     ifnot (valadr(buf,sizeof(struct stat)))
  1129.     return(-1);
  1130.  
  1131.     if ((ino = getinode(fd)) == NULLINODE)
  1132.     return(-1);
  1133.  
  1134.     stcpy(ino,buf);
  1135.     return(0);
  1136. }
  1137.  
  1138. #undef fd
  1139. #undef buf
  1140.  
  1141.  
  1142. /* Utility for stat and fstat */
  1143. stcpy(ino, buf)
  1144. inoptr ino;
  1145. char *buf;
  1146. {
  1147.     /* violently system-dependent */
  1148.     bcopy((char *)&(ino->c_dev), buf, 12);
  1149.     bcopy((char *)&(ino->c_node.i_addr[0]), buf+12, 2);
  1150.     bcopy((char *)&(ino->c_node.i_size), buf+14, 16);
  1151. }
  1152.  
  1153.  
  1154.  
  1155. /************************************
  1156. dup(oldd)
  1157. int16 oldd;
  1158. ************************************/
  1159.  
  1160. #define oldd (uint16)udata.u_argn
  1161.  
  1162. _dup()
  1163. {
  1164.     register int newd;
  1165.     inoptr getinode();
  1166.  
  1167.     if (getinode(oldd) == NULLINODE)
  1168.     return(-1);
  1169.  
  1170.     if ((newd = uf_alloc()) == -1)
  1171.     return (-1);
  1172.  
  1173.     udata.u_files[newd] = udata.u_files[oldd];
  1174.     ++of_tab[udata.u_files[oldd]].o_refs;
  1175.  
  1176.     return(newd);
  1177. }
  1178.  
  1179. #undef oldd
  1180.  
  1181.  
  1182.  
  1183. /****************************************
  1184. dup2(oldd, newd)
  1185. int16 oldd;
  1186. int16 newd;
  1187. ****************************************/
  1188.  
  1189. #define oldd (int16)udata.u_argn1
  1190. #define newd (int16)udata.u_argn
  1191.  
  1192. _dup2()
  1193. {
  1194.     inoptr getinode();
  1195.  
  1196.     if (getinode(oldd) == NULLINODE)
  1197.     return(-1);
  1198.  
  1199.     if (newd < 0 || newd >= UFTSIZE)
  1200.     {
  1201.     udata.u_error = EBADF;
  1202.     return (-1);
  1203.     }
  1204.  
  1205.     ifnot (udata.u_files[newd] & 0x80)
  1206.     doclose(newd);
  1207.  
  1208.     udata.u_files[newd] = udata.u_files[oldd];
  1209.     ++of_tab[udata.u_files[oldd]].o_refs;
  1210.  
  1211.     return(0);
  1212. }
  1213.  
  1214. #undef oldd
  1215. #undef newd
  1216.  
  1217.  
  1218.  
  1219. /**************************************
  1220. umask(mask)
  1221. int mask;
  1222. *************************************/
  1223.  
  1224. #define mask (int16)udata.u_argn
  1225.  
  1226. _umask()
  1227. {
  1228.     register int omask;
  1229.  
  1230.     omask = udata.u_mask;
  1231.     udata.u_mask = mask & 0777;
  1232.     return(omask);
  1233. }
  1234.  
  1235. #undef mask
  1236.  
  1237.  
  1238.  
  1239. /* Special system call returns super-block of given
  1240. filesystem for users to determine free space, etc.
  1241. Should be replaced with a sync() followed by a read
  1242. of block 1 of the device.  */
  1243.  
  1244. /***********************************************
  1245. getfsys(dev,buf)
  1246. int16 dev;
  1247. struct filesys *buf;
  1248. **************************************************/
  1249.  
  1250. #define dev (int16)udata.u_argn1
  1251. #define buf (struct filesys *)udata.u_argn
  1252.  
  1253. _getfsys()
  1254. {
  1255.    if (dev < 0 || dev >= NDEVS || fs_tab[dev].s_mounted != SMOUNTED)
  1256.    {
  1257.        udata.u_error = ENXIO;
  1258.        return(-1);
  1259.     }
  1260.  
  1261.     bcopy((char *)&fs_tab[dev],(char *)buf,sizeof(struct filesys));
  1262.     return(0);
  1263. }
  1264.  
  1265. #undef dev
  1266. #undef buf
  1267.  
  1268.  
  1269.  
  1270. /****************************************
  1271. ioctl(fd, request, data)
  1272. int fd;
  1273. int request;
  1274. char *data;
  1275. *******************************************/
  1276.  
  1277. #define fd (int)udata.u_argn2
  1278. #define request (int)udata.u_argn1
  1279. #define data (char *)udata.u_argn
  1280.  
  1281. _ioctl()
  1282. {
  1283.  
  1284.     register inoptr ino;
  1285.     register int dev;
  1286.     inoptr getinode();
  1287.  
  1288.     if ((ino = getinode(fd)) == NULLINODE)
  1289.     return(-1);
  1290.  
  1291.     ifnot (isdevice(ino))
  1292.     {
  1293.     udata.u_error = ENOTTY;
  1294.     return(-1);
  1295.     }
  1296.  
  1297.     ifnot (getperm(ino) & OTH_WR)
  1298.     {
  1299.     udata.u_error = EPERM;
  1300.     return(-1);
  1301.     }
  1302.  
  1303.     dev = ino->c_node.i_addr[0];
  1304.  
  1305.     if (d_ioctl(dev, request,data))
  1306.     return(-1);
  1307.     return(0);
  1308. }
  1309.  
  1310. #undef fd
  1311. #undef request
  1312. #undef data
  1313.  
  1314.  
  1315.  
  1316. /* This implementation of mount ignores the rwflag */
  1317.  
  1318. /*****************************************
  1319. mount(spec, dir, rwflag)
  1320. char *spec;
  1321. char *dir;
  1322. int rwflag;
  1323. *******************************************/
  1324.  
  1325. #define spec (char *)udata.u_argn2
  1326. #define dir (char *)udata.u_argn1
  1327. #define rwflag (int)udata.u_argn
  1328.  
  1329. _mount()
  1330. {
  1331.     register inoptr sino, dino;
  1332.     register int dev;
  1333.     inoptr n_open();
  1334.  
  1335.     ifnot(super())
  1336.     {
  1337.     udata.u_error = EPERM;
  1338.     return (-1);
  1339.     }
  1340.  
  1341.     ifnot (sino = n_open(spec,NULLINOPTR))
  1342.     return (-1);
  1343.  
  1344.     ifnot (dino = n_open(dir,NULLINOPTR))
  1345.     {
  1346.     i_deref(sino);
  1347.     return (-1);
  1348.     }
  1349.  
  1350.     if (getmode(sino) != F_BDEV)
  1351.     {
  1352.     udata.u_error = ENOTBLK;
  1353.     goto nogood;
  1354.     }
  1355.  
  1356.     if (getmode(dino) != F_DIR)
  1357.     {
  1358.     udata.u_error = ENOTDIR;
  1359.     goto nogood;
  1360.     }
  1361.  
  1362.     dev = (int)sino->c_node.i_addr[0];
  1363.  
  1364.     if ( dev >= NDEVS || d_open(dev))
  1365.     {
  1366.     udata.u_error = ENXIO;
  1367.     goto nogood;
  1368.     }
  1369.  
  1370.     if (fs_tab[dev].s_mounted || dino->c_refs != 1 || dino->c_num == ROOTINODE)
  1371.     {
  1372.        udata.u_error = EBUSY;
  1373.        goto nogood;
  1374.     }
  1375.  
  1376.     _sync();
  1377.  
  1378.     if (fmount(dev,dino))
  1379.     {
  1380.        udata.u_error = EBUSY;
  1381.        goto nogood;
  1382.     }
  1383.  
  1384.     i_deref(dino);
  1385.     i_deref(sino);
  1386.     return(0);
  1387.  
  1388. nogood:
  1389.     i_deref(dino);
  1390.     i_deref(sino);
  1391.     return (-1);
  1392. }
  1393.  
  1394. #undef spec
  1395. #undef dir
  1396. #undef rwflag
  1397.  
  1398.  
  1399.  
  1400. /******************************************
  1401. umount(spec)
  1402. char *spec;
  1403. ******************************************/
  1404.  
  1405. #define spec (char *)udata.u_argn
  1406.  
  1407. _umount()
  1408. {
  1409.     register inoptr sino;
  1410.     register int dev;
  1411.     register inoptr ptr;
  1412.     inoptr n_open();
  1413.  
  1414.     ifnot(super())
  1415.     {
  1416.     udata.u_error = EPERM;
  1417.     return (-1);
  1418.     }
  1419.  
  1420.     ifnot (sino = n_open(spec,NULLINOPTR))
  1421.     return (-1);
  1422.  
  1423.     if (getmode(sino) != F_BDEV)
  1424.     {
  1425.     udata.u_error = ENOTBLK;
  1426.     goto nogood;
  1427.     }
  1428.  
  1429.     dev = (int)sino->c_node.i_addr[0];
  1430.     ifnot (validdev(dev))
  1431.     {
  1432.     udata.u_error = ENXIO;
  1433.     goto nogood;
  1434.     }
  1435.  
  1436.     if (!fs_tab[dev].s_mounted)
  1437.     {
  1438.     udata.u_error = EINVAL;
  1439.     goto nogood;
  1440.     }
  1441.  
  1442.     for (ptr = i_tab; ptr < i_tab+ITABSIZE; ++ptr)
  1443.     if (ptr->c_refs > 0 && ptr->c_dev == dev)
  1444.     {
  1445.         udata.u_error = EBUSY;
  1446.         goto nogood;
  1447.     }
  1448.  
  1449.     _sync();
  1450.     fs_tab[dev].s_mounted = 0;
  1451.     i_deref(fs_tab[dev].s_mntpt);
  1452.  
  1453.     i_deref(sino);
  1454.     return(0);
  1455.  
  1456. nogood:
  1457.     i_deref(sino);
  1458.     return (-1);
  1459. }
  1460.  
  1461. #undef spec
  1462.  
  1463.