Beispiel #1
0
/*
 * This is another tricly sys_* function that you will need to write.
 * It's pretty similar to sys_read(), but you don't need
 * to allocate a whole page, just a single dirent_t. call do_getdents in a
 * loop until you have read getdent_args_t->count bytes (or an error
 * occurs).  You should note that count is the number of bytes in the
 * buffer, not the number of dirents, which means that you'll need to loop
 * a max of something like count / sizeof(dirent_t) times.
 */
static int sys_getdents(getdents_args_t *arg)
{
        getdents_args_t getdents;
        if (copy_from_user(&getdents, arg, sizeof(getdents_args_t)) < 0)    /* Copy from the user the read_args_t */
        {
                curthr->kt_errno = EFAULT;
                return -1;
        }
        int i=0,j=0,max_count=0;
        if(getdents.count<=sizeof(dirent_t))
        {
                max_count=getdents.count;
        }
        else
                getdents.count=sizeof(dirent_t);
        
        while(i<max_count)
        {
                j=do_getdent(getdents.fd, getdents.dirp);
                if(j<0)
                {
                        curthr->kt_errno = -j;
                        return -1;
                }        
                i++;                
        }
        /*NOT_YET_IMPLEMENTED("VM: sys_getdents");*/
        return max_count;
}
Beispiel #2
0
/*
 * This is another tricly sys_* function that you will need to write.
 * It's pretty similar to sys_read(), but you don't need
 * to allocate a whole page, just a single dirent_t. call do_getdents in a
 * loop until you have read getdent_args_t->count bytes (or an error
 * occurs).  You should note that count is the number of bytes in the
 * buffer, not the number of dirents, which means that you'll need to loop
 * a max of something like count / sizeof(dirent_t) times.
 */
static int
sys_getdents(getdents_args_t *arg)
{
	getdents_args_t karg;
	int err,ret;
	size_t offset=0;

	if((err=copy_from_user(&karg,arg,sizeof(getdents_args_t)))<0){
		curthr->kt_errno=-err;
		return -1;
	}
	
	dirent_t dir;
	while(offset<karg.count){
		if((ret=do_getdent(karg.fd, &dir))<0){
			curthr->kt_errno=-ret;
			return -1;
		}
		offset+=ret;
		if(ret==0) break;
	}

	if((err=copy_to_user(arg->dirp,&dir,sizeof(dirent_t)))<0){
		curthr->kt_errno=-err;
		return -1;
	}

	return offset;
}
Beispiel #3
0
/*
 * This is another tricly sys_* function that you will need to write.
 * It's pretty similar to sys_read(), but you don't need
 * to allocate a whole page, just a single dirent_t. call do_getdents in a
 * loop until you have read getdent_args_t->count bytes (or an error
 * occurs).  You should note that count is the number of bytes in the
 * buffer, not the number of dirents, which means that you'll need to loop
 * a max of something like count / sizeof(dirent_t) times.
 */
static int
sys_getdents(getdents_args_t *arg)
{
    getdents_args_t kern_args;
    int err;

    if ((err = copy_from_user(&kern_args, arg, sizeof(getdents_args_t))) < 0) {
        curthr->kt_errno = -err;
        return -1;
    }

    dirent_t dirent;
    size_t maxdir = kern_args.count / sizeof(dirent_t);

    size_t i;
    int total_read = 0;
    for (i = 0 ; i < maxdir ; i++) {
        int actual_read = do_getdent(kern_args.fd, &dirent);
        if (actual_read < 0) {
            curthr->kt_errno = -actual_read;
            return -1;
        }
        KASSERT(actual_read == 0 || actual_read == sizeof(dirent_t));
        /*no more dirents, just break out*/
        if (actual_read == 0) {
            break;
        }

        char *uaddr = (char *)kern_args.dirp + i * sizeof(dirent_t);
        err = copy_to_user(uaddr, &dirent, sizeof(dirent_t));
        if (err < 0) {
            curthr->kt_errno = -err;
            return -1;
        }
        KASSERT(err == 0);

        /*only increment total_read when copy_to_user succeed*/
        total_read += actual_read;
    }

    return total_read;
        /*NOT_YET_IMPLEMENTED("VM: sys_getdents");*/
        /*return -1;*/
}
Beispiel #4
0
/*
 * This is another tricly sys_* function that you will need to write.
 * It's pretty similar to sys_read(), but you don't need
 * to allocate a whole page, just a single dirent_t. call do_getdents in a
 * loop until you have read getdent_args_t->count bytes (or an error
 * occurs).  You should note that count is the number of bytes in the
 * buffer, not the number of dirents, which means that you'll need to loop
 * a max of something like count / sizeof(dirent_t) times.
 */
static int
sys_getdents(getdents_args_t *arg)
{
    /*            NOT_YET_IMPLEMENTED("VM: sys_read");*/

        dbg(DBG_PRINT,"go into sys_getdents\n");
    void* readBuf = NULL;
    getdents_args_t k_args;
    int retVal,retVal_new;
    size_t readBytes = 0;
    
    
    retVal = copy_from_user(&k_args, arg, sizeof(k_args));
	KASSERT(0 <= retVal);
    dirent_t dirent;
    dirent_t *tempDirp = arg->dirp;
        int loopBytes; 
    while(k_args.count > readBytes)
		{
		loopBytes= do_getdent(k_args.fd, &dirent);
       	if(loopBytes == 0)
		{
        		dbg(DBG_PRINT, "(GRADING3B)\n");
                break;
        }
        if(loopBytes < 0)
		{
        		dbg(DBG_PRINT, "(GRADING3C)\n");
                curthr->kt_errno = -loopBytes;
                return -1;
        }

        retVal_new = copy_to_user(tempDirp, &dirent, loopBytes);
		KASSERT(0<=retVal_new);
        tempDirp++;
        readBytes += loopBytes;
    }
    return readBytes;
}
Beispiel #5
0
/*
 * This is another tricly sys_* function that you will need to write.
 * It's pretty similar to sys_read(), but you don't need
 * to allocate a whole page, just a single dirent_t. call do_getdents in a
 * loop until you have read getdent_args_t->count bytes (or an error
 * occurs).  You should note that count is the number of bytes in the
 * buffer, not the number of dirents, which means that you'll need to loop
 * a max of something like count / sizeof(dirent_t) times.
 */
static int sys_getdents(getdents_args_t *arg) {
	/*NOT_YET_IMPLEMENTED("VM: sys_getdents"); */

	getdents_args_t kern_args;

	uint32_t totRead = -1, readC = 0;
	dirent_t dirent;
	int err = copy_from_user(&kern_args, arg, sizeof(getdents_args_t));
	dbg(DBG_PRINT, "(GRADING3F)\n");
	/*if (err < 0) {
		dbg(DBG_ERROR, "(GRADING  test 28)\n");
		curthr->kt_errno = -err;
		return -1;
	}*/
	if ( !(err < 0)){
		totRead = 0;
	while (readC < (kern_args.count / sizeof(dirent_t))) {
		dbg(DBG_PRINT, "(GRADING3F)\n");
		err = do_getdent(kern_args.fd, &dirent);
		if (err == 0) {
			dbg(DBG_PRINT, "(GRADING3F)\n");
			return totRead;
		}
		if (err < 0) {
			dbg(DBG_PRINT, "(GRADING3D 2)\n");
			curthr->kt_errno = -err;
			return -1;
		}
		dbg(DBG_PRINT, "(GRADING3F)\n");
		copy_to_user(kern_args.dirp + readC, &dirent, err);
		totRead += err;
		readC += 1;
	}
	dbg(DBG_PRINT, "(GRADING3F)\n");
	}
	return totRead;

}
Beispiel #6
0
/*
 * This is another tricly sys_* function that you will need to write.
 * It's pretty similar to sys_read(), but you don't need
 * to allocate a whole page, just a single dirent_t. call do_getdents in a
 * loop until you have read getdent_args_t->count bytes (or an error
 * occurs).  You should note that count is the number of bytes in the
 * buffer, not the number of dirents, which means that you'll need to loop
 * a max of something like count / sizeof(dirent_t) times.
 */
static int
sys_getdents(getdents_args_t *arg)
{
    /*NOT_YET_IMPLEMENTED("VM: sys_getdents");*/
    getdents_args_t kern_args;
    int bytes_read, ret;
    if((ret = copy_from_user(&kern_args, arg, sizeof(kern_args))) < 0){
        curthr->kt_errno = -ret;
        return -1;
    }
    
    size_t total_bytes_read = 0;
    
    /* dirent_t *dirp = NULL; */
    dirent_t dirp;

    /* Note: the read operation is performed by do_getdent() */
    while(total_bytes_read < kern_args.count){
        if((bytes_read = do_getdent(kern_args.fd, &dirp)) < 0){
            curthr->kt_errno = -bytes_read;
            return -1;
        } else {
            if(bytes_read == 0)
            {
                break;
            }
        }
        
        if((ret = copy_to_user((void *)((uint32_t)kern_args.dirp + total_bytes_read), &dirp, sizeof(dirent_t))) < 0){
            curthr->kt_errno = -ret;
            return -1;
        }
        total_bytes_read += sizeof(dirent_t);
    }
    return total_bytes_read;
}
Beispiel #7
0
int vfs_selftest(kshell_t *kshell, int argc, char **argv)
{
  int fd1,fd2;
  char *y="/ab/fil";
  char x[2];
  int err;
  do_mkdir("/ab");
  do_mknod("/ab/new", S_IFCHR,MKDEVID(1,1));
  fd1=do_open("/ab/new",2);
  fd2=do_dup2(fd1,NFILES+1);
  if(fd2<0)
    {
      dbg(DBG_PRINT,"File not created\n");
    }
  do_mknod("/ab/notmade",4096,MKDEVID(1,1));
  do_mknod("/ab/new/not",S_IFCHR,MKDEVID(1,1));
  do_mknod("/ab/new", S_IFCHR,MKDEVID(1,1));
  do_mknod("", S_IFCHR,MKDEVID(1,1));

  /*do_close(fd1);*/
    for(fd2=1;fd2<35;fd2++)
    {
      sprintf(x,"%d",fd2);
      strcat(y,x);
      do_mknod(y,S_IFCHR,MKDEVID(1,0));
      err=do_open(y,2);
      if(err<0)
	{
	  break;
	}
      if(fd2<10)
	{
	  y[strlen(y)-1]='\0';
	}
      else
	{
	   y[strlen(y)-2]='\0';
	}
      
    }
do_mknod("/ab/new1", S_IFCHR,MKDEVID(1,1));
 err=do_dup(fd1);
  do_unlink("/ab/new/ab");
 do_unlink("/ab/new");
 do_close(fd1);
 for(fd2=NFILES-1;fd2>0;fd2--)
   {
     err=do_close(fd2);
     sprintf(x,"%d",fd2);
      strcat(y,x);
      do_unlink(y);  
      if(err<0)
	{
	  break;
	}
      if(fd2<10)
	{
	  y[strlen(y)-1]='\0';
	}
      else
	{
	   y[strlen(y)-2]='\0';
	}
   }
 do_link("/a","/dev");
 do_link("/dev","/a");
 do_link("/dev","/a");
 do_rmdir("/a");
 /* mkdir("/k");
    do_link("/ab","/k");*/
  do_rmdir("/ab");
  /*do_rmdir("/k");*/

 /*GS: SELF TESTS*/
    dbg(DBG_PRINT,"\n*************************************************************\n");
    dbg(DBG_PRINT,"\n\n\n\n(GRADING2C)(kmain.c)(selftest_proc_run) selftests begin\n");

    int retVal = 0;
    int i = 0;

    /* 1. dbg(DBG_PRINT, "(GRADING2C) (vfs_syscall.c) (do_stat)  strlen too long, return -ENAMETOOLONG\n");*/
    char longPath[1024 + 1] = {0};
    for(i = 0; i < 1025; i++)
        longPath[i] = 'a';
    struct stat buf;
    retVal = do_stat(longPath, &buf);
    retVal=do_chdir(longPath);

    /*2. dbg(DBG_PRINT, "(GRADING2B) ENOTDIR or ENOENT\n");*/
    retVal = do_stat("", &buf);

    /*3. dbg(DBG_PRINT, "(GRADING2C) (vfs_syscall.c) (do_getdent) Invalid file descriptor fd, return -EBADF\n");*/
    struct dirent dirp;
    retVal = do_getdent(-1, &dirp);

    /*4. dbg(DBG_PRINT, "(GRADING2C) (vfs_syscall.c) (do_getdent) Invalid file descriptor fd, return -EBADF\n");*/
    retVal = do_getdent(1, &dirp);

    /*5. dbg(DBG_PRINT, "(GRADING2C) (vfs_syscall.c) (do_getdent) File descriptor does not refer to a directory, return -ENOTDIR\n");*/
    do_mknod("/./file", S_IFCHR,MKDEVID(1,1));
    fd1 = do_open("/./file",2);
    retVal = do_getdent(fd1, &dirp);

    do_unlink("/./file");
    do_close(fd1);
    /*6. dbg(DBG_PRINT, "(GRADING2C) (vfs_syscall.c) (do_rename) Both are valid names \n");*/
    /* and */
    /*7. dbg(DBG_PRINT, "(GRADING2C) (vfs_syscall.c) (do_rename) error do_link, return error\n"); \n");*/
    retVal = do_rename("/./aaa", "/./bbb");


    dbg(DBG_PRINT,"\n\nretVal=%d",retVal);
    dbg(DBG_PRINT,"\n*************************************************************\n");
  return 0;
}
/* 
 * A little convenience command to clear the files from a directory (though not
 * the directories).  Called from the kshell as cleardir <name>.
 */
int faber_cleardir(kshell_t *ksh, int argc, char **argv) {
        KASSERT(NULL != ksh);

	struct dirent d;	/* The current directory entry */
	char buf[TESTBUFLEN];	/* A buffer used to assemble the pathname */
	int f = -1;		/* File descriptor (dirs must be opened) */
	int rv = 0;		/* Return values */
	int got_one = 1;	/* True if this iteration deleted a file */

	if ( argc < 2 ) {
	    kprintf(ksh, "Usage: cleardir dir\n");
	    return -1;
	}

	/* Because unlinking a file changes the order of the directory entries
	 * - specifically, it moves a directory entry into the spot where the
	 *   unlinked file's directory entry was - this loop starts over every
	 *   time a file is unlinked.  The pseudocode is:
	 *
	 *  repeat
	 *	open the directory.
	 *	find the first directory entry that is neither . nor ..
	 *	unlink it
	 *	close the directory
	 *  until only . and .. are left
	 */
	while ( got_one ) {
	    got_one = 0;
	    /* Open up the directory */
	    if ( (f = do_open(argv[1], O_RDONLY)) < 0 ) {
		kprintf(ksh, "Open failed on %s: %d %s\n", argv[1], f, 
			strerror(-f));
		return -1;
	    }

	    while ( ( rv = do_getdent(f, &d)) > 0 ) {
		/* Keep looking if d contains . or .. */
		if ( strncmp(".", d.d_name, NAME_LEN) == 0 || 
			strncmp("..", d.d_name, NAME_LEN) == 0 ) 
		    continue;
		/* Found a name to delete.  Construct the path and delete it */
		snprintf(buf, TESTBUFLEN, "%s/%s", argv[1], d.d_name);
		kprintf(ksh, "unlinking %s\n", buf);
		if ( (rv = do_unlink(buf)) < 0 ) {
		    /* Something went wrong- d probably points to a directory.
		     * Report the error, close f, and terminate the command. */
		    kprintf(ksh, "Unlink failed on %s: %d %s\n", buf, rv, 
			    strerror(-rv));
		    do_close(f);
		    return rv;
		}
		got_one = 1;
		/* CLose the directory and restart (because it set got_one) */
		break;
	    }
	    do_close(f);
	    /* This branch will be taken if do_getdent fails */
	    if ( rv < 0 ) {
		kprintf(ksh, "get_dent failed on %s: %d %s\n", argv[1], rv, 
			strerror(-rv));
		return rv;
	    }
	}
	/* OK, deleted everything we could. */
	return rv;
}