int16_t _open(void) { int8_t uindex; int8_t oftindex; staticfast inoptr ino; inoptr itmp; 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 { /* 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; } } of_tab[oftindex].o_inode = ino; perm = getperm(ino); if ((r && !(perm & OTH_RD)) || (w && !(perm & OTH_WR))) { udata.u_error = EPERM; goto cantopen; } if (getmode(ino) == F_DIR && w) { udata.u_error = EISDIR; goto cantopen; } itmp = ino; /* d_open may block and thus ino may become invalid as may parent (but we don't need it again) */ if (isdevice(ino) && d_open((int) ino->c_node.i_addr[0], flag) != 0) { udata.u_error = ENXIO; goto cantopen; } /* get the static pointer back */ ino = itmp; if (trunc && getmode(ino) == F_REG) { f_trunc(ino); 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); }
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); }