arg_t _pipe(void) { int8_t u1, u2, oft1, oft2; inoptr ino; /* bug fix SN */ if ((u1 = uf_alloc()) == -1) goto nogood; if ((oft1 = oft_alloc()) == -1) goto nogood; udata.u_files[u1] = oft1; if ((u2 = uf_alloc()) == -1) goto nogood2; if ((oft2 = oft_alloc()) == -1) goto nogood2; if (!(ino = i_open(root_dev, 0))) { oft_deref(oft2); goto nogood2; } udata.u_files[u2] = oft2; of_tab[oft1].o_ptr = 0; of_tab[oft1].o_inode = ino; of_tab[oft1].o_access = O_RDONLY; of_tab[oft2].o_ptr = 0; of_tab[oft2].o_inode = ino; of_tab[oft2].o_access = O_WRONLY; ++ino->c_refs; ino->c_node.i_mode = F_PIPE | 0777; /* No permissions necessary on pipes */ ino->c_node.i_nlink = 0; /* a pipe is not in any directory */ // write results to userspace uputw(u1, fildes); uputw(u2, fildes + 1); return (0); nogood2: oft_deref(oft1); udata.u_files[u1] = NO_FILE; nogood: return (-1); }
arg_t make_socket(struct sockinfo *s, struct socket **np) { struct socket *n; int8_t uindex; int8_t oftindex; inoptr ino; /* RAW sockets are superuser */ if (s->priv && esuper()) return -1; if (np) n = *np; else { n = alloc_socket(); if (n == NULL) return -1; } n->s_type = s - socktypes; /* Pointer or uint8_t best ? */ n->s_state = SS_INIT; if (net_init(n) == -1) goto nosock; /* Start by getting the file and inode table entries */ if ((uindex = uf_alloc()) == -1) goto nosock; if ((oftindex = oft_alloc()) == -1) goto nooft; /* We need an inode : FIXME - do we want a pipedev aka Unix ? */ if (!(ino = i_open(root_dev, 0))) goto noalloc; /* All good - now set it up */ /* The nlink cheat needs to be taught to fsck! */ ino->c_node.i_mode = F_SOCK | 0777; ino->c_node.i_nlink = n->s_num; /* Cheat !! */ ino->c_readers = 1; ino->c_writers = 1; of_tab[oftindex].o_inode = ino; of_tab[oftindex].o_access = O_RDWR; udata.u_files[uindex] = oftindex; sock_wait_leave(n, 0, SS_INIT); if (np) *np = n; return uindex; noalloc: oft_deref(oftindex); /* Will call i_deref! */ nooft: udata.u_files[uindex] = NO_FILE; nosock: n->s_state = SS_UNUSED; return -1; }
arg_t _dup(void) { int8_t newd; if (getinode(oldd) == NULLINODE) return (-1); if ((newd = uf_alloc()) == -1) return (-1); udata.u_files[newd] = udata.u_files[oldd]; ++of_tab[udata.u_files[oldd]].o_refs; return (newd); }
arg_t make_socket(struct sockinfo *s, int8_t *np) { int8_t n; int8_t uindex; int8_t oftindex; inoptr ino; /* RAW sockets are superuser */ if (s->priv && esuper()) return -1; /* Start by getting the file and inode table entries */ if ((uindex = uf_alloc()) == -1) return -1; if ((oftindex = oft_alloc()) == -1) goto nooft; if (np) n = *np; else { n = alloc_socket(); if (n == -1) goto noalloc; } /* We need an inode : FIXME - do we want a pipedev aka Unix ? */ if (!(ino = i_open(root_dev, 0))) goto noalloc; /* All good - now set it up */ /* The nlink cheat needs to be taught to fsck! */ ino->c_node.i_mode = F_SOCK | 0777; ino->c_node.i_nlink = n; /* Cheat !! */ of_tab[oftindex].o_inode = ino; of_tab[oftindex].o_access = O_RDWR; udata.u_files[uindex] = oftindex; sockets[n].s_inode = ino; sockets[n].s_type = s - socktypes; /* Pointer or uint8_t best ? */ sockets[n].s_state = SS_UNCONNECTED; if (np) *np = n; return uindex; noalloc: oft_deref(oftindex); /* Will call i_deref! */ nooft: udata.u_files[uindex] = NO_FILE; 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) goto cantopen; /* New file */ if (!(flag & O_CREAT)) { udata.u_error = ENOENT; goto cantopen; } filename(name, fname); /* newfile drops parent for us */ if (parent && (ino = newfile(parent, fname))) { ino->c_node.i_mode = (F_REG | (mode & MODE_MASK & ~udata.u_mask)); setftime(ino, A_TIME | M_TIME | C_TIME); wr_inode(ino); } else { udata.u_error = ENFILE; /* FIXME, should be set in newfile not bodged to a guessed code */ goto cantopen; } } /* 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) == F_DIR ) { udata.u_error = EISDIR; goto cantopen; } if (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 (trunc && getmode(ino) == 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); /* FIXME: ATIME ? */ /* * Sleep process if no writer or reader */ if (getmode(ino) == 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); }