Index: boot/Makefile.common
===================================================================
--- boot/Makefile.common	(revision db81577a2edad8340ee140d0f23af2b17579e167)
+++ boot/Makefile.common	(revision 48e31904fcd0b717c586d68fd42458d05940cb20)
@@ -107,4 +107,5 @@
 	$(USPACE_PATH)/srv/fs/cdfs/cdfs \
 	$(USPACE_PATH)/srv/fs/exfat/exfat \
+	$(USPACE_PATH)/srv/fs/udf/udf \
 	$(USPACE_PATH)/srv/fs/ext2fs/ext2fs \
 	$(USPACE_PATH)/srv/fs/ext4fs/ext4fs \
Index: uspace/Makefile
===================================================================
--- uspace/Makefile	(revision db81577a2edad8340ee140d0f23af2b17579e167)
+++ uspace/Makefile	(revision 48e31904fcd0b717c586d68fd42458d05940cb20)
@@ -95,4 +95,5 @@
 	srv/bd/part/mbr_part \
 	srv/fs/exfat \
+	srv/fs/udf \
 	srv/fs/fat \
 	srv/fs/cdfs \
Index: uspace/srv/fs/udf/Makefile
===================================================================
--- uspace/srv/fs/udf/Makefile	(revision 48e31904fcd0b717c586d68fd42458d05940cb20)
+++ uspace/srv/fs/udf/Makefile	(revision 48e31904fcd0b717c586d68fd42458d05940cb20)
@@ -0,0 +1,45 @@
+#
+# Copyright (c) 2005 Martin Decky
+# Copyright (c) 2007 Jakub Jermar
+# Copyright (c) 2012 Julia Medvedeva
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# - Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# - Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the distribution.
+# - The name of the author may not be used to endorse or promote products
+#   derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+USPACE_PREFIX = ../../..
+LIBS = $(LIBBLOCK_PREFIX)/libblock.a $(LIBFS_PREFIX)/libfs.a
+EXTRA_CFLAGS += -I$(LIBBLOCK_PREFIX) -I$(LIBFS_PREFIX)
+BINARY = udf
+
+SOURCES = \
+	udf.c \
+	udf_volume.c \
+	udf_ops.c \
+	udf_osta.c \
+	udf_cksum.c \
+	udf_file.c \
+	udf_idx.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/fs/udf/udf.c
===================================================================
--- uspace/srv/fs/udf/udf.c	(revision 48e31904fcd0b717c586d68fd42458d05940cb20)
+++ uspace/srv/fs/udf/udf.c	(revision 48e31904fcd0b717c586d68fd42458d05940cb20)
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2006 Martin Decky
+ * Copyright (c) 2008 Jakub Jermar
+ * Copyright (c) 2012 Julia Medvedeva
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup fs
+ * @{
+ */
+/**
+ * @file udf.c
+ * @brief UDF 1.02 file system driver for HelenOS.
+ */
+
+#include <ipc/services.h>
+#include <ns.h>
+#include <async.h>
+#include <errno.h>
+#include <unistd.h>
+#include <task.h>
+#include <libfs.h>
+#include <str.h>
+#include <io/log.h>
+#include "../../vfs/vfs.h"
+#include "udf.h"
+#include "udf_idx.h"
+
+#define NAME  "udf"
+
+vfs_info_t udf_vfs_info = {
+	.name = NAME,
+	.concurrent_read_write = false,
+	.write_retains_size = false,
+	.instance = 0,
+};
+
+int main(int argc, char *argv[])
+{
+	log_init(NAME, LVL_NOTE);
+	log_msg(LVL_NOTE, "HelenOS UDF 1.02 file system server");
+	
+	if (argc == 3) {
+		if (!str_cmp(argv[1], "--instance"))
+			udf_vfs_info.instance = strtol(argv[2], NULL, 10);
+		else {
+			log_msg(LVL_FATAL, "Unrecognized parameters");
+			return 1;
+		}
+	}
+	
+	async_sess_t *vfs_sess =
+	    service_connect_blocking(EXCHANGE_SERIALIZE, SERVICE_VFS, 0, 0);
+	if (!vfs_sess) {
+		log_msg(LVL_FATAL, "Failed to connect to VFS");
+		return 2;
+	}
+	
+	int rc = fs_register(vfs_sess, &udf_vfs_info, &udf_ops,
+	    &udf_libfs_ops);
+	if (rc != EOK)
+		goto err;
+	
+	rc = udf_idx_init();
+	if (rc != EOK)
+		goto err;
+	
+	log_msg(LVL_NOTE, "Accepting connections");
+	task_retval(0);
+	async_manager();
+	
+	/* Not reached */
+	return 0;
+	
+err:
+	log_msg(LVL_FATAL, "Failed to register file system (%d)", rc);
+	return rc;
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/fs/udf/udf.h
===================================================================
--- uspace/srv/fs/udf/udf.h	(revision 48e31904fcd0b717c586d68fd42458d05940cb20)
+++ uspace/srv/fs/udf/udf.h	(revision 48e31904fcd0b717c586d68fd42458d05940cb20)
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2008 Jakub Jermar
+ * Copyright (c) 2012 Julia Medvedeva
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup fs
+ * @{
+ */
+
+#ifndef UDF_UDF_H_
+#define UDF_UDF_H_
+
+#include <fibril_synch.h>
+#include <libfs.h>
+#include <atomic.h>
+#include <sys/types.h>
+#include <bool.h>
+#include "../../vfs/vfs.h"
+#include "udf_types.h"
+
+#define UDF_NODE(node) \
+	((node) ? (udf_node_t *) (node)->data : NULL)
+
+#define FS_NODE(node) \
+	((node) ? (fs_node_t *) ((node)->fs_node) : NULL)
+
+#define BS_BLOCK     0
+#define MIN_SIZE     512
+#define MAX_SIZE     8192
+#define DEFAULT_VOL  0
+
+#define NODE_DIR   0
+#define NODE_FILE  1
+
+#define MAX_FILE_NAME_LEN  512
+
+#define MIN_FID_LEN  38
+
+#define SPACE_TABLE   0
+#define SPACE_BITMAP  1
+
+typedef struct udf_partition {
+	/* Partition info */
+	uint16_t number;
+	uint32_t access_type;
+	uint32_t start;
+	uint32_t lenght;
+} udf_partition_t;
+
+typedef struct udf_lvolume {
+	udf_partition_t **partitions;
+	size_t partition_cnt;
+	uint32_t logical_block_size;
+	fs_index_t root_dir;
+} udf_lvolume_t;
+
+typedef struct {
+	service_id_t service_id;
+	size_t open_nodes_count;
+	udf_charspec_t charset;
+	
+	uint32_t sector_size;
+	udf_lvolume_t *volumes;
+	udf_partition_t *partitions;
+	size_t partition_cnt;
+	udf_unallocated_space_descriptor_t *uasd;
+	uint64_t uaspace_start;
+	uint64_t uaspace_lenght;
+	uint8_t space_type;
+} udf_instance_t;
+
+typedef struct udf_allocator {
+	uint32_t length;
+	uint32_t position;
+} udf_allocator_t;
+
+typedef struct udf_node {
+	udf_instance_t *instance;
+	fs_node_t *fs_node;
+	fibril_mutex_t lock;
+	
+	fs_index_t index;  /* FID logical block */
+	link_t link;
+	size_t ref_cnt;
+	size_t link_cnt;
+	
+	uint8_t type;  /* 1 - file, 0 - directory */
+	uint64_t data_size;
+	uint8_t *data;
+	udf_allocator_t *allocators;
+	size_t alloc_size;
+} udf_node_t;
+
+extern vfs_out_ops_t udf_ops;
+extern libfs_ops_t udf_libfs_ops;
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/srv/fs/udf/udf_cksum.c
===================================================================
--- uspace/srv/fs/udf/udf_cksum.c	(revision 48e31904fcd0b717c586d68fd42458d05940cb20)
+++ uspace/srv/fs/udf/udf_cksum.c	(revision 48e31904fcd0b717c586d68fd42458d05940cb20)
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2012 Julia Medvedeva
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup fs
+ * @{
+ */
+/**
+ * @file udf_cksum.c
+ * @brief Implementation of various checksum functions.
+ */
+
+#include "udf_cksum.h"
+
+/** CRC 010041 */
+static uint16_t crc_table[256] = {
+	0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
+	0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
+	0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
+	0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
+	0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
+	0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
+	0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
+	0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
+	0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
+	0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
+	0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
+	0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
+	0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
+	0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
+	0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
+	0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
+	0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
+	0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
+	0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
+	0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
+	0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
+	0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
+	0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
+	0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
+	0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
+	0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
+	0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
+	0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
+	0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
+	0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
+	0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
+	0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
+};
+
+/** Calculate CRC16
+ *
+ */
+uint16_t udf_cksum(uint8_t *buf, size_t len)
+{
+	uint16_t crc = 0;
+	
+	while (len-- > 0)
+		crc = crc_table[(crc >> 8 ^ *buf++) & 0xff] ^ (crc << 8);
+	
+	return crc;
+}
+
+/** Unicode checksum
+ *
+ */
+uint16_t udf_unicode_cksum(uint16_t *buf, size_t len)
+{
+	uint16_t crc = 0;
+	
+	while (len-- > 0) {
+		/*
+		 * Take high order byte first (corresponds to a big endian
+		 * byte stream).
+		 */
+		crc = crc_table[(crc >> 8 ^ (*buf >> 8)) & 0xff] ^ (crc << 8);
+		crc = crc_table[(crc >> 8 ^ (*buf++ & 0xff)) & 0xff] ^ (crc << 8);
+	}
+	
+	return crc;
+}
+
+/** EA checksum
+ *
+ * Calculate a 16-bit checksum of the Implementation Use
+ * Extended Attribute header or Application Use Extended Attribute
+ * header. The fields AttributeType through ImplementationIdentifier
+ * (or ApplicationIdentifier) inclusively represent the
+ * data covered by the checksum (48 bytes).
+ *
+ */
+uint16_t udf_ea_cksum(uint8_t *data)
+{
+	uint16_t checksum = 0;
+	size_t count;
+	
+	for (count = 0; count < 48; count++)
+		checksum += *data++;
+	
+	return checksum;
+}
+
+/** Calculate descriptor tag checksum
+ *
+ */
+uint8_t udf_tag_checksum(uint8_t *tag)
+{
+	uint8_t result = 0;
+	
+	for (size_t i = 0; i < UDF_TAG_SIZE; i++) {
+		if (i == 4)
+			continue;
+		
+		result = (result + tag[i]) % 256;
+	}
+	
+	return result;
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/fs/udf/udf_cksum.h
===================================================================
--- uspace/srv/fs/udf/udf_cksum.h	(revision 48e31904fcd0b717c586d68fd42458d05940cb20)
+++ uspace/srv/fs/udf/udf_cksum.h	(revision 48e31904fcd0b717c586d68fd42458d05940cb20)
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2012 Julia Medvedeva
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup fs
+ * @{
+ */
+
+#ifndef UDF_CKSUM_H_
+#define UDF_CKSUM_H_
+
+#include <sys/types.h>
+#include <bool.h>
+
+#define UDF_TAG_SIZE  16
+
+extern uint16_t udf_cksum(uint8_t *, size_t);
+extern uint16_t udf_unicode_cksum(uint16_t *, size_t);
+extern uint16_t udf_ea_cksum(uint8_t *);
+extern uint8_t udf_tag_checksum(uint8_t *);
+
+#endif /* UDF_CKSUM_H_ */
+
+/**
+ * @}
+ */
Index: uspace/srv/fs/udf/udf_file.c
===================================================================
--- uspace/srv/fs/udf/udf_file.c	(revision 48e31904fcd0b717c586d68fd42458d05940cb20)
+++ uspace/srv/fs/udf/udf_file.c	(revision 48e31904fcd0b717c586d68fd42458d05940cb20)
@@ -0,0 +1,739 @@
+/*
+ * Copyright (c) 2012 Julia Medvedeva
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup fs
+ * @{
+ */
+/**
+ * @file udf_file.c
+ * @brief Implementation of file operations. Reading and writing functions.
+ */
+
+#include <block.h>
+#include <libfs.h>
+#include <errno.h>
+#include <malloc.h>
+#include <inttypes.h>
+#include <io/log.h>
+#include <mem.h>
+#include "udf.h"
+#include "udf_file.h"
+#include "udf_cksum.h"
+#include "udf_volume.h"
+
+/** Read extended allocator in allocation sequence
+ *
+ * @paran node     UDF node
+ * @param icb_flag Type of allocators in sequence.
+ *                 According to ECMA 167 4/14.8.8
+ * @param pos      Position with which we read
+ *
+ * @return EOK on success or a negative error code.
+ *
+ */
+int udf_read_extended_allocator(udf_node_t *node, uint16_t icb_flag,
+    uint32_t pos)
+{
+	block_t *block = NULL;
+	int rc = block_get(&block, node->instance->service_id, pos,
+	    BLOCK_FLAGS_NONE);
+	if (rc != EOK)
+		return rc;
+	
+	udf_ext_ad_t *exd = (udf_ext_ad_t *) block->data;
+	uint32_t start = node->instance->partitions[
+	    FLE16(exd->extent_location.partition_num)].start +
+	    FLE32(exd->extent_location.lblock_num);
+	
+	log_msg(LVL_DEBUG,
+	    "Extended allocator: start=%d, block_num=%d, len=%d", start,
+	    FLE32(exd->extent_location.lblock_num), FLE32(exd->info_length));
+	
+	uint32_t len = FLE32(exd->info_length);
+	block_put(block);
+	
+	return udf_read_allocation_sequence(node, NULL, icb_flag, start, len);
+}
+
+/** Read ICB sequence of allocators in (Extended) File entry descriptor
+ *
+ * @parem node     UDF node
+ * @param af       (Extended) File entry descriptor
+ * @param icb_flag Type of allocators in sequence.
+ *                 According to ECMA 167 4/14.8.8
+ * @param start_alloc Offset of the allocator
+ * @param len         Length of sequence
+ *
+ * @return EOK on success or a negative error code.
+ *
+ */
+int udf_read_allocation_sequence(udf_node_t *node, uint8_t *af,
+    uint16_t icb_flag, uint32_t start_alloc, uint32_t len)
+{
+	node->alloc_size = 0;
+	
+	switch (icb_flag) {
+	case UDF_SHORT_AD:
+		log_msg(LVL_DEBUG,
+		    "ICB: sequence of allocation descriptors - icbflag = short_ad_t");
+		
+		/*
+		 * Identify number of current partition. Virtual partition
+		 * could placed inside of physical partition. It means that same
+		 * sector could be inside of both partition physical and virtual.
+		 */
+		size_t pd_num = (size_t) -1;
+		size_t min_start = 0;
+		
+		for (size_t i = 0; i < node->instance->partition_cnt; i++) {
+			if ((node->index >= node->instance->partitions[i].start) &&
+			    (node->index < node->instance->partitions[i].start +
+			    node->instance->partitions[i].lenght)) {
+				if (node->instance->partitions[i].start >= min_start) {
+					min_start = node->instance->partitions[i].start;
+					pd_num = i;
+				}
+			}
+		}
+		
+		if (pd_num == (size_t) -1)
+			return ENOENT;
+		
+		/*
+		 * According to doc, in this we should stop our loop if pass
+		 * all allocators. Count of items in sequence of allocators
+		 * cnt = len / sizeof(udf_long_ad_t)
+		 * But in case of Blu-Ray data len could be zero.
+		 * It means that we have only two conditions for stopping
+		 * which we check inside of loop.
+		 */
+		
+		while (true) {
+			udf_short_ad_t *short_d =
+			    (udf_short_ad_t *) (af + start_alloc +
+			    node->alloc_size * sizeof(udf_short_ad_t));
+			
+			if (FLE32(short_d->length) == 0)
+				break;
+			
+			/*
+			 * ECMA 167 4/12 - next sequence of allocation descriptors
+			 * condition according to 167 4/14.6.8
+			 */
+			if (FLE32(short_d->length) >> 30 == 3) {
+				udf_read_extended_allocator(node, icb_flag,
+				    node->instance->partitions[pd_num].start +
+				    FLE32(short_d->position));
+				break;
+			}
+			
+			node->allocators = realloc(node->allocators,
+			    (node->alloc_size + 1) * sizeof(udf_allocator_t));
+			node->allocators[node->alloc_size].length =
+			    EXT_LENGTH(FLE32(short_d->length));
+			node->allocators[node->alloc_size].position =
+			    node->instance->partitions[pd_num].start + FLE32(short_d->position);
+			node->alloc_size++;
+		}
+		
+		node->allocators = realloc(node->allocators,
+		    node->alloc_size * sizeof(udf_allocator_t));
+		break;
+		
+	case UDF_LONG_AD:
+		log_msg(LVL_DEBUG,
+		    "ICB: sequence of allocation descriptors - icbflag = long_ad_t");
+		
+		while (true) {
+			udf_long_ad_t *long_d =
+			    (udf_long_ad_t *) (af + start_alloc +
+			    node->alloc_size * sizeof(udf_long_ad_t));
+			
+			if (FLE32(long_d->length) == 0)
+				break;
+			
+			uint32_t pos_long_ad = udf_long_ad_to_pos(node->instance, long_d);
+			
+			/*
+			 * ECMA 167 4/12 - next sequence of allocation descriptors
+			 * condition according to 167 4/14.6.8
+			 */
+			if (FLE32(long_d->length) >> 30 == 3) {
+				udf_read_extended_allocator (node, icb_flag, pos_long_ad);
+				break;
+			}
+			
+			node->allocators = realloc(node->allocators,
+			    (node->alloc_size + 1) * sizeof(udf_allocator_t));
+			node->allocators[node->alloc_size].length =
+			    EXT_LENGTH(FLE32(long_d->length));
+			node->allocators[node->alloc_size].position = pos_long_ad;
+			
+			node->alloc_size++;
+		}
+		
+		node->allocators = realloc(node->allocators,
+		    node->alloc_size * sizeof(udf_allocator_t));
+		break;
+		
+	case UDF_EXTENDED_AD:
+		log_msg(LVL_DEBUG,
+		    "ICB: sequence of allocation descriptors - icbflag = extended_ad_t");
+		break;
+		
+	case UDF_DATA_AD:
+		log_msg(LVL_DEBUG,
+		    "ICB: sequence of allocation descriptors - icbflag = 3, node contains data itself");
+		
+		node->data = malloc(node->data_size);
+		if (!node->data)
+			return ENOMEM;
+		
+		memcpy(node->data, (af + start_alloc), node->data_size);
+		node->alloc_size = 0;
+		break;
+	}
+	
+	return EOK;
+}
+
+/** Read ICB sequence of descriptors
+ *
+ * Read sequence of descriptors (file entry descriptors or
+ * extended file entry descriptors). Each descriptor contains
+ * sequence of allocators.
+ *
+ * @param node    UDF node
+ *
+ * @return    EOK on success or a negative error code.
+ */
+int udf_read_icb(udf_node_t *node)
+{
+	while (true) {
+		fs_index_t pos = node->index;
+		
+		block_t *block = NULL;
+		int rc = block_get(&block, node->instance->service_id, pos,
+		    BLOCK_FLAGS_NONE);
+		if (rc != EOK)
+			return rc;
+		
+		udf_descriptor_tag_t *data = (udf_descriptor_tag_t *) block->data;
+		if (data->checksum != udf_tag_checksum((uint8_t *) data)) {
+			block_put(block);
+			return EINVAL;
+		}
+		
+		/* One sector size descriptors */
+		switch (FLE16(data->id)) {
+		case UDF_FILE_ENTRY:
+			log_msg(LVL_DEBUG, "ICB: File entry descriptor found");
+			
+			udf_file_entry_descriptor_t *file =
+			    (udf_file_entry_descriptor_t *) block->data;
+			uint16_t icb_flag = FLE16(file->icbtag.flags) & UDF_ICBFLAG_MASK;
+			node->data_size = FLE64(file->info_lenght);
+			node->type = (file->icbtag.file_type == UDF_ICBTYPE_DIR) ? NODE_DIR : NODE_FILE;
+			
+			rc = udf_read_allocation_sequence(node, (uint8_t *) file, icb_flag,
+			    FLE32(file->ea_lenght) + UDF_FE_OFFSET, FLE32(file->ad_lenght));
+			block_put(block);
+			return rc;
+			
+		case UDF_EFILE_ENTRY:
+			log_msg(LVL_DEBUG, "ICB: Extended file entry descriptor found");
+			
+			udf_extended_file_entry_descriptor_t *efile =
+			    (udf_extended_file_entry_descriptor_t *) block->data;
+			icb_flag = FLE16(efile->icbtag.flags) & UDF_ICBFLAG_MASK;
+			node->data_size = FLE64(efile->info_lenght);
+			node->type = (efile->icbtag.file_type == UDF_ICBTYPE_DIR) ? NODE_DIR : NODE_FILE;
+			
+			rc = udf_read_allocation_sequence(node, (uint8_t *) efile, icb_flag,
+			    FLE32(efile->ea_lenght) + UDF_EFE_OFFSET, FLE32(efile->ad_lenght));
+			block_put(block);
+			return rc;
+			
+		case UDF_ICB_TERMINAL:
+			log_msg(LVL_DEBUG, "ICB: Terminal entry descriptor found");
+			block_put(block);
+			return EOK;
+		}
+		
+		pos++;
+		
+		rc = block_put(block);
+		if (rc != EOK)
+			return rc;
+	}
+	
+	return EOK;
+}
+
+/** Read ICB sequence of allocators in Unallocated space entry descriptor
+ *
+ * This function read ICB sequence if free space is saved by space table.
+ * Not finished.
+ *
+ * @param uased       Unallocated space entry descriptor
+ * @param icb_flag    Type of allocators in sequence.
+ *                    According to ECMA 167 4/14.8.8
+ * @param start_alloc Offset of the allocator
+ * @param len         Length of sequence
+ *
+ * @return EOK on success or a negative error code.
+ *
+ */
+int udf_read_free_space(uint8_t *uased, uint16_t icb_flag,
+    uint32_t start_alloc, uint32_t len)
+{
+	switch (icb_flag) {
+	case UDF_SHORT_AD:
+		log_msg(LVL_DEBUG,
+		    "UAICB: sequence of allocation descriptors - icbflag = short_ad_t");
+		
+		/* Identify number of current partition */
+		
+		size_t cnt = len / sizeof(udf_short_ad_t);
+		size_t n = 0;
+		
+		while (n < cnt) {
+			udf_short_ad_t *short_d =
+			    (udf_short_ad_t *) (uased + start_alloc + n * sizeof(udf_short_ad_t));
+			
+			if (short_d->length == 0)
+				break;
+			
+			n++;
+		}
+		
+		break;
+		
+	case UDF_LONG_AD:
+		log_msg(LVL_DEBUG,
+		    "UAICB: sequence of allocation descriptors - icbflag = long_ad_t");
+		
+		cnt = len / sizeof(udf_long_ad_t);
+		n = 0;
+		
+		while (n < cnt) {
+			udf_long_ad_t *long_d =
+			    (udf_long_ad_t *) (uased + start_alloc + n * sizeof(udf_long_ad_t));
+			
+			if (long_d->length == 0)
+				break;
+			
+			n++;
+		}
+		
+		break;
+		
+	case UDF_EXTENDED_AD:
+		log_msg(LVL_DEBUG,
+		    "UAICB: sequence of allocation descriptors - icbflag = extended_ad_t");
+		break;
+		
+	case UDF_DATA_AD:
+		log_msg(LVL_DEBUG,
+		    "UAICB: sequence of allocation descriptors - icbflag = 3, node contains data itself");
+		break;
+	}
+	
+	return EOK;
+}
+
+/** Read Unallocated space entry descriptor
+ *
+ * Read ICB sequence if free space is saved by space table.
+ * Not finished.
+ *
+ */
+int udf_read_unallocated_space_entry(udf_instance_t * instance, uint64_t pos,
+    uint32_t len)
+{
+	block_t *block = NULL;
+	int rc = block_get(&block, instance->service_id, pos, BLOCK_FLAGS_NONE);
+	if (rc != EOK)
+		return rc;
+	
+	udf_descriptor_tag_t *desc = (udf_descriptor_tag_t *) block->data;
+	if (desc->checksum != udf_tag_checksum((uint8_t *) desc)) {
+		block_put(block);
+		return EINVAL;
+	}
+	
+	if (FLE16(desc->id) != UDF_UASPACE_ENTRY) {
+		// FIXME: Memory leak
+		return EINVAL;
+	}
+	
+	udf_unallocated_space_entry_descriptor_t *uased =
+	    (udf_unallocated_space_entry_descriptor_t *) block->data;
+	if (uased->icbtag.file_type != UDF_ICBTYPE_UASE) {
+		// FIXME: Memory leak
+		return EINVAL;
+	}
+	
+	uint16_t icb_flag = uased->icbtag.flags & UDF_ICBFLAG_MASK;
+	
+	rc = udf_read_free_space((uint8_t *) uased, icb_flag,
+	    UDF_UASE_OFFSET, uased->ad_lenght);
+	
+	return block_put(block);
+}
+
+/** Read data from disk - filling UDF node by allocators
+ *
+ * @param node UDF node
+ *
+ * @return EOK on success or a negative error code.
+ *
+ */
+int udf_node_get_core(udf_node_t *node)
+{
+	node->link_cnt = 1;
+	return udf_read_icb(node);
+}
+
+/** Read directory entry
+ *
+ * @param fid   Returned value
+ * @param block Returned value
+ * @param node  UDF node
+ * @param pos   Number of FID which we need to find
+ *
+ * @return EOK on success or a negative error code.
+ *
+ */
+int udf_get_fid(udf_file_identifier_descriptor_t **fid, block_t **block,
+    udf_node_t *node, aoff64_t pos)
+{
+	if (node->data == NULL)
+		return udf_get_fid_in_allocator(fid, block, node, pos);
+	
+	return udf_get_fid_in_data(fid, node, pos);
+}
+
+/** Read directory entry if all FIDs is saved inside of descriptor
+ *
+ * @param fid  Returned value
+ * @param node UDF node
+ * @param pos  Number of FID which we need to find
+ *
+ * @return EOK on success or a negative error code.
+ *
+ */
+int udf_get_fid_in_data(udf_file_identifier_descriptor_t **fid,
+    udf_node_t *node, aoff64_t pos)
+{
+	size_t fid_sum = 0;
+	size_t n = 0;
+	
+	while (node->data_size - fid_sum >= MIN_FID_LEN) {
+		udf_descriptor_tag_t *desc =
+		    (udf_descriptor_tag_t *) (node->data + fid_sum);
+		if (desc->checksum != udf_tag_checksum((uint8_t *) desc)) {
+			if (fid_sum == 0)
+				return EINVAL;
+			else
+				return ENOENT;
+		}
+		
+		*fid = (udf_file_identifier_descriptor_t *)
+		    (node->data + fid_sum);
+		
+		/* According to ECMA 167 4/14.4.9 */
+		size_t padding = 4 * (((*fid)->lenght_file_id +
+		    FLE16((*fid)->lenght_iu) + 38 + 3) / 4) -
+		    ((*fid)->lenght_file_id + FLE16((*fid)->lenght_iu) + 38);
+		size_t size_fid = (*fid)->lenght_file_id +
+		    FLE16((*fid)->lenght_iu) + padding + 38;
+		
+		fid_sum += size_fid;
+		
+		/* aAcording to ECMA 167 4/8.6 */
+		if (((*fid)->lenght_file_id != 0) &&
+		    (((*fid)->file_characteristics & 4) == 0)) {
+			n++;
+			
+			if (n == pos + 1)
+				return EOK;
+		}
+	}
+	
+	return ENOENT;
+}
+
+/** Read directory entry if all FIDS is saved in allocators.
+ *
+ * @param fid   Returned value
+ * @param block Returned value
+ * @param node  UDF node
+ * @param pos   Number of FID which we need to find
+ *
+ * @return EOK on success or a negative error code.
+ *
+ */
+int udf_get_fid_in_allocator(udf_file_identifier_descriptor_t **fid,
+    block_t **block, udf_node_t *node, aoff64_t pos)
+{
+	void *buf = malloc(node->instance->sector_size);
+	
+	// FIXME: Check for NULL return value
+	
+	size_t j = 0;
+	size_t n = 0;
+	size_t len = 0;
+	
+	while (j < node->alloc_size) {
+		size_t i = 0;
+		while (i * node->instance->sector_size < node->allocators[j].length) {
+			int rc = block_get(block, node->instance->service_id,
+			    node->allocators[j].position + i, BLOCK_FLAGS_NONE);
+			if (rc != EOK) {
+				// FIXME: Memory leak
+				return rc;
+			}
+			
+			/*
+			 * Last item in allocator is a part of sector. We take
+			 * this fragment and join it to part of sector in next allocator.
+			 */
+			if ((node->allocators[j].length / node->instance->sector_size == i) &&
+			    (node->allocators[j].length - i * node->instance->sector_size <
+			    MIN_FID_LEN)) {
+				size_t len = node->allocators[j].length - i * node->instance->sector_size;
+				memcpy(buf, (*block)->data, len);
+				block_put(*block);
+				*block = NULL;
+				break;
+			}
+			
+			rc = udf_get_fid_in_sector(fid, block, node, pos, &n, &buf, &len);
+			if (rc == EOK) {
+				// FIXME: Memory leak
+				return EOK;
+			}
+			
+			if (rc == EINVAL) {
+				// FIXME: Memory leak
+				return ENOENT;
+			}
+			
+			if (rc == ENOENT) {
+				if (block) {
+					rc = block_put(*block);
+					*block = NULL;
+					
+					if (rc != EOK)
+						return rc;
+				}
+			}
+			
+			i++;
+		}
+		
+		j++;
+	}
+	
+	if (buf)
+		free(buf);
+	
+	return ENOENT;
+}
+
+/** Read FIDs in sector inside of current allocator
+ *
+ * @param fid   Returned value.
+ * @param block Returned value
+ * @param node  UDF node
+ * @param pos   Number FID which we need to find
+ * @param n     Count of FIDs which we already have passed
+ * @param buf   Part of FID from last sector (current allocator or previous)
+ * @param len   Length of buf
+ *
+ * @return EOK on success or a negative error code.
+ *
+ */
+int udf_get_fid_in_sector(udf_file_identifier_descriptor_t **fid,
+    block_t **block, udf_node_t *node, aoff64_t pos, size_t *n, void **buf,
+    size_t *len)
+{
+	void *fidbuf = malloc(node->instance->sector_size);
+	
+	// FIXME: Check for NULL return value
+	
+	bool buf_flag;
+	
+	if (*len > 0) {
+		memcpy(fidbuf, *buf, *len);
+		buf_flag = true;
+	} else
+		buf_flag = false;
+	
+	size_t fid_sum = 0;
+	while (node->instance->sector_size - fid_sum > 0) {
+		if (node->instance->sector_size - fid_sum >= MIN_FID_LEN) {
+			void *fid_data;
+			
+			if (buf_flag) {
+				memcpy((fidbuf + *len), (*block)->data,
+				    node->instance->sector_size - *len);
+				fid_data = fidbuf;
+			} else
+				fid_data = (*block)->data + fid_sum;
+			
+			udf_descriptor_tag_t *desc =
+			    (udf_descriptor_tag_t *) fid_data;
+			
+			if (desc->checksum != udf_tag_checksum((uint8_t *) desc)) {
+				if (fidbuf)
+					free(fidbuf);
+				
+				if (*buf) {
+					free(*buf);
+					*buf = NULL;
+					*len = 0;
+				}
+				
+				return EINVAL;
+			}
+			
+			*fid = (udf_file_identifier_descriptor_t *) fid_data;
+			
+			/* According to ECMA 167 4/14.4.9 */
+			size_t padding = 4 * (((*fid)->lenght_file_id +
+			    FLE16((*fid)->lenght_iu) + 38 + 3) / 4) -
+			    ((*fid)->lenght_file_id + FLE16((*fid)->lenght_iu) + 38);
+			size_t size_fid = (*fid)->lenght_file_id +
+			    FLE16((*fid)->lenght_iu) + padding + 38;
+			if (buf_flag)
+				fid_sum += size_fid - *len;
+			else
+				fid_sum += size_fid;
+			
+			/* According to ECMA 167 4/8.6 */
+			if (((*fid)->lenght_file_id != 0) &&
+			    (((*fid)->file_characteristics & 4) == 0)) {
+				(*n)++;
+				if (*n == pos + 1) {
+					if (fidbuf)
+						free(fidbuf);
+					
+					return EOK;
+				}
+			}
+			
+			if (fidbuf) {
+				buf_flag = false;
+				free(fidbuf);
+				fidbuf = NULL;
+			}
+			
+			if (*buf) {
+				free(*buf);
+				*buf = NULL;
+				*len = 0;
+			}
+		} else {
+			if (*buf)
+				free(*buf);
+			
+			*len = node->instance->sector_size - fid_sum;
+			*buf = malloc(*len);
+			buf_flag = false;
+			memcpy(*buf, ((*block)->data + fid_sum), *len);
+			
+			return ENOENT;
+		}
+	}
+	
+	return ENOENT;
+}
+
+/** Read file if it is saved in allocators.
+ *
+ * @param read_len Returned value. Length file or part file which we could read.
+ * @param callid
+ * @param node     UDF node
+ * @param pos      Position in file since we have to read.
+ * @param len      Length of data for reading
+ *
+ * @return EOK on success or a negative error code.
+ *
+ */
+int udf_read_file(size_t *read_len, ipc_callid_t callid, udf_node_t *node,
+    aoff64_t pos, size_t len)
+{
+	size_t i = 0;
+	size_t l = 0;
+	
+	while (i < node->alloc_size) {
+		if (pos >= l + node->allocators[i].length) {
+			l += node->allocators[i].length;
+			i++;
+		} else
+			break;
+	}
+	
+	size_t sector_cnt = ALL_UP(l, node->instance->sector_size);
+	size_t sector_num = pos / node->instance->sector_size;
+	
+	block_t *block = NULL;
+	int rc = block_get(&block, node->instance->service_id,
+	    node->allocators[i].position + (sector_num - sector_cnt),
+	    BLOCK_FLAGS_NONE);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return rc;
+	}
+	
+	size_t sector_pos = pos % node->instance->sector_size;
+	
+	if (sector_pos + len < node->instance->sector_size)
+		*read_len = len;
+	else
+		*read_len = node->instance->sector_size - sector_pos;
+	
+	if (ALL_UP(node->allocators[i].length, node->instance->sector_size) ==
+	    sector_num - sector_cnt + 1) {
+		if (pos + len > node->allocators[i].length + l)
+			*read_len = node->allocators[i].length -
+			    (sector_num - sector_cnt) * node->instance->sector_size -
+			    sector_pos;
+		else
+			*read_len = len;
+	}
+	
+	async_data_read_finalize(callid, block->data + sector_pos, *read_len);
+	return block_put(block);
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/fs/udf/udf_file.h
===================================================================
--- uspace/srv/fs/udf/udf_file.h	(revision 48e31904fcd0b717c586d68fd42458d05940cb20)
+++ uspace/srv/fs/udf/udf_file.h	(revision 48e31904fcd0b717c586d68fd42458d05940cb20)
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2012 Julia Medvedeva
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup fs
+ * @{
+ */
+
+#ifndef UDF_FILE_H_
+#define UDF_FILE_H_
+
+#include <sys/types.h>
+#include <ipc/loc.h>
+#include <block.h>
+#include "udf_types.h"
+
+#define UDF_TAG_FILESET  256
+#define UDF_TAG_FILEID   257
+
+#define UDF_ICB_TERMINAL   260
+#define UDF_FILE_ENTRY     261
+#define UDF_UASPACE_ENTRY  263
+#define UDF_SPACE_BITMAP   264
+#define UDF_EFILE_ENTRY    266
+
+#define UDF_FE_OFFSET   176
+#define UDF_EFE_OFFSET  216
+#define UDF_SB_OFFSET   24
+
+/* ECMA 4/14.11 */
+#define UDF_UASE_OFFSET  40
+
+/* ECMA 167 4/14.6.8 */
+#define UDF_ICBFLAG_MASK  7
+
+/* ECMA 167 4/17 */
+#define UDF_ICBTYPE_UASE  1
+#define UDF_ICBTYPE_DIR   4
+
+/* ECMA 167 4/14.6.8 */
+#define UDF_SHORT_AD     0
+#define UDF_LONG_AD      1
+#define UDF_EXTENDED_AD  2
+
+/* File in allocation descriptor */
+#define UDF_DATA_AD  3
+
+/* File Set Descriptor (ECMA 167 4/14.1) */
+typedef struct udf_fileset_descriptor {
+	udf_descriptor_tag_t tag;
+	udf_timestamp_t recording_date_and_time;
+	uint16_t interchange_level;
+	uint16_t max_interchange_level;
+	uint32_t charset_list;
+	uint32_t max_charset_list;
+	uint32_t fileset_number;
+	uint32_t fileset_descriptor_number;
+	udf_charspec_t logical_volume_id_charset;
+	udf_dstring logical_volume_id[128];
+	udf_charspec_t fileset_charset;
+	udf_dstring fileset_id[32];
+	udf_dstring copyright_file_id[32];
+	udf_dstring abstract_file_id[32];
+	udf_long_ad_t root_dir_icb;
+	udf_regid_t domain_id;
+	udf_long_ad_t next_extent;
+	udf_long_ad_t system_stream_dir_icb;
+	uint8_t reserved[32];
+} __attribute__((packed)) udf_fileset_descriptor_t;
+
+/* File identifier descriptor format (ECMA 167 4/14.4) */
+typedef struct udf_file_identifier_descriptor {
+	udf_descriptor_tag_t tag;
+	uint16_t file_version_number;
+	uint8_t file_characteristics;
+	uint8_t lenght_file_id;
+	udf_long_ad_t icb;
+	uint16_t lenght_iu;
+	uint8_t implementation_use[0];
+	udf_dstring file_id[0];
+}__attribute__((packed)) udf_file_identifier_descriptor_t;
+
+/* ICB tag - Information Control Block  (ECMA 167 4/14.6) */
+typedef struct udf_icbtag {
+	uint32_t prior_recorder_nimber;
+	uint16_t strategy_type;
+	uint8_t strategy_parameter[2];
+	uint16_t max_number;
+	uint8_t reserved[1];
+	uint8_t file_type;
+	udf_lb_addr_t parent_icb;
+	uint16_t flags;
+} __attribute__((packed)) udf_icbtag_t;
+
+/* File Entry format (ECMA 167 4/14.9) */
+typedef struct udf_file_entry_descriptor {
+	udf_descriptor_tag_t tag;
+	udf_icbtag_t icbtag;
+	uint32_t uid;
+	uint32_t gid;
+	uint32_t permission;
+	uint16_t file_link_count;
+	uint8_t record_format;
+	uint8_t record_display_attributes;
+	uint32_t record_lenght;
+	uint64_t info_lenght;
+	uint64_t lblocks_recorded;
+	udf_timestamp_t access_data_and_time;
+	udf_timestamp_t mod_data_and_time;
+	udf_timestamp_t attribute_data_and_time;
+	uint32_t checkpoint;
+	udf_long_ad_t extended_attribute_icb;
+	udf_regid_t implementation_id;
+	uint64_t unique_id;
+	uint32_t ea_lenght;
+	uint32_t ad_lenght;
+	uint8_t extended_attributes [0];
+	uint8_t allocation_descriptors[0];
+} __attribute__((packed)) udf_file_entry_descriptor_t;
+
+/* Extended File Entry format (ECMA 167 4/14.17) */
+typedef struct udf_extended_file_entry_descriptor {
+	udf_descriptor_tag_t tag;
+	udf_icbtag_t icbtag;
+	uint32_t uid;
+	uint32_t gid;
+	uint32_t permission;
+	uint16_t file_link_count;
+	uint8_t record_format;
+	uint8_t record_display_attributes;
+	uint32_t record_lenght;
+	uint64_t info_lenght;
+	uint64_t object_size;
+	uint64_t lblocks_recorded;
+	udf_timestamp_t access_data_and_time;
+	udf_timestamp_t mod_data_and_time;
+	udf_timestamp_t creation_data_and_time;
+	udf_timestamp_t attribute_data_and_time;
+	uint32_t checkpoint;
+	udf_long_ad_t extended_attribute_icb;
+	udf_regid_t implementation_id;
+	uint64_t unique_id;
+	uint32_t ea_lenght;
+	uint32_t ad_lenght;
+	uint8_t extended_attributes [0];
+	uint8_t allocation_descriptors[0];
+} __attribute__((packed)) udf_extended_file_entry_descriptor_t;
+
+/* Terminal Entry Descriptor (ECMA 167 4/14.8) */
+typedef struct terminal_entry_descriptor {
+	udf_descriptor_tag_t tag;
+	udf_icbtag_t icbtag;
+} __attribute__((packed)) udf_terminal_entry_descriptor;
+
+/* Unallocated Space Entry format (ECMA 167 4/14.11)*/
+typedef struct udf_unallocated_space_entry_descriptor {
+	udf_descriptor_tag_t tag;
+	udf_icbtag_t icbtag;
+	uint32_t ad_lenght;
+	uint8_t allocation_descriptors[0];
+}__attribute__((packed)) udf_unallocated_space_entry_descriptor_t;
+
+/* Space Bitmap Descriptor format (ECMA 167 4/14.12) */
+typedef struct udf_space_bitmap_descriptor {
+	udf_descriptor_tag_t tag;
+	uint32_t bits_number;
+	uint32_t byts_number;
+	uint8_t bitmap[0];
+}__attribute__((packed)) udf_space_bitmap_descriptor_t;
+
+extern int udf_node_get_core(udf_node_t *);
+extern int udf_read_icb(udf_node_t *);
+extern int udf_read_allocation_sequence(udf_node_t *, uint8_t *, uint16_t,
+    uint32_t, uint32_t);
+extern int udf_read_extended_allocator(udf_node_t *, uint16_t, uint32_t);
+extern int udf_read_file(size_t *, ipc_callid_t, udf_node_t *, aoff64_t,
+    size_t);
+extern int udf_get_fid(udf_file_identifier_descriptor_t **, block_t **,
+    udf_node_t *, aoff64_t);
+extern int udf_get_fid_in_data(udf_file_identifier_descriptor_t **,
+    udf_node_t *, aoff64_t);
+extern int udf_get_fid_in_allocator(udf_file_identifier_descriptor_t **,
+    block_t **, udf_node_t *, aoff64_t);
+extern int udf_get_fid_in_sector(udf_file_identifier_descriptor_t **,
+    block_t **, udf_node_t *, aoff64_t, size_t *, void **, size_t *);
+extern int udf_read_free_space(uint8_t *, uint16_t, uint32_t, uint32_t);
+extern int udf_read_unallocated_space_entry(udf_instance_t *, uint64_t,
+    uint32_t);
+
+#endif /* UDF_FILE_H_ */
+
+/**
+ * @}
+ */
Index: uspace/srv/fs/udf/udf_idx.c
===================================================================
--- uspace/srv/fs/udf/udf_idx.c	(revision 48e31904fcd0b717c586d68fd42458d05940cb20)
+++ uspace/srv/fs/udf/udf_idx.c	(revision 48e31904fcd0b717c586d68fd42458d05940cb20)
@@ -0,0 +1,253 @@
+/*
+ * Copyright (c) 2012 Julia Medvedeva
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup fs
+ * @{
+ */
+/**
+ * @file udf_idx.c
+ * @brief Very simple UDF hashtable for nodes
+ */
+
+#include "../../vfs/vfs.h"
+#include <errno.h>
+#include <str.h>
+#include <assert.h>
+#include <fibril_synch.h>
+#include <malloc.h>
+#include <adt/hash_table.h>
+#include <adt/list.h>
+#include "udf_idx.h"
+#include "udf.h"
+
+#define UDF_IDX_KEYS  2
+#define UDF_IDX_KEY   1
+
+#define UDF_IDX_SERVICE_ID_KEY  0
+#define UDF_IDX_BUCKETS         1024
+
+static FIBRIL_MUTEX_INITIALIZE(udf_idx_lock);
+
+static hash_table_t udf_idx;
+
+/** Calculate value of hash by key
+ *
+ * @param Key for calculation of function
+ *
+ * @return Value of hash function
+ *
+ */
+static hash_index_t udf_idx_hash(unsigned long key[])
+{
+	/* TODO: This is very simple and probably can be improved */
+	return key[UDF_IDX_KEY] % UDF_IDX_BUCKETS;
+}
+
+/** Compare two items of hash table
+ *
+ * @param key  Key of hash table item. Include several items.
+ * @param keys Number of parts of key.
+ * @param item Item of hash table
+ *
+ * @return True if input value of key equivalent key of node from hash table
+ *
+ */
+static int udf_idx_compare(unsigned long key[], hash_count_t keys, link_t *item)
+{
+	assert(keys > 0);
+	
+	udf_node_t *node = hash_table_get_instance(item, udf_node_t, link);
+	
+	if (node->instance->service_id !=
+	    ((service_id_t) key[UDF_IDX_SERVICE_ID_KEY]))
+		return false;
+	
+	assert(keys == 2);
+	return (node->index == key[UDF_IDX_KEY]);
+}
+
+/** Remove callback
+ *
+ */
+static void udf_idx_remove_cb(link_t *link)
+{
+	/* We don't use remove callback for this hash table */
+}
+
+static hash_table_operations_t udf_idx_ops = {
+	.hash = udf_idx_hash,
+	.compare = udf_idx_compare,
+	.remove_callback = udf_idx_remove_cb,
+};
+
+/** Initialization of hash table
+ *
+ * @return EOK on success or a negative error code.
+ *
+ */
+int udf_idx_init(void)
+{
+	if (!hash_table_create(&udf_idx, UDF_IDX_BUCKETS, UDF_IDX_KEYS,
+	    &udf_idx_ops))
+		return ENOMEM;
+	
+	return EOK;
+}
+
+/** Delete hash table
+ *
+ * @return EOK on success or a negative error code.
+ *
+ */
+int udf_idx_fini(void)
+{
+	hash_table_destroy(&udf_idx);
+	return EOK;
+}
+
+/** Get node from hash table
+ *
+ * @param udfn     Returned value - UDF node
+ * @param instance UDF instance
+ * @param index    Absolute position of ICB (sector)
+ *
+ * @return EOK on success or a negative error code.
+ *
+ */
+int udf_idx_get(udf_node_t **udfn, udf_instance_t *instance, fs_index_t index)
+{
+	fibril_mutex_lock(&udf_idx_lock);
+	
+	unsigned long key[] = {
+		[UDF_IDX_SERVICE_ID_KEY] = instance->service_id,
+		[UDF_IDX_KEY] = index
+	};
+	
+	link_t *already_open = hash_table_find(&udf_idx, key);
+	if (already_open) {
+		udf_node_t *node = hash_table_get_instance(already_open,
+		    udf_node_t, link);
+		node->ref_cnt++;
+		
+		*udfn = node;
+		
+		fibril_mutex_unlock(&udf_idx_lock);
+		return EOK;
+	}
+	
+	fibril_mutex_unlock(&udf_idx_lock);
+	return ENOENT;
+}
+
+/** Create new node in hash table
+ *
+ * @param udfn     Returned value - new UDF node
+ * @param instance UDF instance
+ * @param index    Absolute position of ICB (sector)
+ *
+ * @return EOK on success or a negative error code.
+ *
+ */
+int udf_idx_add(udf_node_t **udfn, udf_instance_t *instance, fs_index_t index)
+{
+	fibril_mutex_lock(&udf_idx_lock);
+	
+	udf_node_t *udf_node = malloc(sizeof(udf_node_t));
+	if (udf_node == NULL) {
+		fibril_mutex_unlock(&udf_idx_lock);
+		return ENOMEM;
+	}
+	
+	fs_node_t *fs_node = malloc(sizeof(fs_node_t));
+	if (fs_node == NULL) {
+		free(udf_node);
+		fibril_mutex_unlock(&udf_idx_lock);
+		return ENOMEM;
+	}
+	
+	fs_node_initialize(fs_node);
+	
+	udf_node->index = index;
+	udf_node->instance = instance;
+	udf_node->ref_cnt = 1;
+	udf_node->link_cnt = 0;
+	udf_node->fs_node = fs_node;
+	udf_node->data = NULL;
+	udf_node->allocators = NULL;
+	
+	fibril_mutex_initialize(&udf_node->lock);
+	link_initialize(&udf_node->link);
+	fs_node->data = udf_node;
+	
+	unsigned long key[] = {
+		[UDF_IDX_SERVICE_ID_KEY] = instance->service_id,
+		[UDF_IDX_KEY] = index
+	};
+	
+	hash_table_insert(&udf_idx, key, &udf_node->link);
+	instance->open_nodes_count++;
+	
+	*udfn = udf_node;
+	
+	fibril_mutex_unlock(&udf_idx_lock);
+	return EOK;
+}
+
+/** Delete node from hash table
+ *
+ * @param node UDF node
+ *
+ * @return EOK on success or a negative error code.
+ *
+ */
+int udf_idx_del(udf_node_t *node)
+{
+	assert(node->ref_cnt == 0);
+	
+	fibril_mutex_lock(&udf_idx_lock);
+	
+	unsigned long key[] = {
+		[UDF_IDX_SERVICE_ID_KEY] = node->instance->service_id,
+		[UDF_IDX_KEY] = node->index
+	};
+	
+	hash_table_remove(&udf_idx, key, UDF_IDX_KEYS);
+	
+	assert(node->instance->open_nodes_count > 0);
+	node->instance->open_nodes_count--;
+	
+	free(node->fs_node);
+	free(node);
+	
+	fibril_mutex_unlock(&udf_idx_lock);
+	return EOK;
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/fs/udf/udf_idx.h
===================================================================
--- uspace/srv/fs/udf/udf_idx.h	(revision 48e31904fcd0b717c586d68fd42458d05940cb20)
+++ uspace/srv/fs/udf/udf_idx.h	(revision 48e31904fcd0b717c586d68fd42458d05940cb20)
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2012 Julia Medvedeva
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup fs
+ * @{
+ */
+
+#ifndef UDF_IDX_H_
+#define UDF_IDX_H_
+
+#include "udf.h"
+
+extern int udf_idx_init(void);
+extern int udf_idx_fini(void);
+extern int udf_idx_get(udf_node_t **, udf_instance_t *, fs_index_t);
+extern int udf_idx_add(udf_node_t **, udf_instance_t *, fs_index_t);
+extern int udf_idx_del(udf_node_t *);
+
+#endif /* UDF_IDX_H_ */
+
+/**
+ * @}
+ */
Index: uspace/srv/fs/udf/udf_ops.c
===================================================================
--- uspace/srv/fs/udf/udf_ops.c	(revision 48e31904fcd0b717c586d68fd42458d05940cb20)
+++ uspace/srv/fs/udf/udf_ops.c	(revision 48e31904fcd0b717c586d68fd42458d05940cb20)
@@ -0,0 +1,530 @@
+/*
+ * Copyright (c) 2008 Jakub Jermar
+ * Copyright (c) 2012 Julia Medvedeva
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup fs
+ * @{
+ */
+/**
+ * @file udf_ops.c
+ * @brief Implementation of VFS operations for the UDF file system
+ *        server.
+ */
+
+#include <libfs.h>
+#include <block.h>
+#include <ipc/services.h>
+#include <ipc/loc.h>
+#include <macros.h>
+#include <async.h>
+#include <errno.h>
+#include <str.h>
+#include <byteorder.h>
+#include <adt/hash_table.h>
+#include <adt/list.h>
+#include <assert.h>
+#include <fibril_synch.h>
+#include <sys/mman.h>
+#include <align.h>
+#include <malloc.h>
+#include <inttypes.h>
+#include <io/log.h>
+#include "../../vfs/vfs.h"
+#include "udf.h"
+#include "udf_cksum.h"
+#include "udf_volume.h"
+#include "udf_idx.h"
+#include "udf_file.h"
+#include "udf_osta.h"
+
+/** Mutex protecting the list of cached free nodes. */
+static FIBRIL_MUTEX_INITIALIZE(ffn_mutex);
+
+/** List of cached free nodes. */
+static LIST_INITIALIZE(ffn_list);
+
+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 service_id_t udf_service_get(fs_node_t *node)
+{
+	udf_node_t *udfn = UDF_NODE(node);
+	if (udfn)
+		return udfn->instance->service_id;
+	
+	return 0;
+}
+
+static int udf_match(fs_node_t **rfn, fs_node_t *pfn, const char *component)
+{
+	char *name = malloc(MAX_FILE_NAME_LEN + 1);
+	if (name == NULL)
+		return ENOMEM;
+	
+	block_t *block = NULL;
+	udf_file_identifier_descriptor_t *fid = NULL;
+	size_t pos = 0;
+	
+	while (udf_get_fid(&fid, &block, UDF_NODE(pfn), pos) == EOK) {
+		udf_long_ad_t long_ad = fid->icb;
+		
+		udf_to_unix_name(name, MAX_FILE_NAME_LEN,
+		    (char *) fid->implementation_use + FLE16(fid->lenght_iu),
+		    fid->lenght_file_id, &UDF_NODE(pfn)->instance->charset);
+		
+		if (stricmp(name, component) == 0) {
+			int rc = udf_node_get(rfn, udf_service_get(pfn),
+			    udf_long_ad_to_pos(UDF_NODE(pfn)->instance, &long_ad));
+			
+			if (block != NULL)
+				block_put(block);
+			
+			free(name);
+			return rc;
+		}
+		
+		if (block != NULL) {
+			int rc = block_put(block);
+			if (rc != EOK)
+				return rc;
+		}
+		
+		pos++;
+	}
+	
+	free(name);
+	return ENOENT;
+}
+
+static int udf_node_open(fs_node_t *fn)
+{
+	return EOK;
+}
+
+static int udf_node_put(fs_node_t *fn)
+{
+	udf_node_t *node = UDF_NODE(fn);
+	if (!node)
+		return EINVAL;
+	
+	fibril_mutex_lock(&node->lock);
+	node->ref_cnt--;
+	fibril_mutex_unlock(&node->lock);
+	
+	/* Delete node from hash table and memory */
+	if (!node->ref_cnt)
+		udf_idx_del(node);
+	
+	return EOK;
+}
+
+static int udf_create_node(fs_node_t **rfn, service_id_t service_id, int flags)
+{
+	return ENOTSUP;
+}
+
+static int udf_destroy_node(fs_node_t *fn)
+{
+	return ENOTSUP;
+}
+
+static int udf_link(fs_node_t *pfn, fs_node_t *cfn, const char *name)
+{
+	return ENOTSUP;
+}
+
+static int udf_unlink(fs_node_t *pfn, fs_node_t *cfn, const char *nm)
+{
+	return ENOTSUP;
+}
+
+static int udf_has_children(bool *has_children, fs_node_t *fn)
+{
+	*has_children = true;
+	return EOK;
+}
+
+static fs_index_t udf_index_get(fs_node_t *fn)
+{
+	udf_node_t *node = UDF_NODE(fn);
+	if (node)
+		return node->index;
+	
+	return 0;
+}
+
+static aoff64_t udf_size_get(fs_node_t *fn)
+{
+	udf_node_t *node = UDF_NODE(fn);
+	if (node)
+		return node->data_size;
+	
+	return 0;
+}
+
+static unsigned int udf_lnkcnt_get(fs_node_t *fn)
+{
+	udf_node_t *node = UDF_NODE(fn);
+	if (node)
+		return node->link_cnt;
+	
+	return 0;
+}
+
+static bool udf_is_directory(fs_node_t *fn)
+{
+	udf_node_t *node = UDF_NODE(fn);
+	if (node)
+		return node->type == NODE_DIR;
+	
+	return false;
+}
+
+static bool udf_is_file(fs_node_t *fn)
+{
+	udf_node_t *node = UDF_NODE(fn);
+	if (node)
+		return node->type == NODE_FILE;
+	
+	return false;
+}
+
+libfs_ops_t udf_libfs_ops = {
+	.root_get = udf_root_get,
+	.match = udf_match,
+	.node_get = udf_node_get,
+	.node_open = udf_node_open,
+	.node_put = udf_node_put,
+	.create = udf_create_node,
+	.destroy = udf_destroy_node,
+	.link = udf_link,
+	.unlink = udf_unlink,
+	.has_children = udf_has_children,
+	.index_get = udf_index_get,
+	.size_get = udf_size_get,
+	.lnkcnt_get = udf_lnkcnt_get,
+	.is_directory = udf_is_directory,
+	.is_file = udf_is_file,
+	.service_get = udf_service_get
+};
+
+static int udf_mounted(service_id_t service_id, const char *opts,
+    fs_index_t *index, aoff64_t *size, unsigned *linkcnt)
+{
+	enum cache_mode cmode;
+	
+	/* Check for option enabling write through. */
+	if (str_cmp(opts, "wtcache") == 0)
+		cmode = CACHE_MODE_WT;
+	else
+		cmode = CACHE_MODE_WB;
+	
+	udf_instance_t *instance = malloc(sizeof(udf_instance_t));
+	if (!instance)
+		return ENOMEM;
+	
+	instance->sector_size = 0;
+	
+	/* Check for block size. Will be enhanced later */
+	if (str_cmp(opts, "bs=512") == 0)
+		instance->sector_size = 512;
+	else if (str_cmp(opts, "bs=1024") == 0)
+		instance->sector_size = 1024;
+	else if (str_cmp(opts, "bs=2048") == 0)
+		instance->sector_size = 2048;
+	
+	/* initialize block cache */
+	int rc = block_init(EXCHANGE_SERIALIZE, service_id, MAX_SIZE);
+	if (rc != EOK)
+		return rc;
+	
+	rc = fs_instance_create(service_id, instance);
+	if (rc != EOK) {
+		free(instance);
+		block_fini(service_id);
+		return rc;
+	}
+	
+	instance->service_id = service_id;
+	instance->open_nodes_count = 0;
+	
+	/* Check Volume Recognition Sequence */
+	rc = udf_volume_recongnition(service_id);
+	if (rc != EOK) {
+		log_msg(LVL_NOTE, "VRS failed");
+		fs_instance_destroy(service_id);
+		free(instance);
+		block_fini(service_id);
+		return rc;
+	}
+	
+	/* Search for Anchor Volume Descriptor */
+	udf_anchor_volume_descriptor_t avd;
+	rc = udf_get_anchor_volume_descriptor(service_id, &avd);
+	if (rc != EOK) {
+		log_msg(LVL_NOTE, "Anchor read failed");
+		fs_instance_destroy(service_id);
+		free(instance);
+		block_fini(service_id);
+		return rc;
+	}
+	
+	log_msg(LVL_DEBUG,
+	    "Volume: Anchor volume descriptor found. Sector size=%" PRIu32,
+	    instance->sector_size);
+	log_msg(LVL_DEBUG,
+	    "Anchor: main sequence [length=%" PRIu32 " (bytes), start=%"
+	    PRIu32 " (sector)]", avd.main_extent.length,
+	    avd.main_extent.location);
+	log_msg(LVL_DEBUG,
+	    "Anchor: reserve sequence [length=%" PRIu32 " (bytes), start=%"
+	    PRIu32 " (sector)]", avd.reserve_extent.length,
+	    avd.reserve_extent.location);
+	
+	/* Initialize the block cache */
+	rc = block_cache_init(service_id, instance->sector_size, 0, cmode);
+	if (rc != EOK) {
+		fs_instance_destroy(service_id);
+		free(instance);
+		block_fini(service_id);
+		return rc;
+	}
+	
+	/* Read Volume Descriptor Sequence */
+	rc = udf_read_volume_descriptor_sequence(service_id, avd.main_extent);
+	if (rc != EOK) {
+		log_msg(LVL_NOTE, "Volume Descriptor Sequence read failed");
+		fs_instance_destroy(service_id);
+		free(instance);
+		block_cache_fini(service_id);
+		block_fini(service_id);
+		return rc;
+	}
+	
+	fs_node_t *rfn;
+	rc = udf_node_get(&rfn, service_id, instance->volumes[DEFAULT_VOL].root_dir);
+	if (rc != EOK) {
+		log_msg(LVL_NOTE, "Can't create root node");
+		fs_instance_destroy(service_id);
+		free(instance);
+		block_cache_fini(service_id);
+		block_fini(service_id);
+		return rc;
+	}
+	
+	udf_node_t *node = UDF_NODE(rfn);
+	*index = instance->volumes[DEFAULT_VOL].root_dir;
+	*size = node->data_size;
+	*linkcnt = node->link_cnt;
+	
+	return EOK;
+}
+
+static int udf_unmounted(service_id_t service_id)
+{
+	fs_node_t *fn;
+	int rc = udf_root_get(&fn, service_id);
+	if (rc != EOK)
+		return rc;
+	
+	udf_node_t *nodep = UDF_NODE(fn);
+	udf_instance_t *instance = nodep->instance;
+	
+	/*
+	 * We expect exactly two references on the root node.
+	 * One for the udf_root_get() above and one created in
+	 * udf_mounted().
+	 */
+	if (nodep->ref_cnt != 2) {
+		udf_node_put(fn);
+		return EBUSY;
+	}
+	
+	/*
+	 * Put the root node twice.
+	 */
+	udf_node_put(fn);
+	udf_node_put(fn);
+	
+	fs_instance_destroy(service_id);
+	free(instance);
+	block_cache_fini(service_id);
+	block_fini(service_id);
+	
+	return EOK;
+}
+
+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;
+		}
+	}
+}
+
+static int udf_close(service_id_t service_id, fs_index_t index)
+{
+	return EOK;
+}
+
+static int udf_sync(service_id_t service_id, fs_index_t index)
+{
+	return ENOTSUP;
+}
+
+static int udf_write(service_id_t service_id, fs_index_t index, aoff64_t pos,
+    size_t *wbytes, aoff64_t *nsize)
+{
+	return ENOTSUP;
+}
+
+static int udf_truncate(service_id_t service_id, fs_index_t index,
+    aoff64_t size)
+{
+	return ENOTSUP;
+}
+
+static int udf_destroy(service_id_t service_id, fs_index_t index)
+{
+	return ENOTSUP;
+}
+
+vfs_out_ops_t udf_ops = {
+	.mounted = udf_mounted,
+	.unmounted = udf_unmounted,
+	.read = udf_read,
+	.write = udf_write,
+	.truncate = udf_truncate,
+	.close = udf_close,
+	.destroy = udf_destroy,
+	.sync = udf_sync
+};
+
+/**
+ * @}
+ */
Index: uspace/srv/fs/udf/udf_osta.c
===================================================================
--- uspace/srv/fs/udf/udf_osta.c	(revision 48e31904fcd0b717c586d68fd42458d05940cb20)
+++ uspace/srv/fs/udf/udf_osta.c	(revision 48e31904fcd0b717c586d68fd42458d05940cb20)
@@ -0,0 +1,367 @@
+/*
+ * Copyright (c) 2012 Julia Medvedeva
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * OSTA compliant Unicode compression, uncompression routines,
+ * file name translation routine for OS/2, Windows 95, Windows NT,
+ * Macintosh and UNIX.
+ * Copyright 1995 Micro Design International, Inc.
+ * Written by Jason M. Rinn.
+ * Micro Design International gives permission for the free use of the
+ * following source code.
+ */
+
+/** @addtogroup fs
+ * @{
+ */
+/**
+ * @file udf_osta.c
+ * @brief OSTA compliant functions.
+ */
+
+#include <malloc.h>
+#include <str.h>
+#include <macros.h>
+#include <errno.h>
+#include "udf_osta.h"
+#include "udf_cksum.h"
+
+/** Calculate length of UTF-16 string
+ *
+ * FIXME: This is wrong! UTF-16 is not a fixed-width encoding,
+ *        it is a variable-width encoding (mind the surrogate
+ *        pairs).
+ *
+ */
+static size_t utf16_length(uint16_t *string) {
+	size_t len = 0;
+	
+	while (*string++ != 0)
+		len++;
+	
+	return len;
+}
+
+/** Illegal UNIX characters are NULL and slash.
+ *
+ */
+static bool legal_check(uint16_t ch)
+{
+	if ((ch == 0x0000) || (ch == 0x002F))
+		return false;
+	
+	return true;
+}
+
+/** Convert OSTA CS0 compressed Unicode name to Unicode.
+ *
+ * The Unicode output will be in the byte order that the local compiler
+ * uses for 16-bit values.
+ *
+ * NOTE: This routine only performs error checking on the comp_id.
+ * It is up to the user to ensure that the Unicode buffer is large
+ * enough, and that the compressed Unicode name is correct.
+ *
+ * @param[in]  number_of_bytes Number of bytes read from media
+ * @param[in]  udf_compressed  Bytes read from media
+ * @param[out] unicode         Uncompressed unicode characters
+ * @param[in]  unicode_max_len Size of output array
+ *
+ * @return Number of Unicode characters which were uncompressed.
+ *
+ */
+size_t udf_uncompress_unicode(size_t number_of_bytes, uint8_t *udf_compressed,
+    uint16_t *unicode, size_t unicode_max_len)
+{
+	/* Use udf_compressed to store current byte being read. */
+	uint8_t comp_id = udf_compressed[0];
+	
+	/* First check for valid compID. */
+	if ((comp_id != 8) && (comp_id != 16))
+		return 0;
+	
+	size_t unicode_idx = 0;
+	size_t byte_idx = 1;
+	
+	/* Loop through all the bytes. */
+	while ((byte_idx < number_of_bytes) && (unicode_idx < unicode_max_len)) {
+		if (comp_id == 16) {
+			/*
+			 * Move the first byte to the high bits of the
+			 * Unicode char.
+			 */
+			unicode[unicode_idx] = udf_compressed[byte_idx++] << 8;
+		} else
+			unicode[unicode_idx] = 0;
+		
+		if (byte_idx < number_of_bytes) {
+			/* Then the next byte to the low bits. */
+			unicode[unicode_idx] |= udf_compressed[byte_idx++];
+		}
+		
+		unicode_idx++;
+	}
+	
+	return unicode_idx;
+}
+
+/** Convert Unicode wide characters to OSTA CS0 compressed Unicode string.
+ *
+ * The Unicode MUST be in the byte order of the compiler in order
+ * to obtain correct results. Returns an error if the compression ID
+ * is invalid.
+ *
+ * NOTE: This routine assumes the implementation already knows,
+ * by the local environment, how many bits are appropriate and therefore
+ * does no checking to test if the input characters fit into that number
+ * of bits or not.
+ *
+ * @param[in]  number_of_chars Number of unicode characters.
+ * @param[in]  comp_id         Compression ID to be used.
+ * @param[in]  unicode         Unicode characters to compress.
+ * @param[out] udf_compressed  Compressed string, as bytes.
+ *
+ * @return The total number of bytes in the compressed OSTA CS0 string,
+ *         including the compression ID.
+ *
+ */
+size_t udf_compress_unicode(size_t number_of_chars, uint8_t comp_id,
+    uint16_t *unicode, uint8_t *udf_compressed)
+{
+	if ((comp_id != 8) && (comp_id != 16))
+		return 0;
+	
+	/* Place compression code in first byte. */
+	udf_compressed[0] = comp_id;
+	
+	size_t byte_idx = 1;
+	size_t unicode_idx = 0;
+	
+	while (unicode_idx < number_of_chars) {
+		if (comp_id == 16) {
+			/*
+			 * First, place the high bits of the char
+			 * into the byte stream.
+			 */
+			udf_compressed[byte_idx++] =
+			    (unicode[unicode_idx] & 0xFF00) >> 8;
+		}
+		
+		/* Then place the low bits into the stream. */
+		udf_compressed[byte_idx++] = unicode[unicode_idx] & 0x00FF;
+		unicode_idx++;
+	}
+	
+	return byte_idx;
+}
+
+/** Translate a long file name
+ *
+ * Translate a long file name to one using a MAXLEN and an illegal char set
+ * in accord with the OSTA requirements. Assumes the name has already been
+ * translated to Unicode.
+ *
+ * @param[out] new_name Translated name. Must be of length MAXLEN
+ * @param[in]  udf_name Name from UDF volume
+ * @param[in]  udf_len  Length of UDF Name
+ *
+ * @return Number of Unicode characters in translated name.
+ *
+ */
+size_t udf_translate_name(uint16_t *new_name, uint16_t *udf_name,
+    size_t udf_len)
+{
+	bool needs_crc = false;
+	bool has_ext = false;
+	size_t ext_idx = 0;
+	size_t new_idx = 0;
+	size_t new_ext_idx = 0;
+	
+	for (size_t idx = 0; idx < udf_len; idx++) {
+		uint16_t current = udf_name[idx];
+		
+		if ((!legal_check(current)) || (!ascii_check(current))) {
+			needs_crc = true;
+			
+			/*
+			 * Replace Illegal and non-displayable chars with
+			 * underscore.
+			 */
+			current = ILLEGAL_CHAR_MARK;
+			
+			/*
+			 * Skip any other illegal or non-displayable
+			 * characters.
+			 */
+			while ((idx + 1 < udf_len) &&
+			    (!legal_check(udf_name[idx + 1]) ||
+			    (!ascii_check(udf_name[idx + 1]))))
+				idx++;
+		}
+		
+		/* Record position of extension, if one is found. */
+		if ((current == PERIOD) && ((udf_len - idx - 1) <= EXT_SIZE)) {
+			if (udf_len == idx + 1) {
+				/* A trailing period is NOT an extension. */
+				has_ext = false;
+			} else {
+				has_ext = true;
+				ext_idx = idx;
+				new_ext_idx = new_idx;
+			}
+		}
+		
+		if (new_idx < MAXLEN)
+			new_name[new_idx++] = current;
+		else
+			needs_crc = true;
+	}
+	
+	if (needs_crc) {
+		uint16_t ext[EXT_SIZE];
+		size_t local_ext_idx = 0;
+		
+		if (has_ext) {
+			size_t max_filename_len;
+			
+			/* Translate extension, and store it in ext. */
+			for (size_t idx = 0; (idx < EXT_SIZE) &&
+			    (ext_idx + idx + 1 < udf_len); idx++) {
+				uint16_t current = udf_name[ext_idx + idx + 1];
+				
+				if ((!legal_check(current)) || (!ascii_check(current))) {
+					needs_crc = true;
+					
+					/*
+					 * Replace Illegal and non-displayable
+					 * chars with underscore.
+					 */
+					current = ILLEGAL_CHAR_MARK;
+					
+					/*
+					 * Skip any other illegal or
+					 * non-displayable characters.
+					 */
+					while ((idx + 1 < EXT_SIZE) &&
+					    ((!legal_check(udf_name[ext_idx + idx + 2])) ||
+					    (!ascii_check(udf_name[ext_idx + idx + 2]))))
+						idx++;
+				}
+				
+				ext[local_ext_idx++] = current;
+			}
+			
+			/*
+			 * Truncate filename to leave room for extension and
+			 * CRC.
+			 */
+			max_filename_len = ((MAXLEN - 5) - local_ext_idx - 1);
+			if (new_idx > max_filename_len)
+				new_idx = max_filename_len;
+			else
+				new_idx = new_ext_idx;
+		} else if (new_idx > MAXLEN - 5) {
+			/* If no extension, make sure to leave room for CRC. */
+			new_idx = MAXLEN - 5;
+		}
+		
+		/* Add mark for CRC. */
+		new_name[new_idx++] = CRC_MARK;
+		
+		/* Calculate CRC from original filename. */
+		uint16_t value_crc = udf_unicode_cksum(udf_name, udf_len);
+		
+		/* Convert 16-bits of CRC to hex characters. */
+		const char hex_char[] = "0123456789ABCDEF";
+		
+		new_name[new_idx++] = hex_char[(value_crc & 0xf000) >> 12];
+		new_name[new_idx++] = hex_char[(value_crc & 0x0f00) >> 8];
+		new_name[new_idx++] = hex_char[(value_crc & 0x00f0) >> 4];
+		new_name[new_idx++] = hex_char[(value_crc & 0x000f)];
+		
+		/* Place a translated extension at end, if found. */
+		if (has_ext) {
+			new_name[new_idx++] = PERIOD;
+			
+			for (size_t idx = 0; idx < local_ext_idx; idx++)
+				new_name[new_idx++] = ext[idx];
+		}
+	}
+	
+	return new_idx;
+}
+
+/** Decode from dchar to utf8
+ *
+ * @param result     Returned value - utf8 string
+ * @param result_len Length of output string
+ * @param id         Input string
+ * @param len        Length of input string
+ * @param chsp       Decode method
+ *
+ */
+void udf_to_unix_name(char *result, size_t result_len, char *id, size_t len,
+    udf_charspec_t *chsp)
+{
+	const char *osta_id = "OSTA Compressed Unicode";
+	size_t ucode_chars, nice_uchars;
+	
+	uint16_t *raw_name = malloc(MAX_BUF * sizeof(uint16_t));
+	uint16_t *unix_name = malloc(MAX_BUF * sizeof(uint16_t));
+	
+	// FIXME: Check for malloc returning NULL
+	
+	bool is_osta_typ0 = (chsp->type == 0) &&
+	    (str_cmp((char *) chsp->info, osta_id) == 0);
+	
+	if (is_osta_typ0) {
+		*raw_name = 0;
+		*unix_name = 0;
+		
+		ucode_chars =
+		    udf_uncompress_unicode(len, (uint8_t *) id, raw_name, MAX_BUF);
+		ucode_chars = min(ucode_chars, utf16_length(raw_name));
+		nice_uchars =
+		    udf_translate_name(unix_name, raw_name, ucode_chars);
+		
+		/* Output UTF-8 */
+		unix_name[nice_uchars] = 0;
+		utf16_to_str(result, result_len, unix_name);
+	} else {
+		/* Assume 8 bit char length byte Latin-1 */
+		str_ncpy(result, result_len, (char *) (id + 1),
+		    str_size((char *) (id + 1)));
+	}
+	
+	free(raw_name);
+	free(unix_name);
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/fs/udf/udf_osta.h
===================================================================
--- uspace/srv/fs/udf/udf_osta.h	(revision 48e31904fcd0b717c586d68fd42458d05940cb20)
+++ uspace/srv/fs/udf/udf_osta.h	(revision 48e31904fcd0b717c586d68fd42458d05940cb20)
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2012 Julia Medvedeva
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * OSTA compliant Unicode compression, uncompression routines,
+ * file name translation routine for OS/2, Windows 95, Windows NT,
+ * Macintosh and UNIX.
+ * Copyright 1995 Micro Design International, Inc.
+ * Written by Jason M. Rinn.
+ * Micro Design International gives permission for the free use of the
+ * following source code.
+ */
+
+#ifndef UDF_OSTA_H_
+#define UDF_OSTA_H_
+
+#include <sys/types.h>
+#include <bool.h>
+#include "udf_types.h"
+
+#define MAXLEN    255
+#define MAX_BUF   1024
+#define EXT_SIZE  5
+
+#define ILLEGAL_CHAR_MARK  0x005F
+#define CRC_MARK           0x0023
+#define PERIOD             0x002E
+
+extern size_t udf_uncompress_unicode(size_t, uint8_t *, uint16_t *, size_t);
+extern size_t udf_compress_unicode(size_t, uint8_t, uint16_t *, uint8_t *);
+extern size_t udf_translate_name(uint16_t *, uint16_t *, size_t);
+extern void udf_to_unix_name(char *, size_t, char *, size_t, udf_charspec_t *);
+
+#endif /* UDF_OSTA_H_ */
Index: uspace/srv/fs/udf/udf_types.h
===================================================================
--- uspace/srv/fs/udf/udf_types.h	(revision 48e31904fcd0b717c586d68fd42458d05940cb20)
+++ uspace/srv/fs/udf/udf_types.h	(revision 48e31904fcd0b717c586d68fd42458d05940cb20)
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2012 Julia Medvedeva
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup fs
+ * @{
+ */
+/**
+ * @file udf_types.h
+ * @brief UDF common types
+ */
+
+#ifndef UDF_UDF_TYPES_H_
+#define UDF_UDF_TYPES_H_
+
+#include <sys/types.h>
+#include <bool.h>
+#include <byteorder.h>
+
+#define GET_LE16(x)  x = uint16_t_le2host(x)
+#define GET_LE32(x)  x = uint32_t_le2host(x)
+
+#define FLE16(x)  uint16_t_le2host(x)
+#define FLE32(x)  uint32_t_le2host(x)
+#define FLE64(x)  uint64_t_le2host(x)
+
+#define ALL_UP(n, b)  ((n) / (b) + ((n) % (b) != 0))
+
+#define EXT_LENGTH(x)  (x & 0x3FFFFFFF)
+
+typedef uint8_t udf_dstring;
+
+/* Timestamp descriptor (ECMA 167 1/7.3) */
+typedef struct udf_timestamp {
+	uint16_t type_and_tz;
+	uint16_t year;
+	uint8_t month;
+	uint8_t day;
+	uint8_t hour;
+	uint8_t min;
+	uint8_t sec;
+	uint8_t centisec;
+	uint8_t h_of_mcsec;
+	uint8_t mcsec;
+} __attribute__((packed)) udf_timestamp_t;
+
+/* Universal descriptor tag (ECMA 167 3/7.2) */
+typedef struct udf_descriptor_tag {
+	uint16_t id;
+	uint16_t version;
+	uint8_t checksum;
+	uint8_t reserved;
+	uint16_t serial;
+	uint16_t descriptor_crc;
+	uint16_t descriptor_crc_length;
+	uint32_t location;
+} __attribute__((packed)) udf_descriptor_tag_t;
+
+/* Entity descriptor (ECMA 167 1/7.4) */
+typedef struct udf_regid {
+	uint8_t flags;
+	uint8_t id[23];
+	uint8_t id_suffix[8];
+} __attribute__((packed)) udf_regid_t;
+
+/* Character set specification (ECMA 167 1/7.2.1) */
+typedef struct udf_charspec {
+	uint8_t type;
+	uint8_t info[63];
+} __attribute__((packed)) udf_charspec_t;
+
+/* Recorded address (ECMA 167 4/7.1) */
+typedef struct udf_lb_addr {
+	uint32_t lblock_num;     /* Relative to start of the partition (from 0) */
+	uint16_t partition_num;  /* Relative to logical volume or not? */
+} __attribute__((packed)) udf_lb_addr_t;
+
+/* Long Allocation Descriptor (ECMA 167 4/14.14.2) */
+typedef struct udf_long_ad {
+	uint32_t length;
+	udf_lb_addr_t location;
+	uint8_t implementation_use[6];
+} __attribute__((packed)) udf_long_ad_t;
+
+/* Short Allocation Descriptor (ECMA 167 4/14.14.1) */
+typedef struct udf_short_ad {
+	uint32_t length;
+	uint32_t position;
+} __attribute__((packed)) udf_short_ad_t;
+
+/* Extended Allocation Descriptor (ECMA 167 4/14.14.3) */
+typedef struct udf_ext_ad {
+	uint32_t extent_length;
+	uint32_t recorded_length;
+	uint32_t info_length;
+	udf_lb_addr_t extent_location;
+	uint8_t implementation_use[2];
+} __attribute__((packed)) udf_ext_ad_t;
+
+/* Extent descriptor (ECMA 167 3/7.1) */
+typedef struct udf_extent {
+	uint32_t length;    /* Bytes */
+	uint32_t location;  /* Sectors */
+} __attribute__((packed)) udf_extent_t;
+
+/* Terminating Descriptor (ECMA 167 3/10.9) */
+typedef struct udf_terminating_descriptor {
+	udf_descriptor_tag_t tag;
+	uint8_t reserved[496];
+} __attribute__((packed)) udf_terminating_descriptor_t;
+
+/* Unallocated Space Descriptor (ECMA 167 3/10.8) */
+typedef struct udf_unallocated_space_descriptor {
+	udf_descriptor_tag_t tag;
+	uint32_t sequence_number;
+	uint32_t allocation_descriptors_num;
+	udf_extent_t allocation_descriptors[0];
+} __attribute__((packed)) udf_unallocated_space_descriptor_t;
+
+extern void udf_prepare_tag(udf_descriptor_tag_t *);
+
+#endif
+
+/**
+ * @}
+ */
Index: uspace/srv/fs/udf/udf_volume.c
===================================================================
--- uspace/srv/fs/udf/udf_volume.c	(revision 48e31904fcd0b717c586d68fd42458d05940cb20)
+++ uspace/srv/fs/udf/udf_volume.c	(revision 48e31904fcd0b717c586d68fd42458d05940cb20)
@@ -0,0 +1,850 @@
+/*
+ * Copyright (c) 2012 Julia Medvedeva
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup fs
+ * @{
+ */
+/**
+ * @file udf_volume.c
+ * @brief Implementation of volume recognition operations.
+ */
+
+#include <byteorder.h>
+#include <block.h>
+#include <libfs.h>
+#include <errno.h>
+#include <str.h>
+#include <malloc.h>
+#include <mem.h>
+#include <inttypes.h>
+#include <io/log.h>
+#include "udf.h"
+#include "udf_volume.h"
+#include "udf_osta.h"
+#include "udf_cksum.h"
+#include "udf_file.h"
+
+/** Convert long_ad to absolute sector position
+ *
+ * Convert address sector concerning origin of partition to position
+ * sector concerning origin of start of disk.
+ *
+ * @param instance UDF instance
+ * @param long_ad  UDF long address
+ *
+ * @return Position of sector concerning origin of start of disk.
+ *
+ */
+fs_index_t udf_long_ad_to_pos(udf_instance_t *instance, udf_long_ad_t *long_ad)
+{
+	log_msg(LVL_DEBUG, "Long_Ad to Pos: "
+	    "partition_num=%" PRIu16 ", partition_block=%" PRIu32,
+	    FLE16(long_ad->location.partition_num),
+	    FLE32(long_ad->location.lblock_num));
+	
+	return instance->partitions[
+	    FLE16(long_ad->location.partition_num)].start +
+	    FLE32(long_ad->location.lblock_num);
+}
+
+/** Check type and version of VRS
+ *
+ * Not exactly clear which values could have type and version.
+ *
+ * @param service_id
+ * @param addr       Position sector with Volume Descriptor
+ * @param vd         Returned value - Volume Descriptor.
+ *
+ * @return EOK on success or a negative error code.
+ *
+ */
+static int udf_volume_recongnition_structure_test(service_id_t service_id,
+    aoff64_t addr, udf_vrs_descriptor_t *vd)
+{
+	return block_read_bytes_direct(service_id, addr,
+	    sizeof(udf_vrs_descriptor_t), vd);
+}
+
+/** Read Volume Recognition Sequence
+ *
+ * It is a first udf data which we read.
+ * It stars from fixed address VRS_ADDR = 32768 (bytes)
+ *
+ * @param service_id
+ *
+ * @return    EOK on success or a negative error code.
+ */
+int udf_volume_recongnition(service_id_t service_id) 
+{
+	aoff64_t addr = VRS_ADDR;
+	bool nsr_found = false;
+
+	udf_vrs_descriptor_t *vd = malloc(sizeof(udf_vrs_descriptor_t));
+	if (!vd)
+		return ENOMEM;
+	
+	int rc = udf_volume_recongnition_structure_test(service_id, addr, vd);
+	if (rc != EOK) {
+		free(vd);
+		return rc;
+	}
+	
+	for (size_t i = 0; i < VRS_DEPTH; i++) {
+		addr += sizeof(udf_vrs_descriptor_t);
+		
+		rc = udf_volume_recongnition_structure_test(service_id, addr, vd);
+		if (rc != EOK) {
+			free(vd);
+			return rc;
+		}
+		
+		/*
+		 * UDF standard identifier. According to ECMA 167 2/9.1.2
+		 */
+		if ((str_lcmp(VRS_NSR2, (char *) vd->identifier, VRS_ID_LEN) == 0) ||
+		    (str_lcmp(VRS_NSR3, (char *) vd->identifier, VRS_ID_LEN) == 0)) {
+			nsr_found = true;
+			log_msg(LVL_DEBUG, "VRS: NSR found");
+			continue;
+		}
+		
+		if (str_lcmp(VRS_END, (char *) vd->identifier, VRS_ID_LEN) == 0) {
+			log_msg(LVL_DEBUG, "VRS: end found");
+			break;
+		}
+	}
+	
+	free(vd);
+	
+	if (nsr_found)
+		return EOK;
+	else
+		return EINVAL;
+}
+
+/** Convert descriptor tag fields from little-endian to current byte order
+ *
+ */
+void udf_prepare_tag(udf_descriptor_tag_t *tag)
+{
+	GET_LE16(tag->id);
+	GET_LE16(tag->version);
+	GET_LE16(tag->serial);
+	GET_LE16(tag->descriptor_crc);
+	GET_LE16(tag->descriptor_crc_length);
+	GET_LE32(tag->location);
+}
+
+/** Identification of the sector size
+ *
+ * We try to read Anchor Volume Descriptor by using one item from
+ * sequence of default values. If we could read avd, we found sector size.
+ *
+ * @param service_id
+ * @param avd        Returned value - Anchor Volume Descriptor
+ *
+ * @return EOK on success or a negative error code.
+ *
+ */
+int udf_get_anchor_volume_descriptor(service_id_t service_id,
+    udf_anchor_volume_descriptor_t *avd)
+{
+	uint32_t default_sector_size[] = {512, 1024, 2048, 4096, 8192, 0};
+	
+	udf_instance_t *instance;
+	int rc = fs_instance_get(service_id, (void **) &instance);
+	if (rc != EOK)
+		return rc;
+	
+	if (instance->sector_size) {
+		return udf_get_anchor_volume_descriptor_by_ssize(service_id, avd,
+		    instance->sector_size);
+	} else {
+		size_t i = 0;
+		while (default_sector_size[i] != 0) {
+			rc = udf_get_anchor_volume_descriptor_by_ssize(service_id, avd,
+			    default_sector_size[i]);
+			if (rc == EOK) {
+				instance->sector_size = default_sector_size[i];
+				return EOK;
+			}
+			
+			i++;
+		}
+	}
+	
+	return EINVAL;
+}
+
+/** Read AVD by using one of default sector size from array
+ *
+ * @param service_id
+ * @param avd         Returned value - Anchor Volume Descriptor
+ * @param sector_size Expected sector size
+ *
+ * @return EOK on success or a negative error code.
+ *
+ */
+int udf_get_anchor_volume_descriptor_by_ssize(service_id_t service_id,
+    udf_anchor_volume_descriptor_t *avd, uint32_t sector_size)
+{
+	int rc = block_read_bytes_direct(service_id,
+	    UDF_AVDP_SECTOR * sector_size,
+	    sizeof(udf_anchor_volume_descriptor_t), avd);
+	if (rc != EOK)
+		return rc;
+	
+	if (avd->tag.checksum != udf_tag_checksum((uint8_t *) &avd->tag))
+		return EINVAL;
+	
+	// TODO: Should be tested in BegEndian mode
+	udf_prepare_tag(&avd->tag);
+	
+	if (avd->tag.id != UDF_TAG_AVDP)
+		return EINVAL;
+	
+	GET_LE32(avd->main_extent.length);
+	GET_LE32(avd->main_extent.location);
+	GET_LE32(avd->reserve_extent.length);
+	GET_LE32(avd->reserve_extent.location);
+	
+	return EOK;
+}
+
+/** Check on prevailing primary volume descriptor
+ *
+ * Some discs couldn't be rewritten and new information is identified
+ * by descriptors with same data as one of already created descriptors.
+ * We should find prevailing descriptor (descriptor with the highest number)
+ * and delete old descriptor.
+ *
+ * @param pvd  Array of primary volumes descriptors
+ * @param cnt  Count of items in array
+ * @param desc Descriptor which could prevail over one
+ *             of descriptors in array.
+ *
+ * @return True if desc prevails over some descriptor in array
+ *
+ */
+static bool udf_check_prevailing_pvd(udf_primary_volume_descriptor_t *pvd,
+    size_t cnt, udf_primary_volume_descriptor_t *desc)
+{
+	for (size_t i = 0; i < cnt; i++) {
+		/*
+		 * According to ECMA 167 3/8.4.3
+		 * PVD, each of which has same contents of the corresponding
+		 * Volume Identifier, Volume set identifier
+		 * and Descriptor char set field.
+		 */
+		if ((bcmp((uint8_t *) pvd[i].volume_id,
+		    (uint8_t *) desc->volume_id, 32) == 0) &&
+		    (bcmp((uint8_t *) pvd[i].volume_set_id,
+		    (uint8_t *) desc->volume_set_id, 128) == 0) &&
+		    (bcmp((uint8_t *) &pvd[i].descriptor_charset,
+		    (uint8_t *) &desc->descriptor_charset, 64) == 0) &&
+		    (FLE32(desc->sequence_number) > FLE32(pvd[i].sequence_number))) {
+			memcpy(&pvd[i], desc, sizeof(udf_primary_volume_descriptor_t));
+			return true;
+		}
+	}
+	
+	return false;
+}
+
+/** Check on prevailing logic volume descriptor
+ *
+ * Some discs couldn't be rewritten and new information is identified
+ * by descriptors with same data as one of already created descriptors.
+ * We should find  prevailing descriptor (descriptor with the highest number)
+ * and delete old descriptor.
+ *
+ * @param lvd  Array of logic volumes descriptors
+ * @param cnt  Count of items in array
+ * @param desc Descriptor which could prevail over one
+ *             of descriptors in array.
+ *
+ * @return True if desc prevails over some descriptor in array
+ *
+ */
+static bool udf_check_prevailing_lvd(udf_logical_volume_descriptor_t *lvd,
+    size_t cnt, udf_logical_volume_descriptor_t *desc)
+{
+	for (size_t i = 0; i < cnt; i++) {
+		/*
+		 * According to ECMA 167 3/8.4.3
+		 * LVD, each of which has same contents of the corresponding
+		 * Logic Volume Identifier and Descriptor char set field.
+		 */
+		if ((bcmp((uint8_t *) lvd[i].logical_volume_id,
+		    (uint8_t *) desc->logical_volume_id, 128) == 0) &&
+		    (bcmp((uint8_t *) &lvd[i].charset,
+		    (uint8_t *) &desc->charset, 64) == 0) &&
+		    (FLE32(desc->sequence_number) > FLE32(lvd[i].sequence_number))) {
+			memcpy(&lvd[i], desc, sizeof(udf_logical_volume_descriptor_t));
+			return true;
+		}
+	}
+	
+	return false;
+}
+
+/** Check on prevailing partition descriptor
+ *
+ * Some discs couldn't be rewritten and new information is identified
+ * by descriptors with same data as one of already created descriptors.
+ * We should find  prevailing descriptor (descriptor with the highest number)
+ * and delete old descriptor.
+ *
+ * @param pvd  Array of partition descriptors
+ * @param cnt  Count of items in array
+ * @param desc Descriptor which could prevail over one
+ *             of descriptors in array.
+ *
+ * @return True if desc prevails over some descriptor in array
+ *
+ */
+static bool udf_check_prevailing_pd(udf_partition_descriptor_t *pd, size_t cnt,
+    udf_partition_descriptor_t *desc)
+{
+	for (size_t i = 0; i < cnt; i++) {
+		/*
+		 * According to ECMA 167 3/8.4.3
+		 * Partition descriptors with identical Partition Number
+		 */
+		if ((FLE16(pd[i].number) == FLE16(desc->number)) &&
+		    (FLE32(desc->sequence_number) > FLE32(pd[i].sequence_number))) {
+			memcpy(&pd[i], desc, sizeof(udf_partition_descriptor_t));
+			return true;
+		}
+	}
+	
+	return false;
+}
+
+/** Read information about virtual partition
+ *
+ * Fill start and length fields for partition. This function quite similar of
+ * udf_read_icd. But in this we can meet only two descriptors and
+ * we have to read only one allocator.
+ *
+ * @param instance UDF instance
+ * @param pos      Position (Extended) File entry descriptor
+ * @param id       Index of partition in instance::partitions array
+ *
+ * @return EOK on success or a negative error code.
+ *
+ */
+static int udf_read_virtual_partition(udf_instance_t *instance, uint32_t pos,
+    uint32_t id)
+{
+	block_t *block = NULL;
+	int rc = block_get(&block, instance->service_id, pos,
+	    BLOCK_FLAGS_NONE);
+	if (rc != EOK)
+		return rc;
+	
+	udf_descriptor_tag_t *desc = (udf_descriptor_tag_t *) (block->data);
+	if (desc->checksum != udf_tag_checksum((uint8_t *) desc)) {
+		block_put(block);
+		return EINVAL;
+	}
+	
+	/*
+	 * We think that we have only one allocator. It is means that virtual
+	 * partition, like physical, isn't fragmented.
+	 * According to doc the type of allocator is short_ad.
+	 */
+	switch (FLE16(desc->id)) {
+	case UDF_FILE_ENTRY:
+		log_msg(LVL_DEBUG, "ICB: File entry descriptor found");
+		
+		udf_file_entry_descriptor_t *fed =
+		    (udf_file_entry_descriptor_t *) block->data;
+		uint32_t start_alloc = FLE32(fed->ea_lenght) + UDF_FE_OFFSET;
+		udf_short_ad_t *short_d =
+		    (udf_short_ad_t *) ((uint8_t *) fed + start_alloc);
+		instance->partitions[id].start = FLE32(short_d->position);
+		instance->partitions[id].lenght = FLE32(short_d->length);
+		break;
+		
+	case UDF_EFILE_ENTRY:
+		log_msg(LVL_DEBUG, "ICB: Extended file entry descriptor found");
+		
+		udf_extended_file_entry_descriptor_t *efed =
+		    (udf_extended_file_entry_descriptor_t *) block->data;
+		start_alloc = FLE32(efed->ea_lenght) + UDF_EFE_OFFSET;
+		short_d = (udf_short_ad_t *) ((uint8_t *) efed + start_alloc);
+		instance->partitions[id].start = FLE32(short_d->position);
+		instance->partitions[id].lenght = FLE32(short_d->length);
+		break;
+	}
+	
+	return block_put(block);
+}
+
+/** Search partition in array of partitions
+ *
+ * Used only in function udf_fill_volume_info
+ *
+ * @param pd     Array of partitions
+ * @param pd_cnt Count items in array
+ * @param id     Number partition (not index) which we want to find
+ *
+ * @return Index of partition or (size_t) -1 if we didn't find anything
+ *
+ */
+static size_t udf_find_partition(udf_partition_descriptor_t *pd, size_t pd_cnt,
+    size_t id)
+{
+	for (size_t i = 0; i < pd_cnt; i++) {
+		if (FLE16(pd[i].number) == id)
+			return i;
+	}
+	
+	return (size_t) -1;
+}
+
+/** Fill instance structures by information about partitions and logic
+ *
+ * @param lvd      Array of logic volumes descriptors
+ * @param lvd_cnt  Count of items in lvd array
+ * @param pd       Array of partition descriptors
+ * @param pd_cnt   Count of items in pd array
+ * @param instance UDF instance
+ *
+ * @return EOK on success or a negative error code.
+ *
+ */
+static int udf_fill_volume_info(udf_logical_volume_descriptor_t *lvd,
+    size_t lvd_cnt, udf_partition_descriptor_t *pd, size_t pd_cnt,
+    udf_instance_t *instance)
+{
+	instance->volumes = calloc(lvd_cnt, sizeof(udf_lvolume_t));
+	if (instance->volumes == NULL)
+		return ENOMEM;
+	
+	instance->partitions = calloc(pd_cnt, sizeof(udf_partition_t));
+	if (instance->partitions == NULL) {
+		free(instance->volumes);
+		return ENOMEM;
+	}
+	
+	instance->partition_cnt = pd_cnt;
+	
+	/*
+	 * Fill information about logical volumes. We will save
+	 * information about all partitions placed inside each volumes.
+	 */
+	
+	size_t vir_pd_cnt = 0;
+	for (size_t i = 0; i < lvd_cnt; i++) {
+		instance->volumes[i].partitions =
+		    calloc(FLE32(lvd[i].number_of_partitions_maps),
+		    sizeof(udf_partition_t *));
+		if (instance->volumes[i].partitions == NULL) {
+			// FIXME: Memory leak, cleanup code missing
+			return ENOMEM;
+		}
+		
+		instance->volumes[i].partition_cnt = 0;
+		instance->volumes[i].logical_block_size =
+		    FLE32(lvd[i].logical_block_size);
+		
+		/*
+		 * In theory we could have more than 1 logical volume. But now
+		 * for current work of driver we will think that it single and all
+		 * partitions from array pd belong to only first lvd
+		 */
+		
+		uint8_t *idx = lvd[i].partition_map;
+		for (size_t j = 0; j < FLE32(lvd[i].number_of_partitions_maps);
+		    j++) {
+			udf_type1_partition_map_t *pm1 =
+			    (udf_type1_partition_map_t *) idx;
+			
+			if (pm1->partition_map_type == 1) {
+				size_t pd_num = udf_find_partition(pd, pd_cnt,
+				    FLE16(pm1->partition_number));
+				if (pd_num == (size_t) -1) {
+					// FIXME: Memory leak, cleanup code missing
+					return ENOENT;
+				}
+				
+				/*
+				 * Fill information about physical partitions. We will save all
+				 * partitions (physical and virtual) inside one array
+				 * instance::partitions
+				 */
+				instance->partitions[j].access_type =
+				    FLE32(pd[pd_num].access_type);
+				instance->partitions[j].lenght =
+				    FLE32(pd[pd_num].length);
+				instance->partitions[j].number =
+				    FLE16(pm1->partition_number);
+				instance->partitions[j].start =
+				    FLE32(pd[pd_num].starting_location);
+				
+				instance->volumes[i].partitions[
+				    instance->volumes[i].partition_cnt] =
+				    &instance->partitions[j];
+				
+				log_msg(LVL_DEBUG, "Volume[%" PRIun "]: partition [type %u] "
+				    "found and filled", i, pm1->partition_map_type);
+				
+				instance->volumes[i].partition_cnt++;
+				idx += pm1->partition_map_lenght;
+				continue;
+			}
+			
+			udf_type2_partition_map_t *pm2 =
+			    (udf_type2_partition_map_t *) idx;
+			
+			if (pm2->partition_map_type == 2) {
+				// TODO: check partition_ident for metadata_partition_map
+				
+				udf_metadata_partition_map_t *metadata =
+				    (udf_metadata_partition_map_t *) idx;
+				
+				log_msg(LVL_DEBUG, "Metadata file location=%u",
+				    FLE32(metadata->metadata_fileloc));
+				
+				vir_pd_cnt++;
+				instance->partitions = realloc(instance->partitions,
+				    (pd_cnt + vir_pd_cnt) * sizeof(udf_partition_t));
+				if (instance->partitions == NULL) {
+					// FIXME: Memory leak, cleanup code missing
+					return ENOMEM;
+				}
+				
+				instance->partition_cnt++;
+				
+				size_t pd_num = udf_find_partition(pd, pd_cnt,
+				    FLE16(metadata->partition_number));
+				if (pd_num == (size_t) -1) {
+					// FIXME: Memory leak, cleanup code missing
+					return ENOENT;
+				}
+				
+				instance->partitions[j].number =
+				    FLE16(metadata->partition_number);
+				int rc = udf_read_virtual_partition(instance,
+				    FLE32(metadata->metadata_fileloc) +
+				    FLE32(pd[pd_num].starting_location), j);
+				if (rc != EOK) {
+					// FIXME: Memory leak, cleanup code missing
+					return rc;
+				}
+				
+				/* Virtual partition placed inside physical */
+				instance->partitions[j].start +=
+				    FLE32(pd[pd_num].starting_location);
+				
+				instance->volumes[i].partitions[
+				    instance->volumes[i].partition_cnt] =
+				    &instance->partitions[j];
+				
+				log_msg(LVL_DEBUG, "Virtual partition: num=%d, start=%d",
+				    instance->partitions[j].number,
+				    instance->partitions[j].start);
+				log_msg(LVL_DEBUG, "Volume[%" PRIun "]: partition [type %u] "
+				    "found and filled", i, pm2->partition_map_type);
+				
+				instance->volumes[i].partition_cnt++;
+				idx += metadata->partition_map_length;
+				continue;
+			}
+			
+			/* Not type 1 nor type 2 */
+			udf_general_type_t *pm = (udf_general_type_t *) idx;
+			
+			log_msg(LVL_DEBUG, "Volume[%" PRIun "]: partition [type %u] "
+			    "found and skipped", i, pm->partition_map_type);
+			
+			idx += pm->partition_map_lenght;
+		}
+	}
+	
+	return EOK;
+}
+
+/** Read volume descriptors sequence
+ *
+ * @param service_id
+ * @param addr       UDF extent descriptor (ECMA 167 3/7.1)
+ *
+ * @return EOK on success or a negative error code.
+ *
+ */
+int udf_read_volume_descriptor_sequence(service_id_t service_id,
+    udf_extent_t addr)
+{
+	udf_instance_t *instance;
+	int rc = fs_instance_get(service_id, (void **) &instance);
+	if (rc != EOK)
+		return rc;
+	
+	aoff64_t pos = addr.location;
+	aoff64_t end = pos + (addr.length / instance->sector_size) - 1;
+	
+	if (pos == end)
+		return EINVAL;
+	
+	size_t max_descriptors = ALL_UP(addr.length, instance->sector_size);
+	
+	udf_primary_volume_descriptor_t *pvd = calloc(max_descriptors,
+	    sizeof(udf_primary_volume_descriptor_t));
+	if (pvd == NULL)
+		return ENOMEM;
+	
+	udf_logical_volume_descriptor_t *lvd = calloc(max_descriptors,
+	    instance->sector_size);
+	if (lvd == NULL) {
+		free(pvd);
+		return ENOMEM;
+	}
+	
+	udf_partition_descriptor_t *pd = calloc(max_descriptors,
+	    sizeof(udf_partition_descriptor_t));
+	if (pd == NULL) {
+		free(pvd);
+		free(lvd);
+		return ENOMEM;
+	}
+	
+	size_t pvd_cnt = 0;
+	size_t lvd_cnt = 0;
+	size_t pd_cnt = 0;
+	
+	while (pos <= end) {
+		block_t *block = NULL;
+		rc = block_get(&block, service_id, pos, BLOCK_FLAGS_NONE);
+		if (rc != EOK) {
+			free(pvd);
+			free(lvd);
+			free(pd);
+			return rc;
+		}
+		
+		udf_volume_descriptor_t *vol =
+		    (udf_volume_descriptor_t *) block->data;
+		
+		switch (FLE16(vol->common.tag.id)) {
+		/* One sector size descriptors */
+		case UDF_TAG_PVD:
+			log_msg(LVL_DEBUG, "Volume: Primary volume descriptor found");
+			
+			if (!udf_check_prevailing_pvd(pvd, pvd_cnt, &vol->volume)) {
+				memcpy(&pvd[pvd_cnt], &vol->volume,
+				    sizeof(udf_primary_volume_descriptor_t));
+				pvd_cnt++;
+			}
+			
+			pos++;
+			break;
+			
+		case UDF_TAG_VDP:
+			log_msg(LVL_DEBUG, "Volume: Volume descriptor pointer found");
+			pos++;
+			break;
+			
+		case UDF_TAG_IUVD:
+			log_msg(LVL_DEBUG,
+			    "Volume: Implementation use volume descriptor found");
+			pos++;
+			break;
+			
+		case UDF_TAG_PD:
+			log_msg(LVL_DEBUG, "Volume: Partition descriptor found");
+			log_msg(LVL_DEBUG, "Partition number: %u, contents: '%.6s', "
+			    "access type: %" PRIu32, FLE16(vol->partition.number),
+			    vol->partition.contents.id, FLE32(vol->partition.access_type));
+			log_msg(LVL_DEBUG, "Partition start: %" PRIu32 " (sector), "
+			    "size: %" PRIu32 " (sectors)",
+			    FLE32(vol->partition.starting_location),
+			    FLE32(vol->partition.length));
+			
+			if (!udf_check_prevailing_pd(pd, pd_cnt, &vol->partition)) {
+				memcpy(&pd[pd_cnt], &vol->partition,
+				    sizeof(udf_partition_descriptor_t));
+				pd_cnt++;
+			}
+			
+			udf_partition_header_descriptor_t *phd =
+			    (udf_partition_header_descriptor_t *) vol->partition.contents_use;
+			if (FLE32(phd->unallocated_space_table.length)) {
+				log_msg(LVL_DEBUG,
+				    "space table: length=%" PRIu32 ", pos=%" PRIu32,
+				    FLE32(phd->unallocated_space_table.length),
+				    FLE32(phd->unallocated_space_table.position));
+				
+				instance->space_type = SPACE_TABLE;
+				instance->uaspace_start =
+				    FLE32(vol->partition.starting_location) +
+				    FLE32(phd->unallocated_space_table.position);
+				instance->uaspace_lenght =
+				    FLE32(phd->unallocated_space_table.length);
+			}
+			
+			if (FLE32(phd->unallocated_space_bitmap.length)) {
+				log_msg(LVL_DEBUG,
+				    "space bitmap: length=%" PRIu32 ", pos=%" PRIu32,
+				    FLE32(phd->unallocated_space_bitmap.length),
+				    FLE32(phd->unallocated_space_bitmap.position));
+				
+				instance->space_type = SPACE_BITMAP;
+				instance->uaspace_start =
+				    FLE32(vol->partition.starting_location) +
+				    FLE32(phd->unallocated_space_bitmap.position);
+				instance->uaspace_lenght =
+				    FLE32(phd->unallocated_space_bitmap.length);
+			}
+			
+			pos++;
+			break;
+			
+		/* Relative size descriptors */
+		case UDF_TAG_LVD:
+			log_msg(LVL_DEBUG, "Volume: Logical volume descriptor found");
+			
+			aoff64_t sct =
+			    ALL_UP((sizeof(udf_logical_volume_descriptor_t) +
+			    FLE32(vol->logical.map_table_length)),
+			    sizeof(udf_common_descriptor_t));
+			pos += sct;
+			char tmp[130];
+			
+			udf_to_unix_name(tmp, 129,
+			    (char *) vol->logical.logical_volume_id, 128,
+			    &vol->logical.charset);
+			
+			log_msg(LVL_DEBUG, "Logical Volume ID: '%s', "
+			    "logical block size: %" PRIu32 " (bytes)", tmp,
+			    FLE32(vol->logical.logical_block_size));
+			log_msg(LVL_DEBUG, "Map table size: %" PRIu32 " (bytes), "
+			    "number of partition maps: %" PRIu32,
+			    FLE32(vol->logical.map_table_length),
+			    FLE32(vol->logical.number_of_partitions_maps));
+			
+			if (!udf_check_prevailing_lvd(lvd, lvd_cnt, &vol->logical)) {
+				memcpy(&lvd[lvd_cnt], &vol->logical,
+				    sizeof(udf_logical_volume_descriptor_t) +
+				    FLE32(vol->logical.map_table_length));
+				lvd_cnt++;
+			}
+			
+			break;
+			
+		case UDF_TAG_USD:
+			log_msg(LVL_DEBUG, "Volume: Unallocated space descriptor found");
+			
+			sct = ALL_UP((sizeof(udf_unallocated_space_descriptor_t) +
+			    FLE32(vol->unallocated.allocation_descriptors_num)*
+			    sizeof(udf_extent_t)), sizeof(udf_common_descriptor_t));
+			instance->uaspace_start = pos;
+			instance->uaspace_lenght = sct;
+			instance->uasd = (udf_unallocated_space_descriptor_t *)
+			    malloc(sct * instance->sector_size);
+			if (instance->uasd == NULL) {
+				// FIXME: Memory leak, cleanup missing
+				return ENOMEM;
+			}
+			
+			memcpy(instance->uasd, block->data, instance->sector_size);
+			pos += sct;
+			break;
+			
+		case UDF_TAG_LVID:
+			log_msg(LVL_DEBUG,
+			    "Volume: Logical volume integrity descriptor found");
+			
+			pos++;
+			break;
+			
+		case UDF_TAG_TD:
+			log_msg(LVL_DEBUG, "Volume: Terminating descriptor found");
+			
+			/* Found terminating descriptor. Exiting */
+			pos = end + 1;
+			break;
+			
+		default:
+			pos++;
+		}
+		
+		rc = block_put(block);
+		if (rc != EOK) {
+			free(pvd);
+			free(lvd);
+			free(pd);
+			return rc;
+		}
+	}
+	
+	/* Fill the instance */
+	udf_fill_volume_info(lvd, lvd_cnt, pd, pd_cnt, instance);
+	
+	for (size_t i = 0; i < lvd_cnt; i++) {
+		pos = udf_long_ad_to_pos(instance,
+		    (udf_long_ad_t *) &lvd[i].logical_volume_conents_use);
+		
+		block_t *block = NULL;
+		rc = block_get(&block, instance->service_id, pos,
+		    BLOCK_FLAGS_NONE);
+		if (rc != EOK) {
+			// FIXME: Memory leak, cleanup missing
+			return rc;
+		}
+		
+		udf_descriptor_tag_t *desc = block->data;
+		
+		log_msg(LVL_DEBUG, "First tag ID=%" PRIu16, desc->id);
+		
+		if (desc->checksum != udf_tag_checksum((uint8_t *) desc)) {
+			// FIXME: Memory leak, cleanup missing
+			return EINVAL;
+		}
+		
+		udf_prepare_tag(desc);
+		
+		udf_fileset_descriptor_t *fd = block->data;
+		memcpy((uint8_t *) &instance->charset,
+		    (uint8_t *) &fd->fileset_charset, sizeof(fd->fileset_charset));
+		
+		instance->volumes[i].root_dir = udf_long_ad_to_pos(instance,
+		    &fd->root_dir_icb);
+	}
+	
+	free(pvd);
+	free(lvd);
+	free(pd);
+	return EOK;
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/fs/udf/udf_volume.h
===================================================================
--- uspace/srv/fs/udf/udf_volume.h	(revision 48e31904fcd0b717c586d68fd42458d05940cb20)
+++ uspace/srv/fs/udf/udf_volume.h	(revision 48e31904fcd0b717c586d68fd42458d05940cb20)
@@ -0,0 +1,226 @@
+/*
+ * Copyright (c) 2012 Julia Medvedeva
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup fs
+ * @{
+ */
+
+#ifndef UDF_UDF_VOLUME_H_
+#define UDF_UDF_VOLUME_H_
+
+#include <sys/types.h>
+#include <ipc/loc.h>
+#include "udf_types.h"
+
+/* Descriptor Tag Identifier (ECMA 167 3/7.2.1) */
+#define UDF_TAG_PVD   0x0001  /* Primary Volume Descriptor */
+#define UDF_TAG_AVDP  0x0002  /* Anchor Volume Descriptor */
+#define UDF_TAG_VDP   0x0003  /* Volume Descriptor Pointer */
+#define UDF_TAG_IUVD  0x0004  /* Implementation Use Volume Descriptor */
+#define UDF_TAG_PD    0x0005  /* Partition Descriptor */
+#define UDF_TAG_LVD   0x0006  /* Logical Volume Descriptor */
+#define UDF_TAG_USD   0x0007  /* Unallocated Space Descriptor */
+#define UDF_TAG_TD    0x0008  /* Terminating Descriptor */
+#define UDF_TAG_LVID  0x0009  /* Logical Volume Integrity Descriptor */
+
+/* Start adress of Anchor Volume Descriptor */
+#define UDF_AVDP_SECTOR  256
+
+/* Volume Recognition Sequence params */
+#define VRS_ADDR     32768
+#define VRS_TYPE     0
+#define VRS_VERSION  1
+#define VRS_BEGIN    "BEA01"
+#define VRS_END      "TEA01"
+#define VRS_NSR2     "NSR02"
+#define VRS_NSR3     "NSR03"
+#define VRS_DEPTH    10
+#define VRS_ID_LEN   5
+
+/* Volume Structure Descriptor (ECMA 167 2/9.1) */
+typedef struct udf_vrs_descriptor {
+	uint8_t type;           /* Structure type */
+	uint8_t identifier[5];  /* Standart identifier */
+	uint8_t version;        /* Structure version */
+	uint8_t data[2041];     /* Structure data */
+} __attribute__((packed)) udf_vrs_descriptor_t;
+
+/* Anchor volume descriptor (ECMA 167 3/10.2) */
+typedef struct udf_anchor_volume_descriptor {
+	udf_descriptor_tag_t tag;     /* Descriptor tag */
+	udf_extent_t main_extent;     /* Main Volume Descriptor Sequence Extent */
+	udf_extent_t reserve_extent;  /* Reserve Volume Descriptor Sequence Extent */
+	uint8_t reserved[480];        /* Structure data */
+} __attribute__((packed)) udf_anchor_volume_descriptor_t;
+
+/* Common Volume Descriptor */
+typedef struct udf_common_descriptor {
+	udf_descriptor_tag_t tag;
+	uint8_t reserved[496];
+} __attribute__((packed)) udf_common_descriptor_t;
+
+/* Volume Descriptor Pointer (ECMA 167 3/10.3) */
+typedef struct udf_volume_pointer_descriptor {
+	udf_descriptor_tag_t tag;
+	uint32_t sequence_number;
+	udf_extent_t next_sequence;
+	uint8_t reserved[484];
+} __attribute__((packed)) udf_volume_pointer_descriptor_t;
+
+/* Primary Volume Descriptor (ECMA 167 3/10.1) */
+typedef struct udf_primary_volume_descriptor {
+	udf_descriptor_tag_t tag;
+	uint32_t sequence_number;
+	uint32_t primary_volume_descriptor_num;
+	udf_dstring volume_id[32];
+	uint16_t max_sequence_number;
+	uint16_t interchange_level;
+	uint16_t max_interchange_level;
+	uint32_t charset_list;
+	uint32_t max_charset_list;
+	udf_dstring volume_set_id[128];
+	udf_charspec_t descriptor_charset;
+	udf_charspec_t explanatory_charset;
+	udf_extent_t volume_abstract;
+	udf_extent_t volume_copyright_notice;
+	udf_regid_t application_id;
+	udf_timestamp_t recording_data_and_time;
+	udf_regid_t implementation_id;
+	uint8_t implementation_use[64];
+	uint32_t predecessor_vds_location;
+	uint16_t flags;
+	uint8_t reserved[22];
+} __attribute__((packed)) udf_primary_volume_descriptor_t;
+
+
+/* Partition Descriptor (ECMA 167 3/10.5) */
+typedef struct udf_partition_descriptor {
+	udf_descriptor_tag_t tag;
+	uint32_t sequence_number;
+	uint16_t flags;
+	uint16_t number;
+	udf_regid_t contents;
+	uint8_t contents_use[128];
+	uint32_t access_type;
+	uint32_t starting_location;
+	uint32_t length;
+	udf_regid_t implementation_id;
+	uint8_t implementation_use[128];
+	uint8_t reserved[156];
+} __attribute__((packed)) udf_partition_descriptor_t;
+
+/* Logical Volume Descriptor (ECMA 167 3/10.6) */
+typedef struct udf_logical_volume_descriptor {
+	udf_descriptor_tag_t tag;
+	uint32_t sequence_number;
+	udf_charspec_t charset;
+	udf_dstring logical_volume_id[128];
+	uint32_t logical_block_size;
+	udf_regid_t domain_id;
+	uint8_t logical_volume_conents_use[16];
+	uint32_t map_table_length;
+	uint32_t number_of_partitions_maps;
+	udf_regid_t implementation_id;
+	uint8_t implementation_use[128];
+	udf_extent_t integrity_sequence_extent;
+	uint8_t partition_map[0];
+} __attribute__((packed)) udf_logical_volume_descriptor_t;
+
+typedef struct udf_volume_descriptor {
+	union {
+		udf_common_descriptor_t common;
+		udf_terminating_descriptor_t terminating;
+		udf_volume_pointer_descriptor_t pointer;
+		udf_partition_descriptor_t partition;
+		udf_logical_volume_descriptor_t logical;
+		udf_unallocated_space_descriptor_t unallocated;
+		udf_primary_volume_descriptor_t volume;
+	};
+} __attribute__((packed)) udf_volume_descriptor_t;
+
+typedef struct udf_general_type {
+	uint8_t partition_map_type;
+	uint8_t partition_map_lenght;
+} __attribute__((packed)) udf_general_type_t;
+
+typedef struct udf_type1_partition_map {
+	uint8_t partition_map_type;
+	uint8_t partition_map_lenght;
+	uint16_t volume_sequence_number;
+	uint16_t partition_number;
+} __attribute__((packed)) udf_type1_partition_map_t;
+
+typedef struct udf_type2_partition_map {
+	uint8_t partition_map_type;
+	uint8_t partition_map_length;
+	uint8_t reserved1[2];
+	udf_regid_t partition_ident;
+	uint16_t volume_sequence_number;
+	uint16_t partition_number;
+} __attribute__((packed)) udf_type2_partition_map_t;
+
+/* Metadata Partition Map (UDF 2.4.0 2.2.10) */
+typedef struct udf_metadata_partition_map {
+	uint8_t partition_map_type;
+	uint8_t partition_map_length;
+	uint8_t reserved1[2];
+	udf_regid_t partition_ident;
+	uint16_t volume_sequence_number;
+	uint16_t partition_number;
+	uint32_t metadata_fileloc;
+	uint32_t metadata_mirror_fileloc;
+	uint32_t metadata_bitmap_fileloc;
+	uint32_t alloc_unit_size;
+	uint16_t align_unit_size;
+	uint8_t flags;
+	uint8_t reserved2[5];
+} __attribute__((packed)) udf_metadata_partition_map_t;
+
+/* Partition Header Descriptor (ECMA 167 4/14.3) */
+typedef struct udf_partition_header_descriptor {
+	udf_short_ad_t unallocated_space_table;
+	udf_short_ad_t unallocated_space_bitmap;
+	udf_short_ad_t partition_integrity_table;
+	udf_short_ad_t freed_space_table;
+	udf_short_ad_t freed_space_bitmap;
+	uint8_t reserved[88];
+} __attribute__((packed)) udf_partition_header_descriptor_t;
+
+extern int udf_volume_recongnition(service_id_t);
+extern int udf_get_anchor_volume_descriptor(service_id_t,
+    udf_anchor_volume_descriptor_t *);
+extern int udf_get_anchor_volume_descriptor_by_ssize(service_id_t,
+    udf_anchor_volume_descriptor_t *, uint32_t);
+extern int udf_read_volume_descriptor_sequence(service_id_t, udf_extent_t);
+extern fs_index_t udf_long_ad_to_pos(udf_instance_t *, udf_long_ad_t *);
+
+#endif
+
+/**
+ * @}
+ */
