blob: 38ba2a3ae6cf735c61f0b41ed2e077ac97455716 [file] [log] [blame]
/*
* Copyright (c) 2000-2001 Silicon Graphics, Inc.
* All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it would be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef CONTENT_INODE_H
#define CONTENT_INODE_H
/* content_inode.h - inode-style content strategy-specific header structure
*/
/* dump startpoint: identifies dump stream boundaries
* NOTE: sp_offset is not a position within a file; it is a quantity of
* bytes to skip. holes do not count.
*/
struct startpt {
xfs_ino_t sp_ino; /* first inode to dump */
off64_t sp_offset; /* bytes to skip in file data fork */
int32_t sp_flags;
int32_t sp_pad1;
};
typedef struct startpt startpt_t;
#define STARTPT_FLAGS_END ( 1 << 0 )
/* this startpt indicates that all extents of all files in
* the stream were completely dumped. the other fields
* are meaningless. this will appear only once per dump
* stream, even if the stream spans multiple media files.
*
* also used in the strategy-specific portion of the
* content header to qualify the ending point.
*/
#define STARTPT_FLAGS_NULL ( 1 << 1 )
/* used to detect if the null file header makes it onto
* media. only necessary after the last file in the stream,
* to allow the end-of-stream flag in the null header to
* be seen.
*/
/* drange_t - describes a range of ino/offset values
*/
struct drange {
startpt_t dr_begin;
startpt_t dr_end;
};
typedef struct drange drange_t;
/* inode-style specific media file header section
*/
#define CONTENT_INODE_HDR_SZ sizeofmember( content_hdr_t, ch_specific )
struct content_inode_hdr {
int32_t cih_mediafiletype; /* 4 4 */
/* dump media file type: see #defines below */
int32_t cih_dumpattr; /* 4 8 */
/* dump attributes: see #defines below */
int32_t cih_level; /* 4 c */
/* dump level */
char pad1[ 4 ]; /* 4 10 */
/* alignment */
time32_t cih_last_time; /* 4 14 */
/* if an incremental,time of previous dump at a lesser level */
time32_t cih_resume_time; /* 4 18 */
/* if a resumed dump, time of interrupted dump */
xfs_ino_t cih_rootino; /* 8 20 */
/* root inode number */
uuid_t cih_last_id; /* 10 30 */
/* if an incremental, uuid of prev dump */
uuid_t cih_resume_id; /* 10 40 */
/* if a resumed dump, uuid of interrupted dump */
startpt_t cih_startpt; /* 18 58 */
/* starting point of media file contents */
startpt_t cih_endpt; /* 18 70 */
/* starting point of next stream */
uint64_t cih_inomap_hnkcnt; /* 8 78 */
uint64_t cih_inomap_segcnt; /* 8 80 */
uint64_t cih_inomap_dircnt; /* 8 88 */
uint64_t cih_inomap_nondircnt; /* 8 90 */
xfs_ino_t cih_inomap_firstino; /* 8 98 */
xfs_ino_t cih_inomap_lastino; /* 8 a0 */
uint64_t cih_inomap_datasz; /* 8 a8 */
/* bytes of non-metadata dumped */
char cih_pad2[ CONTENT_INODE_HDR_SZ - 0xa8 ]; /* 18 c0 */
/* padding */
};
typedef struct content_inode_hdr content_inode_hdr_t;
/* media file types
*/
#define CIH_MEDIAFILETYPE_DATA 0
#define CIH_MEDIAFILETYPE_INVENTORY 1
#define CIH_MEDIAFILETYPE_INDEX 2
/* dump attributes
*/
#define CIH_DUMPATTR_SUBTREE ( 1 << 0 )
#define CIH_DUMPATTR_INDEX ( 1 << 1 )
#define CIH_DUMPATTR_INVENTORY ( 1 << 2 )
#define CIH_DUMPATTR_INCREMENTAL ( 1 << 3 )
#define CIH_DUMPATTR_RETRY ( 1 << 4 )
#define CIH_DUMPATTR_RESUME ( 1 << 5 )
#define CIH_DUMPATTR_INOMAP ( 1 << 6 )
#define CIH_DUMPATTR_DIRDUMP ( 1 << 7 )
#define CIH_DUMPATTR_FILEHDR_CHECKSUM ( 1 << 8 )
#define CIH_DUMPATTR_EXTENTHDR_CHECKSUM ( 1 << 9 )
#define CIH_DUMPATTR_DIRENTHDR_CHECKSUM ( 1 << 10 )
#define CIH_DUMPATTR_DIRENTHDR_GEN ( 1 << 11 )
#define CIH_DUMPATTR_EXTATTR ( 1 << 12 )
#define CIH_DUMPATTR_EXTATTRHDR_CHECKSUM ( 1 << 13 )
#define CIH_DUMPATTR_NOTSELFCONTAINED ( 1 << 14 )
/* timestruct_t - time structure
*
* used in bstat_t below. derived from timestruc_t, to achieve independence
* from changes to timestruc_t.
*/
#define TIMESTRUCT_SZ 8
struct timestruct { /* bytes accum */
int32_t tv_sec; /* seconds 4 4 */
int32_t tv_nsec; /* and nanoseconds 4 8 */
};
typedef struct timestruct timestruct_t;
/* bstat_t - bulk stat structure
*
* used in filehdr_t below. derived from xfs_bstat_t, to achieve independence
* from changes to xfs_bstat_t.
*/
#define BSTAT_SZ 128
#define MODE_SZ 4
struct bstat { /* bytes accum */
xfs_ino_t bs_ino; /* inode number 8 8 */
uint32_t bs_mode; /* type and mode 4 c */
uint32_t bs_nlink; /* number of links 4 10 */
int32_t bs_uid; /* user id 4 14 */
int32_t bs_gid; /* group id 4 18 */
uint32_t bs_rdev; /* device value 4 1c */
int32_t bs_blksize; /* block size 4 20 */
off64_t bs_size; /* file size 8 28 */
timestruct_t bs_atime; /* access time 8 30 */
timestruct_t bs_mtime; /* modify time 8 38 */
timestruct_t bs_ctime; /* inode change time 8 40 */
int64_t bs_blocks; /* number of blocks 8 48 */
uint32_t bs_xflags; /* extended flags 4 4c */
int32_t bs_extsize; /* extent size 4 50 */
int32_t bs_extents; /* number of extents 4 54 */
uint32_t bs_gen; /* generation count 4 58 */
uint16_t bs_projid_lo; /* low 16 of project id 2 5a */
uint16_t bs_forkoff; /* inode fork offset 2 5c */
uint16_t bs_projid_hi; /* hi 16 of project id 2 5e */
char bs_pad[ 10 ]; /* for expansion e 68 */
uint32_t bs_dmevmask; /* DMI event mask 4 6c */
uint16_t bs_dmstate; /* DMI state info 2 6e */
char bs_pad1[ 18 ]; /* for expansion 12 80 */
/* NOTE: old dumps didn't always
* zero first 2 bytes of bs_pad1 */
};
typedef struct bstat bstat_t;
/*
* Project quota id helpers (previously projid was 16bit only
* and using two 16bit values to hold new 32bit projid was choosen
* to retain compatibility with "old" filesystems).
*/
static inline uint32_t
bstat_projid(struct bstat *bs)
{
return (uint32_t)bs->bs_projid_hi << 16 | bs->bs_projid_lo;
}
/* extended inode flags that can only be set after all data
* has been restored to a file.
*/
#define POST_DATA_XFLAGS ( XFS_XFLAG_IMMUTABLE | \
XFS_XFLAG_APPEND | \
XFS_XFLAG_SYNC )
/* filehdr_t - header placed at the beginning of every dumped file.
*
* each fs file placed on dump media begins with a FILEHDR_SZ-byte header.
* following that are one or more variable-length content extents.
* the content extents contain the actual data associated with the fs file.
*/
#define FILEHDR_SZ 256
struct filehdr {
int64_t fh_offset;
int32_t fh_flags;
uint32_t fh_checksum;
bstat_t fh_stat;
char fh_pad2[ FILEHDR_SZ
- sizeof( int64_t )
- sizeof( int32_t )
- sizeof( uint32_t )
- sizeof( bstat_t ) ];
};
typedef struct filehdr filehdr_t;
#define FILEHDR_FLAGS_NULL ( 1 << 0 )
/* identifies a dummy file header. every media file
* is terminated with a dummy file header, unless
* terminated by end of media.
*/
#define FILEHDR_FLAGS_CHECKSUM ( 1 << 1 )
/* indicates the header checksum is valid
*/
#define FILEHDR_FLAGS_END ( 1 << 2 )
/* the last media file in the stream is always terminated by
* a dummy file header, with this flag set.
*/
#define FILEHDR_FLAGS_EXTATTR ( 1 << 3 )
/* special file header followed by one file's (dir or nondir)
* extended attributes.
*/
/* extenthdr_t - a header placed at the beginning of every dumped
* content extent.
*
* a dumped file consists of a filehdr_t followed by zero or more
* extents. for regular files the last extent is always of type LAST.
* for symbolic link files, only one extent is dumped, and it contains the
* symlink path.
*/
#define EXTENTHDR_SZ 32
struct extenthdr {
off64_t eh_sz; /* length of extent, NOT including header, in bytes */
off64_t eh_offset;
int32_t eh_type;
int32_t eh_flags;
uint32_t eh_checksum;
char eh_pad[ 4 ];
};
typedef struct extenthdr extenthdr_t;
#define EXTENTHDR_TYPE_LAST 0
/* always the last extent. sz is always 0
*/
#define EXTENTHDR_TYPE_ALIGN 1
/* used for alignment. sz is the number of bytes to skip,
* in addition to the hdr
*/
#define EXTENTHDR_TYPE_DATA 4
/* heads an extent of ordinary file data. sz is the data
* extent length in bytes, NOT including the hdr. offset
* indicates the byte position of the extent within the file.
* also heads the path in a symlink dump.
*/
#define EXTENTHDR_TYPE_HOLE 8
/* used to encode a hole extent. Offset indicates the byte
* position of the hole within the file and sz is the
* hole extent length.
*/
#define EXTENTHDR_FLAGS_CHECKSUM ( 1 << 0 )
/* direnthdr_t - placed at the beginning of every dumped directory entry.
* a directory entry consists of the fixed size header followed by a variable
* length NULL-terminated name string, followed by enough padding to make the
* overall record size a multiple of 8 bytes. the name string begins
* at the dh_name field. the total number of bytes occupied by
* each directory entry on media is dh_sz.
*
* a sequence of directory entries is always terminated with a null direnthdr_t.
* this is detected by looking for a zero ino.
*/
typedef uint32_t gen_t;
#define DIRENTHDR_ALIGN 8
#define DIRENTHDR_SZ 24
struct direnthdr {
xfs_ino_t dh_ino;
gen_t dh_gen;
uint32_t dh_checksum;
uint16_t dh_sz; /* overall size of record */
char dh_name[ 6 ];
};
typedef struct direnthdr direnthdr_t;
/* the old direnthdr truncated the inode generation number
* to the low 12 bits.
*/
struct direnthdr_v1 {
xfs_ino_t dh_ino;
uint16_t dh_gen; /* generation count & DENTGENMASK of ref'ed inode */
uint16_t dh_sz; /* overall size of record */
uint32_t dh_checksum;
char dh_name[ 8 ];
};
typedef struct direnthdr_v1 direnthdr_v1_t;
/* truncated generation count
*/
#define DENTGENSZ 12 /* leave 4 bits for future flags */
#define DENTGENMASK (( 1 << DENTGENSZ ) - 1 )
#define BIGGEN2GEN( bg ) ( ( gen_t )( bg & DENTGENMASK ))
/* symbolic links will be dumped using an extent header. the extent
* will always be a multiple of SYMLINK_ALIGN bytes. the symlink character
* string will always be null-terminated.
*/
#define SYMLINK_ALIGN 8
/* extattr_hdr_t - hdr for an extended attribute. the first byte of the
* attribute name immediately follows the header. the name is terminated
* with a NULL byte. Each extattr record will be aligned; there may
* be padding at the end of each record to achieve this. NOTE: ah_sz
* includes the hdr sz; adding ah_sz to the offset of one extattr
* gives the offset of the next.
*/
#define EXTATTRHDR_SZ 16
#define EXTATTRHDR_ALIGN 8
struct extattrhdr {
uint32_t ah_sz; /* overall size of extended attribute record */
uint16_t ah_valoff; /* byte offset within record of value */
uint16_t ah_flags; /* see EXTATTRHDR_FLAGS_... below */
uint32_t ah_valsz; /* size of value */
uint32_t ah_checksum; /* hdr checksum */
};
typedef struct extattrhdr extattrhdr_t;
#define EXTATTRHDR_FLAGS_ROOT ( 1 << 0 )
/* a "root" mode attribute
*/
#define EXTATTRHDR_FLAGS_NULL ( 1 << 1 )
/* marks the end of the attributes associated with the leading filehdr_t
*/
#define EXTATTRHDR_FLAGS_OLD_CHECKSUM ( 1 << 2 )
/* old xfsdumps used this flag to indicate a checksum is present,
* but the checksum was not calculated properly. the presence of
* this flag now indicates a checksum that cannot be verified.
*/
#define EXTATTRHDR_FLAGS_SECURE ( 1 << 3 )
/* a linux "secure" mode attribute
*/
#define EXTATTRHDR_FLAGS_CHECKSUM ( 1 << 4 )
/* checksum is present.
*/
/* Routines for calculating and validating checksums on xfsdump headers.
* The header length must be an integral number of uint32_t's.
*/
static inline uint32_t
calc_checksum(void *bufp, size_t len)
{
uint32_t sum = 0;
uint32_t *sump = bufp;
uint32_t *endp = sump + len / sizeof(uint32_t);
assert(len % sizeof(uint32_t) == 0);
while (sump < endp)
sum += *sump++;
return ~sum + 1;
}
static inline bool_t
is_checksum_valid(void *bufp, size_t len)
{
uint32_t sum = 0;
uint32_t *sump = bufp;
uint32_t *endp = sump + len / sizeof(uint32_t);
assert(len % sizeof(uint32_t) == 0);
while (sump < endp)
sum += *sump++;
return sum == 0 ? BOOL_TRUE : BOOL_FALSE;
}
#endif /* CONTENT_INODE_H */