Пример #1
0
Файл: wk.c Проект: aunali1/exopc
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);
}
Пример #2
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();
	}
    }
}
Пример #3
0
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) {
Пример #4
0
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);
}