1N/A/*
1N/A * attrib.h - Exports for attribute handling. Part of the Linux-NTFS project.
1N/A *
1N/A * Copyright (c) 2000-2004 Anton Altaparmakov
1N/A * Copyright (c) 2004-2007 Yura Pakhuchiy
1N/A *
1N/A * This program/include file is free software; you can redistribute it and/or
1N/A * modify it under the terms of the GNU General Public License as published
1N/A * by the Free Software Foundation; either version 2 of the License, or
1N/A * (at your option) any later version.
1N/A *
1N/A * This program/include file is distributed in the hope that it will be
1N/A * useful, but WITHOUT ANY WARRANTY; without even the implied warranty
1N/A * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1N/A * GNU General Public License for more details.
1N/A *
1N/A * You should have received a copy of the GNU General Public License
1N/A * along with this program (in the main directory of the Linux-NTFS
1N/A * distribution in the file COPYING); if not, write to the Free Software
1N/A * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1N/A */
1N/A
1N/A#ifndef _NTFS_ATTRIB_H
1N/A#define _NTFS_ATTRIB_H
1N/A
1N/A/* Forward declarations */
1N/Atypedef struct _ntfs_attr ntfs_attr;
1N/Atypedef struct _ntfs_attr_search_ctx ntfs_attr_search_ctx;
1N/A
1N/A#include "list.h"
1N/A#include "types.h"
1N/A#include "inode.h"
1N/A#include "unistr.h"
1N/A#include "runlist.h"
1N/A#include "volume.h"
1N/A#include "debug.h"
1N/A#include "logging.h"
1N/A#include "crypto.h"
1N/A
1N/Aextern ntfschar AT_UNNAMED[];
1N/A
1N/A/**
1N/A * enum ntfs_lcn_special_values - special return values for ntfs_*_vcn_to_lcn()
1N/A *
1N/A * Special return values for ntfs_rl_vcn_to_lcn() and ntfs_attr_vcn_to_lcn().
1N/A *
1N/A * TODO: Describe them.
1N/A */
1N/Atypedef enum {
1N/A LCN_HOLE = -1, /* Keep this as highest value or die! */
1N/A LCN_RL_NOT_MAPPED = -2,
1N/A LCN_ENOENT = -3,
1N/A LCN_EINVAL = -4,
1N/A LCN_EIO = -5,
1N/A} ntfs_lcn_special_values;
1N/A
1N/A/**
1N/A * struct ntfs_attr_search_ctx - search context used in attribute search functions
1N/A * @mrec: buffer containing mft record to search
1N/A * @attr: attribute record in @mrec where to begin/continue search
1N/A * @is_first: if true lookup_attr() begins search with @attr, else after @attr
1N/A *
1N/A * Structure must be initialized to zero before the first call to one of the
1N/A * attribute search functions. Initialize @mrec to point to the mft record to
1N/A * search, and @attr to point to the first attribute within @mrec (not necessary
1N/A * if calling the _first() functions), and set @is_first to TRUE (not necessary
1N/A * if calling the _first() functions).
1N/A *
1N/A * If @is_first is TRUE, the search begins with @attr. If @is_first is FALSE,
1N/A * the search begins after @attr. This is so that, after the first call to one
1N/A * of the search attribute functions, we can call the function again, without
1N/A * any modification of the search context, to automagically get the next
1N/A * matching attribute.
1N/A */
1N/Astruct _ntfs_attr_search_ctx {
1N/A MFT_RECORD *mrec;
1N/A ATTR_RECORD *attr;
1N/A BOOL is_first;
1N/A ntfs_inode *ntfs_ino;
1N/A ATTR_LIST_ENTRY *al_entry;
1N/A ntfs_inode *base_ntfs_ino;
1N/A MFT_RECORD *base_mrec;
1N/A ATTR_RECORD *base_attr;
1N/A};
1N/A
1N/Aextern void ntfs_attr_reinit_search_ctx(ntfs_attr_search_ctx *ctx);
1N/Aextern ntfs_attr_search_ctx *ntfs_attr_get_search_ctx(ntfs_inode *ni,
1N/A MFT_RECORD *mrec);
1N/Aextern void ntfs_attr_put_search_ctx(ntfs_attr_search_ctx *ctx);
1N/A
1N/Aextern int ntfs_attr_lookup(const ATTR_TYPES type, const ntfschar *name,
1N/A const u32 name_len, const IGNORE_CASE_BOOL ic,
1N/A const VCN lowest_vcn, const u8 *val, const u32 val_len,
1N/A ntfs_attr_search_ctx *ctx);
1N/A
1N/Aextern ATTR_DEF *ntfs_attr_find_in_attrdef(const ntfs_volume *vol,
1N/A const ATTR_TYPES type);
1N/A
1N/A/**
1N/A * ntfs_attrs_walk - syntactic sugar for walking all attributes in an inode
1N/A * @ctx: initialised attribute search context
1N/A *
1N/A * Syntactic sugar for walking attributes in an inode.
1N/A *
1N/A * Return 0 on success and -1 on error with errno set to the error code from
1N/A * ntfs_attr_lookup().
1N/A *
1N/A * Example: When you want to enumerate all attributes in an open ntfs inode
1N/A * @ni, you can simply do:
1N/A *
1N/A * int err;
1N/A * ntfs_attr_search_ctx *ctx = ntfs_attr_get_search_ctx(ni, NULL);
1N/A * if (!ctx)
1N/A * // Error code is in errno. Handle this case.
1N/A * while (!(err = ntfs_attrs_walk(ctx))) {
1N/A * ATTR_RECORD *attr = ctx->attr;
1N/A * // attr now contains the next attribute. Do whatever you want
1N/A * // with it and then just continue with the while loop.
1N/A * }
1N/A * if (err && errno != ENOENT)
1N/A * // Ooops. An error occurred! You should handle this case.
1N/A * // Now finished with all attributes in the inode.
1N/A */
1N/Astatic __inline__ int ntfs_attrs_walk(ntfs_attr_search_ctx *ctx)
1N/A{
1N/A return ntfs_attr_lookup(AT_UNUSED, NULL, 0, CASE_SENSITIVE, 0,
1N/A NULL, 0, ctx);
1N/A}
1N/A
1N/A/**
1N/A * struct ntfs_attr - ntfs in memory non-resident attribute structure
1N/A * @rl: if not NULL, the decompressed runlist
1N/A * @ni: base ntfs inode to which this attribute belongs
1N/A * @type: attribute type
1N/A * @name: Unicode name of the attribute
1N/A * @name_len: length of @name in Unicode characters
1N/A * @state: NTFS attribute specific flags describing this attribute
1N/A * @allocated_size: copy from the attribute record
1N/A * @data_size: copy from the attribute record
1N/A * @initialized_size: copy from the attribute record
1N/A * @compressed_size: copy from the attribute record
1N/A * @compression_block_size: size of a compression block (cb)
1N/A * @compression_block_size_bits: log2 of the size of a cb
1N/A * @compression_block_clusters: number of clusters per cb
1N/A * @crypto: (valid only for encrypted) see description below
1N/A *
1N/A * This structure exists purely to provide a mechanism of caching the runlist
1N/A * of an attribute. If you want to operate on a particular attribute extent,
1N/A * you should not be using this structure at all. If you want to work with a
1N/A * resident attribute, you should not be using this structure at all. As a
1N/A * fail-safe check make sure to test NAttrNonResident() and if it is false, you
1N/A * know you shouldn't be using this structure.
1N/A *
1N/A * If you want to work on a resident attribute or on a specific attribute
1N/A * extent, you should use ntfs_lookup_attr() to retrieve the attribute (extent)
1N/A * record, edit that, and then write back the mft record (or set the
1N/A * corresponding ntfs inode dirty for delayed write back).
1N/A *
1N/A * @rl is the decompressed runlist of the attribute described by this
1N/A * structure. Obviously this only makes sense if the attribute is not resident,
1N/A * i.e. NAttrNonResident() is true. If the runlist hasn't been decompressed yet
1N/A * @rl is NULL, so be prepared to cope with @rl == NULL.
1N/A *
1N/A * @ni is the base ntfs inode of the attribute described by this structure.
1N/A *
1N/A * @type is the attribute type (see layout.h for the definition of ATTR_TYPES),
1N/A * @name and @name_len are the little endian Unicode name and the name length
1N/A * in Unicode characters of the attribute, respectively.
1N/A *
1N/A * @state contains NTFS attribute specific flags describing this attribute
1N/A * structure. See ntfs_attr_state_bits above.
1N/A *
1N/A * @crypto points to private structure of crypto code. You should not access
1N/A * fields of this structure, but you can check whether it is NULL or not. If it
1N/A * is not NULL, then we successfully obtained FEK (File Encryption Key) and
1N/A * ntfs_attr_p{read,write} calls probably would succeed. If it is NULL, then we
1N/A * failed to obtain FEK (do not have corresponding PFX file, wrong password,
1N/A * etc..) or library was compiled without crypto support. Attribute size can be
1N/A * changed without knowledge of FEK, so you can use ntfs_attr_truncate in any
1N/A * case.
1N/A * NOTE: This field valid only if attribute encrypted (eg., NAttrEncrypted
1N/A * returns non-zero).
1N/A */
1N/Astruct _ntfs_attr {
1N/A runlist_element *rl;
1N/A ntfs_inode *ni;
1N/A ATTR_TYPES type;
1N/A ntfschar *name;
1N/A u32 name_len;
1N/A unsigned long state;
1N/A s64 allocated_size;
1N/A s64 data_size;
1N/A s64 initialized_size;
1N/A s64 compressed_size;
1N/A u32 compression_block_size;
1N/A u8 compression_block_size_bits;
1N/A u8 compression_block_clusters;
1N/A ntfs_crypto_attr *crypto;
1N/A struct list_head list_entry;
1N/A int nr_references;
1N/A};
1N/A
1N/A/**
1N/A * enum ntfs_attr_state_bits - bits for the state field in the ntfs_attr
1N/A * structure
1N/A */
1N/Atypedef enum {
1N/A NA_Initialized, /* 1: structure is initialized. */
1N/A NA_NonResident, /* 1: Attribute is not resident. */
1N/A} ntfs_attr_state_bits;
1N/A
1N/A#define test_nattr_flag(na, flag) test_bit(NA_##flag, (na)->state)
1N/A#define set_nattr_flag(na, flag) set_bit(NA_##flag, (na)->state)
1N/A#define clear_nattr_flag(na, flag) clear_bit(NA_##flag, (na)->state)
1N/A
1N/A#define NAttrInitialized(na) test_nattr_flag(na, Initialized)
1N/A#define NAttrSetInitialized(na) set_nattr_flag(na, Initialized)
1N/A#define NAttrClearInitialized(na) clear_nattr_flag(na, Initialized)
1N/A
1N/A#define NAttrNonResident(na) test_nattr_flag(na, NonResident)
1N/A#define NAttrSetNonResident(na) set_nattr_flag(na, NonResident)
1N/A#define NAttrClearNonResident(na) clear_nattr_flag(na, NonResident)
1N/A
1N/A#define GenNAttrIno(func_name,flag) \
1N/Astatic inline int NAttr##func_name(ntfs_attr *na) \
1N/A{ \
1N/A if (na->type == AT_DATA && na->name == AT_UNNAMED) \
1N/A return (na->ni->flags & FILE_ATTR_##flag) ? 1 : 0; \
1N/A return 0; \
1N/A} \
1N/Astatic inline void NAttrSet##func_name(ntfs_attr *na) \
1N/A{ \
1N/A if (na->type == AT_DATA && na->name == AT_UNNAMED) \
1N/A na->ni->flags |= FILE_ATTR_##flag; \
1N/A else \
1N/A ntfs_log_trace("BUG! Should be called only for " \
1N/A "unnamed data attribute.\n"); \
1N/A} \
1N/Astatic inline void NAttrClear##func_name(ntfs_attr *na) \
1N/A{ \
1N/A if (na->type == AT_DATA && na->name == AT_UNNAMED) \
1N/A na->ni->flags &= ~FILE_ATTR_##flag; \
1N/A}
1N/A
1N/AGenNAttrIno(Compressed, COMPRESSED)
1N/AGenNAttrIno(Encrypted, ENCRYPTED)
1N/AGenNAttrIno(Sparse, SPARSE_FILE)
1N/A
1N/A#ifndef __sun
1N/A/**
1N/A * union attr_val - Union of all known attribute values
1N/A *
1N/A * For convenience. Used in the attr structure.
1N/A */
1N/Atypedef union {
1N/A u8 _default; /* Unnamed u8 to serve as default when just using
1N/A a_val without specifying any of the below. */
1N/A STANDARD_INFORMATION std_inf;
1N/A ATTR_LIST_ENTRY al_entry;
1N/A FILE_NAME_ATTR filename;
1N/A OBJECT_ID_ATTR obj_id;
1N/A SECURITY_DESCRIPTOR_ATTR sec_desc;
1N/A VOLUME_NAME vol_name;
1N/A VOLUME_INFORMATION vol_inf;
1N/A DATA_ATTR data;
1N/A INDEX_ROOT index_root;
1N/A INDEX_BLOCK index_blk;
1N/A BITMAP_ATTR bmp;
1N/A REPARSE_POINT reparse;
1N/A EA_INFORMATION ea_inf;
1N/A EA_ATTR ea;
1N/A PROPERTY_SET property_set;
1N/A LOGGED_UTILITY_STREAM logged_util_stream;
1N/A EFS_ATTR_HEADER efs;
1N/A} attr_val;
1N/A#endif /* __sun */
1N/A
1N/Aextern void ntfs_attr_init(ntfs_attr *na, const BOOL non_resident,
1N/A const BOOL compressed, const BOOL encrypted, const BOOL sparse,
1N/A const s64 allocated_size, const s64 data_size,
1N/A const s64 initialized_size, const s64 compressed_size,
1N/A const u8 compression_unit);
1N/A
1N/Aextern ntfs_attr *ntfs_attr_open(ntfs_inode *ni, const ATTR_TYPES type,
1N/A ntfschar *name, u32 name_len);
1N/Aextern void ntfs_attr_close(ntfs_attr *na);
1N/A
1N/Aextern s64 ntfs_attr_pread(ntfs_attr *na, const s64 pos, s64 count,
1N/A void *b);
1N/Aextern s64 ntfs_attr_pwrite(ntfs_attr *na, const s64 pos, s64 count,
1N/A const void *b);
1N/A
1N/Aextern void *ntfs_attr_readall(ntfs_inode *ni, const ATTR_TYPES type,
1N/A ntfschar *name, u32 name_len, s64 *data_size);
1N/A
1N/Aextern s64 ntfs_attr_mst_pread(ntfs_attr *na, const s64 pos,
1N/A const s64 bk_cnt, const u32 bk_size, void *dst);
1N/Aextern s64 ntfs_attr_mst_pwrite(ntfs_attr *na, const s64 pos,
1N/A s64 bk_cnt, const u32 bk_size, void *src);
1N/A
1N/Aextern int ntfs_attr_map_runlist(ntfs_attr *na, VCN vcn);
1N/Aextern int ntfs_attr_map_runlist_range(ntfs_attr *na, VCN from_vcn, VCN to_vcn);
1N/Aextern int ntfs_attr_map_whole_runlist(ntfs_attr *na);
1N/A
1N/Aextern LCN ntfs_attr_vcn_to_lcn(ntfs_attr *na, const VCN vcn);
1N/Aextern runlist_element *ntfs_attr_find_vcn(ntfs_attr *na, const VCN vcn);
1N/A
1N/Aextern int ntfs_attr_size_bounds_check(const ntfs_volume *vol,
1N/A const ATTR_TYPES type, const s64 size);
1N/Aextern int ntfs_attr_can_be_non_resident(const ntfs_volume *vol,
1N/A const ATTR_TYPES type);
1N/Aextern int ntfs_attr_can_be_resident(const ntfs_volume *vol,
1N/A const ATTR_TYPES type);
1N/A
1N/Aextern int ntfs_make_room_for_attr(MFT_RECORD *m, u8 *pos, u32 size);
1N/A
1N/Aextern int ntfs_resident_attr_record_add(ntfs_inode *ni, ATTR_TYPES type,
1N/A ntfschar *name, u8 name_len, u8 *val, u32 size,
1N/A ATTR_FLAGS flags);
1N/Aextern int ntfs_non_resident_attr_record_add(ntfs_inode *ni, ATTR_TYPES type,
1N/A ntfschar *name, u8 name_len, VCN lowest_vcn, int dataruns_size,
1N/A ATTR_FLAGS flags);
1N/Aextern int ntfs_attr_record_rm(ntfs_attr_search_ctx *ctx);
1N/A
1N/Aextern int ntfs_attr_add(ntfs_inode *ni, ATTR_TYPES type,
1N/A ntfschar *name, u8 name_len, u8 *val, s64 size);
1N/Aextern int ntfs_attr_rm(ntfs_attr *na);
1N/A
1N/Aextern int ntfs_attr_record_resize(MFT_RECORD *m, ATTR_RECORD *a, u32 new_size);
1N/A
1N/Aextern int ntfs_resident_attr_value_resize(MFT_RECORD *m, ATTR_RECORD *a,
1N/A const u32 new_size);
1N/A
1N/Aextern int ntfs_attr_record_move_to(ntfs_attr_search_ctx *ctx, ntfs_inode *ni);
1N/Aextern int ntfs_attr_record_move_away(ntfs_attr_search_ctx *ctx, int extra);
1N/A
1N/Aextern int ntfs_attr_update_mapping_pairs(ntfs_attr *na, VCN from_vcn);
1N/A
1N/Aextern int __ntfs_attr_truncate(ntfs_attr *na, const s64 newsize, BOOL sparse);
1N/Aextern int ntfs_attr_truncate(ntfs_attr *na, const s64 newsize);
1N/A
1N/Aextern int ntfs_attr_exist(ntfs_inode *ni, const ATTR_TYPES type,
1N/A ntfschar *name, u32 name_len);
1N/A
1N/Astatic __inline__ ntfschar *ntfs_attr_get_name(ATTR_RECORD *attr)
1N/A{
1N/A return (ntfschar*)((u8*)attr + le16_to_cpu(attr->name_offset));
1N/A}
1N/A
1N/A// FIXME / TODO: Above here the file is cleaned up. (AIA)
1N/A/**
1N/A * get_attribute_value_length - return the length of the value of an attribute
1N/A * @a: pointer to a buffer containing the attribute record
1N/A *
1N/A * Return the byte size of the attribute value of the attribute @a (as it
1N/A * would be after eventual decompression and filling in of holes if sparse).
1N/A * If we return 0, check errno. If errno is 0 the actual length was 0,
1N/A * otherwise errno describes the error.
1N/A *
1N/A * FIXME: Describe possible errnos.
1N/A */
1N/As64 ntfs_get_attribute_value_length(const ATTR_RECORD *a);
1N/A
1N/A/**
1N/A * get_attribute_value - return the attribute value of an attribute
1N/A * @vol: volume on which the attribute is present
1N/A * @a: attribute to get the value of
1N/A * @b: destination buffer for the attribute value
1N/A *
1N/A * Make a copy of the attribute value of the attribute @a into the destination
1N/A * buffer @b. Note, that the size of @b has to be at least equal to the value
1N/A * returned by get_attribute_value_length(@a).
1N/A *
1N/A * Return number of bytes copied. If this is zero check errno. If errno is 0
1N/A * then nothing was read due to a zero-length attribute value, otherwise
1N/A * errno describes the error.
1N/A */
1N/As64 ntfs_get_attribute_value(const ntfs_volume *vol, const ATTR_RECORD *a,
1N/A u8 *b);
1N/A
1N/A#endif /* defined _NTFS_ATTRIB_H */
1N/A