Esempio n. 1
0
uint fat_write_block(char* name, uint offset, uchar* buffer){
	name = fat_name_conv(name);
	fat_dir_t* entry = fat_search(name);
	
	if(entry == NULL)
		return (uint) -1;

	ushort cluster = entry->cluster_low;
	if(cluster >= 0xFFF0){	//If the cluster is the end, make a new one
		cluster = fat_next_cluster();
		entry->cluster_low = cluster;
		cluster_list[cluster] = 0xFFFF;
	}

	while(offset != 0){
		if(cluster_list[cluster] >= 0xFFF0){ //End? Make a new one and continue
			cluster_list[cluster] = fat_next_cluster();
			cluster_list[cluster_list[cluster]] = 0xFFFF;
		}
		
		cluster = cluster_list[cluster];
		offset--;
	}
	
	ata_write_blocks((ushort*) buffer, cluster_to_lba(cluster), FAT_SPC);
	return 0;
}
Esempio n. 2
0
File: fat.c Progetto: mitlab/oggbox
/* get the next sector in the current file. */
int fat_next_sector(int fd) {
  int c;
  int rerrno;
#ifdef TRACE
  printf("fat_next_sector(%d)\n", fd);
#endif
  /* if the current sector was written write to disc */
  if(fat_flush(fd)) {
    return -1;
  }
  /* see if we need another cluster */
  if(file_num[fd].sectors_left > 0) {
    file_num[fd].sectors_left--;
    file_num[fd].file_sector++;
    file_num[fd].cursor = 0;
    return block_read(++file_num[fd].sector, file_num[fd].buffer);
  } else {
    c = fat_next_cluster(fd, &rerrno);
    if(c > -1) {
      file_num[fd].file_sector++;
      return fat_select_cluster(fd, c);
    } else {
      return -1;
    }
  }
}
Esempio n. 3
0
/*
 * Find empty directory entry and put new entry on it.
 * This search is done only in directory of specified cluster.
 * @dvp: vnode for directory.
 * @np: pointer to fat node
 */
int
fatfs_add_node(vnode_t dvp, struct fatfs_node *np)
{
	struct fatfsmount *fmp;
	u_long cl, sec, sec_start;
	int err;
	u_long i, next;

	fmp = (struct fatfsmount *)dvp->v_mount->m_data;
	cl = dvp->v_blkno;

	DPRINTF(("fatfs_add_node: cl=%d\n", cl));

	if (cl == CL_ROOT && !(FAT32(fmp))) {
		/* Add entry in root directory */
		sec_start = fmp->root_start;
		for (sec = sec_start; sec < fmp->data_start; sec++) {
			err = fat_add_dirent(fmp, sec, np);
			if (err != ENOENT)
				return err;
		}
	} else {
		/* Search entry in sub directory */
		if(cl == CL_ROOT)	/* CL_ROOT of FAT32 */
			cl = fmp->root_start;
		while (!IS_EOFCL(fmp, cl)) {
			sec = cl_to_sec(fmp, cl);
			for (i = 0; i < fmp->sec_per_cl; i++) {
				err = fat_add_dirent(fmp, sec, np);
				if (err != ENOENT)
					return err;
				sec++;
			}
			err = fat_next_cluster(fmp, cl, &next);
			if (err)
				return err;
			cl = next;
		}
		/* No entry found, add one more free cluster for directory */
		DPRINTF(("fatfs_add_node: expand dir\n"));
		err = fat_expand_dir(fmp, cl, &next);
		if (err)
			return err;

		/* Initialize free cluster. */
		memset(fmp->dir_buf, 0, SEC_SIZE);
		sec = cl_to_sec(fmp, next);
		for (i = 0; i < fmp->sec_per_cl; i++) {
			err = fat_write_dirent(fmp, sec);
			if (err)
				return err;
			sec++;
		}
		/* Try again */
		sec = cl_to_sec(fmp, next);
		err = fat_add_dirent(fmp, sec, np);
		return err;
	}
	return ENOENT;
}
Esempio n. 4
0
/*
 * Find directory entry for specified name in directory.
 * The fat vnode data is filled if success.
 *
 * @dvp: vnode for directory.
 * @name: file name
 * @np: pointer to fat node
 */
int
fatfs_lookup_node(vnode_t dvp, char *name, struct fatfs_node *np)
{
	struct fatfsmount *fmp;
	char fat_name[12];
	u_long i, cl, sec, sec_start;
	int err;

	if (name == NULL)
		return ENOENT;

	DPRINTF(("fat_lookup_denode: cl=%d name=%s\n", dvp->v_blkno, name));

	fat_convert_name(name, fat_name);
	*(fat_name + 11) = '\0';

	fmp = (struct fatfsmount *)dvp->v_mount->m_data;
	cl = dvp->v_blkno;
	if (cl == CL_ROOT && !(FAT32(fmp))) {
		/* Search entry in root directory */
		sec_start = fmp->root_start;
		for (sec = sec_start; sec < fmp->data_start; sec++) {
			err = fat_lookup_dirent(fmp, sec, fat_name, np);
			if (err != EAGAIN)
				return err;
		}
	} else {
		/* Search entry in sub directory */
		if(cl == CL_ROOT)	/* CL_ROOT of FAT32 */
			cl = fmp->root_start;
		while (!IS_EOFCL(fmp, cl)) {
			sec = cl_to_sec(fmp, cl);
			for (i = 0; i < fmp->sec_per_cl; i++) {
				err = fat_lookup_dirent(fmp, sec, fat_name,
						   np);
				if (err != EAGAIN)
					return err;
				sec++;
			}
			err = fat_next_cluster(fmp, cl, &cl);
			if (err)
				return err;
		}
	}
	return ENOENT;
}
Esempio n. 5
0
/*
 * Get directory entry for specified index.
 *
 * @dvp: vnode for directory.
 * @index: index of the entry
 * @np: pointer to fat node
 */
int
fatfs_get_node(vnode_t dvp, int index, struct fatfs_node *np)
{
	struct fatfsmount *fmp;
	u_long i, cl, sec, sec_start;
	int cur_index, err;

	fmp = (struct fatfsmount *)dvp->v_mount->m_data;
	cl = dvp->v_blkno;
	cur_index = 0;

	DPRINTF(("fatfs_get_node: index=%d\n", index));

	if (cl == CL_ROOT && !(FAT32(fmp))) {
		/* Get entry from the root directory */
		sec_start = fmp->root_start;
		for (sec = sec_start; sec < fmp->data_start; sec++) {
			err = fat_get_dirent(fmp, sec, index, &cur_index, np);
			if (err != EAGAIN)
				return err;
		}
	} else {
		if(cl == CL_ROOT)	/* CL_ROOT of FAT32 */
			cl = fmp->root_start;
		/* Get entry from the sub directory */
		while (!IS_EOFCL(fmp, cl)) {
			sec = cl_to_sec(fmp, cl);
			for (i = 0; i < fmp->sec_per_cl; i++) {
				err = fat_get_dirent(fmp, sec, index,
						     &cur_index, np);
				if (err != EAGAIN)
					return err;
				sec++;
			}
			err = fat_next_cluster(fmp, cl, &cl);
			if (err)
				return err;
		}
	}
	return ENOENT;
}
Esempio n. 6
0
File: fat.c Progetto: mitlab/oggbox
int fat_lseek(int fd, int ptr, int dir, int *rerrno) {
  unsigned int new_pos;
  unsigned int old_pos;
  int new_sec;
  int i;
  int file_cluster;
  (*rerrno) = 0;

  if(fd >= MAX_OPEN_FILES) {
    (*rerrno) = EBADF;
    return ptr-1;
  }
  if(!(file_num[fd].flags & FAT_FLAG_OPEN)) {
    (*rerrno) = EBADF;
    return ptr-1;    /* tried to seek on a file that's not open */
  }
  
  fat_flush(fd);
  old_pos = file_num[fd].file_sector * 512 + file_num[fd].cursor;
  if(dir == SEEK_SET) {
    new_pos = ptr;
  } else if(dir == SEEK_CUR) {
    new_pos = file_num[fd].file_sector * 512 + file_num[fd].cursor + ptr;
  } else {
    new_pos = file_num[fd].size + ptr;
  }
  if(new_pos > file_num[fd].size) {
    return ptr-1; /* tried to seek outside a file */
  }
  // optimisation cases
  if((old_pos/512) == (new_pos/512)) {
    // case 1: seeking within a disk block
    file_num[fd].cursor = new_pos & 0x1ff;
    return new_pos;
  } else if((new_pos / (fatfs.sectors_per_cluster * 512)) == (old_pos / (fatfs.sectors_per_cluster * 512))) {
    // case 2: seeking within the cluster, just need to hop forward/back some sectors
    file_num[fd].file_sector = new_pos / 512;
    file_num[fd].sector = file_num[fd].sector + (new_pos/512) - (old_pos/512);
    file_num[fd].sectors_left = file_num[fd].sectors_left + (new_pos/512) - (old_pos/512);
    file_num[fd].cursor = new_pos & 0x1ff;
    if(block_read(file_num[fd].sector, file_num[fd].buffer)) {
      return ptr - 1;
    }
    return new_pos;
  }
  // otherwise we need to seek the cluster chain
  file_cluster = new_pos / (fatfs.sectors_per_cluster * 512);
  
  file_num[fd].cluster = file_num[fd].full_first_cluster;
  i = 0;
  // walk the FAT cluster chain until we get to the right one
  while(i<file_cluster) {
    file_num[fd].cluster = fat_next_cluster(fd, rerrno);
    i++;
  }
  file_num[fd].file_sector = new_pos / 512;
  file_num[fd].cursor = new_pos & 0x1ff;
  new_sec = new_pos - file_cluster * fatfs.sectors_per_cluster * 512;
  new_sec = new_sec / 512;
  file_num[fd].sector = file_num[fd].cluster * fatfs.sectors_per_cluster + fatfs.cluster0 + new_sec;
  file_num[fd].sectors_left = fatfs.sectors_per_cluster - new_sec - 1;
  if(block_read(file_num[fd].sector, file_num[fd].buffer)) {
    return ptr-1;
  }
  return new_pos;
}
Esempio n. 7
0
static int
fatfs_write(vnode_t vp, file_t fp, void *buf, size_t size, size_t *result)
{
    struct fatfsmount *fmp;
    struct fatfs_node *np;
    struct fat_dirent *de;
    int nr_copy, nr_write, buf_pos, i, cl_size, error;
    u_long file_pos, end_pos;
    u_long cl;

    DPRINTF(("fatfs_write: vp=%x size=%d\n", vp, size));

    *result = 0;
    fmp = vp->v_mount->m_data;

    if (vp->v_type == VDIR)
        return EISDIR;
    if (vp->v_type != VREG)
        return EINVAL;

    mutex_lock(&fmp->lock);

    /* Check if file position exceeds the end of file. */
    end_pos = vp->v_size;
    file_pos = (fp->f_flags & O_APPEND) ? end_pos : fp->f_offset;
    if (file_pos + size > end_pos) {
        /* Expand the file size before writing to it */
        end_pos = file_pos + size;
        error = fat_expand_file(fmp, vp->v_blkno, end_pos);
        if (error) {
            error = EIO;
            goto out;
        }

        /* Update directory entry */
        np = vp->v_data;
        de = &np->dirent;
        de->size = end_pos;
        error = fatfs_put_node(fmp, np);
        if (error)
            goto out;
        vp->v_size = end_pos;
    }

    /* Seek to the cluster for the file offset */
    error = fat_seek_cluster(fmp, vp->v_blkno, file_pos, &cl);
    if (error)
        goto out;

    buf_pos = file_pos % fmp->cluster_size;
    cl_size = size / fmp->cluster_size + 1;
    nr_write = 0;
    i = 0;
    do {
        /* First and last cluster must be read before write */
        if (i == 0 || i == cl_size) {
            if (fat_read_cluster(fmp, cl)) {
                error = EIO;
                goto out;
            }
        }
        nr_copy = fmp->cluster_size;
        if (buf_pos > 0)
            nr_copy -= buf_pos;
        if (buf_pos + size < fmp->cluster_size)
            nr_copy = size;
        memcpy(fmp->io_buf + buf_pos, buf, nr_copy);

        if (fat_write_cluster(fmp, cl)) {
            error = EIO;
            goto out;
        }
        file_pos += nr_copy;
        nr_write += nr_copy;
        size -= nr_copy;
        if (size <= 0)
            break;

        error = fat_next_cluster(fmp, cl, &cl);
        if (error)
            goto out;

        buf = (void *)((u_long)buf + nr_copy);
        buf_pos = 0;
        i++;
    } while (!IS_EOFCL(fmp, cl));

    fp->f_offset = file_pos;

    /*
     * XXX: Todo!
     *    de.time = ?
     *    de.date = ?
     *    if (dirent_set(fp, &de))
     *        return EIO;
     */
    *result = nr_write;
    error = 0;
out:
    mutex_unlock(&fmp->lock);
    return error;
}
Esempio n. 8
0
static int
fatfs_read(vnode_t vp, file_t fp, void *buf, size_t size, size_t *result)
{
    struct fatfsmount *fmp;
    int nr_read, nr_copy, buf_pos, error;
    u_long cl, file_pos;

    DPRINTF(("fatfs_read: vp=%x\n", vp));

    *result = 0;
    fmp = vp->v_mount->m_data;

    if (vp->v_type == VDIR)
        return EISDIR;
    if (vp->v_type != VREG)
        return EINVAL;

    /* Check if current file position is already end of file. */
    file_pos = fp->f_offset;
    if (file_pos >= vp->v_size)
        return 0;

    mutex_lock(&fmp->lock);

    /* Get the actual read size. */
    if (vp->v_size - file_pos < size)
        size = vp->v_size - file_pos;

    /* Seek to the cluster for the file offset */
    error = fat_seek_cluster(fmp, vp->v_blkno, file_pos, &cl);
    if (error)
        goto out;

    /* Read and copy data */
    nr_read = 0;
    buf_pos = file_pos % fmp->cluster_size;
    do {
        if (fat_read_cluster(fmp, cl)) {
            error = EIO;
            goto out;
        }

        nr_copy = fmp->cluster_size;
        if (buf_pos > 0)
            nr_copy -= buf_pos;
        if (buf_pos + size < fmp->cluster_size)
            nr_copy = size;
        memcpy(buf, fmp->io_buf + buf_pos, nr_copy);

        file_pos += nr_copy;
        nr_read += nr_copy;
        size -= nr_copy;
        if (size <= 0)
            break;

        error = fat_next_cluster(fmp, cl, &cl);
        if (error)
            goto out;

        buf = (void *)((u_long)buf + nr_copy);
        buf_pos = 0;
    } while (!IS_EOFCL(fmp, cl));

    fp->f_offset = file_pos;
    *result = nr_read;
    error = 0;
out:
    mutex_unlock(&fmp->lock);
    return error;
}