예제 #1
0
파일: udf_ops.c 프로젝트: jvesely/helenos
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;
}
예제 #2
0
파일: udf_ops.c 프로젝트: jvesely/helenos
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);
}
예제 #3
0
파일: udf_ops.c 프로젝트: jvesely/helenos
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;
}
예제 #4
0
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;
}
예제 #5
0
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;
}
예제 #6
0
파일: udf_ops.c 프로젝트: jvesely/helenos
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;
		}
	}
}