/* * 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; }
int fat_directory_write(fat_directory_t *di, const char *name, fat_dentry_t *de) { int rc; void *data; fat_instance_t *instance; rc = fs_instance_get(di->nodep->idx->service_id, &data); assert(rc == EOK); instance = (fat_instance_t *) data; if (fat_valid_short_name(name)) { /* * NAME could be directly stored in dentry without creating * LFN. */ fat_dentry_name_set(de, name); if (fat_directory_is_sfn_exist(di, de)) return EEXIST; rc = fat_directory_lookup_free(di, 1); if (rc != EOK) return rc; rc = fat_directory_write_dentry(di, de); return rc; } else if (instance->lfn_enabled && fat_valid_name(name)) { /* We should create long entries to store name */ int long_entry_count; uint8_t checksum; uint16_t wname[FAT_LFN_NAME_SIZE]; size_t lfn_size, lfn_offset; rc = str_to_utf16(wname, FAT_LFN_NAME_SIZE, name); if (rc != EOK) return rc; lfn_size = utf16_length(wname); long_entry_count = lfn_size / FAT_LFN_ENTRY_SIZE; if (lfn_size % FAT_LFN_ENTRY_SIZE) long_entry_count++; rc = fat_directory_lookup_free(di, long_entry_count + 1); if (rc != EOK) return rc; aoff64_t start_pos = di->pos; /* Write Short entry */ rc = fat_directory_create_sfn(di, de, name); if (rc != EOK) return rc; checksum = fat_dentry_chksum(de->name); rc = fat_directory_seek(di, start_pos + long_entry_count); if (rc != EOK) return rc; rc = fat_directory_write_dentry(di, de); if (rc != EOK) return rc; /* Write Long entry by parts */ lfn_offset = 0; fat_dentry_t *d; size_t idx = 0; do { rc = fat_directory_prev(di); if (rc != EOK) return rc; rc = fat_directory_get(di, &d); if (rc != EOK) return rc; fat_lfn_set_entry(wname, &lfn_offset, lfn_size + 1, d); FAT_LFN_CHKSUM(d) = checksum; FAT_LFN_ORDER(d) = ++idx; di->b->dirty = true; } while (lfn_offset < lfn_size); FAT_LFN_ORDER(d) |= FAT_LFN_LAST; rc = fat_directory_seek(di, start_pos + long_entry_count); return rc; } return ENOTSUP; }
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; }