static int udf_node_get(fs_node_t **rfn, service_id_t service_id, fs_index_t index) { udf_instance_t *instance; int rc = fs_instance_get(service_id, (void **) &instance); if (rc != EOK) return rc; udf_node_t *node; rc = udf_idx_get(&node, instance, index); if (rc != EOK) { rc = udf_idx_add(&node, instance, index); if (rc != EOK) return rc; rc = udf_node_get_core(node); if (rc != EOK) { udf_idx_del(node); return rc; } } *rfn = FS_NODE(node); return EOK; }
static int udf_root_get(fs_node_t **rfn, service_id_t service_id) { udf_instance_t *instance; int rc = fs_instance_get(service_id, (void **) &instance); if (rc != EOK) return rc; return udf_node_get(rfn, service_id, instance->volumes[DEFAULT_VOL].root_dir); }
static int udf_size_block(service_id_t service_id, uint32_t *size) { udf_instance_t *instance; int rc = fs_instance_get(service_id, (void **) &instance); if (rc != EOK) return rc; if (NULL == instance) return ENOENT; *size = instance->volumes[DEFAULT_VOL].logical_block_size; return EOK; }
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; }
int fat_directory_read(fat_directory_t *di, char *name, fat_dentry_t **de) { fat_dentry_t *d = NULL; uint16_t wname[FAT_LFN_NAME_SIZE]; size_t lfn_offset, lfn_size; bool long_entry = false; int long_entry_count = 0; uint8_t checksum = 0; 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; do { rc = fat_directory_get(di, &d); if (rc != EOK) return rc; switch (fat_classify_dentry(d)) { case FAT_DENTRY_LAST: long_entry_count = 0; long_entry = false; return ENOENT; case FAT_DENTRY_LFN: if (long_entry) { /* We found long entry */ long_entry_count--; if ((FAT_LFN_ORDER(d) == long_entry_count) && (checksum == FAT_LFN_CHKSUM(d))) { /* Right order! */ fat_lfn_get_entry(d, wname, &lfn_offset); } else { /* * Something wrong with order. * Skip this long entries set. */ long_entry_count = 0; long_entry = false; } } else if (FAT_IS_LFN(d) && instance->lfn_enabled) { /* We found Last long entry! */ if (FAT_LFN_COUNT(d) <= FAT_LFN_MAX_COUNT) { long_entry = true; long_entry_count = FAT_LFN_COUNT(d); lfn_size = (FAT_LFN_ENTRY_SIZE * (FAT_LFN_COUNT(d) - 1)) + fat_lfn_size(d); lfn_offset = lfn_size; fat_lfn_get_entry(d, wname, &lfn_offset); checksum = FAT_LFN_CHKSUM(d); } } break; case FAT_DENTRY_VALID: if (long_entry && (checksum == fat_dentry_chksum(d->name))) { wname[lfn_size] = '\0'; if (utf16_to_str(name, FAT_LFN_NAME_SIZE, wname) != EOK) fat_dentry_name_get(d, name); } else fat_dentry_name_get(d, name); *de = d; return EOK; default: case FAT_DENTRY_SKIP: case FAT_DENTRY_FREE: long_entry_count = 0; long_entry = false; break; } } while (fat_directory_next(di) == EOK); return ENOENT; }
static int udf_read(service_id_t service_id, fs_index_t index, aoff64_t pos, size_t *rbytes) { udf_instance_t *instance; int rc = fs_instance_get(service_id, (void **) &instance); if (rc != EOK) return rc; fs_node_t *rfn; rc = udf_node_get(&rfn, service_id, index); if (rc != EOK) return rc; udf_node_t *node = UDF_NODE(rfn); ipc_callid_t callid; size_t len = 0; if (!async_data_read_receive(&callid, &len)) { async_answer_0(callid, EINVAL); udf_node_put(rfn); return EINVAL; } if (node->type == NODE_FILE) { if (pos >= node->data_size) { *rbytes = 0; async_data_read_finalize(callid, NULL, 0); udf_node_put(rfn); return EOK; } size_t read_len = 0; if (node->data == NULL) rc = udf_read_file(&read_len, callid, node, pos, len); else { /* File in allocation descriptors area */ read_len = (len < node->data_size) ? len : node->data_size; async_data_read_finalize(callid, node->data + pos, read_len); rc = EOK; } *rbytes = read_len; (void) udf_node_put(rfn); return rc; } else { block_t *block = NULL; udf_file_identifier_descriptor_t *fid = NULL; if (udf_get_fid(&fid, &block, node, pos) == EOK) { char *name = malloc(MAX_FILE_NAME_LEN + 1); // FIXME: Check for NULL return value udf_to_unix_name(name, MAX_FILE_NAME_LEN, (char *) fid->implementation_use + FLE16(fid->lenght_iu), fid->lenght_file_id, &node->instance->charset); async_data_read_finalize(callid, name, str_size(name) + 1); *rbytes = 1; free(name); udf_node_put(rfn); if (block != NULL) return block_put(block); return EOK; } else { *rbytes = 0; udf_node_put(rfn); async_answer_0(callid, ENOENT); return ENOENT; } } }