blob: 5da42c66ad6bbd2c768f9e7c48d013457b150128 [file] [log] [blame]
Steve Kondike68cb602016-08-28 00:45:36 -07001/*
2 * Declarations for processing log data
3 *
4 * Copyright (c) 2000-2005 Anton Altaparmakov
5 * Copyright (c) 2014-2015 Jean-Pierre Andre
6 */
7
8/*
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program (in the main directory of the NTFS-3G
21 * distribution in the file COPYING); if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
24
25/*
26 * TODO
27 * This file partially duplicates logfile.h (with modifications).
28 * The generic declarations are to be moved to logfile.h, thus
29 * implying adapting (at least) libntfs-3g/logfile.c and
30 * ntfsprogs/ntfsdump_logfile.c, and the declarations specific to
31 * ntfsrecover should be kept in this file.
32 * (removing ntfsdump_logfile.c might also be considered).
33 */
34
35#define getle16(p,x) le16_to_cpu(*(const le16*)((const char*)(p) + (x)))
36#define getle32(p,x) le32_to_cpu(*(const le32*)((const char*)(p) + (x)))
37#define getle64(p,x) le64_to_cpu(*(const le64*)((const char*)(p) + (x)))
38
39#define feedle16(p,x) (*(const le16*)((const char*)(p) + (x)))
40#define feedle32(p,x) (*(const le32*)((const char*)(p) + (x)))
41#define feedle64(p,x) (*(const le64*)((const char*)(p) + (x)))
42
43enum LOG_RECORD_TYPE {
44 LOG_STANDARD = 1,
45 LOG_CHECKPOINT = 2
46} ;
47
48 /* These flags were introduced in Vista in field attribute_flags */
49enum ATTRIBUTE_FLAGS {
50 ACTS_ON_MFT = 2,
51 ACTS_ON_INDX = 8
52} ;
53
54enum ACTIONS {
55 Noop, /* 0 */
56 CompensationlogRecord, /* 1 */
57 InitializeFileRecordSegment, /* 2 */
58 DeallocateFileRecordSegment, /* 3 */
59 WriteEndofFileRecordSegment, /* 4 */
60 CreateAttribute, /* 5 */
61 DeleteAttribute, /* 6 */
62 UpdateResidentValue, /* 7 */
63 UpdateNonResidentValue, /* 8 */
64 UpdateMappingPairs, /* 9 */
65 DeleteDirtyClusters, /* 10 */
66 SetNewAttributeSizes, /* 11 */
67 AddIndexEntryRoot, /* 12 */
68 DeleteIndexEntryRoot, /* 13 */
69 AddIndexEntryAllocation, /* 14 */
70 DeleteIndexEntryAllocation, /* 15 */
71 WriteEndOfIndexBuffer, /* 16 */
72 SetIndexEntryVcnRoot, /* 17 */
73 SetIndexEntryVcnAllocation, /* 18 */
74 UpdateFileNameRoot, /* 19 */
75 UpdateFileNameAllocation, /* 20 */
76 SetBitsInNonResidentBitMap, /* 21 */
77 ClearBitsInNonResidentBitMap, /* 22 */
78 HotFix, /* 23 */
79 EndTopLevelAction, /* 24 */
80 PrepareTransaction, /* 25 */
81 CommitTransaction, /* 26 */
82 ForgetTransaction, /* 27 */
83 OpenNonResidentAttribute, /* 28 */
84 OpenAttributeTableDump, /* 29 */
85 AttributeNamesDump, /* 30 */
86 DirtyPageTableDump, /* 31 */
87 TransactionTableDump, /* 32 */
88 UpdateRecordDataRoot, /* 33 */
89 UpdateRecordDataAllocation, /* 34 */
90 Win10Action35, /* 35 */
91 Win10Action36, /* 36 */
92 Win10Action37, /* 37 */
93 LastAction /* 38 */
94} ;
95
96 /* Flags for field log_record_flags, their meaning is unclear */
97enum RECORD_FLAGS {
98 RECORD_UNKNOWN = 1,
99 /* The flags below were introduced in Windows 10 */
100 RECORD_DELETING = 2,
101 RECORD_ADDING = 4
102} ;
103typedef le16 LOG_RECORD_FLAGS;
104
105#define LOGFILE_NO_CLIENT const_cpu_to_le16(0xffff)
106#define RESTART_VOLUME_IS_CLEAN const_cpu_to_le16(0x0002)
107
108/* ntfsdoc p 39 (47), not in layout.h */
109
110typedef struct RESTART_PAGE_HEADER { /* size 32 */
111 NTFS_RECORD head;
112 leLSN chkdsk_lsn;
113 le32 system_page_size;
114 le32 log_page_size;
115 le16 restart_offset;
116 le16 minor_ver;
117 le16 major_ver;
118 le16 usn;
119} __attribute__((__packed__)) RESTART_PAGE_HEADER;
120
121/* ntfsdoc p 40 (48), not in layout.h */
122
123struct RESTART_AREA { /* size 44 */
124 leLSN current_lsn;
125 le16 log_clients;
126 le16 client_free_list;
127 le16 client_in_use_list;
128 le16 flags;
129 le32 seq_number_bits;
130 le16 restart_area_length;
131 le16 client_array_offset;
132 le64 file_size;
133 le32 last_lsn_data_length;
134 le16 record_length;
135 le16 log_page_data_offset;
136 le32 restart_log_open_count;
137} __attribute__((__packed__)) ;
138
139typedef struct RESTART_CLIENT { /* size 160 */
140/*Ofs*/
141/* 0*/ leLSN oldest_lsn; /* Oldest LSN needed by this client. On create
142 set to 0. */
143/* 8*/ leLSN client_restart_lsn;/* LSN at which this client needs to restart
144 the volume, i.e. the current position within
145 the log file. At present, if clean this
146 should = current_lsn in restart area but it
147 probably also = current_lsn when dirty most
148 of the time. At create set to 0. */
149/* 16*/ le16 prev_client; /* The offset to the previous log client record
150 in the array of log client records.
151 LOGFILE_NO_CLIENT means there is no previous
152 client record, i.e. this is the first one.
153 This is always LOGFILE_NO_CLIENT. */
154/* 18*/ le16 next_client; /* The offset to the next log client record in
155 the array of log client records.
156 LOGFILE_NO_CLIENT means there are no next
157 client records, i.e. this is the last one.
158 This is always LOGFILE_NO_CLIENT. */
159/* 20*/ le16 seq_number; /* On Win2k and presumably earlier, this is set
160 to zero every time the logfile is restarted
161 and it is incremented when the logfile is
162 closed at dismount time. Thus it is 0 when
163 dirty and 1 when clean. On WinXP and
164 presumably later, this is always 0. */
165/* 22*/ u8 reserved[6]; /* Reserved/alignment. */
166/* 28*/ le32 client_name_length;/* Length of client name in bytes. Should
167 always be 8. */
168/* 32*/ le16 client_name[64]; /* Name of the client in Unicode. Should
169 always be "NTFS" with the remaining bytes
170 set to 0. */
171/* sizeof() = 160 (0xa0) bytes */
172} __attribute__((__packed__)) LOG_CLIENT_RECORD;
173
174/* ntfsdoc p 41 (49), not in layout.h */
175
176struct RECORD_PAGE_HEADER { /* size 40 */
177 NTFS_RECORD head; /* the magic is "RCRD" */
178 union {
179 leLSN last_lsn;
180 le32 file_offset;
181 } __attribute__((__packed__)) copy;
182 le32 flags;
183 le16 page_count;
184 le16 page_position;
185 le16 next_record_offset;
186 le16 reserved4[3];
187 leLSN last_end_lsn;
188} __attribute__((__packed__)) ;
189
190/* ntfsdoc p 42 (50), not in layout.h */
191
192#define LOG_RECORD_HEAD_SZ 0x30 /* size of header of struct LOG_RECORD */
193
194typedef struct LOG_RECORD { /* size 80 */
195 leLSN this_lsn;
196 leLSN client_previous_lsn;
197 leLSN client_undo_next_lsn;
198 le32 client_data_length;
199 struct {
200 le16 seq_number;
201 le16 client_index;
202 } __attribute__((__packed__)) client_id;
203 le32 record_type;
204 le32 transaction_id;
205 LOG_RECORD_FLAGS log_record_flags;
206 le16 reserved1[3];
207 le16 redo_operation;
208 le16 undo_operation;
209 le16 redo_offset;
210 le16 redo_length;
211 union {
212 struct {
213 le16 undo_offset;
214 le16 undo_length;
215 le16 target_attribute;
216 le16 lcns_to_follow;
217 le16 record_offset;
218 le16 attribute_offset;
219 le16 cluster_index;
220 le16 attribute_flags;
221 le32 target_vcn;
222 le32 reserved3;
223 le64 lcn_list[0];
224 } __attribute__((__packed__));
225 struct {
226 leLSN transaction_lsn;
227 leLSN attributes_lsn;
228 leLSN names_lsn;
229 leLSN dirty_pages_lsn;
230 le64 unknown_list[0];
231 } __attribute__((__packed__));
232 } __attribute__((__packed__));
233} __attribute__((__packed__)) LOG_RECORD;
234
235struct BUFFER {
236 unsigned int num;
237 unsigned int size;
238 unsigned int headsz;
239 BOOL safe;
240 union {
241 struct RESTART_PAGE_HEADER restart;
242 struct RECORD_PAGE_HEADER record;
243 char data[1];
244 } block; /* variable length, keep at the end */
245} ;
246
247struct ACTION_RECORD {
248 struct ACTION_RECORD *next;
249 struct ACTION_RECORD *prev;
250 int num;
251 unsigned int flags;
252 struct LOG_RECORD record; /* variable length, keep at the end */
253} ;
254
255enum { /* Flag values for ACTION_RECORD */
256 ACTION_TO_REDO = 1 /* Committed, possibly not synced */
257 } ;
258
259struct ATTR {
260 u64 inode;
261 u64 lsn;
262 le32 type;
263 u16 key;
264 u16 namelen;
265 le16 name[1];
266} ;
267
268struct BITMAP_ACTION {
269 le32 firstbit;
270 le32 count;
271} ;
272
273/* Danger in arrays : contains le64's though size is not a multiple of 8 */
274typedef struct ATTR_OLD { /* Format up to Win10 (44 bytes) */
275 le64 unknown1;
276 le64 unknown2;
277 le64 inode;
278 leLSN lsn;
279 le32 unknown3;
280 le32 type;
281 le32 unknown4;
282} __attribute__((__packed__)) ATTR_OLD;
283
284typedef struct ATTR_NEW { /* Format since Win10 (40 bytes) */
285 le64 unknown1;
286 le64 unknown2;
287 le32 type;
288 le32 unknown3;
289 le64 inode;
290 leLSN lsn;
291} __attribute__((__packed__)) ATTR_NEW;
292
293extern u32 clustersz;
294extern int clusterbits;
295extern u32 blocksz;
296extern int blockbits;
297extern u16 bytespersect;
298extern u64 mftlcn;
299extern u32 mftrecsz;
300extern int mftrecbits;
301extern u32 mftcnt; /* number of entries */
302extern BOOL optc;
303extern BOOL optn;
304extern int opts;
305extern int optv;
306extern unsigned int redocount;
307extern unsigned int undocount;
308extern ntfs_inode *log_ni;
309extern ntfs_attr *log_na;
310extern u64 logfilelcn;
311extern u32 logfilesz; /* bytes */
312extern u64 redos_met;
313extern u64 committed_lsn;
314extern u64 synced_lsn;
315extern u64 latest_lsn;
316extern u64 restart_lsn;
317
318extern struct RESTART_AREA restart;
319extern struct RESTART_CLIENT client;
320
321const char *actionname(int op);
322const char *mftattrname(ATTR_TYPES attr);
323void showname(const char *prefix, const char *name, int cnt);
324int fixnamelen(const char *name, int len);
325BOOL within_lcn_range(const struct LOG_RECORD *logr);
326struct ATTR *getattrentry(unsigned int key, unsigned int lth);
327void copy_attribute(struct ATTR *pa, const char *buf, int length);
328u32 get_undo_offset(const struct LOG_RECORD *logr);
329u32 get_redo_offset(const struct LOG_RECORD *logr);
330u32 get_extra_offset(const struct LOG_RECORD *logr);
331BOOL exception(int num);
332
333struct STORE;
334BOOL ntfs_check_logfile(ntfs_attr *log_na, RESTART_PAGE_HEADER **rp);
335extern int play_undos(ntfs_volume *vol, const struct ACTION_RECORD *firstundo);
336extern int play_redos(ntfs_volume *vol, const struct ACTION_RECORD *firstredo);
337extern void show_redos(void);
338extern void freeclusterentry(struct STORE*);
339void hexdump(const char *buf, unsigned int lth);