void i_deref(inoptr ino) { magic(ino); if(!ino->c_refs) panic("inode freed."); if((ino->c_node.i_mode & F_MASK) == F_PIPE) wakeup((char *)ino); /* If the inode has no links and no refs, it must have its blocks freed. */ if(!(--ino->c_refs || ino->c_node.i_nlink)) /* SN (mcy) */ if(((ino->c_node.i_mode & F_MASK) == F_REG) || ((ino->c_node.i_mode & F_MASK) == F_DIR) || ((ino->c_node.i_mode & F_MASK) == F_PIPE)) f_trunc(ino); /* If the inode was modified, we must write it to disk. */ if(!(ino->c_refs) && ino->c_dirty) { if(!(ino->c_node.i_nlink)) { ino->c_node.i_mode = 0; i_free(ino->c_dev, ino->c_num); } wr_inode(ino); } }
inoptr newfile(inoptr pino, char *name) { inoptr nindex; uint8_t j; /* First see if parent is writeable */ if(!(getperm(pino) & OTH_WR)) goto nogood; if(!(nindex = i_open(pino->c_dev, 0))) goto nogood; /* BUG FIX: user/group setting was missing SN */ nindex->c_node.i_uid = udata.u_euid; nindex->c_node.i_gid = udata.u_egid; nindex->c_node.i_mode = F_REG; /* For the time being */ nindex->c_node.i_nlink = 1; nindex->c_node.i_size = 0; for(j=0; j <20; j++) nindex->c_node.i_addr[j] = 0; wr_inode(nindex); if(!ch_link(pino, "", name, nindex)) { i_deref(nindex); goto nogood; } i_deref(pino); return nindex; nogood: i_deref(pino); return NULLINODE; }
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) == 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; }
uint8_t write_core_image(void) { inoptr parent = NULLINODE; inoptr ino; udata.u_error = 0; /* FIXME: need to think more about the case sp is lala */ if (uput("core", (uint8_t *)udata.u_syscall_sp - 5, 5)) return 0; ino = n_open((char *)udata.u_syscall_sp - 5, &parent); if (ino) { i_deref(parent); return 0; } if (parent) { i_lock(parent); if ((ino = newfile(parent, "core")) != NULL) { ino->c_node.i_mode = F_REG | 0400; setftime(ino, A_TIME | M_TIME | C_TIME); wr_inode(ino); f_trunc(ino); #if 0 /* FIXME address ranges for different models - move core writer for address spaces into helpers ? */ /* FIXME: need to add some arch specific header bits, and also pull stuff like the true sp and registers out of the return stack properly */ corehdr.ch_base = pagemap_base; corehdr.ch_break = udata.u_break; corehdr.ch_sp = udata.u_syscall_sp; corehdr.ch_top = PROGTOP; udata.u_offset = 0; udata.u_base = (uint8_t *)&corehdr; udata.u_sysio = true; udata.u_count = sizeof(corehdr); writei(ino, 0); udata.u_sysio = false; udata.u_base = (uint8_t *)pagemap_base; udata.u_count = udata.u_break - pagemap_base; writei(ino, 0); udata.u_base = udata.u_sp; udata.u_count = PROGTOP - (uint32_t)udata.u_sp; writei(ino, 0); #endif i_unlock_deref(ino); return W_COREDUMP; } } return 0; }
uint8_t write_core_image(void) { inoptr parent = NULLINODE; inoptr ino; udata.u_error = 0; /* FIXME: need to think more about the case sp is lala */ if (uput("core", udata.u_syscall_sp - 5, 5)) return 0; ino = n_open(udata.u_syscall_sp - 5, &parent); if (ino) { i_deref(parent); return 0; } if (parent) { i_lock(parent); if (ino = newfile(parent, "core")) { ino->c_node.i_mode = F_REG | 0400; setftime(ino, A_TIME | M_TIME | C_TIME); wr_inode(ino); f_trunc(ino); /* FIXME: need to add some arch specific header bits, and also pull stuff like the true sp and registers out of the return stack properly */ corehdr.ch_base = MAPBASE; corehdr.ch_break = udata.u_break; corehdr.ch_sp = udata.u_syscall_sp; corehdr.ch_top = PROGTOP; udata.u_offset = 0; udata.u_base = (uint8_t *)&corehdr; udata.u_sysio = true; udata.u_count = sizeof(corehdr); writei(ino, 0); udata.u_sysio = false; udata.u_base = MAPBASE; udata.u_count = udata.u_break - MAPBASE; writei(ino, 0); udata.u_base = udata.u_sp; udata.u_count = PROGTOP - (uint16_t)udata.u_sp; writei(ino, 0); i_unlock_deref(ino); return W_COREDUMP; } } return 0; }
int16_t _sync(void) { inoptr ino; /* Write out modified inodes */ for (ino = i_tab; ino < i_tab + ITABSIZE; ++ino) if (ino->c_refs > 0 && ino->c_dirty != 0) { wr_inode(ino); ino->c_dirty = 0; } /* This now also indirectly does the superblocks as they are buffers that are pinned */ bufsync(); /* Clear buffer pool */ return 0; }
arg_t _mknod(void) { inoptr ino; inoptr parent; char fname[FILENAME_LEN + 1]; udata.u_error = 0; if (!super() && ((mode & F_MASK) != F_PIPE)) { udata.u_error = EPERM; goto nogood3; } if ((ino = n_open(name, &parent)) != NULL) { udata.u_error = EEXIST; goto nogood; } if (!parent) { udata.u_error = ENOENT; return (-1); } filename(name, fname); ino = newfile(parent, fname); if(!ino) goto nogood3; /* parent inode is derefed in newfile. SN */ /* Initialize mode and dev */ ino->c_node.i_mode = mode & ~udata.u_mask; ino->c_node.i_addr[0] = isdevice(ino) ? dev : 0; setftime(ino, A_TIME | M_TIME | C_TIME); wr_inode(ino); i_deref(ino); return (0); nogood: i_deref(ino); i_deref(parent); nogood3: 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); }