1*9663SMark.Logan@Sun.COM /* 2*9663SMark.Logan@Sun.COM * logfile.h - Exports for $LogFile handling. Part of the Linux-NTFS project. 3*9663SMark.Logan@Sun.COM * 4*9663SMark.Logan@Sun.COM * Copyright (c) 2000-2005 Anton Altaparmakov 5*9663SMark.Logan@Sun.COM * Copyright (c) 2005-2007 Yura Pakhuchiy 6*9663SMark.Logan@Sun.COM * 7*9663SMark.Logan@Sun.COM * This program/include file is free software; you can redistribute it and/or 8*9663SMark.Logan@Sun.COM * modify it under the terms of the GNU General Public License as published 9*9663SMark.Logan@Sun.COM * by the Free Software Foundation; either version 2 of the License, or 10*9663SMark.Logan@Sun.COM * (at your option) any later version. 11*9663SMark.Logan@Sun.COM * 12*9663SMark.Logan@Sun.COM * This program/include file is distributed in the hope that it will be 13*9663SMark.Logan@Sun.COM * useful, but WITHOUT ANY WARRANTY; without even the implied warranty 14*9663SMark.Logan@Sun.COM * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15*9663SMark.Logan@Sun.COM * GNU General Public License for more details. 16*9663SMark.Logan@Sun.COM * 17*9663SMark.Logan@Sun.COM * You should have received a copy of the GNU General Public License 18*9663SMark.Logan@Sun.COM * along with this program (in the main directory of the Linux-NTFS 19*9663SMark.Logan@Sun.COM * distribution in the file COPYING); if not, write to the Free Software 20*9663SMark.Logan@Sun.COM * Foundation,Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21*9663SMark.Logan@Sun.COM */ 22*9663SMark.Logan@Sun.COM 23*9663SMark.Logan@Sun.COM #ifndef _NTFS_LOGFILE_H 24*9663SMark.Logan@Sun.COM #define _NTFS_LOGFILE_H 25*9663SMark.Logan@Sun.COM 26*9663SMark.Logan@Sun.COM #include "types.h" 27*9663SMark.Logan@Sun.COM #include "endians.h" 28*9663SMark.Logan@Sun.COM #include "layout.h" 29*9663SMark.Logan@Sun.COM 30*9663SMark.Logan@Sun.COM /* 31*9663SMark.Logan@Sun.COM * Journal ($LogFile) organization: 32*9663SMark.Logan@Sun.COM * 33*9663SMark.Logan@Sun.COM * Two restart areas present in the first two pages (restart pages, one restart 34*9663SMark.Logan@Sun.COM * area in each page). When the volume is dismounted they should be identical, 35*9663SMark.Logan@Sun.COM * except for the update sequence array which usually has a different update 36*9663SMark.Logan@Sun.COM * sequence number. 37*9663SMark.Logan@Sun.COM * 38*9663SMark.Logan@Sun.COM * These are followed by log records organized in pages headed by a log record 39*9663SMark.Logan@Sun.COM * header going up to log file size. Not all pages contain log records when a 40*9663SMark.Logan@Sun.COM * volume is first formatted, but as the volume ages, all records will be used. 41*9663SMark.Logan@Sun.COM * When the log file fills up, the records at the beginning are purged (by 42*9663SMark.Logan@Sun.COM * modifying the oldest_lsn to a higher value presumably) and writing begins 43*9663SMark.Logan@Sun.COM * at the beginning of the file. Effectively, the log file is viewed as a 44*9663SMark.Logan@Sun.COM * circular entity. 45*9663SMark.Logan@Sun.COM * 46*9663SMark.Logan@Sun.COM * NOTE: Windows NT, 2000, and XP all use log file version 1.1 but they accept 47*9663SMark.Logan@Sun.COM * versions <= 1.x, including 0.-1. (Yes, that is a minus one in there!) We 48*9663SMark.Logan@Sun.COM * probably only want to support 1.1 as this seems to be the current version 49*9663SMark.Logan@Sun.COM * and we don't know how that differs from the older versions. The only 50*9663SMark.Logan@Sun.COM * exception is if the journal is clean as marked by the two restart pages 51*9663SMark.Logan@Sun.COM * then it doesn't matter whether we are on an earlier version. We can just 52*9663SMark.Logan@Sun.COM * reinitialize the logfile and start again with version 1.1. 53*9663SMark.Logan@Sun.COM */ 54*9663SMark.Logan@Sun.COM 55*9663SMark.Logan@Sun.COM /* Some $LogFile related constants. */ 56*9663SMark.Logan@Sun.COM #define MaxLogFileSize 0x100000000ULL 57*9663SMark.Logan@Sun.COM #define DefaultLogPageSize 4096 58*9663SMark.Logan@Sun.COM #define MinLogRecordPages 48 59*9663SMark.Logan@Sun.COM 60*9663SMark.Logan@Sun.COM /** 61*9663SMark.Logan@Sun.COM * struct RESTART_PAGE_HEADER - Log file restart page header. 62*9663SMark.Logan@Sun.COM * 63*9663SMark.Logan@Sun.COM * Begins the restart area. 64*9663SMark.Logan@Sun.COM */ 65*9663SMark.Logan@Sun.COM #ifdef __sun 66*9663SMark.Logan@Sun.COM #pragma pack(1) 67*9663SMark.Logan@Sun.COM #endif 68*9663SMark.Logan@Sun.COM typedef struct { 69*9663SMark.Logan@Sun.COM /*Ofs*/ 70*9663SMark.Logan@Sun.COM /* 0 NTFS_RECORD; -- Unfolded here as gcc doesn't like unnamed structs. */ 71*9663SMark.Logan@Sun.COM /* 0*/ NTFS_RECORD_TYPES magic;/* The magic is "RSTR". */ 72*9663SMark.Logan@Sun.COM /* 4*/ le16 usa_ofs; /* See NTFS_RECORD definition in layout.h. 73*9663SMark.Logan@Sun.COM When creating, set this to be immediately 74*9663SMark.Logan@Sun.COM after this header structure (without any 75*9663SMark.Logan@Sun.COM alignment). */ 76*9663SMark.Logan@Sun.COM /* 6*/ le16 usa_count; /* See NTFS_RECORD definition in layout.h. */ 77*9663SMark.Logan@Sun.COM 78*9663SMark.Logan@Sun.COM /* 8*/ leLSN chkdsk_lsn; /* The last log file sequence number found by 79*9663SMark.Logan@Sun.COM chkdsk. Only used when the magic is changed 80*9663SMark.Logan@Sun.COM to "CHKD". Otherwise this is zero. */ 81*9663SMark.Logan@Sun.COM /* 16*/ le32 system_page_size; /* Byte size of system pages when the log file 82*9663SMark.Logan@Sun.COM was created, has to be >= 512 and a power of 83*9663SMark.Logan@Sun.COM 2. Use this to calculate the required size 84*9663SMark.Logan@Sun.COM of the usa (usa_count) and add it to usa_ofs. 85*9663SMark.Logan@Sun.COM Then verify that the result is less than the 86*9663SMark.Logan@Sun.COM value of the restart_area_offset. */ 87*9663SMark.Logan@Sun.COM /* 20*/ le32 log_page_size; /* Byte size of log file pages, has to be >= 88*9663SMark.Logan@Sun.COM 512 and a power of 2. The default is 4096 89*9663SMark.Logan@Sun.COM and is used when the system page size is 90*9663SMark.Logan@Sun.COM between 4096 and 8192. Otherwise this is 91*9663SMark.Logan@Sun.COM set to the system page size instead. */ 92*9663SMark.Logan@Sun.COM /* 24*/ le16 restart_area_offset;/* Byte offset from the start of this header to 93*9663SMark.Logan@Sun.COM the RESTART_AREA. Value has to be aligned 94*9663SMark.Logan@Sun.COM to 8-byte boundary. When creating, set this 95*9663SMark.Logan@Sun.COM to be after the usa. */ 96*9663SMark.Logan@Sun.COM /* 26*/ sle16 minor_ver; /* Log file minor version. Only check if major 97*9663SMark.Logan@Sun.COM version is 1. */ 98*9663SMark.Logan@Sun.COM /* 28*/ sle16 major_ver; /* Log file major version. We only support 99*9663SMark.Logan@Sun.COM version 1.1. */ 100*9663SMark.Logan@Sun.COM /* sizeof() = 30 (0x1e) bytes */ 101*9663SMark.Logan@Sun.COM } __attribute__((__packed__)) RESTART_PAGE_HEADER; 102*9663SMark.Logan@Sun.COM #ifdef __sun 103*9663SMark.Logan@Sun.COM #pragma pack() 104*9663SMark.Logan@Sun.COM #endif 105*9663SMark.Logan@Sun.COM 106*9663SMark.Logan@Sun.COM /* 107*9663SMark.Logan@Sun.COM * Constant for the log client indices meaning that there are no client records 108*9663SMark.Logan@Sun.COM * in this particular client array. Also inside the client records themselves, 109*9663SMark.Logan@Sun.COM * this means that there are no client records preceding or following this one. 110*9663SMark.Logan@Sun.COM */ 111*9663SMark.Logan@Sun.COM #define LOGFILE_NO_CLIENT const_cpu_to_le16(0xffff) 112*9663SMark.Logan@Sun.COM #define LOGFILE_NO_CLIENT_CPU 0xffff 113*9663SMark.Logan@Sun.COM 114*9663SMark.Logan@Sun.COM #ifdef __sun 115*9663SMark.Logan@Sun.COM #define RESTART_VOLUME_IS_CLEAN (const_cpu_to_le16(0x0002)) 116*9663SMark.Logan@Sun.COM #else /* not __sun */ 117*9663SMark.Logan@Sun.COM /* 118*9663SMark.Logan@Sun.COM * These are the so far known RESTART_AREA_* flags (16-bit) which contain 119*9663SMark.Logan@Sun.COM * information about the log file in which they are present. 120*9663SMark.Logan@Sun.COM */ 121*9663SMark.Logan@Sun.COM enum { 122*9663SMark.Logan@Sun.COM RESTART_VOLUME_IS_CLEAN = const_cpu_to_le16(0x0002), 123*9663SMark.Logan@Sun.COM RESTART_SPACE_FILLER = const_cpu_to_le16(0xffff), 124*9663SMark.Logan@Sun.COM /* gcc: Force enum bit width to 16. */ 125*9663SMark.Logan@Sun.COM } __attribute__((__packed__)); 126*9663SMark.Logan@Sun.COM #endif /* __sun */ 127*9663SMark.Logan@Sun.COM 128*9663SMark.Logan@Sun.COM typedef le16 RESTART_AREA_FLAGS; 129*9663SMark.Logan@Sun.COM 130*9663SMark.Logan@Sun.COM /** 131*9663SMark.Logan@Sun.COM * struct RESTART_AREA - Log file restart area record. 132*9663SMark.Logan@Sun.COM * 133*9663SMark.Logan@Sun.COM * The offset of this record is found by adding the offset of the 134*9663SMark.Logan@Sun.COM * RESTART_PAGE_HEADER to the restart_area_offset value found in it. 135*9663SMark.Logan@Sun.COM * See notes at restart_area_offset above. 136*9663SMark.Logan@Sun.COM */ 137*9663SMark.Logan@Sun.COM #ifdef __sun 138*9663SMark.Logan@Sun.COM #pragma pack(1) 139*9663SMark.Logan@Sun.COM #endif 140*9663SMark.Logan@Sun.COM typedef struct { 141*9663SMark.Logan@Sun.COM /*Ofs*/ 142*9663SMark.Logan@Sun.COM /* 0*/ leLSN current_lsn; /* The current, i.e. last LSN inside the log 143*9663SMark.Logan@Sun.COM when the restart area was last written. 144*9663SMark.Logan@Sun.COM This happens often but what is the interval? 145*9663SMark.Logan@Sun.COM Is it just fixed time or is it every time a 146*9663SMark.Logan@Sun.COM check point is written or something else? 147*9663SMark.Logan@Sun.COM On create set to 0. */ 148*9663SMark.Logan@Sun.COM /* 8*/ le16 log_clients; /* Number of log client records in the array of 149*9663SMark.Logan@Sun.COM log client records which follows this 150*9663SMark.Logan@Sun.COM restart area. Must be 1. */ 151*9663SMark.Logan@Sun.COM /* 10*/ le16 client_free_list; /* The index of the first free log client record 152*9663SMark.Logan@Sun.COM in the array of log client records. 153*9663SMark.Logan@Sun.COM LOGFILE_NO_CLIENT means that there are no 154*9663SMark.Logan@Sun.COM free log client records in the array. 155*9663SMark.Logan@Sun.COM If != LOGFILE_NO_CLIENT, check that 156*9663SMark.Logan@Sun.COM log_clients > client_free_list. On Win2k 157*9663SMark.Logan@Sun.COM and presumably earlier, on a clean volume 158*9663SMark.Logan@Sun.COM this is != LOGFILE_NO_CLIENT, and it should 159*9663SMark.Logan@Sun.COM be 0, i.e. the first (and only) client 160*9663SMark.Logan@Sun.COM record is free and thus the logfile is 161*9663SMark.Logan@Sun.COM closed and hence clean. A dirty volume 162*9663SMark.Logan@Sun.COM would have left the logfile open and hence 163*9663SMark.Logan@Sun.COM this would be LOGFILE_NO_CLIENT. On WinXP 164*9663SMark.Logan@Sun.COM and presumably later, the logfile is always 165*9663SMark.Logan@Sun.COM open, even on clean shutdown so this should 166*9663SMark.Logan@Sun.COM always be LOGFILE_NO_CLIENT. */ 167*9663SMark.Logan@Sun.COM /* 12*/ le16 client_in_use_list;/* The index of the first in-use log client 168*9663SMark.Logan@Sun.COM record in the array of log client records. 169*9663SMark.Logan@Sun.COM LOGFILE_NO_CLIENT means that there are no 170*9663SMark.Logan@Sun.COM in-use log client records in the array. If 171*9663SMark.Logan@Sun.COM != LOGFILE_NO_CLIENT check that log_clients 172*9663SMark.Logan@Sun.COM > client_in_use_list. On Win2k and 173*9663SMark.Logan@Sun.COM presumably earlier, on a clean volume this 174*9663SMark.Logan@Sun.COM is LOGFILE_NO_CLIENT, i.e. there are no 175*9663SMark.Logan@Sun.COM client records in use and thus the logfile 176*9663SMark.Logan@Sun.COM is closed and hence clean. A dirty volume 177*9663SMark.Logan@Sun.COM would have left the logfile open and hence 178*9663SMark.Logan@Sun.COM this would be != LOGFILE_NO_CLIENT, and it 179*9663SMark.Logan@Sun.COM should be 0, i.e. the first (and only) 180*9663SMark.Logan@Sun.COM client record is in use. On WinXP and 181*9663SMark.Logan@Sun.COM presumably later, the logfile is always 182*9663SMark.Logan@Sun.COM open, even on clean shutdown so this should 183*9663SMark.Logan@Sun.COM always be 0. */ 184*9663SMark.Logan@Sun.COM /* 14*/ RESTART_AREA_FLAGS flags;/* Flags modifying LFS behaviour. On Win2k 185*9663SMark.Logan@Sun.COM and presumably earlier this is always 0. On 186*9663SMark.Logan@Sun.COM WinXP and presumably later, if the logfile 187*9663SMark.Logan@Sun.COM was shutdown cleanly, the second bit, 188*9663SMark.Logan@Sun.COM RESTART_VOLUME_IS_CLEAN, is set. This bit 189*9663SMark.Logan@Sun.COM is cleared when the volume is mounted by 190*9663SMark.Logan@Sun.COM WinXP and set when the volume is dismounted, 191*9663SMark.Logan@Sun.COM thus if the logfile is dirty, this bit is 192*9663SMark.Logan@Sun.COM clear. Thus we don't need to check the 193*9663SMark.Logan@Sun.COM Windows version to determine if the logfile 194*9663SMark.Logan@Sun.COM is clean. Instead if the logfile is closed, 195*9663SMark.Logan@Sun.COM we know it must be clean. If it is open and 196*9663SMark.Logan@Sun.COM this bit is set, we also know it must be 197*9663SMark.Logan@Sun.COM clean. If on the other hand the logfile is 198*9663SMark.Logan@Sun.COM open and this bit is clear, we can be almost 199*9663SMark.Logan@Sun.COM certain that the logfile is dirty. */ 200*9663SMark.Logan@Sun.COM /* 16*/ le32 seq_number_bits; /* How many bits to use for the sequence 201*9663SMark.Logan@Sun.COM number. This is calculated as 67 - the 202*9663SMark.Logan@Sun.COM number of bits required to store the logfile 203*9663SMark.Logan@Sun.COM size in bytes and this can be used in with 204*9663SMark.Logan@Sun.COM the specified file_size as a consistency 205*9663SMark.Logan@Sun.COM check. */ 206*9663SMark.Logan@Sun.COM /* 20*/ le16 restart_area_length;/* Length of the restart area including the 207*9663SMark.Logan@Sun.COM client array. Following checks required if 208*9663SMark.Logan@Sun.COM version matches. Otherwise, skip them. 209*9663SMark.Logan@Sun.COM restart_area_offset + restart_area_length 210*9663SMark.Logan@Sun.COM has to be <= system_page_size. Also, 211*9663SMark.Logan@Sun.COM restart_area_length has to be >= 212*9663SMark.Logan@Sun.COM client_array_offset + (log_clients * 213*9663SMark.Logan@Sun.COM sizeof(log client record)). */ 214*9663SMark.Logan@Sun.COM /* 22*/ le16 client_array_offset;/* Offset from the start of this record to 215*9663SMark.Logan@Sun.COM the first log client record if versions are 216*9663SMark.Logan@Sun.COM matched. When creating, set this to be 217*9663SMark.Logan@Sun.COM after this restart area structure, aligned 218*9663SMark.Logan@Sun.COM to 8-bytes boundary. If the versions do not 219*9663SMark.Logan@Sun.COM match, this is ignored and the offset is 220*9663SMark.Logan@Sun.COM assumed to be (sizeof(RESTART_AREA) + 7) & 221*9663SMark.Logan@Sun.COM ~7, i.e. rounded up to first 8-byte 222*9663SMark.Logan@Sun.COM boundary. Either way, client_array_offset 223*9663SMark.Logan@Sun.COM has to be aligned to an 8-byte boundary. 224*9663SMark.Logan@Sun.COM Also, restart_area_offset + 225*9663SMark.Logan@Sun.COM client_array_offset has to be <= 510. 226*9663SMark.Logan@Sun.COM Finally, client_array_offset + (log_clients 227*9663SMark.Logan@Sun.COM * sizeof(log client record)) has to be <= 228*9663SMark.Logan@Sun.COM system_page_size. On Win2k and presumably 229*9663SMark.Logan@Sun.COM earlier, this is 0x30, i.e. immediately 230*9663SMark.Logan@Sun.COM following this record. On WinXP and 231*9663SMark.Logan@Sun.COM presumably later, this is 0x40, i.e. there 232*9663SMark.Logan@Sun.COM are 16 extra bytes between this record and 233*9663SMark.Logan@Sun.COM the client array. This probably means that 234*9663SMark.Logan@Sun.COM the RESTART_AREA record is actually bigger 235*9663SMark.Logan@Sun.COM in WinXP and later. */ 236*9663SMark.Logan@Sun.COM /* 24*/ sle64 file_size; /* Usable byte size of the log file. If the 237*9663SMark.Logan@Sun.COM restart_area_offset + the offset of the 238*9663SMark.Logan@Sun.COM file_size are > 510 then corruption has 239*9663SMark.Logan@Sun.COM occurred. This is the very first check when 240*9663SMark.Logan@Sun.COM starting with the restart_area as if it 241*9663SMark.Logan@Sun.COM fails it means that some of the above values 242*9663SMark.Logan@Sun.COM will be corrupted by the multi sector 243*9663SMark.Logan@Sun.COM transfer protection. The file_size has to 244*9663SMark.Logan@Sun.COM be rounded down to be a multiple of the 245*9663SMark.Logan@Sun.COM log_page_size in the RESTART_PAGE_HEADER and 246*9663SMark.Logan@Sun.COM then it has to be at least big enough to 247*9663SMark.Logan@Sun.COM store the two restart pages and 48 (0x30) 248*9663SMark.Logan@Sun.COM log record pages. */ 249*9663SMark.Logan@Sun.COM /* 32*/ le32 last_lsn_data_length;/* Length of data of last LSN, not including 250*9663SMark.Logan@Sun.COM the log record header. On create set to 251*9663SMark.Logan@Sun.COM 0. */ 252*9663SMark.Logan@Sun.COM /* 36*/ le16 log_record_header_length;/* Byte size of the log record header. 253*9663SMark.Logan@Sun.COM If the version matches then check that the 254*9663SMark.Logan@Sun.COM value of log_record_header_length is a 255*9663SMark.Logan@Sun.COM multiple of 8, i.e. 256*9663SMark.Logan@Sun.COM (log_record_header_length + 7) & ~7 == 257*9663SMark.Logan@Sun.COM log_record_header_length. When creating set 258*9663SMark.Logan@Sun.COM it to sizeof(LOG_RECORD_HEADER), aligned to 259*9663SMark.Logan@Sun.COM 8 bytes. */ 260*9663SMark.Logan@Sun.COM /* 38*/ le16 log_page_data_offset;/* Offset to the start of data in a log record 261*9663SMark.Logan@Sun.COM page. Must be a multiple of 8. On create 262*9663SMark.Logan@Sun.COM set it to immediately after the update 263*9663SMark.Logan@Sun.COM sequence array of the log record page. */ 264*9663SMark.Logan@Sun.COM /* 40*/ le32 restart_log_open_count;/* A counter that gets incremented every 265*9663SMark.Logan@Sun.COM time the logfile is restarted which happens 266*9663SMark.Logan@Sun.COM at mount time when the logfile is opened. 267*9663SMark.Logan@Sun.COM When creating set to a random value. Win2k 268*9663SMark.Logan@Sun.COM sets it to the low 32 bits of the current 269*9663SMark.Logan@Sun.COM system time in NTFS format (see time.h). */ 270*9663SMark.Logan@Sun.COM /* 44*/ le32 reserved; /* Reserved/alignment to 8-byte boundary. */ 271*9663SMark.Logan@Sun.COM /* sizeof() = 48 (0x30) bytes */ 272*9663SMark.Logan@Sun.COM } __attribute__((__packed__)) RESTART_AREA; 273*9663SMark.Logan@Sun.COM #ifdef __sun 274*9663SMark.Logan@Sun.COM #pragma pack() 275*9663SMark.Logan@Sun.COM #endif 276*9663SMark.Logan@Sun.COM 277*9663SMark.Logan@Sun.COM /** 278*9663SMark.Logan@Sun.COM * struct LOG_CLIENT_RECORD - Log client record. 279*9663SMark.Logan@Sun.COM * 280*9663SMark.Logan@Sun.COM * The offset of this record is found by adding the offset of the 281*9663SMark.Logan@Sun.COM * RESTART_AREA to the client_array_offset value found in it. 282*9663SMark.Logan@Sun.COM */ 283*9663SMark.Logan@Sun.COM #ifdef __sun 284*9663SMark.Logan@Sun.COM #pragma pack(1) 285*9663SMark.Logan@Sun.COM #endif 286*9663SMark.Logan@Sun.COM typedef struct { 287*9663SMark.Logan@Sun.COM /*Ofs*/ 288*9663SMark.Logan@Sun.COM /* 0*/ leLSN oldest_lsn; /* Oldest LSN needed by this client. On create 289*9663SMark.Logan@Sun.COM set to 0. */ 290*9663SMark.Logan@Sun.COM /* 8*/ leLSN client_restart_lsn;/* LSN at which this client needs to restart 291*9663SMark.Logan@Sun.COM the volume, i.e. the current position within 292*9663SMark.Logan@Sun.COM the log file. At present, if clean this 293*9663SMark.Logan@Sun.COM should = current_lsn in restart area but it 294*9663SMark.Logan@Sun.COM probably also = current_lsn when dirty most 295*9663SMark.Logan@Sun.COM of the time. At create set to 0. */ 296*9663SMark.Logan@Sun.COM /* 16*/ le16 prev_client; /* The offset to the previous log client record 297*9663SMark.Logan@Sun.COM in the array of log client records. 298*9663SMark.Logan@Sun.COM LOGFILE_NO_CLIENT means there is no previous 299*9663SMark.Logan@Sun.COM client record, i.e. this is the first one. 300*9663SMark.Logan@Sun.COM This is always LOGFILE_NO_CLIENT. */ 301*9663SMark.Logan@Sun.COM /* 18*/ le16 next_client; /* The offset to the next log client record in 302*9663SMark.Logan@Sun.COM the array of log client records. 303*9663SMark.Logan@Sun.COM LOGFILE_NO_CLIENT means there are no next 304*9663SMark.Logan@Sun.COM client records, i.e. this is the last one. 305*9663SMark.Logan@Sun.COM This is always LOGFILE_NO_CLIENT. */ 306*9663SMark.Logan@Sun.COM /* 20*/ le16 seq_number; /* On Win2k and presumably earlier, this is set 307*9663SMark.Logan@Sun.COM to zero every time the logfile is restarted 308*9663SMark.Logan@Sun.COM and it is incremented when the logfile is 309*9663SMark.Logan@Sun.COM closed at dismount time. Thus it is 0 when 310*9663SMark.Logan@Sun.COM dirty and 1 when clean. On WinXP and 311*9663SMark.Logan@Sun.COM presumably later, this is always 0. */ 312*9663SMark.Logan@Sun.COM /* 22*/ u8 reserved[6]; /* Reserved/alignment. */ 313*9663SMark.Logan@Sun.COM /* 28*/ le32 client_name_length;/* Length of client name in bytes. Should 314*9663SMark.Logan@Sun.COM always be 8. */ 315*9663SMark.Logan@Sun.COM /* 32*/ ntfschar client_name[64];/* Name of the client in Unicode. Should 316*9663SMark.Logan@Sun.COM always be "NTFS" with the remaining bytes 317*9663SMark.Logan@Sun.COM set to 0. */ 318*9663SMark.Logan@Sun.COM /* sizeof() = 160 (0xa0) bytes */ 319*9663SMark.Logan@Sun.COM } __attribute__((__packed__)) LOG_CLIENT_RECORD; 320*9663SMark.Logan@Sun.COM #ifdef __sun 321*9663SMark.Logan@Sun.COM #pragma pack() 322*9663SMark.Logan@Sun.COM #endif 323*9663SMark.Logan@Sun.COM 324*9663SMark.Logan@Sun.COM /** 325*9663SMark.Logan@Sun.COM * struct RECORD_PAGE_HEADER - Log page record page header. 326*9663SMark.Logan@Sun.COM * 327*9663SMark.Logan@Sun.COM * Each log page begins with this header and is followed by several LOG_RECORD 328*9663SMark.Logan@Sun.COM * structures, starting at offset 0x40 (the size of this structure and the 329*9663SMark.Logan@Sun.COM * following update sequence array and then aligned to 8 byte boundary, but is 330*9663SMark.Logan@Sun.COM * this specified anywhere?). 331*9663SMark.Logan@Sun.COM */ 332*9663SMark.Logan@Sun.COM #ifdef __sun 333*9663SMark.Logan@Sun.COM #pragma pack(1) 334*9663SMark.Logan@Sun.COM #endif 335*9663SMark.Logan@Sun.COM typedef struct { 336*9663SMark.Logan@Sun.COM /* 0 NTFS_RECORD; -- Unfolded here as gcc doesn't like unnamed structs. */ 337*9663SMark.Logan@Sun.COM NTFS_RECORD_TYPES magic;/* Usually the magic is "RCRD". */ 338*9663SMark.Logan@Sun.COM u16 usa_ofs; /* See NTFS_RECORD definition in layout.h. 339*9663SMark.Logan@Sun.COM When creating, set this to be immediately 340*9663SMark.Logan@Sun.COM after this header structure (without any 341*9663SMark.Logan@Sun.COM alignment). */ 342*9663SMark.Logan@Sun.COM u16 usa_count; /* See NTFS_RECORD definition in layout.h. */ 343*9663SMark.Logan@Sun.COM 344*9663SMark.Logan@Sun.COM union { 345*9663SMark.Logan@Sun.COM LSN last_lsn; 346*9663SMark.Logan@Sun.COM s64 file_offset; 347*9663SMark.Logan@Sun.COM } __attribute__((__packed__)) copy; 348*9663SMark.Logan@Sun.COM u32 flags; 349*9663SMark.Logan@Sun.COM u16 page_count; 350*9663SMark.Logan@Sun.COM u16 page_position; 351*9663SMark.Logan@Sun.COM union { 352*9663SMark.Logan@Sun.COM struct { 353*9663SMark.Logan@Sun.COM u16 next_record_offset; 354*9663SMark.Logan@Sun.COM u8 reserved[6]; 355*9663SMark.Logan@Sun.COM LSN last_end_lsn; 356*9663SMark.Logan@Sun.COM } __attribute__((__packed__)) packed; 357*9663SMark.Logan@Sun.COM } __attribute__((__packed__)) header; 358*9663SMark.Logan@Sun.COM } __attribute__((__packed__)) RECORD_PAGE_HEADER; 359*9663SMark.Logan@Sun.COM #ifdef __sun 360*9663SMark.Logan@Sun.COM #pragma pack() 361*9663SMark.Logan@Sun.COM #endif 362*9663SMark.Logan@Sun.COM 363*9663SMark.Logan@Sun.COM /** 364*9663SMark.Logan@Sun.COM * enum LOG_RECORD_FLAGS - Possible 16-bit flags for log records. 365*9663SMark.Logan@Sun.COM * 366*9663SMark.Logan@Sun.COM * (Or is it log record pages?) 367*9663SMark.Logan@Sun.COM */ 368*9663SMark.Logan@Sun.COM #ifdef __sun 369*9663SMark.Logan@Sun.COM typedef const uint16_t LOG_RECORD_FLAGS; 370*9663SMark.Logan@Sun.COM #define LOG_RECORD_MULTI_PAGE (const_cpu_to_le16(0x0001)) 371*9663SMark.Logan@Sun.COM #else /* not __sun */ 372*9663SMark.Logan@Sun.COM typedef enum { 373*9663SMark.Logan@Sun.COM LOG_RECORD_MULTI_PAGE = const_cpu_to_le16(0x0001), /* ??? */ 374*9663SMark.Logan@Sun.COM LOG_RECORD_SIZE_PLACE_HOLDER = 0xffff, 375*9663SMark.Logan@Sun.COM /* This has nothing to do with the log record. It is only so 376*9663SMark.Logan@Sun.COM gcc knows to make the flags 16-bit. */ 377*9663SMark.Logan@Sun.COM } __attribute__((__packed__)) LOG_RECORD_FLAGS; 378*9663SMark.Logan@Sun.COM #endif /* __sun */ 379*9663SMark.Logan@Sun.COM 380*9663SMark.Logan@Sun.COM /** 381*9663SMark.Logan@Sun.COM * struct LOG_CLIENT_ID - The log client id structure identifying a log client. 382*9663SMark.Logan@Sun.COM */ 383*9663SMark.Logan@Sun.COM #ifdef __sun 384*9663SMark.Logan@Sun.COM #pragma pack(1) 385*9663SMark.Logan@Sun.COM #endif 386*9663SMark.Logan@Sun.COM typedef struct { 387*9663SMark.Logan@Sun.COM u16 seq_number; 388*9663SMark.Logan@Sun.COM u16 client_index; 389*9663SMark.Logan@Sun.COM } __attribute__((__packed__)) LOG_CLIENT_ID; 390*9663SMark.Logan@Sun.COM #ifdef __sun 391*9663SMark.Logan@Sun.COM #pragma pack() 392*9663SMark.Logan@Sun.COM #endif 393*9663SMark.Logan@Sun.COM 394*9663SMark.Logan@Sun.COM /** 395*9663SMark.Logan@Sun.COM * struct LOG_RECORD - Log record header. 396*9663SMark.Logan@Sun.COM * 397*9663SMark.Logan@Sun.COM * Each log record seems to have a constant size of 0x70 bytes. 398*9663SMark.Logan@Sun.COM */ 399*9663SMark.Logan@Sun.COM #ifdef __sun 400*9663SMark.Logan@Sun.COM #pragma pack(1) 401*9663SMark.Logan@Sun.COM #endif 402*9663SMark.Logan@Sun.COM typedef struct { 403*9663SMark.Logan@Sun.COM LSN this_lsn; 404*9663SMark.Logan@Sun.COM LSN client_previous_lsn; 405*9663SMark.Logan@Sun.COM LSN client_undo_next_lsn; 406*9663SMark.Logan@Sun.COM u32 client_data_length; 407*9663SMark.Logan@Sun.COM LOG_CLIENT_ID client_id; 408*9663SMark.Logan@Sun.COM u32 record_type; 409*9663SMark.Logan@Sun.COM u32 transaction_id; 410*9663SMark.Logan@Sun.COM u16 flags; 411*9663SMark.Logan@Sun.COM u16 reserved_or_alignment[3]; 412*9663SMark.Logan@Sun.COM /* Now are at ofs 0x30 into struct. */ 413*9663SMark.Logan@Sun.COM u16 redo_operation; 414*9663SMark.Logan@Sun.COM u16 undo_operation; 415*9663SMark.Logan@Sun.COM u16 redo_offset; 416*9663SMark.Logan@Sun.COM u16 redo_length; 417*9663SMark.Logan@Sun.COM u16 undo_offset; 418*9663SMark.Logan@Sun.COM u16 undo_length; 419*9663SMark.Logan@Sun.COM u16 target_attribute; 420*9663SMark.Logan@Sun.COM u16 lcns_to_follow; /* Number of lcn_list entries 421*9663SMark.Logan@Sun.COM following this entry. */ 422*9663SMark.Logan@Sun.COM /* Now at ofs 0x40. */ 423*9663SMark.Logan@Sun.COM u16 record_offset; 424*9663SMark.Logan@Sun.COM u16 attribute_offset; 425*9663SMark.Logan@Sun.COM u32 alignment_or_reserved; 426*9663SMark.Logan@Sun.COM VCN target_vcn; 427*9663SMark.Logan@Sun.COM /* Now at ofs 0x50. */ 428*9663SMark.Logan@Sun.COM struct { /* Only present if lcns_to_follow 429*9663SMark.Logan@Sun.COM is not 0. */ 430*9663SMark.Logan@Sun.COM LCN lcn; 431*9663SMark.Logan@Sun.COM } __attribute__((__packed__)) lcn_list[]; 432*9663SMark.Logan@Sun.COM } __attribute__((__packed__)) LOG_RECORD; 433*9663SMark.Logan@Sun.COM #ifdef __sun 434*9663SMark.Logan@Sun.COM #pragma pack() 435*9663SMark.Logan@Sun.COM #endif 436*9663SMark.Logan@Sun.COM 437*9663SMark.Logan@Sun.COM extern BOOL ntfs_check_logfile(ntfs_attr *log_na, RESTART_PAGE_HEADER **rp); 438*9663SMark.Logan@Sun.COM extern BOOL ntfs_is_logfile_clean(ntfs_attr *log_na, RESTART_PAGE_HEADER *rp); 439*9663SMark.Logan@Sun.COM extern int ntfs_empty_logfile(ntfs_attr *na); 440*9663SMark.Logan@Sun.COM 441*9663SMark.Logan@Sun.COM #endif /* defined _NTFS_LOGFILE_H */ 442