int sys_wkpred (u_int sn, struct wk_term *t, int sz) { char *code; u_int *pred_pages; int ret; if (curenv->env_pred) { wk_free (curenv); } if (t) { int m; code = (char *)malloc (WK_MAX_CODE_BYTES); if (!code) return -E_NO_MEM; pred_pages = (u_int *)malloc (WK_MAX_PP * sizeof (int)); if (!pred_pages) { free (code); return -E_NO_MEM; } m = page_fault_mode; page_fault_mode = PFM_PROP; t = trup (t); syscall_pfcleanup = wk_pfcleanup; cleanup_code = code; cleanup_pred_pages = pred_pages; if ((ret = wk_compile (t, sz, code, pred_pages)) < 0) { wk_free (curenv); page_fault_mode = m; return (ret); } page_fault_mode = m; } return (0); }
__XOK_SYNC(UAREA only modified when localized) { int stat; irq_eoi (8); /* MUST read to acknowledge the interrupt */ stat = mc146818_read(NULL, MC_REGC); if (stat & MC_REGC_PF) { if ((!UAREA.u_pendrtc) && UAREA.u_entrtc) { tfp tf; u_int *esp; u_int tt_eip; u_int old_pfm = page_fault_mode; tfp_set (tf, trapno, tf_edi); tt_eip = tf->tf_eip; /* trap time eip */ /* copy interrupt stack frame on to user stack */ page_fault_mode = PFM_PROP; tf->tf_esp -= 12; esp = trup ((u_int *)tf->tf_esp); esp[2] = tf->tf_eflags; esp[1] = tf->tf_cs; esp[0] = tf->tf_eip; page_fault_mode = old_pfm; tf->tf_eip = UAREA.u_entrtc; UAREA.u_pendrtc = 1; env_upcall(); } } }
int sys_fsupdate_directory (u_int sn, int action, struct embdirent *dirent, u_int param2, u_int param3, u_int param4, u_int param5) { u_int param1 = (u_int) dirent; char *dirBlock = (char *) translate_address ((param1 - (param1 % BLOCK_SIZE)), BLOCK_SIZE); if (dirBlock == NULL) { return (-E_INVAL); } dirent = (embdirent_t *) (dirBlock + (param1 % BLOCK_SIZE)); /* GROK -- need to check for write permission on directory. The relevant */ /* inode should be provided automatically by base disk protection software */ if (!isValidDirent(dirBlock, dirent)) { printf ("sys_fsupdate_directory (%d): invalid dirent specified (%x)\n", action, param1); return (-E_INVAL); } /************************** CFFS_DIRECTORY_INITDIRBLOCK ***********************/ if (action == CFFS_DIRECTORY_INITDIRBLOCK) { int i; dinode_t *dinode; if ((u_int)dirent % BLOCK_SIZE) { printf ("sys_fsupdate_directory (%d): dirent not start of block (%p)\n", action, dirent); return (-E_INVAL); } for (i=0; i<(BLOCK_SIZE/CFFS_EMBDIR_SECTOR_SIZE); i++) { dirent->type = (char) 0; dirent->entryLen = CFFS_EMBDIR_SECTOR_SPACEFORNAMES; dirent->preventryLen = 0; dinode = (dinode_t *) ((char *)dirent + CFFS_DINODE_SIZE); dinode->dinodeNum = 0; dinode = (dinode_t *) ((char *)dirent + (2*CFFS_DINODE_SIZE)); dinode->dinodeNum = 0; dinode = (dinode_t *) ((char *)dirent + (3*CFFS_DINODE_SIZE)); dinode->dinodeNum = 0; dirent = (embdirent_t *) ((char *) dirent + CFFS_EMBDIR_SECTOR_SIZE); } /*************************** CFFS_DIRECTORY_SPLITENTRY ************************/ } else if (action == CFFS_DIRECTORY_SPLITENTRY) { embdirent_t *newDirent; int splitspace = param2; int extraspace; extraspace = (dirent->type == (char)0) ? dirent->entryLen : (dirent->entryLen - embdirentsize(dirent)); if ((extraspace < SIZEOF_EMBDIRENT_T) || (extraspace < splitspace)) { printf ("sys_fsupdate_directory (%d): not enough extra space (%d) (wanted %d)\n", action, extraspace, splitspace); return (-E_INVAL); } if (splitspace == 0) { printf ("sys_fsupdate_directory (%d): bad splitspace (%d) (extraspace %d)\n", action, splitspace, extraspace); return (-E_INVAL); } dirent->entryLen -= splitspace; newDirent = (embdirent_t *) ((u_int)dirent + dirent->entryLen); if (newDirent != dirent) { newDirent->preventryLen = dirent->entryLen; } newDirent->entryLen = splitspace; newDirent->type = 0; newDirent->nameLen = 0; newDirent->name[0] = (char) 0; if (((u_int)newDirent + newDirent->entryLen) % CFFS_EMBDIR_SECTOR_SPACEFORNAMES) { dirent = (embdirent_t *) ((char *)newDirent + newDirent->entryLen); dirent->preventryLen = splitspace; } return ((param1 - (param1 % BLOCK_SIZE)) + ((u_int)newDirent - (u_int)dirBlock)); /*************************** CFFS_DIRECTORY_SETNAME ************************/ } else if (action == CFFS_DIRECTORY_SETNAME) { char *name = (char *) trup(param2); u_int namelen = param3; dinode_t *dirDInode = make_dinode(param4); if ((dirDInode == NULL) || (dirDInode->dinodeNum == 0)) { return (-E_INVAL); } /* Note: param5 is fsdev in this case, which should be discoverable */ /* from the dinode's identity... */ if ((dirent->type != 0) && (!isNameUnique(param5, dirDInode, name, namelen))) { printf ("sys_fsupdate_directory (%d): non-unique name specified (%s, %d)\n", action, name, namelen); return (-E_INVAL); } bcopy(name, dirent->name, namelen); dirent->name[namelen] = (char) 0; dirent->nameLen = namelen; /*************************** CFFS_DIRECTORY_MERGEENTRY ************************/ } else if (action == CFFS_DIRECTORY_MERGEENTRY) { embdirent_t *next = NULL; int maxleft = CFFS_EMBDIR_SECTOR_SPACEFORNAMES - (param1 % CFFS_EMBDIR_SECTOR_SIZE); int extraspace = 0; while ((extraspace < param2) && (extraspace < maxleft)) { next = (embdirent_t *) ((char *)dirent + dirent->entryLen); if (next->type != 0) { break; } extraspace += next->entryLen; } if (extraspace != param2) { printf ("sys_fsupdate_directory (%d): mismatched extraspaces (%d != %d) (maxleft %d)\n", action, extraspace, param2, maxleft); printf ("next %p, next->entryLen %d\n", next, ((next) ? (next->entryLen) : -1)); return (-E_INVAL); } dirent->entryLen += extraspace; next = (embdirent_t *) ((char *)dirent + dirent->entryLen); if ((u_int) next % CFFS_EMBDIR_SECTOR_SPACEFORNAMES) { next->preventryLen = dirent->entryLen; } /*************************** CFFS_DIRECTORY_SHIFTENTRY ************************/ } else if (action == CFFS_DIRECTORY_SHIFTENTRY) { /********* Not currently supported! ************/ assert (0); #if 0 embdirent_t *tmp; int extraspace; if ((-param2 > (param1 % CFFS_EMBDIR_SECTOR_SIZE)) || ((param2 + (param1 % CFFS_EMBDIR_SECTOR_SIZE)) >= (CFFS_EMBDIR_SECTOR_SPACEFORNAMES - SIZEOF_EMBDIRENT_T))) { printf ("sys_fsupdate_directory (%d): sizes don't work (currOff %d, move %d)\n", action, (param1 % BLOCK_SIZE), param2); return (-E_INVAL); } if (param2 <= 0) { tmp = (embdirent_t *) ((char *)dirent - dirent->preventryLen); extraspace = (tmp->type == (char)0) ? tmp->entryLen : tmp->entryLen - embdirentsize(tmp); if (extraspace < (-param2)) { printf ("sys_fsupdate_directory (%d): not enough extra space (%d < %d)\n", action, extraspace, param2); return (-E_INVAL); } tmp->entryLen -= (-param2); dirent->preventryLen = tmp->entryLen; dirent->entryLen += (-param2); bcopy ((char *) dirent, ((char *)dirent - (-param2)), embdirentsize(dirent)); tmp = (embdirent_t *) ((char *)dirent + dirent->entryLen); if ((u_int) tmp % CFFS_EMBDIR_SECTOR_SPACEFORNAMES) { tmp->preventryLen = dirent->entryLen; } } else { tmp = (embdirent_t *) ((char *)dirent - dirent->preventryLen); extraspace = dirent->entryLen - embdirentsize(dirent); if (extraspace < param2) { printf ("sys_fsupdate_directory (%d): not enough extra space (%d < %d)\n", action, extraspace, param2); return (-E_INVAL); } tmp->entryLen += param2; dirent->preventryLen = tmp->entryLen; dirent->entryLen -= param2; bcopy ((char *)dirent, ((char *)dirent + param2), embdirentsize(dirent)); dirent = (embdirent_t *) ((char *)dirent + tmp->entryLen); tmp = (embdirent_t *) ((char *)dirent + dirent->entryLen); if ((u_int) tmp % CFFS_EMBDIR_SECTOR_SPACEFORNAMES) { tmp->preventryLen = dirent->entryLen; } } #endif /*************************** CFFS_DIRECTORY_SETINODENUM ***********************/ } else if (action == CFFS_DIRECTORY_SETINODENUM) { u_int inodeNum = param2; /* no restrictions is directory entry is not currently live */ if (dirent->type == 0) { dirent->inodeNum = inodeNum; /* this case causes a change in which inode a dirent points to. */ /* because the dirent is live, it must always point to a live inode. */ } else { dinode_t *olddinode; dinode_t *newdinode; if (inodeNum == 0) { printf ("sys_fsupdate_directory (%d): can't set inodeNum to 0 is live dirent\n", action); return (-E_INVAL); } if ((param3 == 0) || (param4 == 0)) { printf ("sys_fsupdate_directory (%d): passed NULL for a cheat variable (%d, %d)\n", action, param3, param4); return (-E_INVAL); } /* it is a bug in FS code to have valid dirent with 0 for an inodeNum */ assert (dirent->inodeNum != 0); /* this should be retrievable from dirent->inodeNum, which identifies */ /* the containing disk block -- which must be a directory block. */ olddinode = make_dinode (param3); if (olddinode->dinodeNum != dirent->inodeNum) { printf ("sys_fsupdate_directory (%d): mismatching old inodeNums (%d != %d)\n", action, olddinode->dinodeNum, dirent->inodeNum); return (-E_INVAL); } /* this should be retrievable from inodeNum, which identifies the */ /* containing disk block -- which must be a directory block. */ newdinode = make_dinode (param4); if (newdinode->dinodeNum != inodeNum) { printf ("sys_fsupdate_directory (%d): mismatching old inodeNums (%d != %d)\n", action, newdinode->dinodeNum, inodeNum); return (-E_INVAL); } if ((olddinode->type != newdinode->type) && ((cffs_dinode_isDir(olddinode)) || (cffs_dinode_isDir(newdinode)))) { printf ("sys_fsupdate_directory (%d): can't interchange a directory and non-directory (%x != %x)\n", action, olddinode->type, newdinode->type); return (-E_INVAL); } /* this rule helps get us around an ordering requirement!! */ /* (i.e., if we handle ordering in some other way, it can */ /* go away... */ if (newdinode->linkCount < (cffs_dinode_isDir(newdinode) ? 2 : 1)) { printf ("sys_fsupdate_directory (%d): can't link up to disowned inode\n", action); return (-E_INVAL); } /* the big stickler here is that we need to be able to check whether */ /* the caller has the ability to look at newdinode. In particular, */ /* this requires execute permission on a directory that already */ /* contains an existing link. */ if ((olddinode) && (cffs_dinode_isDir(olddinode))) { /* must check that directory is actually empty... */ } /* GROK - I'm pretty sure I've designed away all need for ordering here */ olddinode->linkCount--; newdinode->linkCount++; dirent->inodeNum = inodeNum; dirent->type = newdinode->type >> 8; } /**************************** CFFS_DIRECTORY_SETTYPE **************************/ } else if (action == CFFS_DIRECTORY_SETTYPE) {
int sys_fsupdate_superblock (u_int sn, int action, struct superblock *superblock, u_int param1, u_int param2) { StaticAssert (sizeof(struct superblock) == NBPG); StaticAssert (BLOCK_SIZE == NBPG); superblock = (struct superblock *) translate_address ((uint)superblock, NBPG); if (superblock == NULL) { return (-E_INVAL); } if (action == CFFS_SUPERBLOCK_SETDIRTY) { /* allow anyone to set dirty to a non-zero value at any time. */ /* However, must verify that there are no dirty blocks from this */ /* file system before allowing anyone to set dirty to 0. */ superblock->dirty = param1; } else if (action == CFFS_SUPERBLOCK_SETROOTDINODENUM) { /* verify that the provided rootDInodeNum is in fact the correct */ /* system value -- we should know this based on the superblocks addr */ superblock->rootDInodeNum = param1; } else if (action == CFFS_SUPERBLOCK_SETFSNAME) { /* verify that the provided fsname is in fact the correct value */ /* -- should match XN's expectation... */ /* Also, don't allow it to go out of bounds in superblock... */ char *str = (char *) trup(param1); strcpy (superblock->fsname, str); } else if (action == CFFS_SUPERBLOCK_SETFSDEV) { /* verify that the provided fsdev is in fact the correct system value */ /* -- XN should certainly know this... */ superblock->fsdev = param1; } else if (action == CFFS_SUPERBLOCK_SETALLOCMAP) { /* this is a totally temporary call. This field should be maintained */ /* solely by XN... */ superblock->allocMap = param1; } else if (action == CFFS_SUPERBLOCK_SETNUMBLOCKS) { /* this is a totally temporary call. This field should be maintained */ /* solely by XN... */ superblock->numblocks = param1; } else if (action == CFFS_SUPERBLOCK_SETSIZE) { /* this is a totally temporary call. This field should be maintained */ /* solely by XN... */ superblock->size = param1; } else if (action == CFFS_SUPERBLOCK_SETNUMALLOCED) { /* this is a totally temporary call. This field should be maintained */ /* by the ALLOCATE and DEALLOCATE methods... */ superblock->numalloced = param1; } else if (action == CFFS_SUPERBLOCK_SETXNTYPE) { /* this is a totally temporary call. This field should be maintained */ /* and updated only by newfs!!... */ if ((param1 < 0) || (param1 >= CFFS_MAX_XNTYPES)) { printf ("sys_fsupdate_superblock (%d): bad typeno %d (NUM %d)\n", action, param1, CFFS_MAX_XNTYPES); return -E_INVAL; } superblock->xntypes[param1] = param2; } else if (action == CFFS_SUPERBLOCK_INIT) { /* this is a totally temporary call. Just for when not using XN */ bzero (superblock, BLOCK_SIZE); } else { printf ("sys_fsupdate_superblock: unknown action requested (%d)\n", action); return (-E_INVAL); } return (0); }