/* * 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; }
/* * Read one cluster to buffer. */ static int fat_read_cluster(struct fatfsmount *fmp, u_long cluster) { u_long sec; size_t size; sec = cl_to_sec(fmp, cluster); size = fmp->sec_per_cl * SEC_SIZE; return device_read(fmp->dev, fmp->io_buf, &size, sec); }
/* * 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; }
/* * 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; }