/* * 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; }
/* * Create empty file. */ static int fatfs_create(vnode_t dvp, char *name, mode_t mode) { struct fatfsmount *fmp; struct fatfs_node np; struct fat_dirent *de; u_long cl; int error; DPRINTF(("fatfs_create: %s\n", name)); if (!S_ISREG(mode)) return EINVAL; if (!fat_valid_name(name)) return EINVAL; fmp = dvp->v_mount->m_data; mutex_lock(&fmp->lock); /* Allocate free cluster for new file. */ error = fat_alloc_cluster(fmp, 0, &cl); if (error) goto out; de = &np.dirent; memset(de, 0, sizeof(struct fat_dirent)); fat_convert_name(name, (char *)de->name); de->cluster_hi = (cl & 0xFFFF0000) >> 16; de->cluster = cl & 0x0000FFFF; de->time = TEMP_TIME; de->date = TEMP_DATE; fat_mode_to_attr(mode, &de->attr); error = fatfs_add_node(dvp, &np); if (error) goto out; error = fat_set_cluster(fmp, cl, fmp->fat_eof); out: mutex_unlock(&fmp->lock); return error; }
static int fatfs_mkdir(vnode_t dvp, char *name, mode_t mode) { struct fatfsmount *fmp; struct fatfs_node np; struct fat_dirent *de; u_long cl; int error; if (!S_ISDIR(mode)) return EINVAL; if (!fat_valid_name(name)) return ENOTDIR; fmp = dvp->v_mount->m_data; mutex_lock(&fmp->lock); /* Allocate free cluster for directory data */ error = fat_alloc_cluster(fmp, 0, &cl); if (error) goto out; memset(&np, 0, sizeof(struct fatfs_node)); de = &np.dirent; fat_convert_name(name, (char *)&de->name); de->cluster_hi = (cl & 0xFFFF0000) >> 16; de->cluster = cl & 0x0000FFFF; de->time = TEMP_TIME; de->date = TEMP_DATE; fat_mode_to_attr(mode, &de->attr); error = fatfs_add_node(dvp, &np); if (error) goto out; /* Initialize "." and ".." for new directory */ memset(fmp->io_buf, 0, fmp->cluster_size); de = (struct fat_dirent *)fmp->io_buf; memcpy(de->name, ". ", 11); de->attr = FA_SUBDIR; de->cluster_hi = (cl & 0xFFFF0000) >> 16; de->cluster = cl & 0x0000FFFF; de->time = TEMP_TIME; de->date = TEMP_DATE; de++; memcpy(de->name, ".. ", 11); de->attr = FA_SUBDIR; de->cluster_hi = (dvp->v_blkno & 0xFFFF0000) >> 16; de->cluster = dvp->v_blkno & 0x0000FFFF; de->time = TEMP_TIME; de->date = TEMP_DATE; if (fat_write_cluster(fmp, cl)) { error = EIO; goto out; } /* Add eof */ error = fat_set_cluster(fmp, cl, fmp->fat_eof); out: mutex_unlock(&fmp->lock); return error; }
static int fatfs_rename(vnode_t dvp1, vnode_t vp1, char *name1, vnode_t dvp2, vnode_t vp2, char *name2) { struct fatfsmount *fmp; struct fatfs_node np1; struct fat_dirent *de1, *de2; int error; fmp = dvp1->v_mount->m_data; mutex_lock(&fmp->lock); error = fatfs_lookup_node(dvp1, name1, &np1); if (error) goto out; de1 = &np1.dirent; if (IS_FILE(de1)) { /* Remove destination file, first */ error = fatfs_remove(dvp2, vp1, name2); if (error == EIO) goto out; /* Change file name of directory entry */ fat_convert_name(name2, (char *)de1->name); /* Same directory ? */ if (dvp1 == dvp2) { /* Change the name of existing file */ error = fatfs_put_node(fmp, &np1); if (error) goto out; } else { /* Create new directory entry */ error = fatfs_add_node(dvp2, &np1); if (error) goto out; /* Remove souce file */ error = fatfs_remove(dvp1, vp2, name1); if (error) goto out; } } else { /* remove destination directory */ error = fatfs_rmdir(dvp2, NULL, name2); if (error == EIO) goto out; /* Change file name of directory entry */ fat_convert_name(name2, (char *)de1->name); /* Same directory ? */ if (dvp1 == dvp2) { /* Change the name of existing directory */ error = fatfs_put_node(fmp, &np1); if (error) goto out; } else { /* Create new directory entry */ error = fatfs_add_node(dvp2, &np1); if (error) goto out; /* Update "." and ".." for renamed directory */ if (fat_read_cluster(fmp,(de1->cluster_hi << 16) | de1->cluster)) { error = EIO; goto out; } de2 = (struct fat_dirent *)fmp->io_buf; de2->cluster_hi = de1->cluster_hi; de2->cluster = de1->cluster; de2->time = TEMP_TIME; de2->date = TEMP_DATE; de2++; de2->cluster_hi = (dvp2->v_blkno & 0xFFFF0000) >> 16; de2->cluster = dvp2->v_blkno & 0x0000FFFF; de2->time = TEMP_TIME; de2->date = TEMP_DATE; if (fat_write_cluster(fmp,(de1->cluster_hi << 16) | de1->cluster)) { error = EIO; goto out; } /* Remove souce directory */ error = fatfs_rmdir(dvp1, NULL, name1); if (error) goto out; } } out: mutex_unlock(&fmp->lock); return error; }