1 /* $Id: fsw_core.h 33540 2010-10-28 09:27:05Z vboxsync $ */
3 * fsw_core.h - Core file system wrapper abstraction layer header.
7 * Copyright (C) 2010 Oracle Corporation
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
19 * This code is based on:
21 * Copyright (c) 2006 Christoph Pfisterer
22 * Portions Copyright (c) The Regents of the University of California.
23 * Portions Copyright (c) UNIX System Laboratories, Inc.
25 * Redistribution and use in source and binary forms, with or without
26 * modification, are permitted provided that the following conditions are
29 * * Redistributions of source code must retain the above copyright
30 * notice, this list of conditions and the following disclaimer.
32 * * Redistributions in binary form must reproduce the above copyright
33 * notice, this list of conditions and the following disclaimer in the
34 * documentation and/or other materials provided with the
37 * * Neither the name of Christoph Pfisterer nor the names of the
38 * contributors may be used to endorse or promote products derived
39 * from this software without specific prior written permission.
41 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
42 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
43 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
44 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
45 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
46 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
47 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
48 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
49 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
50 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
51 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
58 #ifdef __MAKEWITH_GNUEFI
59 #include "fsw_efi_base.h"
62 /** Maximum size for a path, specifically symlink target paths. */
64 #define FSW_PATH_MAX (4096)
66 /* Too big allocations are handled with alloca() */
67 #define FSW_PATH_MAX (2048)
70 /** Helper macro for token concatenation. */
71 #define FSW_CONCAT3(a,b,c) a##b##c
72 /** Expands to the name of a fstype dispatch table (fsw_fstype_table) for a named file system type. */
73 #define FSW_FSTYPE_TABLE_NAME(t) FSW_CONCAT3(fsw_,t,_table)
75 /** Indicates that the block cache entry is empty. */
76 #define FSW_INVALID_BNO 0xFFFFFFFFFFFFFFFF
80 // Byte-swapping macros
85 * \name Byte Order Macros
86 * Implements big endian vs. little endian awareness and conversion.
90 typedef fsw_u16 fsw_u16_le
;
91 typedef fsw_u16 fsw_u16_be
;
92 typedef fsw_u32 fsw_u32_le
;
93 typedef fsw_u32 fsw_u32_be
;
94 typedef fsw_u64 fsw_u64_le
;
95 typedef fsw_u64 fsw_u64_be
;
97 #define FSW_SWAPVALUE_U16(v) ((((fsw_u16)(v) & 0xff00) >> 8) | \
98 (((fsw_u16)(v) & 0x00ff) << 8))
99 #define FSW_SWAPVALUE_U32(v) ((((fsw_u32)(v) & 0xff000000UL) >> 24) | \
100 (((fsw_u32)(v) & 0x00ff0000UL) >> 8) | \
101 (((fsw_u32)(v) & 0x0000ff00UL) << 8) | \
102 (((fsw_u32)(v) & 0x000000ffUL) << 24))
103 #define FSW_SWAPVALUE_U64(v) ((((fsw_u64)(v) & 0xff00000000000000ULL) >> 56) | \
104 (((fsw_u64)(v) & 0x00ff000000000000ULL) >> 40) | \
105 (((fsw_u64)(v) & 0x0000ff0000000000ULL) >> 24) | \
106 (((fsw_u64)(v) & 0x000000ff00000000ULL) >> 8) | \
107 (((fsw_u64)(v) & 0x00000000ff000000ULL) << 8) | \
108 (((fsw_u64)(v) & 0x0000000000ff0000ULL) << 24) | \
109 (((fsw_u64)(v) & 0x000000000000ff00ULL) << 40) | \
110 (((fsw_u64)(v) & 0x00000000000000ffULL) << 56))
112 #ifdef FSW_LITTLE_ENDIAN
114 #define fsw_u16_le_swap(v) (v)
115 #define fsw_u16_be_swap(v) FSW_SWAPVALUE_U16(v)
116 #define fsw_u32_le_swap(v) (v)
117 #define fsw_u32_be_swap(v) FSW_SWAPVALUE_U32(v)
118 #define fsw_u64_le_swap(v) (v)
119 #define fsw_u64_be_swap(v) FSW_SWAPVALUE_U64(v)
121 #define fsw_u16_le_sip(var)
122 #define fsw_u16_be_sip(var) (var = FSW_SWAPVALUE_U16(var))
123 #define fsw_u32_le_sip(var)
124 #define fsw_u32_be_sip(var) (var = FSW_SWAPVALUE_U32(var))
125 #define fsw_u64_le_sip(var)
126 #define fsw_u64_be_sip(var) (var = FSW_SWAPVALUE_U64(var))
129 #ifdef FSW_BIG_ENDIAN
131 #define fsw_u16_le_swap(v) FSW_SWAPVALUE_U16(v)
132 #define fsw_u16_be_swap(v) (v)
133 #define fsw_u32_le_swap(v) FSW_SWAPVALUE_U32(v)
134 #define fsw_u32_be_swap(v) (v)
135 #define fsw_u64_le_swap(v) FSW_SWAPVALUE_U64(v)
136 #define fsw_u64_be_swap(v) (v)
138 #define fsw_u16_le_sip(var) (var = FSW_SWAPVALUE_U16(var))
139 #define fsw_u16_be_sip(var)
140 #define fsw_u32_le_sip(var) (var = FSW_SWAPVALUE_U32(var))
141 #define fsw_u32_be_sip(var)
142 #define fsw_u64_le_sip(var) (var = FSW_SWAPVALUE_U64(var))
143 #define fsw_u64_be_sip(var)
146 #fail Neither FSW_BIG_ENDIAN nor FSW_LITTLE_ENDIAN are defined
154 // The following evil hack avoids a lot of casts between generic and fstype-specific
158 #ifndef VOLSTRUCTNAME
159 #define VOLSTRUCTNAME fsw_volume
161 struct VOLSTRUCTNAME
;
163 #ifndef DNODESTRUCTNAME
164 #define DNODESTRUCTNAME fsw_dnode
166 struct DNODESTRUCTNAME
;
171 * Status code type, returned from all functions that can fail.
173 typedef int fsw_status_t
;
176 * Possible status codes.
184 FSW_VOLUME_CORRUPTED
,
190 * Core: A string with explicit length and encoding information.
194 int type
; //!< Encoding of the string - empty, ISO-8859-1, UTF8, UTF16
195 int len
; //!< Length in characters
196 int size
; //!< Total data size in bytes
197 void *data
; //!< Data pointer (may be NULL if type is EMPTY or len is zero)
201 * Possible string types / encodings. In the case of FSW_STRING_TYPE_EMPTY,
202 * all other members of the fsw_string structure may be invalid.
205 FSW_STRING_TYPE_EMPTY
,
206 FSW_STRING_TYPE_ISO88591
,
207 FSW_STRING_TYPE_UTF8
,
208 FSW_STRING_TYPE_UTF16
,
209 FSW_STRING_TYPE_UTF16_SWAPPED
212 #ifdef FSW_LITTLE_ENDIAN
213 #define FSW_STRING_TYPE_UTF16_LE FSW_STRING_TYPE_UTF16
214 #define FSW_STRING_TYPE_UTF16_BE FSW_STRING_TYPE_UTF16_SWAPPED
216 #define FSW_STRING_TYPE_UTF16_LE FSW_STRING_TYPE_UTF16_SWAPPED
217 #define FSW_STRING_TYPE_UTF16_BE FSW_STRING_TYPE_UTF16
220 /** Static initializer for an empty string. */
221 #define FSW_STRING_INIT { FSW_STRING_TYPE_EMPTY, 0, 0, NULL }
224 /* forward declarations */
227 struct fsw_host_table
;
228 struct fsw_fstype_table
;
230 struct fsw_blockcache
{
231 fsw_u32 refcount
; //!< Reference count
232 fsw_u32 cache_level
; //!< Level of importance of this block
233 fsw_u64 phys_bno
; //!< Physical block number
234 void *data
; //!< Block data buffer
238 * Core: Represents a mounted volume.
242 fsw_u32 phys_blocksize
; //!< Block size for disk access / file system structures
243 fsw_u32 log_blocksize
; //!< Block size for logical file data
245 struct DNODESTRUCTNAME
*root
; //!< Root directory dnode
246 struct fsw_string label
; //!< Volume label
248 struct fsw_dnode
*dnode_head
; //!< List of all dnodes allocated for this volume
250 struct fsw_blockcache
*bcache
; //!< Array of block cache entries
251 fsw_u32 bcache_size
; //!< Number of entries in the block cache array
253 void *host_data
; //!< Hook for a host-specific data structure
254 struct fsw_host_table
*host_table
; //!< Dispatch table for host-specific functions
255 struct fsw_fstype_table
*fstype_table
; //!< Dispatch table for file system specific functions
256 int host_string_type
; //!< String type used by the host environment
260 * Core: Represents a "directory node" - a file, directory, symlink, whatever.
264 fsw_u32 refcount
; //!< Reference count
266 struct VOLSTRUCTNAME
*vol
; //!< The volume this dnode belongs to
267 struct DNODESTRUCTNAME
*parent
; //!< Parent directory dnode
268 struct fsw_string name
; //!< Name of this item in the parent directory
270 fsw_u64 tree_id
; //!< Unique id number (usually the btrfs subvolume)
271 fsw_u64 dnode_id
; //!< Unique id number (usually the inode number)
272 int type
; //!< Type of the dnode - file, dir, symlink, special
273 fsw_u64 size
; //!< Data size in bytes
275 struct fsw_dnode
*next
; //!< Doubly-linked list of all dnodes: previous dnode
276 struct fsw_dnode
*prev
; //!< Doubly-linked list of all dnodes: next dnode
280 * Possible dnode types. FSW_DNODE_TYPE_UNKNOWN may only be used before
281 * fsw_dnode_fill has been called on the dnode.
284 FSW_DNODE_TYPE_UNKNOWN
,
287 FSW_DNODE_TYPE_SYMLINK
,
288 FSW_DNODE_TYPE_SPECIAL
292 * Core: Stores the mapping of a region of a file to the data on disk.
296 fsw_u32 type
; //!< Type of extent specification
297 fsw_u64 log_start
; //!< Starting logical block number
298 fsw_u32 log_count
; //!< Logical block count
299 fsw_u64 phys_start
; //!< Starting physical block number (for FSW_EXTENT_TYPE_PHYSBLOCK only)
300 void *buffer
; //!< Allocated buffer pointer (for FSW_EXTENT_TYPE_BUFFER only)
304 * Possible extent representation types. FSW_EXTENT_TYPE_INVALID is for shandle's
305 * internal use only, it must not be returned from a get_extent function.
308 FSW_EXTENT_TYPE_INVALID
,
309 FSW_EXTENT_TYPE_SPARSE
,
310 FSW_EXTENT_TYPE_PHYSBLOCK
,
311 FSW_EXTENT_TYPE_BUFFER
315 * Core: An access structure to a dnode's raw data. There can be multiple
316 * shandles per dnode, each of them has its own position pointer.
320 struct fsw_dnode
*dnode
; //!< The dnode this handle reads data from
322 fsw_u64 pos
; //!< Current file pointer in bytes
323 struct fsw_extent extent
; //!< Current extent
327 * Core: Used in gathering detailed information on a volume.
330 struct fsw_volume_stat
{
331 fsw_u64 total_bytes
; //!< Total size of data area size in bytes
332 fsw_u64 free_bytes
; //!< Bytes still available for storing file data
336 * Core: Used in gathering detailed information on a dnode.
339 struct fsw_dnode_stat
{
340 fsw_u64 used_bytes
; //!< Bytes actually used by the file on disk
341 void (*store_time_posix
)(struct fsw_dnode_stat
*sb
, int which
, fsw_u32 posix_time
); //!< Callback for storing a Posix-style timestamp
342 void (*store_attr_posix
)(struct fsw_dnode_stat
*sb
, fsw_u16 posix_mode
); //!< Callback for storing a Posix-style file mode
343 void *host_data
; //!< Hook for a host-specific data structure
347 * Type of the timestamp passed into store_time_posix.
350 FSW_DNODE_STAT_CTIME
,
351 FSW_DNODE_STAT_MTIME
,
356 * Core: Function table for a host environment.
359 struct fsw_host_table
361 int native_string_type
; //!< String type used by the host environment
363 void (*change_blocksize
)(struct fsw_volume
*vol
,
364 fsw_u32 old_phys_blocksize
, fsw_u32 old_log_blocksize
,
365 fsw_u32 new_phys_blocksize
, fsw_u32 new_log_blocksize
);
366 fsw_status_t (*read_block
)(struct fsw_volume
*vol
, fsw_u64 phys_bno
, void *buffer
);
370 * Core: Function table for a file system driver.
373 struct fsw_fstype_table
375 struct fsw_string name
; //!< String giving the name of the file system
376 fsw_u32 volume_struct_size
; //!< Size for allocating the fsw_volume structure
377 fsw_u32 dnode_struct_size
; //!< Size for allocating the fsw_dnode structure
379 fsw_status_t (*volume_mount
)(struct VOLSTRUCTNAME
*vol
);
380 void (*volume_free
)(struct VOLSTRUCTNAME
*vol
);
381 fsw_status_t (*volume_stat
)(struct VOLSTRUCTNAME
*vol
, struct fsw_volume_stat
*sb
);
383 fsw_status_t (*dnode_fill
)(struct VOLSTRUCTNAME
*vol
, struct DNODESTRUCTNAME
*dno
);
384 void (*dnode_free
)(struct VOLSTRUCTNAME
*vol
, struct DNODESTRUCTNAME
*dno
);
385 fsw_status_t (*dnode_stat
)(struct VOLSTRUCTNAME
*vol
, struct DNODESTRUCTNAME
*dno
,
386 struct fsw_dnode_stat
*sb
);
387 fsw_status_t (*get_extent
)(struct VOLSTRUCTNAME
*vol
, struct DNODESTRUCTNAME
*dno
,
388 struct fsw_extent
*extent
);
390 fsw_status_t (*dir_lookup
)(struct VOLSTRUCTNAME
*vol
, struct DNODESTRUCTNAME
*dno
,
391 struct fsw_string
*lookup_name
, struct DNODESTRUCTNAME
**child_dno
);
392 fsw_status_t (*dir_read
)(struct VOLSTRUCTNAME
*vol
, struct DNODESTRUCTNAME
*dno
,
393 struct fsw_shandle
*shand
, struct DNODESTRUCTNAME
**child_dno
);
394 fsw_status_t (*readlink
)(struct VOLSTRUCTNAME
*vol
, struct DNODESTRUCTNAME
*dno
,
395 struct fsw_string
*link_target
);
400 * \name Volume Functions
404 fsw_status_t
fsw_mount(void *host_data
,
405 struct fsw_host_table
*host_table
,
406 struct fsw_fstype_table
*fstype_table
,
407 struct fsw_volume
**vol_out
);
408 void fsw_unmount(struct fsw_volume
*vol
);
409 fsw_status_t
fsw_volume_stat(struct fsw_volume
*vol
, struct fsw_volume_stat
*sb
);
411 void fsw_set_blocksize(struct VOLSTRUCTNAME
*vol
, fsw_u32 phys_blocksize
, fsw_u32 log_blocksize
);
412 fsw_status_t
fsw_block_get(struct VOLSTRUCTNAME
*vol
, fsw_u64 phys_bno
, fsw_u32 cache_level
, void **buffer_out
);
413 void fsw_block_release(struct VOLSTRUCTNAME
*vol
, fsw_u64 phys_bno
, void *buffer
);
419 * \name dnode Functions
423 fsw_status_t
fsw_dnode_create_root(struct VOLSTRUCTNAME
*vol
, fsw_u64 dnode_id
, struct DNODESTRUCTNAME
**dno_out
);
424 fsw_status_t
fsw_dnode_create(struct DNODESTRUCTNAME
*parent_dno
, fsw_u64 dnode_id
, int type
,
425 struct fsw_string
*name
, struct DNODESTRUCTNAME
**dno_out
);
426 fsw_status_t
fsw_dnode_create_root_with_tree(struct VOLSTRUCTNAME
*vol
, fsw_u64 tree_id
, fsw_u64 dnode_id
, struct DNODESTRUCTNAME
**dno_out
);
427 fsw_status_t
fsw_dnode_create_with_tree(struct DNODESTRUCTNAME
*parent_dno
, fsw_u64 tree_id
, fsw_u64 dnode_id
, int type
,
428 struct fsw_string
*name
, struct DNODESTRUCTNAME
**dno_out
);
429 void fsw_dnode_retain(struct fsw_dnode
*dno
);
430 void fsw_dnode_release(struct fsw_dnode
*dno
);
432 fsw_status_t
fsw_dnode_fill(struct fsw_dnode
*dno
);
433 fsw_status_t
fsw_dnode_stat(struct fsw_dnode
*dno
, struct fsw_dnode_stat
*sb
);
435 fsw_status_t
fsw_dnode_lookup(struct fsw_dnode
*dno
,
436 struct fsw_string
*lookup_name
, struct fsw_dnode
**child_dno_out
);
437 fsw_status_t
fsw_dnode_lookup_path(struct fsw_dnode
*dno
,
438 struct fsw_string
*lookup_path
, char separator
,
439 struct fsw_dnode
**child_dno_out
);
440 fsw_status_t
fsw_dnode_dir_read(struct fsw_shandle
*shand
, struct fsw_dnode
**child_dno_out
);
441 fsw_status_t
fsw_dnode_readlink(struct fsw_dnode
*dno
, struct fsw_string
*link_target
);
442 fsw_status_t
fsw_dnode_readlink_data(struct DNODESTRUCTNAME
*dno
, struct fsw_string
*link_target
);
443 fsw_status_t
fsw_dnode_resolve(struct fsw_dnode
*dno
, struct fsw_dnode
**target_dno_out
);
449 * \name shandle Functions
453 fsw_status_t
fsw_shandle_open(struct DNODESTRUCTNAME
*dno
, struct fsw_shandle
*shand
);
454 void fsw_shandle_close(struct fsw_shandle
*shand
);
455 fsw_status_t
fsw_shandle_read(struct fsw_shandle
*shand
, fsw_u32
*buffer_size_inout
, void *buffer
);
461 * \name Memory Functions
465 fsw_status_t
fsw_alloc_zero(int len
, void **ptr_out
);
466 fsw_status_t
fsw_memdup(void **dest_out
, void *src
, int len
);
472 * \name String Functions
476 int fsw_strlen(struct fsw_string
*s
);
477 int fsw_streq(struct fsw_string
*s1
, struct fsw_string
*s2
);
478 int fsw_streq_cstr(struct fsw_string
*s1
, const char *s2
);
479 fsw_status_t
fsw_strdup_coerce(struct fsw_string
*dest
, int type
, struct fsw_string
*src
);
480 void fsw_strsplit(struct fsw_string
*lookup_name
, struct fsw_string
*buffer
, char separator
);
482 void fsw_strfree(struct fsw_string
*s
);
483 fsw_u16
fsw_to_lower(fsw_u16 ch
);
488 * \name Posix Mode Macros
489 * These macros can be used globally to test fields and bits in
492 * Taken from FreeBSD sys/stat.h.
497 #define S_ISUID 0004000 /* set user id on execution */
498 #define S_ISGID 0002000 /* set group id on execution */
499 #define S_ISTXT 0001000 /* sticky bit */
501 #define S_IRWXU 0000700 /* RWX mask for owner */
502 #define S_IRUSR 0000400 /* R for owner */
503 #define S_IWUSR 0000200 /* W for owner */
504 #define S_IXUSR 0000100 /* X for owner */
506 #define S_IRWXG 0000070 /* RWX mask for group */
507 #define S_IRGRP 0000040 /* R for group */
508 #define S_IWGRP 0000020 /* W for group */
509 #define S_IXGRP 0000010 /* X for group */
511 #define S_IRWXO 0000007 /* RWX mask for other */
512 #define S_IROTH 0000004 /* R for other */
513 #define S_IWOTH 0000002 /* W for other */
514 #define S_IXOTH 0000001 /* X for other */
516 #define S_IFMT 0170000 /* type of file mask */
517 #define S_IFIFO 0010000 /* named pipe (fifo) */
518 #define S_IFCHR 0020000 /* character special */
519 #define S_IFDIR 0040000 /* directory */
520 #define S_IFBLK 0060000 /* block special */
521 #define S_IFREG 0100000 /* regular */
522 #define S_IFLNK 0120000 /* symbolic link */
523 #define S_IFSOCK 0140000 /* socket */
524 #define S_ISVTX 0001000 /* save swapped text even after use */
525 #define S_IFWHT 0160000 /* whiteout */
527 #define S_ISDIR(m) (((m) & 0170000) == 0040000) /* directory */
528 #define S_ISCHR(m) (((m) & 0170000) == 0020000) /* char special */
529 #define S_ISBLK(m) (((m) & 0170000) == 0060000) /* block special */
530 #define S_ISREG(m) (((m) & 0170000) == 0100000) /* regular file */
531 #define S_ISFIFO(m) (((m) & 0170000) == 0010000) /* fifo or socket */
532 #define S_ISLNK(m) (((m) & 0170000) == 0120000) /* symbolic link */
533 #define S_ISSOCK(m) (((m) & 0170000) == 0140000) /* socket */
534 #define S_ISWHT(m) (((m) & 0170000) == 0160000) /* whiteout */
536 #define S_BLKSIZE 512 /* block size used in the stat struct */