summaryrefslogtreecommitdiff
path: root/sys/ntfs/ntfs.h
blob: 1bba2d94e11bcf4d62dae9d0a3afd5171b8d07f6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
/*	$OpenBSD: ntfs.h,v 1.19 2022/01/11 03:13:59 jsg Exp $	*/
/*	$NetBSD: ntfs.h,v 1.5 2003/04/24 07:50:19 christos Exp $	*/

/*-
 * Copyright (c) 1998, 1999 Semen Ustimenko
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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.
 *
 *	Id: ntfs.h,v 1.5 1999/05/12 09:42:51 semenu Exp
 */

/*#define NTFS_DEBUG 1*/
typedef u_int64_t cn_t;
typedef u_int16_t wchar;

#define BBSIZE			1024
#define	BBOFF			((off_t)(0))
#define	BBLOCK			0
#define	NTFS_MFTINO		0
#define	NTFS_VOLUMEINO		3
#define	NTFS_ATTRDEFINO		4
#define	NTFS_ROOTINO		5
#define	NTFS_BITMAPINO		6
#define	NTFS_BOOTINO		7
#define	NTFS_BADCLUSINO		8
#define	NTFS_UPCASEINO		10
#define NTFS_MAXFILENAME	255

/*
 * UFS directories use 32bit inode numbers internally, regardless
 * of what the system on top of it uses.
 */
typedef u_int32_t	ntfsino_t;

struct fixuphdr {
	u_int32_t       fh_magic;
	u_int16_t       fh_foff;
	u_int16_t       fh_fnum;
} __packed;

#define NTFS_AF_INRUN	0x00000001
struct attrhdr {
	u_int32_t       a_type;
	u_int32_t       reclen;
	u_int8_t        a_flag;
	u_int8_t        a_namelen;
	u_int8_t        a_nameoff;
	u_int8_t        reserved1;
	u_int8_t        a_compression;
	u_int8_t        reserved2;
	u_int16_t       a_index;
} __packed;
#define NTFS_A_STD	0x10
#define NTFS_A_ATTRLIST	0x20
#define NTFS_A_NAME	0x30
#define NTFS_A_VOLUMENAME	0x60
#define NTFS_A_DATA	0x80
#define	NTFS_A_INDXROOT	0x90
#define	NTFS_A_INDX	0xA0
#define NTFS_A_INDXBITMAP 0xB0

#define NTFS_MAXATTRNAME	255
struct attr {
	struct attrhdr  a_hdr;
	union {
		struct {
			u_int16_t       a_datalen;
			u_int16_t       reserved1;
			u_int16_t       a_dataoff;
			u_int16_t       a_indexed;
		} __packed	a_S_r;
		struct {
			cn_t            a_vcnstart;
			cn_t            a_vcnend;
			u_int16_t       a_dataoff;
			u_int16_t       a_compressalg;
			u_int32_t       reserved1;
			u_int64_t       a_allocated;
			u_int64_t       a_datalen;
			u_int64_t       a_initialized;
		} __packed	a_S_nr;
	}               a_S;
} __packed;
#define a_r	a_S.a_S_r
#define a_nr	a_S.a_S_nr

typedef struct {
	u_int64_t       t_create;
	u_int64_t       t_write;
	u_int64_t       t_mftwrite;
	u_int64_t       t_access;
} __packed ntfs_times_t;

#define NTFS_FFLAG_RDONLY	0x01LL
#define NTFS_FFLAG_HIDDEN	0x02LL
#define NTFS_FFLAG_SYSTEM	0x04LL
#define NTFS_FFLAG_ARCHIVE	0x20LL
#define NTFS_FFLAG_COMPRESSED	0x0800LL
#define NTFS_FFLAG_DIR		0x10000000LL

struct attr_name {
	u_int32_t       n_pnumber;	/* Parent ntnode */
	u_int32_t       reserved;
	ntfs_times_t    n_times;
	u_int64_t       n_size;
	u_int64_t       n_attrsz;
	u_int64_t       n_flag;
	u_int8_t        n_namelen;
	u_int8_t        n_nametype;
	u_int16_t       n_name[1];
} __packed;

#define NTFS_IRFLAG_INDXALLOC	0x00000001
struct attr_indexroot {
	u_int32_t       ir_unkn1;	/* always 0x30 */
	u_int32_t       ir_unkn2;	/* always 0x1 */
	u_int32_t       ir_size;/* ??? */
	u_int32_t       ir_unkn3;	/* number of cluster */
	u_int32_t       ir_unkn4;	/* always 0x10 */
	u_int32_t       ir_datalen;	/* sizeof something */
	u_int32_t       ir_allocated;	/* same as above */
	u_int16_t       ir_flag;/* ?? always 1 */
	u_int16_t       ir_unkn7;
} __packed;

struct attr_attrlist {
	u_int32_t       al_type;	/* Attribute type */
	u_int16_t       reclen;		/* length of this entry */
	u_int8_t        al_namelen;	/* Attribute name len */
	u_int8_t        al_nameoff;	/* Name offset from entry start */
	u_int64_t       al_vcnstart;	/* VCN number */
	u_int32_t       al_inumber;	/* Parent ntnode */
	u_int32_t       reserved;
	u_int16_t       al_index;	/* Attribute index in MFT record */
	u_int16_t       al_name[1];	/* Name */
} __packed;

#define	NTFS_INDXMAGIC	(u_int32_t)(0x58444E49)
struct attr_indexalloc {
	struct fixuphdr ia_fixup;
	u_int64_t       unknown1;
	cn_t            ia_bufcn;
	u_int16_t       ia_hdrsize;
	u_int16_t       unknown2;
	u_int32_t       ia_inuse;
	u_int32_t       ia_allocated;
} __packed;

#define	NTFS_IEFLAG_SUBNODE	0x00000001
#define	NTFS_IEFLAG_LAST	0x00000002

struct attr_indexentry {
	u_int32_t       ie_number;
	u_int32_t       unknown1;
	u_int16_t       reclen;
	u_int16_t       ie_size;
	u_int32_t       ie_flag;/* 1 - has subnodes, 2 - last */
	u_int32_t       ie_fpnumber;
	u_int32_t       unknown2;
	ntfs_times_t    ie_ftimes;
	u_int64_t       ie_fallocated;
	u_int64_t       ie_fsize;
	u_int64_t       ie_fflag;
	u_int8_t        ie_fnamelen;
	u_int8_t        ie_fnametype;
	wchar           ie_fname[NTFS_MAXFILENAME];
	/* cn_t		ie_bufcn;	 buffer with subnodes */
} __packed;

#define	NTFS_FILEMAGIC	(u_int32_t)(0x454C4946)
#define	NTFS_FRFLAG_DIR	0x0002
struct filerec {
	struct fixuphdr fr_fixup;
	u_int8_t        reserved[8];
	u_int16_t       fr_seqnum;	/* Sequence number */
	u_int16_t       fr_nlink;
	u_int16_t       fr_attroff;	/* offset to attributes */
	u_int16_t       fr_flags;	/* 1-nonresident attr, 2-directory */
	u_int32_t       fr_size;/* hdr + attributes */
	u_int32_t       fr_allocated;	/* allocated length of record */
	u_int64_t       fr_mainrec;	/* main record */
	u_int16_t       fr_attrnum;	/* maximum attr number + 1 ??? */
} __packed;

#define	NTFS_ATTRNAME_MAXLEN	0x40
#define	NTFS_ADFLAG_NONRES	0x0080	/* Attrib can be non resident */
#define	NTFS_ADFLAG_INDEX	0x0002	/* Attrib can be indexed */
struct attrdef {
	wchar		ad_name[NTFS_ATTRNAME_MAXLEN];
	u_int32_t	ad_type;
	u_int32_t	reserved1[2];
	u_int32_t	ad_flag;
	u_int64_t	ad_minlen;
	u_int64_t	ad_maxlen;	/* -1 for nonlimited */
} __packed;

struct ntvattrdef {
	char		ad_name[0x40];
	int		ad_namelen;
	u_int32_t	ad_type;
} __packed;

#define	NTFS_BBID	"NTFS    "
#define	NTFS_BBIDLEN	8
struct bootfile {
	u_int8_t        reserved1[3];	/* asm jmp near ... */
	u_int8_t        bf_sysid[8];	/* 'NTFS    ' */
	u_int16_t       bf_bps;		/* bytes per sector */
	u_int8_t        bf_spc;		/* sectors per cluster */
	u_int8_t        reserved2[7];	/* unused (zeroed) */
	u_int8_t        bf_media;	/* media desc. (0xF8) */
	u_int8_t        reserved3[2];
	u_int16_t       bf_spt;		/* sectors per track */
	u_int16_t       bf_heads;	/* number of heads */
	u_int8_t        reserver4[12];
	u_int64_t       bf_spv;		/* sectors per volume */
	cn_t            bf_mftcn;	/* $MFT cluster number */
	cn_t            bf_mftmirrcn;	/* $MFTMirr cn */
	u_int8_t        bf_mftrecsz;	/* MFT record size (clust) */
					/* 0xF6 indicates 1/4 */
	u_int32_t       bf_ibsz;	/* index buffer size */
	u_int32_t       bf_volsn;	/* volume ser. num. */
} __packed;

typedef wchar (ntfs_wget_func_t)(const char **);
typedef int (ntfs_wput_func_t)(char *, size_t, wchar);
typedef int (ntfs_wcmp_func_t)(wchar, wchar);

/*
 * Maximum number of ntnodes to keep in memory. We do not want to leave
 * large data structures hanging off vnodes indefinitely and the data
 * needed to reload the ntnode should already be in the buffer cache.
 */
#define LOADED_NTNODE_HI 16
struct ntnode;
TAILQ_HEAD(ntnodeq, ntnode);

#define	NTFS_SYSNODESNUM	0x0B
struct ntfsmount {
	struct mount   *ntm_mountp;	/* filesystem vfs structure */
	struct bootfile ntm_bootfile;
	dev_t           ntm_dev;	/* device mounted */
	struct vnode   *ntm_devvp;	/* block device mounted vnode */
	struct vnode   *ntm_sysvn[NTFS_SYSNODESNUM];
	u_int32_t       ntm_bpmftrec;
	uid_t           ntm_uid;
	gid_t           ntm_gid;
	mode_t          ntm_mode;
	u_long          ntm_flag;
	cn_t		ntm_cfree;
	struct ntvattrdef *ntm_ad;
	int		ntm_adnum;
	struct netexport ntm_export;	/* export information */
	ntfs_wget_func_t *ntm_wget;	/* decode string to Unicode string */
	ntfs_wput_func_t *ntm_wput;	/* encode Unicode string to string */
	ntfs_wcmp_func_t *ntm_wcmp;	/* compare to wide characters */
	int		ntm_ntnodes;	/* Number of loaded ntnodes. */
	struct ntnodeq	ntm_ntnodeq;	/* Queue of ntnodes (LRU). */
};

#define ntm_mftcn	ntm_bootfile.bf_mftcn
#define ntm_mftmirrcn	ntm_bootfile.bf_mftmirrcn
#define	ntm_mftrecsz	ntm_bootfile.bf_mftrecsz
#define	ntm_spc		ntm_bootfile.bf_spc
#define	ntm_bps		ntm_bootfile.bf_bps

#define	NTFS_NEXTREC(s, type) ((type)(((caddr_t) s) + (s)->reclen))

/* Convert mount ptr to ntfsmount ptr. */
#define VFSTONTFS(mp)	((struct ntfsmount *)((mp)->mnt_data))
#define VTONT(v)	FTONT(VTOF(v))
#define	VTOF(v)		((struct fnode *)((v)->v_data))
#define	FTOV(f)		((f)->f_vp)
#define	FTONT(f)	((f)->f_ip)
#define ntfs_cntobn(cn)	(daddr_t)((cn) * (ntmp->ntm_spc))
#define ntfs_cntob(cn)	(off_t)((cn) * (ntmp)->ntm_spc * (ntmp)->ntm_bps)
#define ntfs_btocn(off)	(cn_t)((off) / ((ntmp)->ntm_spc * (ntmp)->ntm_bps))
#define ntfs_btocl(off)	(cn_t)((off + ntfs_cntob(1) - 1) / ((ntmp)->ntm_spc * (ntmp)->ntm_bps))
#define ntfs_btocnoff(off)	(off_t)((off) % ((ntmp)->ntm_spc * (ntmp)->ntm_bps))
#define ntfs_bntob(bn)	(int32_t)((bn) * (ntmp)->ntm_bps)

#ifdef _KERNEL
#if defined(NTFS_DEBUG)
extern int ntfs_debug;
#define DNPRINTF(n, x...) do { if(ntfs_debug >= (n)) printf(x); } while(0)
#define DPRINTF(x...) DNPRINTF(1, x)
#define DDPRINTF(x...) DNPRINTF(2, x)
#else /* NTFS_DEBUG */
#define DNPRINTF(n, x...)
#define DPRINTF(x...)
#define DDPRINTF(x...)
#endif

extern const struct vops ntfs_vops;
#endif