Пример #1
0
/*===========================================================================*
 *				fs_putnode				     *
 *===========================================================================*/
PUBLIC int fs_putnode()
{
/* Find the inode specified by the request message and decrease its counter. */
  int count;
  struct dir_record *dir = NULL;

  dir = get_dir_record(fs_m_in.REQ_INODE_NR);
  release_dir_record(dir);
  
  count = fs_m_in.REQ_COUNT;

  if (count <= 0) return(EINVAL);
  
  if (count > dir->d_count) {
     printf("put_inode: count too high: %d > %d\n", count, dir->d_count);
     return(EINVAL);
  }

  if (dir->d_count > 1)
	dir->d_count = dir->d_count - count + 1;/*Keep at least one reference*/

  release_dir_record(dir); /* Actual inode release, might be last reference */

  return(OK);
}
Пример #2
0
/*===========================================================================*
 *				fs_mountpoint				     *
 *===========================================================================*/
PUBLIC int fs_mountpoint()
{
/* This function looks up the mount point, it checks the condition whether
 * the partition can be mounted on the inode or not. 
 */

  register struct dir_record *rip;
  int r = OK;
  
  /* Temporarily open the file. */
  if ((rip = get_dir_record(fs_m_in.REQ_INODE_NR)) == NULL)
	return(EINVAL);

  if (rip->d_mountpoint)
	r = EBUSY;

  /* If the inode is not a dir returns error */
  if ((rip->d_mode & I_TYPE) != I_DIRECTORY)
	r = ENOTDIR;
	
  release_dir_record(rip);

  if (r == OK)
	rip->d_mountpoint = TRUE;

  return(r);
}
Пример #3
0
/*===========================================================================*
 *				fs_putnode				     *
 *===========================================================================*/
PUBLIC int fs_putnode()
{
/* Find the inode specified by the request message and decrease its counter.
 */
  int count;
  struct dir_record *dir = (void *)0;

/*   if (fs_m_in.REQ_INODE_INDEX >= 0 &&  */
/*       fs_m_in.REQ_INODE_INDEX <= NR_DIR_RECORDS && */
/*       ID_DIR_RECORD((dir_records + fs_m_in.REQ_INODE_INDEX)) == fs_m_in.REQ_INODE_NR) { */
/*     dir = &dir_records[fs_m_in.REQ_INODE_INDEX]; */
/*     /\* In this case the dir record by the dir record table *\/ */
/*   } else { */
  dir = get_dir_record(fs_m_in.REQ_INODE_NR);
  /* Get dir record increased the counter. We must decrease it releasing 
   * it */
  release_dir_record(dir);
  
  if (dir == (void *)0) {
    panic(__FILE__, "fs_putnode failed", NO_NUM);
  }
  
  count= fs_m_in.REQ_COUNT;	/* I will check that the values of the count
				 * are the same */

  if (count <= 0) {
    printf("put_inode: bad value for count: %d\n", count);
    panic(__FILE__, "fs_putnode failed", NO_NUM);
    return EINVAL;
  }
  if (count > dir->d_count) {
    printf("put_inode: count too high: %d > %d\n", count, dir->d_count);
     panic(__FILE__, "fs_putnode failed", NO_NUM);
     return EINVAL;
  }

  if (dir->d_count > 1)
    dir->d_count = dir->d_count - count + 1;	/* If the dir record should be released this
						   operation will bring the counter to 1.
						   The next function will further decreases it
						   releasing it completely. */

  release_dir_record(dir);	/* I finally release it */

  return OK;
}
Пример #4
0
/*===========================================================================*
 *				fs_read					     *
 *===========================================================================*/
int fs_read(void) {
    int r, chunk, block_size;
    int nrbytes;
    cp_grant_id_t gid;
    off_t position, f_size, bytes_left;
    unsigned int off, cum_io;
    int completed;
    struct dir_record *dir;

    r = OK;

    /* Try to get inode according to its index */
    dir = get_dir_record(fs_m_in.REQ_INODE_NR);
    if (dir == NULL) return(EINVAL); /* no inode found */

    position = fs_m_in.REQ_SEEK_POS_LO;
    nrbytes = (unsigned) fs_m_in.REQ_NBYTES; /* number of bytes to read */
    block_size = v_pri.logical_block_size_l;
    gid = fs_m_in.REQ_GRANT;
    f_size = dir->d_file_size;

    rdwt_err = OK;		/* set to EIO if disk error occurs */

    cum_io = 0;
    /* Split the transfer into chunks that don't span two blocks. */
    while (nrbytes != 0) {
        off = (unsigned int) (position % block_size);

        chunk = MIN(nrbytes, block_size - off);
        if (chunk < 0) chunk = block_size - off;

        bytes_left = f_size - position;
        if (position >= f_size) break;	/* we are beyond EOF */
        if (chunk > bytes_left) chunk = (int) bytes_left;

        /* Read or write 'chunk' bytes. */
        r = read_chunk(dir, cvul64(position), off, chunk, (unsigned) nrbytes,
                       gid, cum_io, block_size, &completed);

        if (r != OK) break;	/* EOF reached */
        if (rdwt_err < 0) break;

        /* Update counters and pointers. */
        nrbytes -= chunk;	/* bytes yet to be read */
        cum_io += chunk;	/* bytes read so far */
        position += chunk;	/* position within the file */
    }

    fs_m_out.RES_SEEK_POS_LO = position;

    if (rdwt_err != OK) r = rdwt_err;	/* check for disk error */
    if (rdwt_err == END_OF_FILE) r = OK;

    fs_m_out.RES_NBYTES = cum_io; /*dir->d_file_size;*/
    release_dir_record(dir);

    return(r);
}
Пример #5
0
/*===========================================================================*
 *				fs_access				     *
 *===========================================================================*/
int fs_access()
{
  struct dir_record *rip;
  int r = OK;

  /* Temporarily open the file whose access is to be checked. */
  caller_uid = fs_m_in.REQ_UID;
  caller_gid = fs_m_in.REQ_GID;
  
  /* Temporarily open the file. */
  if ( (rip = get_dir_record(fs_m_in.REQ_INODE_NR)) == NULL) {
    printf("ISOFS(%d) get_dir_record by fs_access() failed\n", SELF_E);
    return(EINVAL);
  }

  /* For now ISO9660 doesn't have permission control (read and execution to
   * everybody by default. So the access is always granted. */
  
  release_dir_record(rip);	/* Release the dir record used */
  return(r);
}
Пример #6
0
/*===========================================================================*
 *				fs_getdents				     *
 *===========================================================================*/
int fs_getdents(void) {
    struct dir_record *dir;
    ino_t ino;
    cp_grant_id_t gid;
    size_t block_size;
    off_t pos, block_pos, block, cur_pos, tmpbuf_offset, userbuf_off;
    struct buf *bp;
    struct dir_record *dir_tmp;
    struct dirent *dirp;
    int r,done,o,len,reclen;
    char *cp;
    char name[NAME_MAX + 1];
    char name_old[NAME_MAX + 1];

    /* Initialize the tmp arrays */
    memset(name,'\0',NAME_MAX);
    memset(name_old,'\0',NAME_MAX);

    /* Get input parameters */
    ino = fs_m_in.REQ_INODE_NR;
    gid = fs_m_in.REQ_GRANT;
    pos = fs_m_in.REQ_SEEK_POS_LO;

    block_size = v_pri.logical_block_size_l;
    cur_pos = pos;		/* The current position */
    tmpbuf_offset = 0;
    userbuf_off = 0;
    memset(getdents_buf, '\0', GETDENTS_BUFSIZ);	/* Avoid leaking any data */

    if ((dir = get_dir_record(ino)) == NULL) return(EINVAL);

    block = dir->loc_extent_l;	/* First block of the directory */
    block += pos / block_size; 	/* Shift to the block where start to read */
    done = FALSE;

    while (cur_pos<dir->d_file_size) {
        bp = get_block(block);	/* Get physical block */

        if (bp == NULL) {
            release_dir_record(dir);
            return(EINVAL);
        }

        block_pos = cur_pos % block_size; /* Position where to start read */

        while (block_pos < block_size) {
            dir_tmp = get_free_dir_record();
            create_dir_record(dir_tmp,bp->b_data + block_pos,
                              block*block_size + block_pos);
            if (dir_tmp->length == 0) { /* EOF. I exit and return 0s */
                block_pos = block_size;
                done = TRUE;
                release_dir_record(dir_tmp);
            } else { 	/* The dir record is valid. Copy data... */
                if (dir_tmp->file_id[0] == 0)
                    strlcpy(name, ".", NAME_MAX + 1);
                else if (dir_tmp->file_id[0] == 1)
                    strlcpy(name, "..", NAME_MAX + 1);
                else {
                    /* Extract the name from the field file_id */
                    strncpy(name, dir_tmp->file_id,
                            dir_tmp->length_file_id);
                    name[dir_tmp->length_file_id] = 0;

                    /* Tidy up file name */
                    cp = memchr(name, ';', NAME_MAX);
                    if (cp != NULL) name[cp - name] = 0;

                    /*If no file extension, then remove final '.'*/
                    if (name[strlen(name) - 1] == '.')
                        name[strlen(name) - 1] = '\0';
                }

                if (strcmp(name_old, name) == 0) {
                    cur_pos += dir_tmp->length;
                    release_dir_record(dir_tmp);
                    continue;
                }

                strlcpy(name_old, name, NAME_MAX + 1);

                /* Compute the length of the name */
                cp = memchr(name, '\0', NAME_MAX);
                if (cp == NULL) len = NAME_MAX;
                else len= cp - name;

                /* Compute record length */
                reclen = offsetof(struct dirent, d_name) + len + 1;
                o = (reclen % sizeof(long));
                if (o != 0)
                    reclen += sizeof(long) - o;

                /* If the new record does not fit, then copy the buffer
                 * and start from the beginning. */
                if (tmpbuf_offset + reclen > GETDENTS_BUFSIZ) {
                    r = sys_safecopyto(VFS_PROC_NR, gid, userbuf_off,
                                       (vir_bytes)getdents_buf, tmpbuf_offset);

                    if (r != OK)
                        panic("fs_getdents: sys_safecopyto failed: %d", r);
                    userbuf_off += tmpbuf_offset;
                    tmpbuf_offset= 0;
                }

                /* The standard data structure is created using the
                 * data in the buffer. */
                dirp = (struct dirent *) &getdents_buf[tmpbuf_offset];
                dirp->d_ino = (ino_t)(bp->b_data + block_pos);
                dirp->d_off= cur_pos;
                dirp->d_reclen= reclen;
                memcpy(dirp->d_name, name, len);
                dirp->d_name[len]= '\0';
                tmpbuf_offset += reclen;

                cur_pos += dir_tmp->length;
                release_dir_record(dir_tmp);
            }

            block_pos += dir_tmp->length;
        }

        put_block(bp);		/* release the block */
        if (done == TRUE) break;

        cur_pos += block_size - cur_pos;
        block++;			/* read the next one */
    }

    if (tmpbuf_offset != 0) {
        r = sys_safecopyto(VFS_PROC_NR, gid, userbuf_off,
                           (vir_bytes) getdents_buf, tmpbuf_offset);
        if (r != OK)
            panic("fs_getdents: sys_safecopyto failed: %d", r);

        userbuf_off += tmpbuf_offset;
    }

    fs_m_out.RES_NBYTES = userbuf_off;
    fs_m_out.RES_SEEK_POS_LO = cur_pos;

    release_dir_record(dir);		/* release the inode */
    return(OK);
}