arg_t _acct(void) { #ifdef CONFIG_ACCT inoptr inode; if (esuper()) return -1; if (acct_fh != -1) oft_deref(acct_fh); if (fd != -1) { if ((inode = getinode(fd)) == NULLINODE) return -1; if (getmode(inode) != MODE_R(F_REG)) { udata.u_error = EINVAL; return -1; } if (inode->c_flags & CRDONLY) { udata.u_error = EROFS; return -1; } acct_fh = udata.u_files[fd]; ++of_tab[acct_fh].o_refs; } return 0; #else udata.u_error = EINVAL; return -1; #endif }
arg_t _link(void) { inoptr ino; inoptr ino2; inoptr parent2; char fname[FILENAME_LEN + 1]; if (!(ino = n_open(name1, NULLINOPTR))) return (-1); if (getmode(ino) == MODE_R(F_DIR) && esuper()) goto nogood; if (ino->c_node.i_nlink == 0xFFFF) { udata.u_error = EMLINK; goto nogood; } /* Make sure file2 doesn't exist, and get its parent */ if ((ino2 = n_open(name2, &parent2)) != NULL) { i_deref(ino2); i_deref(parent2); udata.u_error = EEXIST; goto nogood; } if (!parent2) goto nogood; if (ino->c_dev != parent2->c_dev) { i_deref(parent2); udata.u_error = EXDEV; goto nogood; } filename(name2, fname); if (!ch_link(parent2, "", fname, ino)) { i_deref(parent2); goto nogood; } /* Update the link count. */ ++ino->c_node.i_nlink; wr_inode(ino); setftime(ino, C_TIME); i_deref(parent2); i_deref(ino); return 0; nogood: i_deref(ino); return -1; }
static arg_t chdiroot_op(inoptr ino, inoptr * p) { if (getmode(ino) != MODE_R(F_DIR)) { udata.u_error = ENOTDIR; i_deref(ino); return (-1); } i_deref(*p); *p = ino; return 0; }
/* We copy the 32bit offset in and out rather than passing it as a 32bit OS might */ arg_t _lseek(void) { inoptr ino; struct oft *o; off_t p; off_t n; if (uget(offset, &n, sizeof(n))) return -1; if ((ino = getinode(file)) == NULLINODE) return (-1); if (getmode(ino) == MODE_R(F_PIPE)) { udata.u_error = ESPIPE; return (-1); } o = &of_tab[udata.u_files[file]]; p = o->o_ptr; switch (flag) { case 0: p = n; break; case 1: p += n; break; case 2: p = ino->c_node.i_size + n; break; default: goto bad; } if (p < 0) goto bad; o->o_ptr = p; uput(&p, offset, sizeof(n)); return 0; bad: udata.u_error = EINVAL; return (-1); }
arg_t _open(void) { int8_t uindex; int8_t oftindex; staticfast inoptr ino; int16_t perm; staticfast inoptr parent; char fname[FILENAME_LEN + 1]; int trunc; int r; int w; int j; parent = NULLINODE; trunc = flag & O_TRUNC; r = (flag + 1) & 1; w = (flag + 1) & 2; if (O_ACCMODE(flag) == 3 || (flag & O_BADBITS)) { udata.u_error = EINVAL; return (-1); } if ((uindex = uf_alloc()) == -1) return (-1); if ((oftindex = oft_alloc()) == -1) goto nooft; ino = n_open(name, &parent); if (ino) { i_deref(parent); /* O_EXCL test */ if ((flag & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) { udata.u_error = EEXIST; goto idrop; } } else { /* The n_open failed */ if (udata.u_error == EFAULT || parent == NULL) goto cantopen; /* New file */ if (!(flag & O_CREAT)) { udata.u_error = ENOENT; goto cantopen; } filename(name, fname); /* newfile drops parent for us */ ino = newfile(parent, fname); if (!ino) { /* on error, newfile sets udata.u_error */ goto cantopen; } /* new inode, successfully created */ ino->c_node.i_mode = (F_REG | (mode & MODE_MASK & ~udata.u_mask)); setftime(ino, A_TIME | M_TIME | C_TIME); wr_inode(ino); } /* Book our slot in case we block opening a device */ of_tab[oftindex].o_inode = ino; perm = getperm(ino); if ((r && !(perm & OTH_RD)) || (w && !(perm & OTH_WR))) { udata.u_error = EACCES; goto cantopen; } if (w) { if (getmode(ino) == MODE_R(F_DIR)) { udata.u_error = EISDIR; goto cantopen; } /* Special case - devices on a read only file system may be opened read/write */ if (!isdevice(ino) && (ino->c_flags & CRDONLY)) { udata.u_error = EROFS; goto cantopen; } } if (isdevice(ino)) { inoptr *iptr = &of_tab[oftindex].o_inode; /* d_open may block and thus ino may become invalid as may parent (but we don't need it again). It may also be changed by the call to dev_openi */ if (dev_openi(iptr, flag) != 0) goto cantopen; /* May have changed */ /* get the static pointer back in case it changed via dev usage or just because we blocked */ ino = *iptr; } if (w && trunc && getmode(ino) == MODE_R(F_REG)) { if (f_trunc(ino)) goto idrop; for (j = 0; j < OFTSIZE; ++j) /* Arguably should fix at read/write */ if (of_tab[j].o_inode == ino) of_tab[j].o_ptr = 0; } udata.u_files[uindex] = oftindex; of_tab[oftindex].o_ptr = 0; of_tab[oftindex].o_access = flag; /* Save the low bits only */ if (flag & O_CLOEXEC) udata.u_cloexec |= (1 << oftindex); if (O_ACCMODE(flag) != O_RDONLY) ino->c_writers++; if (O_ACCMODE(flag) != O_WRONLY) ino->c_readers++; /* FIXME: ATIME ? */ /* * Sleep process if no writer or reader. * FIXME: check for other of pair now we have proper counts */ if (getmode(ino) == MODE_R(F_PIPE) && of_tab[oftindex].o_refs == 1 && !(flag & O_NDELAY)) psleep(ino); /* From the moment of the psleep ino is invalid */ return (uindex); idrop: i_deref(ino); cantopen: oft_deref(oftindex); /* This will call i_deref() */ nooft: udata.u_files[uindex] = NO_FILE; return (-1); }