~ubuntu-branches/debian/sid/ntfs-3g/sid

« back to all changes in this revision

Viewing changes to .pc/0002-exit-values.patch/ntfsprogs/mkntfs.c

  • Committer: Package Import Robot
  • Author(s): Daniel Baumann
  • Date: 2014-06-11 07:05:11 UTC
  • Revision ID: package-import@ubuntu.com-20140611070511-uff0av8cy0p2j3ty
Tags: 1:2014.2.15AR.1-2
* Adding patch from upstream to fix type inconsistencies in
  ntfs_initialize_file_security (Closes: #749517).
* Moving undocumented ntfsdump_logfile, ntfsmftalloc, and ntfsck to
  ntfs-3g-dev (Closes: #747872).
* Adding patch from upstream to correct exit values (Closes: #741992).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
 * mkntfs - Part of the Linux-NTFS project.
 
3
 *
 
4
 * Copyright (c) 2000-2011 Anton Altaparmakov
 
5
 * Copyright (c) 2001-2005 Richard Russon
 
6
 * Copyright (c) 2002-2006 Szabolcs Szakacsits
 
7
 * Copyright (c) 2005      Erik Sornes
 
8
 * Copyright (c) 2007      Yura Pakhuchiy
 
9
 * Copyright (c) 2010      Jean-Pierre Andre
 
10
 *
 
11
 * This utility will create an NTFS 1.2 or 3.1 volume on a user
 
12
 * specified (block) device.
 
13
 *
 
14
 * Some things (option handling and determination of mount status) have been
 
15
 * adapted from e2fsprogs-1.19 and lib/ext2fs/ismounted.c and misc/mke2fs.c in
 
16
 * particular.
 
17
 *
 
18
 * This program is free software; you can redistribute it and/or modify
 
19
 * it under the terms of the GNU General Public License as published by
 
20
 * the Free Software Foundation; either version 2 of the License, or
 
21
 * (at your option) any later version.
 
22
 *
 
23
 * This program is distributed in the hope that it will be useful,
 
24
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
25
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
26
 * GNU General Public License for more details.
 
27
 *
 
28
 * You should have received a copy of the GNU General Public License
 
29
 * along with this program (in the main directory of the Linux-NTFS source
 
30
 * in the file COPYING); if not, write to the Free Software Foundation,
 
31
 * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
32
 */
 
33
 
 
34
#ifdef HAVE_CONFIG_H
 
35
#include "config.h"
 
36
#endif
 
37
 
 
38
#ifdef  HAVE_UNISTD_H
 
39
#include <unistd.h>
 
40
#endif
 
41
#ifdef HAVE_STDLIB_H
 
42
#include <stdlib.h>
 
43
#endif
 
44
#ifdef HAVE_STDIO_H
 
45
#include <stdio.h>
 
46
#endif
 
47
#ifdef HAVE_STDARG_H
 
48
#include <stdarg.h>
 
49
#endif
 
50
#ifdef HAVE_STRING_H
 
51
#include <string.h>
 
52
#endif
 
53
#ifdef HAVE_ERRNO_H
 
54
#include <errno.h>
 
55
#endif
 
56
#ifdef HAVE_TIME_H
 
57
#include <time.h>
 
58
#endif
 
59
#ifdef HAVE_SYS_STAT_H
 
60
#include <sys/stat.h>
 
61
#endif
 
62
#ifdef HAVE_FCNTL_H
 
63
#include <fcntl.h>
 
64
#endif
 
65
#ifdef HAVE_LIMITS_H
 
66
#include <limits.h>
 
67
#endif
 
68
#ifdef HAVE_LIBGEN_H
 
69
#include <libgen.h>
 
70
#endif
 
71
#ifdef ENABLE_UUID
 
72
#include <uuid/uuid.h>
 
73
#endif
 
74
 
 
75
 
 
76
#ifdef HAVE_GETOPT_H
 
77
#include <getopt.h>
 
78
#else
 
79
        extern char *optarg;
 
80
        extern int optind;
 
81
#endif
 
82
 
 
83
#ifdef HAVE_LINUX_MAJOR_H
 
84
#       include <linux/major.h>
 
85
#       ifndef MAJOR
 
86
#               define MAJOR(dev)       ((dev) >> 8)
 
87
#               define MINOR(dev)       ((dev) & 0xff)
 
88
#       endif
 
89
#       ifndef IDE_DISK_MAJOR
 
90
#               ifndef IDE0_MAJOR
 
91
#                       define IDE0_MAJOR       3
 
92
#                       define IDE1_MAJOR       22
 
93
#                       define IDE2_MAJOR       33
 
94
#                       define IDE3_MAJOR       34
 
95
#                       define IDE4_MAJOR       56
 
96
#                       define IDE5_MAJOR       57
 
97
#                       define IDE6_MAJOR       88
 
98
#                       define IDE7_MAJOR       89
 
99
#                       define IDE8_MAJOR       90
 
100
#                       define IDE9_MAJOR       91
 
101
#               endif
 
102
#               define IDE_DISK_MAJOR(M) \
 
103
                                ((M) == IDE0_MAJOR || (M) == IDE1_MAJOR || \
 
104
                                (M) == IDE2_MAJOR || (M) == IDE3_MAJOR || \
 
105
                                (M) == IDE4_MAJOR || (M) == IDE5_MAJOR || \
 
106
                                (M) == IDE6_MAJOR || (M) == IDE7_MAJOR || \
 
107
                                (M) == IDE8_MAJOR || (M) == IDE9_MAJOR)
 
108
#       endif
 
109
#       ifndef SCSI_DISK_MAJOR
 
110
#               ifndef SCSI_DISK0_MAJOR
 
111
#                       define SCSI_DISK0_MAJOR 8
 
112
#                       define SCSI_DISK1_MAJOR 65
 
113
#                       define SCSI_DISK7_MAJOR 71
 
114
#               endif
 
115
#               define SCSI_DISK_MAJOR(M) \
 
116
                                ((M) == SCSI_DISK0_MAJOR || \
 
117
                                ((M) >= SCSI_DISK1_MAJOR && \
 
118
                                (M) <= SCSI_DISK7_MAJOR))
 
119
#       endif
 
120
#endif
 
121
 
 
122
#include "security.h"
 
123
#include "types.h"
 
124
#include "attrib.h"
 
125
#include "bitmap.h"
 
126
#include "bootsect.h"
 
127
#include "device.h"
 
128
#include "dir.h"
 
129
#include "mft.h"
 
130
#include "mst.h"
 
131
#include "runlist.h"
 
132
#include "utils.h"
 
133
#include "ntfstime.h"
 
134
#include "sd.h"
 
135
#include "boot.h"
 
136
#include "attrdef.h"
 
137
/* #include "version.h" */
 
138
#include "logging.h"
 
139
#include "support.h"
 
140
#include "unistr.h"
 
141
#include "misc.h"
 
142
 
 
143
#if defined(__sun) && defined (__SVR4)
 
144
#undef basename
 
145
#define basename(name) name
 
146
#endif
 
147
 
 
148
typedef enum { WRITE_STANDARD, WRITE_BITMAP, WRITE_LOGFILE } WRITE_TYPE;
 
149
 
 
150
#ifdef NO_NTFS_DEVICE_DEFAULT_IO_OPS
 
151
#error "No default device io operations!  Cannot build mkntfs.  \
 
152
You need to run ./configure without the --disable-default-device-io-ops \
 
153
switch if you want to be able to build the NTFS utilities."
 
154
#endif
 
155
 
 
156
/* Page size on ia32. Can change to 8192 on Alpha. */
 
157
#define NTFS_PAGE_SIZE  4096
 
158
 
 
159
static char EXEC_NAME[] = "mkntfs";
 
160
 
 
161
struct BITMAP_ALLOCATION {
 
162
        struct BITMAP_ALLOCATION *next;
 
163
        LCN     lcn;            /* first allocated cluster */
 
164
        s64     length;         /* count of consecutive clusters */
 
165
} ;
 
166
 
 
167
                /* Upcase $Info, used since Windows 8 */
 
168
struct UPCASEINFO {
 
169
        le32    len;
 
170
        le32    filler;
 
171
        le64    crc;
 
172
        le32    osmajor;
 
173
        le32    osminor;
 
174
        le32    build;
 
175
        le16    packmajor;
 
176
        le16    packminor;
 
177
} ;
 
178
 
 
179
/**
 
180
 * global variables
 
181
 */
 
182
static u8                 *g_buf                  = NULL;
 
183
static int                 g_mft_bitmap_byte_size = 0;
 
184
static u8                 *g_mft_bitmap           = NULL;
 
185
static int                 g_lcn_bitmap_byte_size = 0;
 
186
static int                 g_dynamic_buf_size     = 0;
 
187
static u8                 *g_dynamic_buf          = NULL;
 
188
static struct UPCASEINFO  *g_upcaseinfo           = NULL;
 
189
static runlist            *g_rl_mft               = NULL;
 
190
static runlist            *g_rl_mft_bmp           = NULL;
 
191
static runlist            *g_rl_mftmirr           = NULL;
 
192
static runlist            *g_rl_logfile           = NULL;
 
193
static runlist            *g_rl_boot              = NULL;
 
194
static runlist            *g_rl_bad               = NULL;
 
195
static INDEX_ALLOCATION  *g_index_block   = NULL;
 
196
static ntfs_volume        *g_vol                  = NULL;
 
197
static int                 g_mft_size             = 0;
 
198
static long long           g_mft_lcn              = 0;          /* lcn of $MFT, $DATA attribute */
 
199
static long long           g_mftmirr_lcn          = 0;          /* lcn of $MFTMirr, $DATA */
 
200
static long long           g_logfile_lcn          = 0;          /* lcn of $LogFile, $DATA */
 
201
static int                 g_logfile_size         = 0;          /* in bytes, determined from volume_size */
 
202
static long long           g_mft_zone_end         = 0;          /* Determined from volume_size and mft_zone_multiplier, in clusters */
 
203
static long long           g_num_bad_blocks       = 0;          /* Number of bad clusters */
 
204
static long long          *g_bad_blocks           = NULL;       /* Array of bad clusters */
 
205
 
 
206
static struct BITMAP_ALLOCATION *g_allocation     = NULL;       /* Head of cluster allocations */
 
207
 
 
208
/**
 
209
 * struct mkntfs_options
 
210
 */
 
211
static struct mkntfs_options {
 
212
        char *dev_name;                 /* Name of the device, or file, to use */
 
213
        BOOL enable_compression;        /* -C, enables compression of all files on the volume by default. */
 
214
        BOOL quick_format;              /* -f or -Q, fast format, don't zero the volume first. */
 
215
        BOOL force;                     /* -F, force fs creation. */
 
216
        long heads;                     /* -H, number of heads on device */
 
217
        BOOL disable_indexing;          /* -I, disables indexing of file contents on the volume by default. */
 
218
        BOOL no_action;                 /* -n, do not write to device, only display what would be done. */
 
219
        long long part_start_sect;      /* -p, start sector of partition on parent device */
 
220
        long sector_size;               /* -s, in bytes, power of 2, default is 512 bytes. */
 
221
        long sectors_per_track;         /* -S, number of sectors per track on device */
 
222
        BOOL use_epoch_time;            /* -T, fake the time to be 00:00:00 UTC, Jan 1, 1970. */
 
223
        long mft_zone_multiplier;       /* -z, value from 1 to 4. Default is 1. */
 
224
        long long num_sectors;          /* size of device in sectors */
 
225
        long cluster_size;              /* -c, format with this cluster-size */
 
226
        BOOL with_uuid;                 /* -U, request setting an uuid */
 
227
        char *label;                    /* -L, volume label */
 
228
} opts;
 
229
 
 
230
 
 
231
/**
 
232
 * mkntfs_license
 
233
 */
 
234
static void mkntfs_license(void)
 
235
{
 
236
        ntfs_log_info("%s", ntfs_gpl);
 
237
}
 
238
 
 
239
/**
 
240
 * mkntfs_usage
 
241
 */
 
242
static void mkntfs_usage(void)
 
243
{
 
244
        ntfs_log_info("\nUsage: %s [options] device [number-of-sectors]\n"
 
245
"\n"
 
246
"Basic options:\n"
 
247
"    -f, --fast                      Perform a quick format\n"
 
248
"    -Q, --quick                     Perform a quick format\n"
 
249
"    -L, --label STRING              Set the volume label\n"
 
250
"    -C, --enable-compression        Enable compression on the volume\n"
 
251
"    -I, --no-indexing               Disable indexing on the volume\n"
 
252
"    -n, --no-action                 Do not write to disk\n"
 
253
"\n"
 
254
"Advanced options:\n"
 
255
"    -c, --cluster-size BYTES        Specify the cluster size for the volume\n"
 
256
"    -s, --sector-size BYTES         Specify the sector size for the device\n"
 
257
"    -p, --partition-start SECTOR    Specify the partition start sector\n"
 
258
"    -H, --heads NUM                 Specify the number of heads\n"
 
259
"    -S, --sectors-per-track NUM     Specify the number of sectors per track\n"
 
260
"    -z, --mft-zone-multiplier NUM   Set the MFT zone multiplier\n"
 
261
"    -T, --zero-time                 Fake the time to be 00:00 UTC, Jan 1, 1970\n"
 
262
"    -F, --force                     Force execution despite errors\n"
 
263
"\n"
 
264
"Output options:\n"
 
265
"    -q, --quiet                     Quiet execution\n"
 
266
"    -v, --verbose                   Verbose execution\n"
 
267
"        --debug                     Very verbose execution\n"
 
268
"\n"
 
269
"Help options:\n"
 
270
"    -V, --version                   Display version\n"
 
271
"    -l, --license                   Display licensing information\n"
 
272
"    -h, --help                      Display this help\n"
 
273
"\n", basename(EXEC_NAME));
 
274
        ntfs_log_info("%s%s\n", ntfs_bugs, ntfs_home);
 
275
}
 
276
 
 
277
/**
 
278
 * mkntfs_version
 
279
 */
 
280
static void mkntfs_version(void)
 
281
{
 
282
        ntfs_log_info("\n%s v%s (libntfs-3g)\n\n", EXEC_NAME, VERSION);
 
283
        ntfs_log_info("Create an NTFS volume on a user specified (block) "
 
284
                        "device.\n\n");
 
285
        ntfs_log_info("Copyright (c) 2000-2007 Anton Altaparmakov\n");
 
286
        ntfs_log_info("Copyright (c) 2001-2005 Richard Russon\n");
 
287
        ntfs_log_info("Copyright (c) 2002-2006 Szabolcs Szakacsits\n");
 
288
        ntfs_log_info("Copyright (c) 2005      Erik Sornes\n");
 
289
        ntfs_log_info("Copyright (c) 2007      Yura Pakhuchiy\n");
 
290
        ntfs_log_info("Copyright (c) 2010-2012 Jean-Pierre Andre\n");
 
291
        ntfs_log_info("\n%s\n%s%s\n", ntfs_gpl, ntfs_bugs, ntfs_home);
 
292
}
 
293
 
 
294
/*
 
295
 *  crc64, adapted from http://rpm5.org/docs/api/digest_8c-source.html
 
296
 * ECMA-182 polynomial, see
 
297
 *     http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-182.pdf
 
298
 */
 
299
                /* make sure the needed types are defined */
 
300
#undef byte
 
301
#undef uint32_t
 
302
#undef uint64_t
 
303
#define byte u8
 
304
#define uint32_t u32
 
305
#define uint64_t u64
 
306
static uint64_t crc64(uint64_t crc, const byte * data, size_t size)
 
307
        /*@*/
 
308
{
 
309
        static uint64_t polynomial = 0x9a6c9329ac4bc9b5ULL;
 
310
        static uint64_t xorout = 0xffffffffffffffffULL;
 
311
        static uint64_t table[256];
 
312
 
 
313
        crc ^= xorout;
 
314
 
 
315
        if (data == NULL) {
 
316
        /* generate the table of CRC remainders for all possible bytes */
 
317
                uint64_t c;
 
318
                uint32_t i, j;
 
319
                for (i = 0;  i < 256;  i++) {
 
320
                        c = i;
 
321
                        for (j = 0;  j < 8;  j++) {
 
322
                                if (c & 1)
 
323
                                        c = polynomial ^ (c >> 1);
 
324
                                else
 
325
                                        c = (c >> 1);
 
326
                        }
 
327
                        table[i] = c;
 
328
                }
 
329
        } else
 
330
                while (size) {
 
331
                        crc = table[(crc ^ *data) & 0xff] ^ (crc >> 8);
 
332
                        size--;
 
333
                        data++;
 
334
                }
 
335
 
 
336
        crc ^= xorout;
 
337
 
 
338
        return crc;
 
339
}
 
340
 
 
341
/*
 
342
 *              Mark a run of clusters as allocated
 
343
 *
 
344
 *      Returns FALSE if unsuccessful
 
345
 */
 
346
 
 
347
static BOOL bitmap_allocate(LCN lcn, s64 length)
 
348
{
 
349
        BOOL done;
 
350
        struct BITMAP_ALLOCATION *p;
 
351
        struct BITMAP_ALLOCATION *q;
 
352
        struct BITMAP_ALLOCATION *newall;
 
353
 
 
354
        done = TRUE;
 
355
        if (length) {
 
356
                p = g_allocation;
 
357
                q = (struct BITMAP_ALLOCATION*)NULL;
 
358
                /* locate the first run which starts beyond the requested lcn */
 
359
                while (p && (p->lcn <= lcn)) {
 
360
                        q = p;
 
361
                        p = p->next;
 
362
                }
 
363
                /* make sure the requested lcns were not allocated */
 
364
                if ((q && ((q->lcn + q->length) > lcn))
 
365
                   || (p && ((lcn + length) > p->lcn))) {
 
366
                        ntfs_log_error("Bitmap allocation error\n");
 
367
                        done = FALSE;
 
368
                }
 
369
                if (q && ((q->lcn + q->length) == lcn)) {
 
370
                        /* extend current run, no overlapping possible */
 
371
                        q->length += length;
 
372
                } else {
 
373
                        newall = (struct BITMAP_ALLOCATION*)
 
374
                                    ntfs_malloc(sizeof(struct BITMAP_ALLOCATION));
 
375
                        if (newall) {
 
376
                                newall->lcn = lcn;
 
377
                                newall->length = length;
 
378
                                newall->next = p;
 
379
                                if (q) q->next = newall;
 
380
                                else g_allocation = newall;
 
381
                        } else {
 
382
                                done = FALSE;
 
383
                                ntfs_log_perror("Not enough memory");
 
384
                        }
 
385
                }
 
386
        }
 
387
        return (done);
 
388
}
 
389
 
 
390
/*
 
391
 *              Mark a run of cluster as not allocated
 
392
 *
 
393
 *      Returns FALSE if unsuccessful
 
394
 *              (freeing free clusters is not considered as an error)
 
395
 */
 
396
 
 
397
static BOOL bitmap_deallocate(LCN lcn, s64 length)
 
398
{
 
399
        BOOL done;
 
400
        struct BITMAP_ALLOCATION *p;
 
401
        struct BITMAP_ALLOCATION *q;
 
402
        LCN first, last;
 
403
        s64 begin_length, end_length;
 
404
 
 
405
        done = TRUE;
 
406
        if (length) {
 
407
                p = g_allocation;
 
408
                q = (struct BITMAP_ALLOCATION*)NULL;
 
409
                        /* locate a run which has a common portion */
 
410
                while (p) {
 
411
                        first = (p->lcn > lcn ? p->lcn : lcn);
 
412
                        last = ((p->lcn + p->length) < (lcn + length)
 
413
                                ? p->lcn + p->length : lcn + length);
 
414
                        if (first < last) {
 
415
                                        /* get the parts which must be kept */
 
416
                                begin_length = first - p->lcn;
 
417
                                end_length = p->lcn + p->length - last;
 
418
                                        /* delete the entry */
 
419
                                if (q)
 
420
                                        q->next = p->next;
 
421
                                else
 
422
                                        g_allocation = p->next;
 
423
                                free(p);
 
424
                                /* reallocate the beginning and the end */
 
425
                                if (begin_length
 
426
                                    && !bitmap_allocate(first - begin_length,
 
427
                                                        begin_length))
 
428
                                        done = FALSE;
 
429
                                if (end_length
 
430
                                    && !bitmap_allocate(last, end_length))
 
431
                                        done = FALSE;
 
432
                                        /* restart a full search */
 
433
                                p = g_allocation;
 
434
                                q = (struct BITMAP_ALLOCATION*)NULL;
 
435
                        } else {
 
436
                                q = p;
 
437
                                p = p->next;
 
438
                        }
 
439
                }
 
440
        }
 
441
        return (done);
 
442
}
 
443
 
 
444
/*
 
445
 *              Get the allocation status of a single cluster
 
446
 *      and mark as allocated
 
447
 *
 
448
 *      Returns 1 if the cluster was previously allocated
 
449
 */
 
450
 
 
451
static int bitmap_get_and_set(LCN lcn, unsigned long length)
 
452
{
 
453
        struct BITMAP_ALLOCATION *p;
 
454
        struct BITMAP_ALLOCATION *q;
 
455
        int bit;
 
456
 
 
457
        if (length == 1) {
 
458
                p = g_allocation;
 
459
                q = (struct BITMAP_ALLOCATION*)NULL;
 
460
                /* locate the first run which starts beyond the requested lcn */
 
461
                while (p && (p->lcn <= lcn)) {
 
462
                        q = p;
 
463
                        p = p->next;
 
464
                }
 
465
                if (q && (q->lcn <= lcn) && ((q->lcn + q->length) > lcn))
 
466
                        bit = 1; /* was allocated */
 
467
                else {
 
468
                        bitmap_allocate(lcn, length);
 
469
                        bit = 0;
 
470
                }
 
471
        } else {
 
472
                ntfs_log_error("Can only allocate a single cluster at a time\n");
 
473
                bit = 0;
 
474
        }
 
475
        return (bit);
 
476
}
 
477
 
 
478
/*
 
479
 *              Build a section of the bitmap according to allocation
 
480
 */
 
481
 
 
482
static void bitmap_build(u8 *buf, LCN lcn, s64 length)
 
483
{
 
484
        struct BITMAP_ALLOCATION *p;
 
485
        LCN first, last;
 
486
        int j; /* byte number */
 
487
        int bn; /* bit number */
 
488
 
 
489
        for (j=0; (8*j)<length; j++)
 
490
                buf[j] = 0;
 
491
        for (p=g_allocation; p; p=p->next) {
 
492
                first = (p->lcn > lcn ? p->lcn : lcn);
 
493
                last = ((p->lcn + p->length) < (lcn + length)
 
494
                        ? p->lcn + p->length : lcn + length);
 
495
                if (first < last) {
 
496
                        bn = first - lcn;
 
497
                                /* initial partial byte, if any */
 
498
                        while ((bn < (last - lcn)) && (bn & 7)) {
 
499
                                buf[bn >> 3] |= 1 << (bn & 7);
 
500
                                bn++;
 
501
                        }
 
502
                                /* full bytes */
 
503
                        while (bn < (last - lcn - 7)) {
 
504
                                buf[bn >> 3] = 255;
 
505
                                bn += 8;
 
506
                        }
 
507
                                /* final partial byte, if any */
 
508
                        while (bn < (last - lcn)) {
 
509
                                buf[bn >> 3] |= 1 << (bn & 7);
 
510
                                bn++;
 
511
                        }
 
512
                }
 
513
        }
 
514
}
 
515
 
 
516
/**
 
517
 * mkntfs_parse_long
 
518
 */
 
519
static BOOL mkntfs_parse_long(const char *string, const char *name, long *num)
 
520
{
 
521
        char *end = NULL;
 
522
        long tmp;
 
523
 
 
524
        if (!string || !name || !num)
 
525
                return FALSE;
 
526
 
 
527
        if (*num >= 0) {
 
528
                ntfs_log_error("You may only specify the %s once.\n", name);
 
529
                return FALSE;
 
530
        }
 
531
 
 
532
        tmp = strtol(string, &end, 0);
 
533
        if (end && *end) {
 
534
                ntfs_log_error("Cannot understand the %s '%s'.\n", name, string);
 
535
                return FALSE;
 
536
        } else {
 
537
                *num = tmp;
 
538
                return TRUE;
 
539
        }
 
540
}
 
541
 
 
542
/**
 
543
 * mkntfs_parse_llong
 
544
 */
 
545
static BOOL mkntfs_parse_llong(const char *string, const char *name,
 
546
                long long *num)
 
547
{
 
548
        char *end = NULL;
 
549
        long long tmp;
 
550
 
 
551
        if (!string || !name || !num)
 
552
                return FALSE;
 
553
 
 
554
        if (*num >= 0) {
 
555
                ntfs_log_error("You may only specify the %s once.\n", name);
 
556
                return FALSE;
 
557
        }
 
558
 
 
559
        tmp = strtoll(string, &end, 0);
 
560
        if (end && *end) {
 
561
                ntfs_log_error("Cannot understand the %s '%s'.\n", name,
 
562
                                string);
 
563
                return FALSE;
 
564
        } else {
 
565
                *num = tmp;
 
566
                return TRUE;
 
567
        }
 
568
}
 
569
 
 
570
/**
 
571
 * mkntfs_init_options
 
572
 */
 
573
static void mkntfs_init_options(struct mkntfs_options *opts2)
 
574
{
 
575
        if (!opts2)
 
576
                return;
 
577
 
 
578
        memset(opts2, 0, sizeof(*opts2));
 
579
 
 
580
        /* Mark all the numeric options as "unset". */
 
581
        opts2->cluster_size             = -1;
 
582
        opts2->heads                    = -1;
 
583
        opts2->mft_zone_multiplier      = -1;
 
584
        opts2->num_sectors              = -1;
 
585
        opts2->part_start_sect          = -1;
 
586
        opts2->sector_size              = -1;
 
587
        opts2->sectors_per_track        = -1;
 
588
}
 
589
 
 
590
/**
 
591
 * mkntfs_parse_options
 
592
 */
 
593
static BOOL mkntfs_parse_options(int argc, char *argv[], struct mkntfs_options *opts2)
 
594
{
 
595
        static const char *sopt = "-c:CfFhH:IlL:np:qQs:S:TUvVz:";
 
596
        static const struct option lopt[] = {
 
597
                { "cluster-size",       required_argument,      NULL, 'c' },
 
598
                { "debug",              no_argument,            NULL, 'Z' },
 
599
                { "enable-compression", no_argument,            NULL, 'C' },
 
600
                { "fast",               no_argument,            NULL, 'f' },
 
601
                { "force",              no_argument,            NULL, 'F' },
 
602
                { "heads",              required_argument,      NULL, 'H' },
 
603
                { "help",               no_argument,            NULL, 'h' },
 
604
                { "label",              required_argument,      NULL, 'L' },
 
605
                { "license",            no_argument,            NULL, 'l' },
 
606
                { "mft-zone-multiplier",required_argument,      NULL, 'z' },
 
607
                { "no-action",          no_argument,            NULL, 'n' },
 
608
                { "no-indexing",        no_argument,            NULL, 'I' },
 
609
                { "partition-start",    required_argument,      NULL, 'p' },
 
610
                { "quick",              no_argument,            NULL, 'Q' },
 
611
                { "quiet",              no_argument,            NULL, 'q' },
 
612
                { "sector-size",        required_argument,      NULL, 's' },
 
613
                { "sectors-per-track",  required_argument,      NULL, 'S' },
 
614
                { "with-uuid",          no_argument,            NULL, 'U' },
 
615
                { "verbose",            no_argument,            NULL, 'v' },
 
616
                { "version",            no_argument,            NULL, 'V' },
 
617
                { "zero-time",          no_argument,            NULL, 'T' },
 
618
                { NULL, 0, NULL, 0 }
 
619
        };
 
620
 
 
621
        int c = -1;
 
622
        int lic = 0;
 
623
        int err = 0;
 
624
        int ver = 0;
 
625
 
 
626
        if (!argv || !opts2) {
 
627
                ntfs_log_error("Internal error: invalid parameters to "
 
628
                                "mkntfs_options.\n");
 
629
                return FALSE;
 
630
        }
 
631
 
 
632
        opterr = 0; /* We'll handle the errors, thank you. */
 
633
 
 
634
        while ((c = getopt_long(argc, argv, sopt, lopt, NULL)) != -1) {
 
635
                switch (c) {
 
636
                case 1:         /* A device, or a number of sectors */
 
637
                        if (!opts2->dev_name)
 
638
                                opts2->dev_name = argv[optind - 1];
 
639
                        else if (!mkntfs_parse_llong(optarg,
 
640
                                        "number of sectors",
 
641
                                        &opts2->num_sectors))
 
642
                                err++;
 
643
                        break;
 
644
                case 'C':
 
645
                        opts2->enable_compression = TRUE;
 
646
                        break;
 
647
                case 'c':
 
648
                        if (!mkntfs_parse_long(optarg, "cluster size",
 
649
                                        &opts2->cluster_size))
 
650
                                err++;
 
651
                        break;
 
652
                case 'F':
 
653
                        opts2->force = TRUE;
 
654
                        break;
 
655
                case 'f':       /* fast */
 
656
                case 'Q':       /* quick */
 
657
                        opts2->quick_format = TRUE;
 
658
                        break;
 
659
                case 'H':
 
660
                        if (!mkntfs_parse_long(optarg, "heads", &opts2->heads))
 
661
                                err++;
 
662
                        break;
 
663
                case 'h':
 
664
                        err++;  /* display help */
 
665
                        break;
 
666
                case 'I':
 
667
                        opts2->disable_indexing = TRUE;
 
668
                        break;
 
669
                case 'L':
 
670
                        if (!opts2->label) {
 
671
                                opts2->label = argv[optind-1];
 
672
                        } else {
 
673
                                ntfs_log_error("You may only specify the label "
 
674
                                                "once.\n");
 
675
                                err++;
 
676
                        }
 
677
                        break;
 
678
                case 'l':
 
679
                        lic++;  /* display the license */
 
680
                        break;
 
681
                case 'n':
 
682
                        opts2->no_action = TRUE;
 
683
                        break;
 
684
                case 'p':
 
685
                        if (!mkntfs_parse_llong(optarg, "partition start",
 
686
                                                &opts2->part_start_sect))
 
687
                                err++;
 
688
                        break;
 
689
                case 'q':
 
690
                        ntfs_log_clear_levels(NTFS_LOG_LEVEL_QUIET |
 
691
                                        NTFS_LOG_LEVEL_VERBOSE |
 
692
                                        NTFS_LOG_LEVEL_PROGRESS);
 
693
                        break;
 
694
                case 's':
 
695
                        if (!mkntfs_parse_long(optarg, "sector size",
 
696
                                                &opts2->sector_size))
 
697
                                err++;
 
698
                        break;
 
699
                case 'S':
 
700
                        if (!mkntfs_parse_long(optarg, "sectors per track",
 
701
                                                &opts2->sectors_per_track))
 
702
                                err++;
 
703
                        break;
 
704
                case 'T':
 
705
                        opts2->use_epoch_time = TRUE;
 
706
                        break;
 
707
                case 'U':
 
708
                        opts2->with_uuid = TRUE;
 
709
                        break;
 
710
                case 'v':
 
711
                        ntfs_log_set_levels(NTFS_LOG_LEVEL_QUIET |
 
712
                                        NTFS_LOG_LEVEL_VERBOSE |
 
713
                                        NTFS_LOG_LEVEL_PROGRESS);
 
714
                        break;
 
715
                case 'V':
 
716
                        ver++;  /* display version info */
 
717
                        break;
 
718
                case 'Z':       /* debug - turn on everything */
 
719
                        ntfs_log_set_levels(NTFS_LOG_LEVEL_DEBUG |
 
720
                                        NTFS_LOG_LEVEL_TRACE |
 
721
                                        NTFS_LOG_LEVEL_VERBOSE |
 
722
                                        NTFS_LOG_LEVEL_QUIET);
 
723
                        break;
 
724
                case 'z':
 
725
                        if (!mkntfs_parse_long(optarg, "mft zone multiplier",
 
726
                                                &opts2->mft_zone_multiplier))
 
727
                                err++;
 
728
                        break;
 
729
                default:
 
730
                        if (ntfs_log_parse_option (argv[optind-1]))
 
731
                                break;
 
732
                        if (((optopt == 'c') || (optopt == 'H') ||
 
733
                             (optopt == 'L') || (optopt == 'p') ||
 
734
                             (optopt == 's') || (optopt == 'S') ||
 
735
                             (optopt == 'N') || (optopt == 'z')) &&
 
736
                             (!optarg)) {
 
737
                                ntfs_log_error("Option '%s' requires an "
 
738
                                                "argument.\n", argv[optind-1]);
 
739
                        } else if (optopt != '?') {
 
740
                                ntfs_log_error("Unknown option '%s'.\n",
 
741
                                                argv[optind - 1]);
 
742
                        }
 
743
                        err++;
 
744
                        break;
 
745
                }
 
746
        }
 
747
 
 
748
        if (!err && !ver && !lic) {
 
749
                if (opts2->dev_name == NULL) {
 
750
                        if (argc > 1)
 
751
                                ntfs_log_error("You must specify a device.\n");
 
752
                        err++;
 
753
                }
 
754
        }
 
755
 
 
756
        if (ver)
 
757
                mkntfs_version();
 
758
        if (lic)
 
759
                mkntfs_license();
 
760
        if (err)
 
761
                mkntfs_usage();
 
762
 
 
763
        return (!err && !ver && !lic);
 
764
}
 
765
 
 
766
 
 
767
/**
 
768
 * mkntfs_time
 
769
 */
 
770
static ntfs_time mkntfs_time(void)
 
771
{
 
772
        struct timespec ts;
 
773
 
 
774
        ts.tv_sec = 0;
 
775
        ts.tv_nsec = 0;
 
776
        if (!opts.use_epoch_time)
 
777
                ts.tv_sec = time(NULL);
 
778
        return timespec2ntfs(ts);
 
779
}
 
780
 
 
781
/**
 
782
 * append_to_bad_blocks
 
783
 */
 
784
static BOOL append_to_bad_blocks(unsigned long long block)
 
785
{
 
786
        long long *new_buf;
 
787
 
 
788
        if (!(g_num_bad_blocks & 15)) {
 
789
                new_buf = realloc(g_bad_blocks, (g_num_bad_blocks + 16) *
 
790
                                                        sizeof(long long));
 
791
                if (!new_buf) {
 
792
                        ntfs_log_perror("Reallocating memory for bad blocks "
 
793
                                "list failed");
 
794
                        return FALSE;
 
795
                }
 
796
                g_bad_blocks = new_buf;
 
797
        }
 
798
        g_bad_blocks[g_num_bad_blocks++] = block;
 
799
        return TRUE;
 
800
}
 
801
 
 
802
/**
 
803
 * mkntfs_write
 
804
 */
 
805
static long long mkntfs_write(struct ntfs_device *dev,
 
806
                const void *b, long long count)
 
807
{
 
808
        long long bytes_written, total;
 
809
        int retry;
 
810
 
 
811
        if (opts.no_action)
 
812
                return count;
 
813
        total = 0LL;
 
814
        retry = 0;
 
815
        do {
 
816
                bytes_written = dev->d_ops->write(dev, b, count);
 
817
                if (bytes_written == -1LL) {
 
818
                        retry = errno;
 
819
                        ntfs_log_perror("Error writing to %s", dev->d_name);
 
820
                        errno = retry;
 
821
                        return bytes_written;
 
822
                } else if (!bytes_written) {
 
823
                        retry++;
 
824
                } else {
 
825
                        count -= bytes_written;
 
826
                        total += bytes_written;
 
827
                }
 
828
        } while (count && retry < 3);
 
829
        if (count)
 
830
                ntfs_log_error("Failed to complete writing to %s after three retries."
 
831
                        "\n", dev->d_name);
 
832
        return total;
 
833
}
 
834
 
 
835
/**
 
836
 *              Build and write a part of the global bitmap
 
837
 *      without overflowing from the allocated buffer
 
838
 *
 
839
 * mkntfs_bitmap_write
 
840
 */
 
841
static s64 mkntfs_bitmap_write(struct ntfs_device *dev,
 
842
                        s64 offset, s64 length)
 
843
{
 
844
        s64 partial_length;
 
845
        s64 written;
 
846
 
 
847
        partial_length = length;
 
848
        if (partial_length > g_dynamic_buf_size)
 
849
                partial_length = g_dynamic_buf_size;
 
850
                /* create a partial bitmap section, and write it */
 
851
        bitmap_build(g_dynamic_buf,offset << 3,partial_length << 3);
 
852
        written = dev->d_ops->write(dev, g_dynamic_buf, partial_length);
 
853
        return (written);
 
854
}
 
855
 
 
856
/**
 
857
 *              Build and write a part of the log file
 
858
 *      without overflowing from the allocated buffer
 
859
 *
 
860
 * mkntfs_logfile_write
 
861
 */
 
862
static s64 mkntfs_logfile_write(struct ntfs_device *dev,
 
863
                        s64 offset __attribute__((unused)), s64 length)
 
864
{
 
865
        s64 partial_length;
 
866
        s64 written;
 
867
 
 
868
        partial_length = length;
 
869
        if (partial_length > g_dynamic_buf_size)
 
870
                partial_length = g_dynamic_buf_size;
 
871
                /* create a partial bad cluster section, and write it */
 
872
        memset(g_dynamic_buf, -1, partial_length);
 
873
        written = dev->d_ops->write(dev, g_dynamic_buf, partial_length);
 
874
        return (written);
 
875
}
 
876
 
 
877
/**
 
878
 * ntfs_rlwrite - Write to disk the clusters contained in the runlist @rl
 
879
 * taking the data from @val.  Take @val_len bytes from @val and pad the
 
880
 * rest with zeroes.
 
881
 *
 
882
 * If the @rl specifies a completely sparse file, @val is allowed to be NULL.
 
883
 *
 
884
 * @inited_size if not NULL points to an output variable which will contain
 
885
 * the actual number of bytes written to disk. I.e. this will not include
 
886
 * sparse bytes for example.
 
887
 *
 
888
 * Return the number of bytes written (minus padding) or -1 on error. Errno
 
889
 * will be set to the error code.
 
890
 */
 
891
static s64 ntfs_rlwrite(struct ntfs_device *dev, const runlist *rl,
 
892
                const u8 *val, const s64 val_len, s64 *inited_size,
 
893
                WRITE_TYPE write_type)
 
894
{
 
895
        s64 bytes_written, total, length, delta;
 
896
        int retry, i;
 
897
 
 
898
        if (inited_size)
 
899
                *inited_size = 0LL;
 
900
        if (opts.no_action)
 
901
                return val_len;
 
902
        total = 0LL;
 
903
        delta = 0LL;
 
904
        for (i = 0; rl[i].length; i++) {
 
905
                length = rl[i].length * g_vol->cluster_size;
 
906
                /* Don't write sparse runs. */
 
907
                if (rl[i].lcn == -1) {
 
908
                        total += length;
 
909
                        if (!val)
 
910
                                continue;
 
911
                        /* TODO: Check that *val is really zero at pos and len. */
 
912
                        continue;
 
913
                }
 
914
                /*
 
915
                 * Break up the write into the real data write and then a write
 
916
                 * of zeroes between the end of the real data and the end of
 
917
                 * the (last) run.
 
918
                 */
 
919
                if (total + length > val_len) {
 
920
                        delta = length;
 
921
                        length = val_len - total;
 
922
                        delta -= length;
 
923
                }
 
924
                if (dev->d_ops->seek(dev, rl[i].lcn * g_vol->cluster_size,
 
925
                                SEEK_SET) == (off_t)-1)
 
926
                        return -1LL;
 
927
                retry = 0;
 
928
                do {
 
929
                        /* use specific functions if buffer is not prefilled */
 
930
                        switch (write_type) {
 
931
                        case WRITE_BITMAP :
 
932
                                bytes_written = mkntfs_bitmap_write(dev,
 
933
                                        total, length);
 
934
                                break;
 
935
                        case WRITE_LOGFILE :
 
936
                                bytes_written = mkntfs_logfile_write(dev,
 
937
                                        total, length);
 
938
                                break;
 
939
                        default :
 
940
                                bytes_written = dev->d_ops->write(dev,
 
941
                                        val + total, length);
 
942
                                break;
 
943
                        }
 
944
                        if (bytes_written == -1LL) {
 
945
                                retry = errno;
 
946
                                ntfs_log_perror("Error writing to %s",
 
947
                                        dev->d_name);
 
948
                                errno = retry;
 
949
                                return bytes_written;
 
950
                        }
 
951
                        if (bytes_written) {
 
952
                                length -= bytes_written;
 
953
                                total += bytes_written;
 
954
                                if (inited_size)
 
955
                                        *inited_size += bytes_written;
 
956
                        } else {
 
957
                                retry++;
 
958
                        }
 
959
                } while (length && retry < 3);
 
960
                if (length) {
 
961
                        ntfs_log_error("Failed to complete writing to %s after three "
 
962
                                        "retries.\n", dev->d_name);
 
963
                        return total;
 
964
                }
 
965
        }
 
966
        if (delta) {
 
967
                int eo;
 
968
                char *b = ntfs_calloc(delta);
 
969
                if (!b)
 
970
                        return -1;
 
971
                bytes_written = mkntfs_write(dev, b, delta);
 
972
                eo = errno;
 
973
                free(b);
 
974
                errno = eo;
 
975
                if (bytes_written == -1LL)
 
976
                        return bytes_written;
 
977
        }
 
978
        return total;
 
979
}
 
980
 
 
981
/**
 
982
 * make_room_for_attribute - make room for an attribute inside an mft record
 
983
 * @m:          mft record
 
984
 * @pos:        position at which to make space
 
985
 * @size:       byte size to make available at this position
 
986
 *
 
987
 * @pos points to the attribute in front of which we want to make space.
 
988
 *
 
989
 * Return 0 on success or -errno on error. Possible error codes are:
 
990
 *
 
991
 *      -ENOSPC         There is not enough space available to complete
 
992
 *                      operation. The caller has to make space before calling
 
993
 *                      this.
 
994
 *      -EINVAL         Can only occur if mkntfs was compiled with -DDEBUG. Means
 
995
 *                      the input parameters were faulty.
 
996
 */
 
997
static int make_room_for_attribute(MFT_RECORD *m, char *pos, const u32 size)
 
998
{
 
999
        u32 biu;
 
1000
 
 
1001
        if (!size)
 
1002
                return 0;
 
1003
#ifdef DEBUG
 
1004
        /*
 
1005
         * Rigorous consistency checks. Always return -EINVAL even if more
 
1006
         * appropriate codes exist for simplicity of parsing the return value.
 
1007
         */
 
1008
        if (size != ((size + 7) & ~7)) {
 
1009
                ntfs_log_error("make_room_for_attribute() received non 8-byte aligned "
 
1010
                                "size.\n");
 
1011
                return -EINVAL;
 
1012
        }
 
1013
        if (!m || !pos)
 
1014
                return -EINVAL;
 
1015
        if (pos < (char*)m || pos + size < (char*)m ||
 
1016
                        pos > (char*)m + le32_to_cpu(m->bytes_allocated) ||
 
1017
                        pos + size > (char*)m + le32_to_cpu(m->bytes_allocated))
 
1018
                return -EINVAL;
 
1019
        /* The -8 is for the attribute terminator. */
 
1020
        if (pos - (char*)m > (int)le32_to_cpu(m->bytes_in_use) - 8)
 
1021
                return -EINVAL;
 
1022
#endif
 
1023
        biu = le32_to_cpu(m->bytes_in_use);
 
1024
        /* Do we have enough space? */
 
1025
        if (biu + size > le32_to_cpu(m->bytes_allocated))
 
1026
                return -ENOSPC;
 
1027
        /* Move everything after pos to pos + size. */
 
1028
        memmove(pos + size, pos, biu - (pos - (char*)m));
 
1029
        /* Update mft record. */
 
1030
        m->bytes_in_use = cpu_to_le32(biu + size);
 
1031
        return 0;
 
1032
}
 
1033
 
 
1034
/**
 
1035
 * deallocate_scattered_clusters
 
1036
 */
 
1037
static void deallocate_scattered_clusters(const runlist *rl)
 
1038
{
 
1039
        int i;
 
1040
 
 
1041
        if (!rl)
 
1042
                return;
 
1043
        /* Iterate over all runs in the runlist @rl. */
 
1044
        for (i = 0; rl[i].length; i++) {
 
1045
                /* Skip sparse runs. */
 
1046
                if (rl[i].lcn == -1LL)
 
1047
                        continue;
 
1048
                /* Deallocate the current run. */
 
1049
                bitmap_deallocate(rl[i].lcn, rl[i].length);
 
1050
        }
 
1051
}
 
1052
 
 
1053
/**
 
1054
 * allocate_scattered_clusters
 
1055
 * @clusters: Amount of clusters to allocate.
 
1056
 *
 
1057
 * Allocate @clusters and create a runlist of the allocated clusters.
 
1058
 *
 
1059
 * Return the allocated runlist. Caller has to free the runlist when finished
 
1060
 * with it.
 
1061
 *
 
1062
 * On error return NULL and errno is set to the error code.
 
1063
 *
 
1064
 * TODO: We should be returning the size as well, but for mkntfs this is not
 
1065
 * necessary.
 
1066
 */
 
1067
static runlist * allocate_scattered_clusters(s64 clusters)
 
1068
{
 
1069
        runlist *rl = NULL, *rlt;
 
1070
        VCN vcn = 0LL;
 
1071
        LCN lcn, end, prev_lcn = 0LL;
 
1072
        int rlpos = 0;
 
1073
        int rlsize = 0;
 
1074
        s64 prev_run_len = 0LL;
 
1075
        char bit;
 
1076
 
 
1077
        end = g_vol->nr_clusters;
 
1078
        /* Loop until all clusters are allocated. */
 
1079
        while (clusters) {
 
1080
                /* Loop in current zone until we run out of free clusters. */
 
1081
                for (lcn = g_mft_zone_end; lcn < end; lcn++) {
 
1082
                        bit = bitmap_get_and_set(lcn,1);
 
1083
                        if (bit)
 
1084
                                continue;
 
1085
                        /*
 
1086
                         * Reallocate memory if necessary. Make sure we have
 
1087
                         * enough for the terminator entry as well.
 
1088
                         */
 
1089
                        if ((rlpos + 2) * (int)sizeof(runlist) >= rlsize) {
 
1090
                                rlsize += 4096; /* PAGE_SIZE */
 
1091
                                rlt = realloc(rl, rlsize);
 
1092
                                if (!rlt)
 
1093
                                        goto err_end;
 
1094
                                rl = rlt;
 
1095
                        }
 
1096
                        /* Coalesce with previous run if adjacent LCNs. */
 
1097
                        if (prev_lcn == lcn - prev_run_len) {
 
1098
                                rl[rlpos - 1].length = ++prev_run_len;
 
1099
                                vcn++;
 
1100
                        } else {
 
1101
                                rl[rlpos].vcn = vcn++;
 
1102
                                rl[rlpos].lcn = lcn;
 
1103
                                prev_lcn = lcn;
 
1104
                                rl[rlpos].length = 1LL;
 
1105
                                prev_run_len = 1LL;
 
1106
                                rlpos++;
 
1107
                        }
 
1108
                        /* Done? */
 
1109
                        if (!--clusters) {
 
1110
                                /* Add terminator element and return. */
 
1111
                                rl[rlpos].vcn = vcn;
 
1112
                                rl[rlpos].lcn = 0LL;
 
1113
                                rl[rlpos].length = 0LL;
 
1114
                                return rl;
 
1115
                        }
 
1116
 
 
1117
                }
 
1118
                /* Switch to next zone, decreasing mft zone by factor 2. */
 
1119
                end = g_mft_zone_end;
 
1120
                g_mft_zone_end >>= 1;
 
1121
                /* Have we run out of space on the volume? */
 
1122
                if (g_mft_zone_end <= 0)
 
1123
                        goto err_end;
 
1124
        }
 
1125
        return rl;
 
1126
err_end:
 
1127
        if (rl) {
 
1128
                /* Add terminator element. */
 
1129
                rl[rlpos].vcn = vcn;
 
1130
                rl[rlpos].lcn = -1LL;
 
1131
                rl[rlpos].length = 0LL;
 
1132
                /* Deallocate all allocated clusters. */
 
1133
                deallocate_scattered_clusters(rl);
 
1134
                /* Free the runlist. */
 
1135
                free(rl);
 
1136
        }
 
1137
        return NULL;
 
1138
}
 
1139
 
 
1140
/**
 
1141
 * ntfs_attr_find - find (next) attribute in mft record
 
1142
 * @type:       attribute type to find
 
1143
 * @name:       attribute name to find (optional, i.e. NULL means don't care)
 
1144
 * @name_len:   attribute name length (only needed if @name present)
 
1145
 * @ic:         IGNORE_CASE or CASE_SENSITIVE (ignored if @name not present)
 
1146
 * @val:        attribute value to find (optional, resident attributes only)
 
1147
 * @val_len:    attribute value length
 
1148
 * @ctx:        search context with mft record and attribute to search from
 
1149
 *
 
1150
 * You shouldn't need to call this function directly. Use lookup_attr() instead.
 
1151
 *
 
1152
 * ntfs_attr_find() takes a search context @ctx as parameter and searches the
 
1153
 * mft record specified by @ctx->mrec, beginning at @ctx->attr, for an
 
1154
 * attribute of @type, optionally @name and @val. If found, ntfs_attr_find()
 
1155
 * returns 0 and @ctx->attr will point to the found attribute.
 
1156
 *
 
1157
 * If not found, ntfs_attr_find() returns -1, with errno set to ENOENT and
 
1158
 * @ctx->attr will point to the attribute before which the attribute being
 
1159
 * searched for would need to be inserted if such an action were to be desired.
 
1160
 *
 
1161
 * On actual error, ntfs_attr_find() returns -1 with errno set to the error
 
1162
 * code but not to ENOENT.  In this case @ctx->attr is undefined and in
 
1163
 * particular do not rely on it not changing.
 
1164
 *
 
1165
 * If @ctx->is_first is TRUE, the search begins with @ctx->attr itself. If it
 
1166
 * is FALSE, the search begins after @ctx->attr.
 
1167
 *
 
1168
 * If @type is AT_UNUSED, return the first found attribute, i.e. one can
 
1169
 * enumerate all attributes by setting @type to AT_UNUSED and then calling
 
1170
 * ntfs_attr_find() repeatedly until it returns -1 with errno set to ENOENT to
 
1171
 * indicate that there are no more entries. During the enumeration, each
 
1172
 * successful call of ntfs_attr_find() will return the next attribute in the
 
1173
 * mft record @ctx->mrec.
 
1174
 *
 
1175
 * If @type is AT_END, seek to the end and return -1 with errno set to ENOENT.
 
1176
 * AT_END is not a valid attribute, its length is zero for example, thus it is
 
1177
 * safer to return error instead of success in this case. This also allows us
 
1178
 * to interoperate cleanly with ntfs_external_attr_find().
 
1179
 *
 
1180
 * If @name is AT_UNNAMED search for an unnamed attribute. If @name is present
 
1181
 * but not AT_UNNAMED search for a named attribute matching @name. Otherwise,
 
1182
 * match both named and unnamed attributes.
 
1183
 *
 
1184
 * If @ic is IGNORE_CASE, the @name comparison is not case sensitive and
 
1185
 * @ctx->ntfs_ino must be set to the ntfs inode to which the mft record
 
1186
 * @ctx->mrec belongs. This is so we can get at the ntfs volume and hence at
 
1187
 * the upcase table. If @ic is CASE_SENSITIVE, the comparison is case
 
1188
 * sensitive. When @name is present, @name_len is the @name length in Unicode
 
1189
 * characters.
 
1190
 *
 
1191
 * If @name is not present (NULL), we assume that the unnamed attribute is
 
1192
 * being searched for.
 
1193
 *
 
1194
 * Finally, the resident attribute value @val is looked for, if present.
 
1195
 * If @val is not present (NULL), @val_len is ignored.
 
1196
 *
 
1197
 * ntfs_attr_find() only searches the specified mft record and it ignores the
 
1198
 * presence of an attribute list attribute (unless it is the one being searched
 
1199
 * for, obviously). If you need to take attribute lists into consideration, use
 
1200
 * ntfs_attr_lookup() instead (see below). This also means that you cannot use
 
1201
 * ntfs_attr_find() to search for extent records of non-resident attributes, as
 
1202
 * extents with lowest_vcn != 0 are usually described by the attribute list
 
1203
 * attribute only. - Note that it is possible that the first extent is only in
 
1204
 * the attribute list while the last extent is in the base mft record, so don't
 
1205
 * rely on being able to find the first extent in the base mft record.
 
1206
 *
 
1207
 * Warning: Never use @val when looking for attribute types which can be
 
1208
 *          non-resident as this most likely will result in a crash!
 
1209
 */
 
1210
static int mkntfs_attr_find(const ATTR_TYPES type, const ntfschar *name,
 
1211
                const u32 name_len, const IGNORE_CASE_BOOL ic,
 
1212
                const u8 *val, const u32 val_len, ntfs_attr_search_ctx *ctx)
 
1213
{
 
1214
        ATTR_RECORD *a;
 
1215
        ntfschar *upcase = g_vol->upcase;
 
1216
        u32 upcase_len = g_vol->upcase_len;
 
1217
 
 
1218
        /*
 
1219
         * Iterate over attributes in mft record starting at @ctx->attr, or the
 
1220
         * attribute following that, if @ctx->is_first is TRUE.
 
1221
         */
 
1222
        if (ctx->is_first) {
 
1223
                a = ctx->attr;
 
1224
                ctx->is_first = FALSE;
 
1225
        } else {
 
1226
                a = (ATTR_RECORD*)((char*)ctx->attr +
 
1227
                                le32_to_cpu(ctx->attr->length));
 
1228
        }
 
1229
        for (;; a = (ATTR_RECORD*)((char*)a + le32_to_cpu(a->length))) {
 
1230
                if (p2n(a) < p2n(ctx->mrec) || (char*)a > (char*)ctx->mrec +
 
1231
                                le32_to_cpu(ctx->mrec->bytes_allocated))
 
1232
                        break;
 
1233
                ctx->attr = a;
 
1234
                if (((type != AT_UNUSED) && (le32_to_cpu(a->type) >
 
1235
                                le32_to_cpu(type))) ||
 
1236
                                (a->type == AT_END)) {
 
1237
                        errno = ENOENT;
 
1238
                        return -1;
 
1239
                }
 
1240
                if (!a->length)
 
1241
                        break;
 
1242
                /* If this is an enumeration return this attribute. */
 
1243
                if (type == AT_UNUSED)
 
1244
                        return 0;
 
1245
                if (a->type != type)
 
1246
                        continue;
 
1247
                /*
 
1248
                 * If @name is AT_UNNAMED we want an unnamed attribute.
 
1249
                 * If @name is present, compare the two names.
 
1250
                 * Otherwise, match any attribute.
 
1251
                 */
 
1252
                if (name == AT_UNNAMED) {
 
1253
                        /* The search failed if the found attribute is named. */
 
1254
                        if (a->name_length) {
 
1255
                                errno = ENOENT;
 
1256
                                return -1;
 
1257
                        }
 
1258
                } else if (name && !ntfs_names_are_equal(name, name_len,
 
1259
                                (ntfschar*)((char*)a + le16_to_cpu(a->name_offset)),
 
1260
                                a->name_length, ic, upcase, upcase_len)) {
 
1261
                        int rc;
 
1262
 
 
1263
                        rc = ntfs_names_full_collate(name, name_len,
 
1264
                                        (ntfschar*)((char*)a +
 
1265
                                        le16_to_cpu(a->name_offset)),
 
1266
                                        a->name_length, IGNORE_CASE,
 
1267
                                        upcase, upcase_len);
 
1268
                        /*
 
1269
                         * If @name collates before a->name, there is no
 
1270
                         * matching attribute.
 
1271
                         */
 
1272
                        if (rc == -1) {
 
1273
                                errno = ENOENT;
 
1274
                                return -1;
 
1275
                        }
 
1276
                        /* If the strings are not equal, continue search. */
 
1277
                        if (rc)
 
1278
                                continue;
 
1279
                        rc = ntfs_names_full_collate(name, name_len,
 
1280
                                        (ntfschar*)((char*)a +
 
1281
                                        le16_to_cpu(a->name_offset)),
 
1282
                                        a->name_length, CASE_SENSITIVE,
 
1283
                                        upcase, upcase_len);
 
1284
                        if (rc == -1) {
 
1285
                                errno = ENOENT;
 
1286
                                return -1;
 
1287
                        }
 
1288
                        if (rc)
 
1289
                                continue;
 
1290
                }
 
1291
                /*
 
1292
                 * The names match or @name not present and attribute is
 
1293
                 * unnamed. If no @val specified, we have found the attribute
 
1294
                 * and are done.
 
1295
                 */
 
1296
                if (!val) {
 
1297
                        return 0;
 
1298
                /* @val is present; compare values. */
 
1299
                } else {
 
1300
                        int rc;
 
1301
 
 
1302
                        rc = memcmp(val, (char*)a +le16_to_cpu(a->value_offset),
 
1303
                                        min(val_len,
 
1304
                                        le32_to_cpu(a->value_length)));
 
1305
                        /*
 
1306
                         * If @val collates before the current attribute's
 
1307
                         * value, there is no matching attribute.
 
1308
                         */
 
1309
                        if (!rc) {
 
1310
                                u32 avl;
 
1311
                                avl = le32_to_cpu(a->value_length);
 
1312
                                if (val_len == avl)
 
1313
                                        return 0;
 
1314
                                if (val_len < avl) {
 
1315
                                        errno = ENOENT;
 
1316
                                        return -1;
 
1317
                                }
 
1318
                        } else if (rc < 0) {
 
1319
                                errno = ENOENT;
 
1320
                                return -1;
 
1321
                        }
 
1322
                }
 
1323
        }
 
1324
        ntfs_log_trace("File is corrupt. Run chkdsk.\n");
 
1325
        errno = EIO;
 
1326
        return -1;
 
1327
}
 
1328
 
 
1329
/**
 
1330
 * ntfs_attr_lookup - find an attribute in an ntfs inode
 
1331
 * @type:       attribute type to find
 
1332
 * @name:       attribute name to find (optional, i.e. NULL means don't care)
 
1333
 * @name_len:   attribute name length (only needed if @name present)
 
1334
 * @ic:         IGNORE_CASE or CASE_SENSITIVE (ignored if @name not present)
 
1335
 * @lowest_vcn: lowest vcn to find (optional, non-resident attributes only)
 
1336
 * @val:        attribute value to find (optional, resident attributes only)
 
1337
 * @val_len:    attribute value length
 
1338
 * @ctx:        search context with mft record and attribute to search from
 
1339
 *
 
1340
 * Find an attribute in an ntfs inode. On first search @ctx->ntfs_ino must
 
1341
 * be the base mft record and @ctx must have been obtained from a call to
 
1342
 * ntfs_attr_get_search_ctx().
 
1343
 *
 
1344
 * This function transparently handles attribute lists and @ctx is used to
 
1345
 * continue searches where they were left off at.
 
1346
 *
 
1347
 * If @type is AT_UNUSED, return the first found attribute, i.e. one can
 
1348
 * enumerate all attributes by setting @type to AT_UNUSED and then calling
 
1349
 * ntfs_attr_lookup() repeatedly until it returns -1 with errno set to ENOENT
 
1350
 * to indicate that there are no more entries. During the enumeration, each
 
1351
 * successful call of ntfs_attr_lookup() will return the next attribute, with
 
1352
 * the current attribute being described by the search context @ctx.
 
1353
 *
 
1354
 * If @type is AT_END, seek to the end of the base mft record ignoring the
 
1355
 * attribute list completely and return -1 with errno set to ENOENT.  AT_END is
 
1356
 * not a valid attribute, its length is zero for example, thus it is safer to
 
1357
 * return error instead of success in this case.  It should never be needed to
 
1358
 * do this, but we implement the functionality because it allows for simpler
 
1359
 * code inside ntfs_external_attr_find().
 
1360
 *
 
1361
 * If @name is AT_UNNAMED search for an unnamed attribute. If @name is present
 
1362
 * but not AT_UNNAMED search for a named attribute matching @name. Otherwise,
 
1363
 * match both named and unnamed attributes.
 
1364
 *
 
1365
 * After finishing with the attribute/mft record you need to call
 
1366
 * ntfs_attr_put_search_ctx() to cleanup the search context (unmapping any
 
1367
 * mapped extent inodes, etc).
 
1368
 *
 
1369
 * Return 0 if the search was successful and -1 if not, with errno set to the
 
1370
 * error code.
 
1371
 *
 
1372
 * On success, @ctx->attr is the found attribute, it is in mft record
 
1373
 * @ctx->mrec, and @ctx->al_entry is the attribute list entry for this
 
1374
 * attribute with @ctx->base_* being the base mft record to which @ctx->attr
 
1375
 * belongs.  If no attribute list attribute is present @ctx->al_entry and
 
1376
 * @ctx->base_* are NULL.
 
1377
 *
 
1378
 * On error ENOENT, i.e. attribute not found, @ctx->attr is set to the
 
1379
 * attribute which collates just after the attribute being searched for in the
 
1380
 * base ntfs inode, i.e. if one wants to add the attribute to the mft record
 
1381
 * this is the correct place to insert it into, and if there is not enough
 
1382
 * space, the attribute should be placed in an extent mft record.
 
1383
 * @ctx->al_entry points to the position within @ctx->base_ntfs_ino->attr_list
 
1384
 * at which the new attribute's attribute list entry should be inserted.  The
 
1385
 * other @ctx fields, base_ntfs_ino, base_mrec, and base_attr are set to NULL.
 
1386
 * The only exception to this is when @type is AT_END, in which case
 
1387
 * @ctx->al_entry is set to NULL also (see above).
 
1388
 *
 
1389
 * The following error codes are defined:
 
1390
 *      ENOENT  Attribute not found, not an error as such.
 
1391
 *      EINVAL  Invalid arguments.
 
1392
 *      EIO     I/O error or corrupt data structures found.
 
1393
 *      ENOMEM  Not enough memory to allocate necessary buffers.
 
1394
 */
 
1395
static int mkntfs_attr_lookup(const ATTR_TYPES type, const ntfschar *name,
 
1396
                const u32 name_len, const IGNORE_CASE_BOOL ic,
 
1397
                const VCN lowest_vcn __attribute__((unused)), const u8 *val,
 
1398
                const u32 val_len, ntfs_attr_search_ctx *ctx)
 
1399
{
 
1400
        ntfs_inode *base_ni;
 
1401
 
 
1402
        if (!ctx || !ctx->mrec || !ctx->attr) {
 
1403
                errno = EINVAL;
 
1404
                return -1;
 
1405
        }
 
1406
        if (ctx->base_ntfs_ino)
 
1407
                base_ni = ctx->base_ntfs_ino;
 
1408
        else
 
1409
                base_ni = ctx->ntfs_ino;
 
1410
        if (!base_ni || !NInoAttrList(base_ni) || type == AT_ATTRIBUTE_LIST)
 
1411
                return mkntfs_attr_find(type, name, name_len, ic, val, val_len,
 
1412
                                ctx);
 
1413
        errno = EOPNOTSUPP;
 
1414
        return -1;
 
1415
}
 
1416
 
 
1417
/**
 
1418
 * insert_positioned_attr_in_mft_record
 
1419
 *
 
1420
 * Create a non-resident attribute with a predefined on disk location
 
1421
 * specified by the runlist @rl. The clusters specified by @rl are assumed to
 
1422
 * be allocated already.
 
1423
 *
 
1424
 * Return 0 on success and -errno on error.
 
1425
 */
 
1426
static int insert_positioned_attr_in_mft_record(MFT_RECORD *m,
 
1427
                const ATTR_TYPES type, const char *name, u32 name_len,
 
1428
                const IGNORE_CASE_BOOL ic, const ATTR_FLAGS flags,
 
1429
                const runlist *rl, const u8 *val, const s64 val_len)
 
1430
{
 
1431
        ntfs_attr_search_ctx *ctx;
 
1432
        ATTR_RECORD *a;
 
1433
        u16 hdr_size;
 
1434
        int asize, mpa_size, err, i;
 
1435
        s64 bw = 0, inited_size;
 
1436
        VCN highest_vcn;
 
1437
        ntfschar *uname = NULL;
 
1438
        int uname_len = 0;
 
1439
        /*
 
1440
        if (base record)
 
1441
                attr_lookup();
 
1442
        else
 
1443
        */
 
1444
 
 
1445
        uname = ntfs_str2ucs(name, &uname_len);
 
1446
        if (!uname)
 
1447
                return -errno;
 
1448
 
 
1449
        /* Check if the attribute is already there. */
 
1450
        ctx = ntfs_attr_get_search_ctx(NULL, m);
 
1451
        if (!ctx) {
 
1452
                ntfs_log_error("Failed to allocate attribute search context.\n");
 
1453
                err = -ENOMEM;
 
1454
                goto err_out;
 
1455
        }
 
1456
        if (ic == IGNORE_CASE) {
 
1457
                ntfs_log_error("FIXME: Hit unimplemented code path #1.\n");
 
1458
                err = -EOPNOTSUPP;
 
1459
                goto err_out;
 
1460
        }
 
1461
        if (!mkntfs_attr_lookup(type, uname, uname_len, ic, 0, NULL, 0, ctx)) {
 
1462
                err = -EEXIST;
 
1463
                goto err_out;
 
1464
        }
 
1465
        if (errno != ENOENT) {
 
1466
                ntfs_log_error("Corrupt inode.\n");
 
1467
                err = -errno;
 
1468
                goto err_out;
 
1469
        }
 
1470
        a = ctx->attr;
 
1471
        if (flags & ATTR_COMPRESSION_MASK) {
 
1472
                ntfs_log_error("Compressed attributes not supported yet.\n");
 
1473
                /* FIXME: Compress attribute into a temporary buffer, set */
 
1474
                /* val accordingly and save the compressed size. */
 
1475
                err = -EOPNOTSUPP;
 
1476
                goto err_out;
 
1477
        }
 
1478
        if (flags & (ATTR_IS_ENCRYPTED | ATTR_IS_SPARSE)) {
 
1479
                ntfs_log_error("Encrypted/sparse attributes not supported.\n");
 
1480
                err = -EOPNOTSUPP;
 
1481
                goto err_out;
 
1482
        }
 
1483
        if (flags & ATTR_COMPRESSION_MASK) {
 
1484
                hdr_size = 72;
 
1485
                /* FIXME: This compression stuff is all wrong. Never mind for */
 
1486
                /* now. (AIA) */
 
1487
                if (val_len)
 
1488
                        mpa_size = 0; /* get_size_for_compressed_mapping_pairs(rl); */
 
1489
                else
 
1490
                        mpa_size = 0;
 
1491
        } else {
 
1492
                hdr_size = 64;
 
1493
                if (val_len) {
 
1494
                        mpa_size = ntfs_get_size_for_mapping_pairs(g_vol, rl, 0, INT_MAX);
 
1495
                        if (mpa_size < 0) {
 
1496
                                err = -errno;
 
1497
                                ntfs_log_error("Failed to get size for mapping "
 
1498
                                                "pairs.\n");
 
1499
                                goto err_out;
 
1500
                        }
 
1501
                } else {
 
1502
                        mpa_size = 0;
 
1503
                }
 
1504
        }
 
1505
        /* Mapping pairs array and next attribute must be 8-byte aligned. */
 
1506
        asize = (((int)hdr_size + ((name_len + 7) & ~7) + mpa_size) + 7) & ~7;
 
1507
        /* Get the highest vcn. */
 
1508
        for (i = 0, highest_vcn = 0LL; rl[i].length; i++)
 
1509
                highest_vcn += rl[i].length;
 
1510
        /* Does the value fit inside the allocated size? */
 
1511
        if (highest_vcn * g_vol->cluster_size < val_len) {
 
1512
                ntfs_log_error("BUG: Allocated size is smaller than data size!\n");
 
1513
                err = -EINVAL;
 
1514
                goto err_out;
 
1515
        }
 
1516
        err = make_room_for_attribute(m, (char*)a, asize);
 
1517
        if (err == -ENOSPC) {
 
1518
                /*
 
1519
                 * FIXME: Make space! (AIA)
 
1520
                 * can we make it non-resident? if yes, do that.
 
1521
                 *      does it fit now? yes -> do it.
 
1522
                 * m's $DATA or $BITMAP+$INDEX_ALLOCATION resident?
 
1523
                 * yes -> make non-resident
 
1524
                 *      does it fit now? yes -> do it.
 
1525
                 * make all attributes non-resident
 
1526
                 *      does it fit now? yes -> do it.
 
1527
                 * m is a base record? yes -> allocate extension record
 
1528
                 *      does the new attribute fit in there? yes -> do it.
 
1529
                 * split up runlist into extents and place each in an extension
 
1530
                 * record.
 
1531
                 * FIXME: the check for needing extension records should be
 
1532
                 * earlier on as it is very quick: asize > m->bytes_allocated?
 
1533
                 */
 
1534
                err = -EOPNOTSUPP;
 
1535
                goto err_out;
 
1536
#ifdef DEBUG
 
1537
        } else if (err == -EINVAL) {
 
1538
                ntfs_log_error("BUG(): in insert_positioned_attribute_in_mft_"
 
1539
                                "record(): make_room_for_attribute() returned "
 
1540
                                "error: EINVAL!\n");
 
1541
                goto err_out;
 
1542
#endif
 
1543
        }
 
1544
        a->type = type;
 
1545
        a->length = cpu_to_le32(asize);
 
1546
        a->non_resident = 1;
 
1547
        a->name_length = name_len;
 
1548
        a->name_offset = cpu_to_le16(hdr_size);
 
1549
        a->flags = flags;
 
1550
        a->instance = m->next_attr_instance;
 
1551
        m->next_attr_instance = cpu_to_le16((le16_to_cpu(m->next_attr_instance)
 
1552
                        + 1) & 0xffff);
 
1553
        a->lowest_vcn = cpu_to_le64(0);
 
1554
        a->highest_vcn = cpu_to_sle64(highest_vcn - 1LL);
 
1555
        a->mapping_pairs_offset = cpu_to_le16(hdr_size + ((name_len + 7) & ~7));
 
1556
        memset(a->reserved1, 0, sizeof(a->reserved1));
 
1557
        /* FIXME: Allocated size depends on compression. */
 
1558
        a->allocated_size = cpu_to_sle64(highest_vcn * g_vol->cluster_size);
 
1559
        a->data_size = cpu_to_sle64(val_len);
 
1560
        if (name_len)
 
1561
                memcpy((char*)a + hdr_size, uname, name_len << 1);
 
1562
        if (flags & ATTR_COMPRESSION_MASK) {
 
1563
                if (flags & ATTR_COMPRESSION_MASK & ~ATTR_IS_COMPRESSED) {
 
1564
                        ntfs_log_error("Unknown compression format. Reverting "
 
1565
                                        "to standard compression.\n");
 
1566
                        a->flags &= ~ATTR_COMPRESSION_MASK;
 
1567
                        a->flags |= ATTR_IS_COMPRESSED;
 
1568
                }
 
1569
                a->compression_unit = 4;
 
1570
                inited_size = val_len;
 
1571
                /* FIXME: Set the compressed size. */
 
1572
                a->compressed_size = cpu_to_le64(0);
 
1573
                /* FIXME: Write out the compressed data. */
 
1574
                /* FIXME: err = build_mapping_pairs_compressed(); */
 
1575
                err = -EOPNOTSUPP;
 
1576
        } else {
 
1577
                a->compression_unit = 0;
 
1578
                if ((type == AT_DATA)
 
1579
                    && (m->mft_record_number
 
1580
                                 == const_cpu_to_le32(FILE_LogFile)))
 
1581
                        bw = ntfs_rlwrite(g_vol->dev, rl, val, val_len,
 
1582
                                        &inited_size, WRITE_LOGFILE);
 
1583
                else
 
1584
                        bw = ntfs_rlwrite(g_vol->dev, rl, val, val_len,
 
1585
                                        &inited_size, WRITE_STANDARD);
 
1586
                if (bw != val_len) {
 
1587
                        ntfs_log_error("Error writing non-resident attribute "
 
1588
                                        "value.\n");
 
1589
                        return -errno;
 
1590
                }
 
1591
                err = ntfs_mapping_pairs_build(g_vol, (u8*)a + hdr_size +
 
1592
                                ((name_len + 7) & ~7), mpa_size, rl, 0, NULL);
 
1593
        }
 
1594
        a->initialized_size = cpu_to_sle64(inited_size);
 
1595
        if (err < 0 || bw != val_len) {
 
1596
                /* FIXME: Handle error. */
 
1597
                /* deallocate clusters */
 
1598
                /* remove attribute */
 
1599
                if (err >= 0)
 
1600
                        err = -EIO;
 
1601
                ntfs_log_error("insert_positioned_attr_in_mft_record failed "
 
1602
                                "with error %i.\n", err < 0 ? err : (int)bw);
 
1603
        }
 
1604
err_out:
 
1605
        if (ctx)
 
1606
                ntfs_attr_put_search_ctx(ctx);
 
1607
        ntfs_ucsfree(uname);
 
1608
        return err;
 
1609
}
 
1610
 
 
1611
/**
 
1612
 * insert_non_resident_attr_in_mft_record
 
1613
 *
 
1614
 * Return 0 on success and -errno on error.
 
1615
 */
 
1616
static int insert_non_resident_attr_in_mft_record(MFT_RECORD *m,
 
1617
                const ATTR_TYPES type, const char *name, u32 name_len,
 
1618
                const IGNORE_CASE_BOOL ic, const ATTR_FLAGS flags,
 
1619
                const u8 *val, const s64 val_len,
 
1620
                WRITE_TYPE write_type)
 
1621
{
 
1622
        ntfs_attr_search_ctx *ctx;
 
1623
        ATTR_RECORD *a;
 
1624
        u16 hdr_size;
 
1625
        int asize, mpa_size, err, i;
 
1626
        runlist *rl = NULL;
 
1627
        s64 bw = 0;
 
1628
        ntfschar *uname = NULL;
 
1629
        int uname_len = 0;
 
1630
        /*
 
1631
        if (base record)
 
1632
                attr_lookup();
 
1633
        else
 
1634
        */
 
1635
 
 
1636
        uname = ntfs_str2ucs(name, &uname_len);
 
1637
        if (!uname)
 
1638
                return -errno;
 
1639
 
 
1640
        /* Check if the attribute is already there. */
 
1641
        ctx = ntfs_attr_get_search_ctx(NULL, m);
 
1642
        if (!ctx) {
 
1643
                ntfs_log_error("Failed to allocate attribute search context.\n");
 
1644
                err = -ENOMEM;
 
1645
                goto err_out;
 
1646
        }
 
1647
        if (ic == IGNORE_CASE) {
 
1648
                ntfs_log_error("FIXME: Hit unimplemented code path #2.\n");
 
1649
                err = -EOPNOTSUPP;
 
1650
                goto err_out;
 
1651
        }
 
1652
        if (!mkntfs_attr_lookup(type, uname, uname_len, ic, 0, NULL, 0, ctx)) {
 
1653
                err = -EEXIST;
 
1654
                goto err_out;
 
1655
        }
 
1656
        if (errno != ENOENT) {
 
1657
                ntfs_log_error("Corrupt inode.\n");
 
1658
                err = -errno;
 
1659
                goto err_out;
 
1660
        }
 
1661
        a = ctx->attr;
 
1662
        if (flags & ATTR_COMPRESSION_MASK) {
 
1663
                ntfs_log_error("Compressed attributes not supported yet.\n");
 
1664
                /* FIXME: Compress attribute into a temporary buffer, set */
 
1665
                /* val accordingly and save the compressed size. */
 
1666
                err = -EOPNOTSUPP;
 
1667
                goto err_out;
 
1668
        }
 
1669
        if (flags & (ATTR_IS_ENCRYPTED | ATTR_IS_SPARSE)) {
 
1670
                ntfs_log_error("Encrypted/sparse attributes not supported.\n");
 
1671
                err = -EOPNOTSUPP;
 
1672
                goto err_out;
 
1673
        }
 
1674
        if (val_len) {
 
1675
                rl = allocate_scattered_clusters((val_len +
 
1676
                                g_vol->cluster_size - 1) / g_vol->cluster_size);
 
1677
                if (!rl) {
 
1678
                        err = -errno;
 
1679
                        ntfs_log_perror("Failed to allocate scattered clusters");
 
1680
                        goto err_out;
 
1681
                }
 
1682
        } else {
 
1683
                rl = NULL;
 
1684
        }
 
1685
        if (flags & ATTR_COMPRESSION_MASK) {
 
1686
                hdr_size = 72;
 
1687
                /* FIXME: This compression stuff is all wrong. Never mind for */
 
1688
                /* now. (AIA) */
 
1689
                if (val_len)
 
1690
                        mpa_size = 0; /* get_size_for_compressed_mapping_pairs(rl); */
 
1691
                else
 
1692
                        mpa_size = 0;
 
1693
        } else {
 
1694
                hdr_size = 64;
 
1695
                if (val_len) {
 
1696
                        mpa_size = ntfs_get_size_for_mapping_pairs(g_vol, rl, 0, INT_MAX);
 
1697
                        if (mpa_size < 0) {
 
1698
                                err = -errno;
 
1699
                                ntfs_log_error("Failed to get size for mapping "
 
1700
                                                "pairs.\n");
 
1701
                                goto err_out;
 
1702
                        }
 
1703
                } else {
 
1704
                        mpa_size = 0;
 
1705
                }
 
1706
        }
 
1707
        /* Mapping pairs array and next attribute must be 8-byte aligned. */
 
1708
        asize = (((int)hdr_size + ((name_len + 7) & ~7) + mpa_size) + 7) & ~7;
 
1709
        err = make_room_for_attribute(m, (char*)a, asize);
 
1710
        if (err == -ENOSPC) {
 
1711
                /*
 
1712
                 * FIXME: Make space! (AIA)
 
1713
                 * can we make it non-resident? if yes, do that.
 
1714
                 *      does it fit now? yes -> do it.
 
1715
                 * m's $DATA or $BITMAP+$INDEX_ALLOCATION resident?
 
1716
                 * yes -> make non-resident
 
1717
                 *      does it fit now? yes -> do it.
 
1718
                 * make all attributes non-resident
 
1719
                 *      does it fit now? yes -> do it.
 
1720
                 * m is a base record? yes -> allocate extension record
 
1721
                 *      does the new attribute fit in there? yes -> do it.
 
1722
                 * split up runlist into extents and place each in an extension
 
1723
                 * record.
 
1724
                 * FIXME: the check for needing extension records should be
 
1725
                 * earlier on as it is very quick: asize > m->bytes_allocated?
 
1726
                 */
 
1727
                err = -EOPNOTSUPP;
 
1728
                goto err_out;
 
1729
#ifdef DEBUG
 
1730
        } else if (err == -EINVAL) {
 
1731
                ntfs_log_error("BUG(): in insert_non_resident_attribute_in_"
 
1732
                                "mft_record(): make_room_for_attribute() "
 
1733
                                "returned error: EINVAL!\n");
 
1734
                goto err_out;
 
1735
#endif
 
1736
        }
 
1737
        a->type = type;
 
1738
        a->length = cpu_to_le32(asize);
 
1739
        a->non_resident = 1;
 
1740
        a->name_length = name_len;
 
1741
        a->name_offset = cpu_to_le16(hdr_size);
 
1742
        a->flags = flags;
 
1743
        a->instance = m->next_attr_instance;
 
1744
        m->next_attr_instance = cpu_to_le16((le16_to_cpu(m->next_attr_instance)
 
1745
                        + 1) & 0xffff);
 
1746
        a->lowest_vcn = cpu_to_le64(0);
 
1747
        for (i = 0; rl[i].length; i++)
 
1748
                ;
 
1749
        a->highest_vcn = cpu_to_sle64(rl[i].vcn - 1);
 
1750
        a->mapping_pairs_offset = cpu_to_le16(hdr_size + ((name_len + 7) & ~7));
 
1751
        memset(a->reserved1, 0, sizeof(a->reserved1));
 
1752
        /* FIXME: Allocated size depends on compression. */
 
1753
        a->allocated_size = cpu_to_sle64((val_len + (g_vol->cluster_size - 1)) &
 
1754
                        ~(g_vol->cluster_size - 1));
 
1755
        a->data_size = cpu_to_sle64(val_len);
 
1756
        a->initialized_size = cpu_to_sle64(val_len);
 
1757
        if (name_len)
 
1758
                memcpy((char*)a + hdr_size, uname, name_len << 1);
 
1759
        if (flags & ATTR_COMPRESSION_MASK) {
 
1760
                if (flags & ATTR_COMPRESSION_MASK & ~ATTR_IS_COMPRESSED) {
 
1761
                        ntfs_log_error("Unknown compression format. Reverting "
 
1762
                                        "to standard compression.\n");
 
1763
                        a->flags &= ~ATTR_COMPRESSION_MASK;
 
1764
                        a->flags |= ATTR_IS_COMPRESSED;
 
1765
                }
 
1766
                a->compression_unit = 4;
 
1767
                /* FIXME: Set the compressed size. */
 
1768
                a->compressed_size = cpu_to_le64(0);
 
1769
                /* FIXME: Write out the compressed data. */
 
1770
                /* FIXME: err = build_mapping_pairs_compressed(); */
 
1771
                err = -EOPNOTSUPP;
 
1772
        } else {
 
1773
                a->compression_unit = 0;
 
1774
                bw = ntfs_rlwrite(g_vol->dev, rl, val, val_len, NULL,
 
1775
                                        write_type);
 
1776
                if (bw != val_len) {
 
1777
                        ntfs_log_error("Error writing non-resident attribute "
 
1778
                                        "value.\n");
 
1779
                        return -errno;
 
1780
                }
 
1781
                err = ntfs_mapping_pairs_build(g_vol, (u8*)a + hdr_size +
 
1782
                                ((name_len + 7) & ~7), mpa_size, rl, 0, NULL);
 
1783
        }
 
1784
        if (err < 0 || bw != val_len) {
 
1785
                /* FIXME: Handle error. */
 
1786
                /* deallocate clusters */
 
1787
                /* remove attribute */
 
1788
                if (err >= 0)
 
1789
                        err = -EIO;
 
1790
                ntfs_log_error("insert_non_resident_attr_in_mft_record failed with "
 
1791
                        "error %lld.\n", (long long) (err < 0 ? err : bw));
 
1792
        }
 
1793
err_out:
 
1794
        if (ctx)
 
1795
                ntfs_attr_put_search_ctx(ctx);
 
1796
        ntfs_ucsfree(uname);
 
1797
        free(rl);
 
1798
        return err;
 
1799
}
 
1800
 
 
1801
/**
 
1802
 * insert_resident_attr_in_mft_record
 
1803
 *
 
1804
 * Return 0 on success and -errno on error.
 
1805
 */
 
1806
static int insert_resident_attr_in_mft_record(MFT_RECORD *m,
 
1807
                const ATTR_TYPES type, const char *name, u32 name_len,
 
1808
                const IGNORE_CASE_BOOL ic, const ATTR_FLAGS flags,
 
1809
                const RESIDENT_ATTR_FLAGS res_flags,
 
1810
                const u8 *val, const u32 val_len)
 
1811
{
 
1812
        ntfs_attr_search_ctx *ctx;
 
1813
        ATTR_RECORD *a;
 
1814
        int asize, err;
 
1815
        ntfschar *uname = NULL;
 
1816
        int uname_len = 0;
 
1817
        /*
 
1818
        if (base record)
 
1819
                mkntfs_attr_lookup();
 
1820
        else
 
1821
        */
 
1822
 
 
1823
        uname = ntfs_str2ucs(name, &uname_len);
 
1824
        if (!uname)
 
1825
                return -errno;
 
1826
 
 
1827
        /* Check if the attribute is already there. */
 
1828
        ctx = ntfs_attr_get_search_ctx(NULL, m);
 
1829
        if (!ctx) {
 
1830
                ntfs_log_error("Failed to allocate attribute search context.\n");
 
1831
                err = -ENOMEM;
 
1832
                goto err_out;
 
1833
        }
 
1834
        if (ic == IGNORE_CASE) {
 
1835
                ntfs_log_error("FIXME: Hit unimplemented code path #3.\n");
 
1836
                err = -EOPNOTSUPP;
 
1837
                goto err_out;
 
1838
        }
 
1839
        if (!mkntfs_attr_lookup(type, uname, uname_len, ic, 0, val, val_len,
 
1840
                        ctx)) {
 
1841
                err = -EEXIST;
 
1842
                goto err_out;
 
1843
        }
 
1844
        if (errno != ENOENT) {
 
1845
                ntfs_log_error("Corrupt inode.\n");
 
1846
                err = -errno;
 
1847
                goto err_out;
 
1848
        }
 
1849
        a = ctx->attr;
 
1850
        /* sizeof(resident attribute record header) == 24 */
 
1851
        asize = ((24 + ((name_len*2 + 7) & ~7) + val_len) + 7) & ~7;
 
1852
        err = make_room_for_attribute(m, (char*)a, asize);
 
1853
        if (err == -ENOSPC) {
 
1854
                /*
 
1855
                 * FIXME: Make space! (AIA)
 
1856
                 * can we make it non-resident? if yes, do that.
 
1857
                 *      does it fit now? yes -> do it.
 
1858
                 * m's $DATA or $BITMAP+$INDEX_ALLOCATION resident?
 
1859
                 * yes -> make non-resident
 
1860
                 *      does it fit now? yes -> do it.
 
1861
                 * make all attributes non-resident
 
1862
                 *      does it fit now? yes -> do it.
 
1863
                 * m is a base record? yes -> allocate extension record
 
1864
                 *      does the new attribute fit in there? yes -> do it.
 
1865
                 * split up runlist into extents and place each in an extension
 
1866
                 * record.
 
1867
                 * FIXME: the check for needing extension records should be
 
1868
                 * earlier on as it is very quick: asize > m->bytes_allocated?
 
1869
                 */
 
1870
                err = -EOPNOTSUPP;
 
1871
                goto err_out;
 
1872
        }
 
1873
#ifdef DEBUG
 
1874
        if (err == -EINVAL) {
 
1875
                ntfs_log_error("BUG(): in insert_resident_attribute_in_mft_"
 
1876
                                "record(): make_room_for_attribute() returned "
 
1877
                                "error: EINVAL!\n");
 
1878
                goto err_out;
 
1879
        }
 
1880
#endif
 
1881
        a->type = type;
 
1882
        a->length = cpu_to_le32(asize);
 
1883
        a->non_resident = 0;
 
1884
        a->name_length = name_len;
 
1885
        if (type == AT_OBJECT_ID)
 
1886
                a->name_offset = const_cpu_to_le16(0);
 
1887
        else
 
1888
                a->name_offset = const_cpu_to_le16(24);
 
1889
        a->flags = flags;
 
1890
        a->instance = m->next_attr_instance;
 
1891
        m->next_attr_instance = cpu_to_le16((le16_to_cpu(m->next_attr_instance)
 
1892
                        + 1) & 0xffff);
 
1893
        a->value_length = cpu_to_le32(val_len);
 
1894
        a->value_offset = cpu_to_le16(24 + ((name_len*2 + 7) & ~7));
 
1895
        a->resident_flags = res_flags;
 
1896
        a->reservedR = 0;
 
1897
        if (name_len)
 
1898
                memcpy((char*)a + 24, uname, name_len << 1);
 
1899
        if (val_len)
 
1900
                memcpy((char*)a + le16_to_cpu(a->value_offset), val, val_len);
 
1901
err_out:
 
1902
        if (ctx)
 
1903
                ntfs_attr_put_search_ctx(ctx);
 
1904
        ntfs_ucsfree(uname);
 
1905
        return err;
 
1906
}
 
1907
 
 
1908
 
 
1909
/**
 
1910
 * add_attr_std_info
 
1911
 *
 
1912
 * Return 0 on success or -errno on error.
 
1913
 */
 
1914
static int add_attr_std_info(MFT_RECORD *m, const FILE_ATTR_FLAGS flags,
 
1915
                le32 security_id)
 
1916
{
 
1917
        STANDARD_INFORMATION si;
 
1918
        int err, sd_size;
 
1919
 
 
1920
        sd_size = 48;
 
1921
 
 
1922
        si.creation_time = mkntfs_time();
 
1923
        si.last_data_change_time = si.creation_time;
 
1924
        si.last_mft_change_time = si.creation_time;
 
1925
        si.last_access_time = si.creation_time;
 
1926
        si.file_attributes = flags; /* already LE */
 
1927
        si.maximum_versions = cpu_to_le32(0);
 
1928
        si.version_number = cpu_to_le32(0);
 
1929
        si.class_id = cpu_to_le32(0);
 
1930
        si.security_id = security_id;
 
1931
        if (si.security_id != const_cpu_to_le32(0))
 
1932
                sd_size = 72;
 
1933
        /* FIXME: $Quota support... */
 
1934
        si.owner_id = cpu_to_le32(0);
 
1935
        si.quota_charged = cpu_to_le64(0ULL);
 
1936
        /* FIXME: $UsnJrnl support... Not needed on fresh w2k3-volume */
 
1937
        si.usn = cpu_to_le64(0ULL);
 
1938
        /* NTFS 1.2: size of si = 48, NTFS 3.[01]: size of si = 72 */
 
1939
        err = insert_resident_attr_in_mft_record(m, AT_STANDARD_INFORMATION,
 
1940
                        NULL, 0, CASE_SENSITIVE, const_cpu_to_le16(0),
 
1941
                        0, (u8*)&si, sd_size);
 
1942
        if (err < 0)
 
1943
                ntfs_log_perror("add_attr_std_info failed");
 
1944
        return err;
 
1945
}
 
1946
 
 
1947
/*
 
1948
 *              Tell whether the unnamed data is non resident
 
1949
 */
 
1950
 
 
1951
static BOOL non_resident_unnamed_data(MFT_RECORD *m)
 
1952
{
 
1953
        ATTR_RECORD *a;
 
1954
        ntfs_attr_search_ctx *ctx;
 
1955
        BOOL nonres;
 
1956
 
 
1957
        ctx = ntfs_attr_get_search_ctx(NULL, m);
 
1958
        if (ctx && !mkntfs_attr_find(AT_DATA,
 
1959
                                (const ntfschar*)NULL, 0, CASE_SENSITIVE,
 
1960
                                (u8*)NULL, 0, ctx)) {
 
1961
                a = ctx->attr;
 
1962
                nonres = a->non_resident != 0;
 
1963
        } else {
 
1964
                ntfs_log_error("BUG: Unnamed data not found\n");
 
1965
                nonres = TRUE;
 
1966
        }
 
1967
        if (ctx)
 
1968
                ntfs_attr_put_search_ctx(ctx);
 
1969
        return (nonres);
 
1970
}
 
1971
 
 
1972
/*
 
1973
 *              Get the time stored in the standard information attribute
 
1974
 */
 
1975
 
 
1976
static ntfs_time stdinfo_time(MFT_RECORD *m)
 
1977
{
 
1978
        STANDARD_INFORMATION *si;
 
1979
        ntfs_attr_search_ctx *ctx;
 
1980
        ntfs_time info_time;
 
1981
 
 
1982
        ctx = ntfs_attr_get_search_ctx(NULL, m);
 
1983
        if (ctx && !mkntfs_attr_find(AT_STANDARD_INFORMATION,
 
1984
                                (const ntfschar*)NULL, 0, CASE_SENSITIVE,
 
1985
                                (u8*)NULL, 0, ctx)) {
 
1986
                si = (STANDARD_INFORMATION*)((char*)ctx->attr +
 
1987
                                le16_to_cpu(ctx->attr->value_offset));
 
1988
                info_time = si->creation_time;
 
1989
        } else {
 
1990
                ntfs_log_error("BUG: Standard information not found\n");
 
1991
                info_time = mkntfs_time();
 
1992
        }
 
1993
        if (ctx)
 
1994
                ntfs_attr_put_search_ctx(ctx);
 
1995
        return (info_time);
 
1996
}
 
1997
 
 
1998
/**
 
1999
 * add_attr_file_name
 
2000
 *
 
2001
 * Return 0 on success or -errno on error.
 
2002
 */
 
2003
static int add_attr_file_name(MFT_RECORD *m, const leMFT_REF parent_dir,
 
2004
                const s64 allocated_size, const s64 data_size,
 
2005
                const FILE_ATTR_FLAGS flags, const u16 packed_ea_size,
 
2006
                const u32 reparse_point_tag, const char *file_name,
 
2007
                const FILE_NAME_TYPE_FLAGS file_name_type)
 
2008
{
 
2009
        ntfs_attr_search_ctx *ctx;
 
2010
        STANDARD_INFORMATION *si;
 
2011
        FILE_NAME_ATTR *fn;
 
2012
        int i, fn_size;
 
2013
        ntfschar *uname;
 
2014
 
 
2015
        /* Check if the attribute is already there. */
 
2016
        ctx = ntfs_attr_get_search_ctx(NULL, m);
 
2017
        if (!ctx) {
 
2018
                ntfs_log_error("Failed to get attribute search context.\n");
 
2019
                return -ENOMEM;
 
2020
        }
 
2021
        if (mkntfs_attr_lookup(AT_STANDARD_INFORMATION, AT_UNNAMED, 0,
 
2022
                                CASE_SENSITIVE, 0, NULL, 0, ctx)) {
 
2023
                int eo = errno;
 
2024
                ntfs_log_error("BUG: Standard information attribute not "
 
2025
                                "present in file record.\n");
 
2026
                ntfs_attr_put_search_ctx(ctx);
 
2027
                return -eo;
 
2028
        }
 
2029
        si = (STANDARD_INFORMATION*)((char*)ctx->attr +
 
2030
                        le16_to_cpu(ctx->attr->value_offset));
 
2031
        i = (strlen(file_name) + 1) * sizeof(ntfschar);
 
2032
        fn_size = sizeof(FILE_NAME_ATTR) + i;
 
2033
        fn = ntfs_malloc(fn_size);
 
2034
        if (!fn) {
 
2035
                ntfs_attr_put_search_ctx(ctx);
 
2036
                return -errno;
 
2037
        }
 
2038
        fn->parent_directory = parent_dir;
 
2039
 
 
2040
        fn->creation_time = si->creation_time;
 
2041
        fn->last_data_change_time = si->last_data_change_time;
 
2042
        fn->last_mft_change_time = si->last_mft_change_time;
 
2043
        fn->last_access_time = si->last_access_time;
 
2044
        ntfs_attr_put_search_ctx(ctx);
 
2045
 
 
2046
        fn->allocated_size = cpu_to_sle64(allocated_size);
 
2047
        fn->data_size = cpu_to_sle64(data_size);
 
2048
        fn->file_attributes = flags;
 
2049
        /* These are in a union so can't have both. */
 
2050
        if (packed_ea_size && reparse_point_tag) {
 
2051
                free(fn);
 
2052
                return -EINVAL;
 
2053
        }
 
2054
        if (packed_ea_size) {
 
2055
                fn->packed_ea_size = cpu_to_le16(packed_ea_size);
 
2056
                fn->reserved = cpu_to_le16(0);
 
2057
        } else {
 
2058
                fn->reparse_point_tag = cpu_to_le32(reparse_point_tag);
 
2059
        }
 
2060
        fn->file_name_type = file_name_type;
 
2061
        uname = fn->file_name;
 
2062
        i = ntfs_mbstoucs_libntfscompat(file_name, &uname, i);
 
2063
        if (i < 1) {
 
2064
                free(fn);
 
2065
                return -EINVAL;
 
2066
        }
 
2067
        if (i > 0xff) {
 
2068
                free(fn);
 
2069
                return -ENAMETOOLONG;
 
2070
        }
 
2071
        /* No terminating null in file names. */
 
2072
        fn->file_name_length = i;
 
2073
        fn_size = sizeof(FILE_NAME_ATTR) + i * sizeof(ntfschar);
 
2074
        i = insert_resident_attr_in_mft_record(m, AT_FILE_NAME, NULL, 0,
 
2075
                        CASE_SENSITIVE, const_cpu_to_le16(0),
 
2076
                        RESIDENT_ATTR_IS_INDEXED, (u8*)fn, fn_size);
 
2077
        free(fn);
 
2078
        if (i < 0)
 
2079
                ntfs_log_error("add_attr_file_name failed: %s\n", strerror(-i));
 
2080
        return i;
 
2081
}
 
2082
 
 
2083
/**
 
2084
 * add_attr_object_id -
 
2085
 *
 
2086
 * Note we insert only a basic object id which only has the GUID and none of
 
2087
 * the extended fields.  This is because we currently only use this function
 
2088
 * when creating the object id for the volume.
 
2089
 *
 
2090
 * Return 0 on success or -errno on error.
 
2091
 */
 
2092
static int add_attr_object_id(MFT_RECORD *m, const GUID *object_id)
 
2093
{
 
2094
        OBJECT_ID_ATTR oi;
 
2095
        int err;
 
2096
 
 
2097
        oi = (OBJECT_ID_ATTR) {
 
2098
                .object_id = *object_id,
 
2099
        };
 
2100
        err = insert_resident_attr_in_mft_record(m, AT_OBJECT_ID, NULL,
 
2101
                        0, CASE_SENSITIVE, const_cpu_to_le16(0),
 
2102
                        0, (u8*)&oi, sizeof(oi.object_id));
 
2103
        if (err < 0)
 
2104
                ntfs_log_error("add_attr_vol_info failed: %s\n", strerror(-err));
 
2105
        return err;
 
2106
}
 
2107
 
 
2108
/**
 
2109
 * add_attr_sd
 
2110
 *
 
2111
 * Create the security descriptor attribute adding the security descriptor @sd
 
2112
 * of length @sd_len to the mft record @m.
 
2113
 *
 
2114
 * Return 0 on success or -errno on error.
 
2115
 */
 
2116
static int add_attr_sd(MFT_RECORD *m, const u8 *sd, const s64 sd_len)
 
2117
{
 
2118
        int err;
 
2119
 
 
2120
        /* Does it fit? NO: create non-resident. YES: create resident. */
 
2121
        if (le32_to_cpu(m->bytes_in_use) + 24 + sd_len >
 
2122
                                                le32_to_cpu(m->bytes_allocated))
 
2123
                err = insert_non_resident_attr_in_mft_record(m,
 
2124
                                AT_SECURITY_DESCRIPTOR, NULL, 0,
 
2125
                                CASE_SENSITIVE, const_cpu_to_le16(0), sd,
 
2126
                                sd_len, WRITE_STANDARD);
 
2127
        else
 
2128
                err = insert_resident_attr_in_mft_record(m,
 
2129
                                AT_SECURITY_DESCRIPTOR, NULL, 0,
 
2130
                                CASE_SENSITIVE, const_cpu_to_le16(0), 0, sd,
 
2131
                                sd_len);
 
2132
        if (err < 0)
 
2133
                ntfs_log_error("add_attr_sd failed: %s\n", strerror(-err));
 
2134
        return err;
 
2135
}
 
2136
 
 
2137
/**
 
2138
 * add_attr_data
 
2139
 *
 
2140
 * Return 0 on success or -errno on error.
 
2141
 */
 
2142
static int add_attr_data(MFT_RECORD *m, const char *name, const u32 name_len,
 
2143
                const IGNORE_CASE_BOOL ic, const ATTR_FLAGS flags,
 
2144
                const u8 *val, const s64 val_len)
 
2145
{
 
2146
        int err;
 
2147
 
 
2148
        /*
 
2149
         * Does it fit? NO: create non-resident. YES: create resident.
 
2150
         *
 
2151
         * FIXME: Introduced arbitrary limit of mft record allocated size - 512.
 
2152
         * This is to get around the problem that if $Bitmap/$DATA becomes too
 
2153
         * big, but is just small enough to be resident, we would make it
 
2154
         * resident, and later run out of space when creating the other
 
2155
         * attributes and this would cause us to abort as making resident
 
2156
         * attributes non-resident is not supported yet.
 
2157
         * The proper fix is to support making resident attribute non-resident.
 
2158
         */
 
2159
        if (le32_to_cpu(m->bytes_in_use) + 24 + val_len >
 
2160
                        min(le32_to_cpu(m->bytes_allocated),
 
2161
                        le32_to_cpu(m->bytes_allocated) - 512))
 
2162
                err = insert_non_resident_attr_in_mft_record(m, AT_DATA, name,
 
2163
                                name_len, ic, flags, val, val_len,
 
2164
                                WRITE_STANDARD);
 
2165
        else
 
2166
                err = insert_resident_attr_in_mft_record(m, AT_DATA, name,
 
2167
                                name_len, ic, flags, 0, val, val_len);
 
2168
 
 
2169
        if (err < 0)
 
2170
                ntfs_log_error("add_attr_data failed: %s\n", strerror(-err));
 
2171
        return err;
 
2172
}
 
2173
 
 
2174
/**
 
2175
 * add_attr_data_positioned
 
2176
 *
 
2177
 * Create a non-resident data attribute with a predefined on disk location
 
2178
 * specified by the runlist @rl. The clusters specified by @rl are assumed to
 
2179
 * be allocated already.
 
2180
 *
 
2181
 * Return 0 on success or -errno on error.
 
2182
 */
 
2183
static int add_attr_data_positioned(MFT_RECORD *m, const char *name,
 
2184
                const u32 name_len, const IGNORE_CASE_BOOL ic,
 
2185
                const ATTR_FLAGS flags, const runlist *rl,
 
2186
                const u8 *val, const s64 val_len)
 
2187
{
 
2188
        int err;
 
2189
 
 
2190
        err = insert_positioned_attr_in_mft_record(m, AT_DATA, name, name_len,
 
2191
                        ic, flags, rl, val, val_len);
 
2192
        if (err < 0)
 
2193
                ntfs_log_error("add_attr_data_positioned failed: %s\n",
 
2194
                                strerror(-err));
 
2195
        return err;
 
2196
}
 
2197
 
 
2198
/**
 
2199
 * add_attr_vol_name
 
2200
 *
 
2201
 * Create volume name attribute specifying the volume name @vol_name as a null
 
2202
 * terminated char string of length @vol_name_len (number of characters not
 
2203
 * including the terminating null), which is converted internally to a little
 
2204
 * endian ntfschar string. The name is at least 1 character long (though
 
2205
 * Windows accepts zero characters), and at most 128 characters long (not
 
2206
 * counting the terminating null).
 
2207
 *
 
2208
 * Return 0 on success or -errno on error.
 
2209
 */
 
2210
static int add_attr_vol_name(MFT_RECORD *m, const char *vol_name,
 
2211
                const int vol_name_len __attribute__((unused)))
 
2212
{
 
2213
        ntfschar *uname = NULL;
 
2214
        int uname_len = 0;
 
2215
        int i;
 
2216
 
 
2217
        if (vol_name) {
 
2218
                uname_len = ntfs_mbstoucs(vol_name, &uname);
 
2219
                if (uname_len < 0)
 
2220
                        return -errno;
 
2221
                if (uname_len > 128) {
 
2222
                        free(uname);
 
2223
                        return -ENAMETOOLONG;
 
2224
                }
 
2225
        }
 
2226
        i = insert_resident_attr_in_mft_record(m, AT_VOLUME_NAME, NULL, 0,
 
2227
                        CASE_SENSITIVE, const_cpu_to_le16(0),
 
2228
                        0, (u8*)uname, uname_len*sizeof(ntfschar));
 
2229
        free(uname);
 
2230
        if (i < 0)
 
2231
                ntfs_log_error("add_attr_vol_name failed: %s\n", strerror(-i));
 
2232
        return i;
 
2233
}
 
2234
 
 
2235
/**
 
2236
 * add_attr_vol_info
 
2237
 *
 
2238
 * Return 0 on success or -errno on error.
 
2239
 */
 
2240
static int add_attr_vol_info(MFT_RECORD *m, const VOLUME_FLAGS flags,
 
2241
                const u8 major_ver, const u8 minor_ver)
 
2242
{
 
2243
        VOLUME_INFORMATION vi;
 
2244
        int err;
 
2245
 
 
2246
        memset(&vi, 0, sizeof(vi));
 
2247
        vi.major_ver = major_ver;
 
2248
        vi.minor_ver = minor_ver;
 
2249
        vi.flags = flags & VOLUME_FLAGS_MASK;
 
2250
        err = insert_resident_attr_in_mft_record(m, AT_VOLUME_INFORMATION, NULL,
 
2251
                        0, CASE_SENSITIVE, const_cpu_to_le16(0),
 
2252
                        0, (u8*)&vi, sizeof(vi));
 
2253
        if (err < 0)
 
2254
                ntfs_log_error("add_attr_vol_info failed: %s\n", strerror(-err));
 
2255
        return err;
 
2256
}
 
2257
 
 
2258
/**
 
2259
 * add_attr_index_root
 
2260
 *
 
2261
 * Return 0 on success or -errno on error.
 
2262
 */
 
2263
static int add_attr_index_root(MFT_RECORD *m, const char *name,
 
2264
                const u32 name_len, const IGNORE_CASE_BOOL ic,
 
2265
                const ATTR_TYPES indexed_attr_type,
 
2266
                const COLLATION_RULES collation_rule,
 
2267
                const u32 index_block_size)
 
2268
{
 
2269
        INDEX_ROOT *r;
 
2270
        INDEX_ENTRY_HEADER *e;
 
2271
        int err, val_len;
 
2272
 
 
2273
        val_len = sizeof(INDEX_ROOT) + sizeof(INDEX_ENTRY_HEADER);
 
2274
        r = ntfs_malloc(val_len);
 
2275
        if (!r)
 
2276
                return -errno;
 
2277
        r->type = (indexed_attr_type == AT_FILE_NAME)
 
2278
                                ? AT_FILE_NAME : const_cpu_to_le32(0);
 
2279
        if (indexed_attr_type == AT_FILE_NAME &&
 
2280
                        collation_rule != COLLATION_FILE_NAME) {
 
2281
                free(r);
 
2282
                ntfs_log_error("add_attr_index_root: indexed attribute is $FILE_NAME "
 
2283
                        "but collation rule is not COLLATION_FILE_NAME.\n");
 
2284
                return -EINVAL;
 
2285
        }
 
2286
        r->collation_rule = collation_rule;
 
2287
        r->index_block_size = cpu_to_le32(index_block_size);
 
2288
        if (index_block_size >= g_vol->cluster_size) {
 
2289
                if (index_block_size % g_vol->cluster_size) {
 
2290
                        ntfs_log_error("add_attr_index_root: index block size is not "
 
2291
                                        "a multiple of the cluster size.\n");
 
2292
                        free(r);
 
2293
                        return -EINVAL;
 
2294
                }
 
2295
                r->clusters_per_index_block = index_block_size /
 
2296
                                g_vol->cluster_size;
 
2297
        } else { /* if (g_vol->cluster_size > index_block_size) */
 
2298
                if (index_block_size & (index_block_size - 1)) {
 
2299
                        ntfs_log_error("add_attr_index_root: index block size is not "
 
2300
                                        "a power of 2.\n");
 
2301
                        free(r);
 
2302
                        return -EINVAL;
 
2303
                }
 
2304
                if (index_block_size < (u32)opts.sector_size) {
 
2305
                         ntfs_log_error("add_attr_index_root: index block size "
 
2306
                                         "is smaller than the sector size.\n");
 
2307
                         free(r);
 
2308
                         return -EINVAL;
 
2309
                }
 
2310
                r->clusters_per_index_block = index_block_size
 
2311
                                >> NTFS_BLOCK_SIZE_BITS;
 
2312
        }
 
2313
        memset(&r->reserved, 0, sizeof(r->reserved));
 
2314
        r->index.entries_offset = const_cpu_to_le32(sizeof(INDEX_HEADER));
 
2315
        r->index.index_length = const_cpu_to_le32(sizeof(INDEX_HEADER) +
 
2316
                        sizeof(INDEX_ENTRY_HEADER));
 
2317
        r->index.allocated_size = r->index.index_length;
 
2318
        r->index.ih_flags = SMALL_INDEX;
 
2319
        memset(&r->index.reserved, 0, sizeof(r->index.reserved));
 
2320
        e = (INDEX_ENTRY_HEADER*)((u8*)&r->index +
 
2321
                        le32_to_cpu(r->index.entries_offset));
 
2322
        /*
 
2323
         * No matter whether this is a file index or a view as this is a
 
2324
         * termination entry, hence no key value / data is associated with it
 
2325
         * at all. Thus, we just need the union to be all zero.
 
2326
         */
 
2327
        e->indexed_file = const_cpu_to_le64(0LL);
 
2328
        e->length = const_cpu_to_le16(sizeof(INDEX_ENTRY_HEADER));
 
2329
        e->key_length = const_cpu_to_le16(0);
 
2330
        e->flags = INDEX_ENTRY_END;
 
2331
        e->reserved = const_cpu_to_le16(0);
 
2332
        err = insert_resident_attr_in_mft_record(m, AT_INDEX_ROOT, name,
 
2333
                                name_len, ic, const_cpu_to_le16(0), 0,
 
2334
                                (u8*)r, val_len);
 
2335
        free(r);
 
2336
        if (err < 0)
 
2337
                ntfs_log_error("add_attr_index_root failed: %s\n", strerror(-err));
 
2338
        return err;
 
2339
}
 
2340
 
 
2341
/**
 
2342
 * add_attr_index_alloc
 
2343
 *
 
2344
 * Return 0 on success or -errno on error.
 
2345
 */
 
2346
static int add_attr_index_alloc(MFT_RECORD *m, const char *name,
 
2347
                const u32 name_len, const IGNORE_CASE_BOOL ic,
 
2348
                const u8 *index_alloc_val, const u32 index_alloc_val_len)
 
2349
{
 
2350
        int err;
 
2351
 
 
2352
        err = insert_non_resident_attr_in_mft_record(m, AT_INDEX_ALLOCATION,
 
2353
                        name, name_len, ic, const_cpu_to_le16(0),
 
2354
                        index_alloc_val, index_alloc_val_len, WRITE_STANDARD);
 
2355
        if (err < 0)
 
2356
                ntfs_log_error("add_attr_index_alloc failed: %s\n", strerror(-err));
 
2357
        return err;
 
2358
}
 
2359
 
 
2360
/**
 
2361
 * add_attr_bitmap
 
2362
 *
 
2363
 * Return 0 on success or -errno on error.
 
2364
 */
 
2365
static int add_attr_bitmap(MFT_RECORD *m, const char *name, const u32 name_len,
 
2366
                const IGNORE_CASE_BOOL ic, const u8 *bitmap,
 
2367
                const u32 bitmap_len)
 
2368
{
 
2369
        int err;
 
2370
 
 
2371
        /* Does it fit? NO: create non-resident. YES: create resident. */
 
2372
        if (le32_to_cpu(m->bytes_in_use) + 24 + bitmap_len >
 
2373
                                                le32_to_cpu(m->bytes_allocated))
 
2374
                err = insert_non_resident_attr_in_mft_record(m, AT_BITMAP, name,
 
2375
                                name_len, ic, const_cpu_to_le16(0), bitmap,
 
2376
                                bitmap_len, WRITE_STANDARD);
 
2377
        else
 
2378
                err = insert_resident_attr_in_mft_record(m, AT_BITMAP, name,
 
2379
                                name_len, ic, const_cpu_to_le16(0), 0,
 
2380
                                bitmap, bitmap_len);
 
2381
 
 
2382
        if (err < 0)
 
2383
                ntfs_log_error("add_attr_bitmap failed: %s\n", strerror(-err));
 
2384
        return err;
 
2385
}
 
2386
 
 
2387
/**
 
2388
 * add_attr_bitmap_positioned
 
2389
 *
 
2390
 * Create a non-resident bitmap attribute with a predefined on disk location
 
2391
 * specified by the runlist @rl. The clusters specified by @rl are assumed to
 
2392
 * be allocated already.
 
2393
 *
 
2394
 * Return 0 on success or -errno on error.
 
2395
 */
 
2396
static int add_attr_bitmap_positioned(MFT_RECORD *m, const char *name,
 
2397
                const u32 name_len, const IGNORE_CASE_BOOL ic,
 
2398
                const runlist *rl, const u8 *bitmap, const u32 bitmap_len)
 
2399
{
 
2400
        int err;
 
2401
 
 
2402
        err = insert_positioned_attr_in_mft_record(m, AT_BITMAP, name, name_len,
 
2403
                        ic, const_cpu_to_le16(0), rl, bitmap, bitmap_len);
 
2404
        if (err < 0)
 
2405
                ntfs_log_error("add_attr_bitmap_positioned failed: %s\n",
 
2406
                                strerror(-err));
 
2407
        return err;
 
2408
}
 
2409
 
 
2410
 
 
2411
/**
 
2412
 * upgrade_to_large_index
 
2413
 *
 
2414
 * Create bitmap and index allocation attributes, modify index root
 
2415
 * attribute accordingly and move all of the index entries from the index root
 
2416
 * into the index allocation.
 
2417
 *
 
2418
 * Return 0 on success or -errno on error.
 
2419
 */
 
2420
static int upgrade_to_large_index(MFT_RECORD *m, const char *name,
 
2421
                u32 name_len, const IGNORE_CASE_BOOL ic,
 
2422
                INDEX_ALLOCATION **idx)
 
2423
{
 
2424
        ntfs_attr_search_ctx *ctx;
 
2425
        ATTR_RECORD *a;
 
2426
        INDEX_ROOT *r;
 
2427
        INDEX_ENTRY *re;
 
2428
        INDEX_ALLOCATION *ia_val = NULL;
 
2429
        ntfschar *uname = NULL;
 
2430
        int uname_len = 0;
 
2431
        u8 bmp[8];
 
2432
        char *re_start, *re_end;
 
2433
        int i, err, index_block_size;
 
2434
 
 
2435
        uname = ntfs_str2ucs(name, &uname_len);
 
2436
        if (!uname)
 
2437
                return -errno;
 
2438
 
 
2439
        /* Find the index root attribute. */
 
2440
        ctx = ntfs_attr_get_search_ctx(NULL, m);
 
2441
        if (!ctx) {
 
2442
                ntfs_log_error("Failed to allocate attribute search context.\n");
 
2443
                ntfs_ucsfree(uname);
 
2444
                return -ENOMEM;
 
2445
        }
 
2446
        if (ic == IGNORE_CASE) {
 
2447
                ntfs_log_error("FIXME: Hit unimplemented code path #4.\n");
 
2448
                err = -EOPNOTSUPP;
 
2449
                ntfs_ucsfree(uname);
 
2450
                goto err_out;
 
2451
        }
 
2452
        err = mkntfs_attr_lookup(AT_INDEX_ROOT, uname, uname_len, ic, 0, NULL, 0,
 
2453
                        ctx);
 
2454
        ntfs_ucsfree(uname);
 
2455
        if (err) {
 
2456
                err = -ENOTDIR;
 
2457
                goto err_out;
 
2458
        }
 
2459
        a = ctx->attr;
 
2460
        if (a->non_resident || a->flags) {
 
2461
                err = -EINVAL;
 
2462
                goto err_out;
 
2463
        }
 
2464
        r = (INDEX_ROOT*)((char*)a + le16_to_cpu(a->value_offset));
 
2465
        re_end = (char*)r + le32_to_cpu(a->value_length);
 
2466
        re_start = (char*)&r->index + le32_to_cpu(r->index.entries_offset);
 
2467
        re = (INDEX_ENTRY*)re_start;
 
2468
        index_block_size = le32_to_cpu(r->index_block_size);
 
2469
        memset(bmp, 0, sizeof(bmp));
 
2470
        ntfs_bit_set(bmp, 0ULL, 1);
 
2471
        /* Bitmap has to be at least 8 bytes in size. */
 
2472
        err = add_attr_bitmap(m, name, name_len, ic, bmp, sizeof(bmp));
 
2473
        if (err)
 
2474
                goto err_out;
 
2475
        ia_val = ntfs_calloc(index_block_size);
 
2476
        if (!ia_val) {
 
2477
                err = -errno;
 
2478
                goto err_out;
 
2479
        }
 
2480
        /* Setup header. */
 
2481
        ia_val->magic = magic_INDX;
 
2482
        ia_val->usa_ofs = cpu_to_le16(sizeof(INDEX_ALLOCATION));
 
2483
        if (index_block_size >= NTFS_BLOCK_SIZE) {
 
2484
                ia_val->usa_count = cpu_to_le16(index_block_size /
 
2485
                                NTFS_BLOCK_SIZE + 1);
 
2486
        } else {
 
2487
                ia_val->usa_count = cpu_to_le16(1);
 
2488
                ntfs_log_error("Sector size is bigger than index block size. "
 
2489
                                "Setting usa_count to 1. If Windows chkdsk "
 
2490
                                "reports this as corruption, please email %s "
 
2491
                                "stating that you saw this message and that "
 
2492
                                "the filesystem created was corrupt.  "
 
2493
                                "Thank you.", NTFS_DEV_LIST);
 
2494
        }
 
2495
        /* Set USN to 1. */
 
2496
        *(le16*)((char*)ia_val + le16_to_cpu(ia_val->usa_ofs)) =
 
2497
                        cpu_to_le16(1);
 
2498
        ia_val->lsn = cpu_to_le64(0);
 
2499
        ia_val->index_block_vcn = cpu_to_le64(0);
 
2500
        ia_val->index.ih_flags = LEAF_NODE;
 
2501
        /* Align to 8-byte boundary. */
 
2502
        ia_val->index.entries_offset = cpu_to_le32((sizeof(INDEX_HEADER) +
 
2503
                        le16_to_cpu(ia_val->usa_count) * 2 + 7) & ~7);
 
2504
        ia_val->index.allocated_size = cpu_to_le32(index_block_size -
 
2505
                        (sizeof(INDEX_ALLOCATION) - sizeof(INDEX_HEADER)));
 
2506
        /* Find the last entry in the index root and save it in re. */
 
2507
        while ((char*)re < re_end && !(re->ie_flags & INDEX_ENTRY_END)) {
 
2508
                /* Next entry in index root. */
 
2509
                re = (INDEX_ENTRY*)((char*)re + le16_to_cpu(re->length));
 
2510
        }
 
2511
        /* Copy all the entries including the termination entry. */
 
2512
        i = (char*)re - re_start + le16_to_cpu(re->length);
 
2513
        memcpy((char*)&ia_val->index +
 
2514
                        le32_to_cpu(ia_val->index.entries_offset), re_start, i);
 
2515
        /* Finish setting up index allocation. */
 
2516
        ia_val->index.index_length = cpu_to_le32(i +
 
2517
                        le32_to_cpu(ia_val->index.entries_offset));
 
2518
        /* Move the termination entry forward to the beginning if necessary. */
 
2519
        if ((char*)re > re_start) {
 
2520
                memmove(re_start, (char*)re, le16_to_cpu(re->length));
 
2521
                re = (INDEX_ENTRY*)re_start;
 
2522
        }
 
2523
        /* Now fixup empty index root with pointer to index allocation VCN 0. */
 
2524
        r->index.ih_flags = LARGE_INDEX;
 
2525
        re->ie_flags |= INDEX_ENTRY_NODE;
 
2526
        if (le16_to_cpu(re->length) < sizeof(INDEX_ENTRY_HEADER) + sizeof(VCN))
 
2527
                re->length = cpu_to_le16(le16_to_cpu(re->length) + sizeof(VCN));
 
2528
        r->index.index_length = cpu_to_le32(le32_to_cpu(r->index.entries_offset)
 
2529
                        + le16_to_cpu(re->length));
 
2530
        r->index.allocated_size = r->index.index_length;
 
2531
        /* Resize index root attribute. */
 
2532
        if (ntfs_resident_attr_value_resize(m, a, sizeof(INDEX_ROOT) -
 
2533
                        sizeof(INDEX_HEADER) +
 
2534
                        le32_to_cpu(r->index.allocated_size))) {
 
2535
                /* TODO: Remove the added bitmap! */
 
2536
                /* Revert index root from index allocation. */
 
2537
                err = -errno;
 
2538
                goto err_out;
 
2539
        }
 
2540
        /* Set VCN pointer to 0LL. */
 
2541
        *(leVCN*)((char*)re + cpu_to_le16(re->length) - sizeof(VCN)) =
 
2542
                        cpu_to_le64(0);
 
2543
        err = ntfs_mst_pre_write_fixup((NTFS_RECORD*)ia_val, index_block_size);
 
2544
        if (err) {
 
2545
                err = -errno;
 
2546
                ntfs_log_error("ntfs_mst_pre_write_fixup() failed in "
 
2547
                                "upgrade_to_large_index.\n");
 
2548
                goto err_out;
 
2549
        }
 
2550
        err = add_attr_index_alloc(m, name, name_len, ic, (u8*)ia_val,
 
2551
                        index_block_size);
 
2552
        ntfs_mst_post_write_fixup((NTFS_RECORD*)ia_val);
 
2553
        if (err) {
 
2554
                /* TODO: Remove the added bitmap! */
 
2555
                /* Revert index root from index allocation. */
 
2556
                goto err_out;
 
2557
        }
 
2558
        *idx = ia_val;
 
2559
        ntfs_attr_put_search_ctx(ctx);
 
2560
        return 0;
 
2561
err_out:
 
2562
        ntfs_attr_put_search_ctx(ctx);
 
2563
        free(ia_val);
 
2564
        return err;
 
2565
}
 
2566
 
 
2567
/**
 
2568
 * make_room_for_index_entry_in_index_block
 
2569
 *
 
2570
 * Create space of @size bytes at position @pos inside the index block @idx.
 
2571
 *
 
2572
 * Return 0 on success or -errno on error.
 
2573
 */
 
2574
static int make_room_for_index_entry_in_index_block(INDEX_BLOCK *idx,
 
2575
                INDEX_ENTRY *pos, u32 size)
 
2576
{
 
2577
        u32 biu;
 
2578
 
 
2579
        if (!size)
 
2580
                return 0;
 
2581
#ifdef DEBUG
 
2582
        /*
 
2583
         * Rigorous consistency checks. Always return -EINVAL even if more
 
2584
         * appropriate codes exist for simplicity of parsing the return value.
 
2585
         */
 
2586
        if (size != ((size + 7) & ~7)) {
 
2587
                ntfs_log_error("make_room_for_index_entry_in_index_block() received "
 
2588
                                "non 8-byte aligned size.\n");
 
2589
                return -EINVAL;
 
2590
        }
 
2591
        if (!idx || !pos)
 
2592
                return -EINVAL;
 
2593
        if ((char*)pos < (char*)idx || (char*)pos + size < (char*)idx ||
 
2594
                        (char*)pos > (char*)idx + sizeof(INDEX_BLOCK) -
 
2595
                                sizeof(INDEX_HEADER) +
 
2596
                                le32_to_cpu(idx->index.allocated_size) ||
 
2597
                        (char*)pos + size > (char*)idx + sizeof(INDEX_BLOCK) -
 
2598
                                sizeof(INDEX_HEADER) +
 
2599
                                le32_to_cpu(idx->index.allocated_size))
 
2600
                return -EINVAL;
 
2601
        /* The - sizeof(INDEX_ENTRY_HEADER) is for the index terminator. */
 
2602
        if ((char*)pos - (char*)&idx->index >
 
2603
                        (int)le32_to_cpu(idx->index.index_length)
 
2604
                        - (int)sizeof(INDEX_ENTRY_HEADER))
 
2605
                return -EINVAL;
 
2606
#endif
 
2607
        biu = le32_to_cpu(idx->index.index_length);
 
2608
        /* Do we have enough space? */
 
2609
        if (biu + size > le32_to_cpu(idx->index.allocated_size))
 
2610
                return -ENOSPC;
 
2611
        /* Move everything after pos to pos + size. */
 
2612
        memmove((char*)pos + size, (char*)pos, biu - ((char*)pos -
 
2613
                        (char*)&idx->index));
 
2614
        /* Update index block. */
 
2615
        idx->index.index_length = cpu_to_le32(biu + size);
 
2616
        return 0;
 
2617
}
 
2618
 
 
2619
/**
 
2620
 * ntfs_index_keys_compare
 
2621
 *
 
2622
 * not all types of COLLATION_RULES supported yet...
 
2623
 * added as needed.. (remove this comment when all are added)
 
2624
 */
 
2625
static int ntfs_index_keys_compare(u8 *key1, u8 *key2, int key1_length,
 
2626
                int key2_length, COLLATION_RULES collation_rule)
 
2627
{
 
2628
        u32 u1, u2;
 
2629
        int i;
 
2630
 
 
2631
        if (collation_rule == COLLATION_NTOFS_ULONG) {
 
2632
                /* i.e. $SII or $QUOTA-$Q */
 
2633
                u1 = le32_to_cpup((const le32*)key1);
 
2634
                u2 = le32_to_cpup((const le32*)key2);
 
2635
                if (u1 < u2)
 
2636
                        return -1;
 
2637
                if (u1 > u2)
 
2638
                        return 1;
 
2639
                /* u1 == u2 */
 
2640
                return 0;
 
2641
        }
 
2642
        if (collation_rule == COLLATION_NTOFS_ULONGS) {
 
2643
                /* i.e $OBJID-$O */
 
2644
                i = 0;
 
2645
                while (i < min(key1_length, key2_length)) {
 
2646
                        u1 = le32_to_cpup((const le32*)(key1 + i));
 
2647
                        u2 = le32_to_cpup((const le32*)(key2 + i));
 
2648
                        if (u1 < u2)
 
2649
                                return -1;
 
2650
                        if (u1 > u2)
 
2651
                                return 1;
 
2652
                        /* u1 == u2 */
 
2653
                        i += sizeof(u32);
 
2654
                }
 
2655
                if (key1_length < key2_length)
 
2656
                        return -1;
 
2657
                if (key1_length > key2_length)
 
2658
                        return 1;
 
2659
                return 0;
 
2660
        }
 
2661
        if (collation_rule == COLLATION_NTOFS_SECURITY_HASH) {
 
2662
                /* i.e. $SDH */
 
2663
                u1 = le32_to_cpu(((SDH_INDEX_KEY*)key1)->hash);
 
2664
                u2 = le32_to_cpu(((SDH_INDEX_KEY*)key2)->hash);
 
2665
                if (u1 < u2)
 
2666
                        return -1;
 
2667
                if (u1 > u2)
 
2668
                        return 1;
 
2669
                /* u1 == u2 */
 
2670
                u1 = le32_to_cpu(((SDH_INDEX_KEY*)key1)->security_id);
 
2671
                u2 = le32_to_cpu(((SDH_INDEX_KEY*)key2)->security_id);
 
2672
                if (u1 < u2)
 
2673
                        return -1;
 
2674
                if (u1 > u2)
 
2675
                        return 1;
 
2676
                return 0;
 
2677
        }
 
2678
        if (collation_rule == COLLATION_NTOFS_SID) {
 
2679
                /* i.e. $QUOTA-O */
 
2680
                i = memcmp(key1, key2, min(key1_length, key2_length));
 
2681
                if (!i) {
 
2682
                        if (key1_length < key2_length)
 
2683
                                return -1;
 
2684
                        if (key1_length > key2_length)
 
2685
                                return 1;
 
2686
                }
 
2687
                return i;
 
2688
        }
 
2689
        ntfs_log_critical("ntfs_index_keys_compare called without supported "
 
2690
                        "collation rule.\n");
 
2691
        return 0;       /* Claim they're equal.  What else can we do? */
 
2692
}
 
2693
 
 
2694
/**
 
2695
 * insert_index_entry_in_res_dir_index
 
2696
 *
 
2697
 * i.e. insert an index_entry in some named index_root
 
2698
 * simplified search method, works for mkntfs
 
2699
 */
 
2700
static int insert_index_entry_in_res_dir_index(INDEX_ENTRY *idx, u32 idx_size,
 
2701
                MFT_RECORD *m, ntfschar *name, u32 name_size, ATTR_TYPES type)
 
2702
{
 
2703
        ntfs_attr_search_ctx *ctx;
 
2704
        INDEX_HEADER *idx_header;
 
2705
        INDEX_ENTRY *idx_entry, *idx_end;
 
2706
        ATTR_RECORD *a;
 
2707
        COLLATION_RULES collation_rule;
 
2708
        int err, i;
 
2709
 
 
2710
        err = 0;
 
2711
        /* does it fit ?*/
 
2712
        if (g_vol->mft_record_size > idx_size + le32_to_cpu(m->bytes_allocated))
 
2713
                return -ENOSPC;
 
2714
        /* find the INDEX_ROOT attribute:*/
 
2715
        ctx = ntfs_attr_get_search_ctx(NULL, m);
 
2716
        if (!ctx) {
 
2717
                ntfs_log_error("Failed to allocate attribute search "
 
2718
                                "context.\n");
 
2719
                err = -ENOMEM;
 
2720
                goto err_out;
 
2721
        }
 
2722
        if (mkntfs_attr_lookup(AT_INDEX_ROOT, name, name_size,
 
2723
                        CASE_SENSITIVE, 0, NULL, 0, ctx)) {
 
2724
                err = -EEXIST;
 
2725
                goto err_out;
 
2726
        }
 
2727
        /* found attribute */
 
2728
        a = (ATTR_RECORD*)ctx->attr;
 
2729
        collation_rule = ((INDEX_ROOT*)((u8*)a +
 
2730
                        le16_to_cpu(a->value_offset)))->collation_rule;
 
2731
        idx_header = (INDEX_HEADER*)((u8*)a + le16_to_cpu(a->value_offset)
 
2732
                        + 0x10);
 
2733
        idx_entry = (INDEX_ENTRY*)((u8*)idx_header +
 
2734
                        le32_to_cpu(idx_header->entries_offset));
 
2735
        idx_end = (INDEX_ENTRY*)((u8*)idx_entry +
 
2736
                        le32_to_cpu(idx_header->index_length));
 
2737
        /*
 
2738
         * Loop until we exceed valid memory (corruption case) or until we
 
2739
         * reach the last entry.
 
2740
         */
 
2741
        if (type == AT_FILE_NAME) {
 
2742
                while (((u8*)idx_entry < (u8*)idx_end) &&
 
2743
                                !(idx_entry->ie_flags & INDEX_ENTRY_END)) {
 
2744
                        /*
 
2745
                        i = ntfs_file_values_compare(&idx->key.file_name,
 
2746
                                        &idx_entry->key.file_name, 1,
 
2747
                                        IGNORE_CASE, g_vol->upcase,
 
2748
                                        g_vol->upcase_len);
 
2749
                        */
 
2750
                        i = ntfs_names_full_collate(idx->key.file_name.file_name, idx->key.file_name.file_name_length,
 
2751
                                        idx_entry->key.file_name.file_name, idx_entry->key.file_name.file_name_length,
 
2752
                                        IGNORE_CASE, g_vol->upcase,
 
2753
                                        g_vol->upcase_len);
 
2754
                        /*
 
2755
                         * If @file_name collates before ie->key.file_name,
 
2756
                         * there is no matching index entry.
 
2757
                         */
 
2758
                        if (i == -1)
 
2759
                                break;
 
2760
                        /* If file names are not equal, continue search. */
 
2761
                        if (i)
 
2762
                                goto do_next;
 
2763
                        if (idx->key.file_name.file_name_type !=
 
2764
                                        FILE_NAME_POSIX ||
 
2765
                                        idx_entry->key.file_name.file_name_type
 
2766
                                        != FILE_NAME_POSIX)
 
2767
                                return -EEXIST;
 
2768
                        /*
 
2769
                        i = ntfs_file_values_compare(&idx->key.file_name,
 
2770
                                        &idx_entry->key.file_name, 1,
 
2771
                                        CASE_SENSITIVE, g_vol->upcase,
 
2772
                                        g_vol->upcase_len);
 
2773
                        */
 
2774
                        i = ntfs_names_full_collate(idx->key.file_name.file_name, idx->key.file_name.file_name_length,
 
2775
                                        idx_entry->key.file_name.file_name, idx_entry->key.file_name.file_name_length,
 
2776
                                        CASE_SENSITIVE, g_vol->upcase,
 
2777
                                        g_vol->upcase_len);
 
2778
                        if (!i)
 
2779
                                return -EEXIST;
 
2780
                        if (i == -1)
 
2781
                                break;
 
2782
do_next:
 
2783
                        idx_entry = (INDEX_ENTRY*)((u8*)idx_entry +
 
2784
                                        le16_to_cpu(idx_entry->length));
 
2785
                }
 
2786
        } else if (type == AT_UNUSED) {  /* case view */
 
2787
                while (((u8*)idx_entry < (u8*)idx_end) &&
 
2788
                                !(idx_entry->ie_flags & INDEX_ENTRY_END)) {
 
2789
                        i = ntfs_index_keys_compare((u8*)idx + 0x10,
 
2790
                                        (u8*)idx_entry + 0x10,
 
2791
                                        le16_to_cpu(idx->key_length),
 
2792
                                        le16_to_cpu(idx_entry->key_length),
 
2793
                                        collation_rule);
 
2794
                        if (!i)
 
2795
                                return -EEXIST;
 
2796
                        if (i == -1)
 
2797
                                break;
 
2798
                        idx_entry = (INDEX_ENTRY*)((u8*)idx_entry +
 
2799
                                        le16_to_cpu(idx_entry->length));
 
2800
                }
 
2801
        } else
 
2802
                return -EINVAL;
 
2803
        memmove((u8*)idx_entry + idx_size, (u8*)idx_entry,
 
2804
                        le32_to_cpu(m->bytes_in_use) -
 
2805
                        ((u8*)idx_entry - (u8*)m));
 
2806
        memcpy((u8*)idx_entry, (u8*)idx, idx_size);
 
2807
        /* Adjust various offsets, etc... */
 
2808
        m->bytes_in_use = cpu_to_le32(le32_to_cpu(m->bytes_in_use) + idx_size);
 
2809
        a->length = cpu_to_le32(le32_to_cpu(a->length) + idx_size);
 
2810
        a->value_length = cpu_to_le32(le32_to_cpu(a->value_length) + idx_size);
 
2811
        idx_header->index_length = cpu_to_le32(
 
2812
                        le32_to_cpu(idx_header->index_length) + idx_size);
 
2813
        idx_header->allocated_size = cpu_to_le32(
 
2814
                        le32_to_cpu(idx_header->allocated_size) + idx_size);
 
2815
err_out:
 
2816
        if (ctx)
 
2817
                ntfs_attr_put_search_ctx(ctx);
 
2818
        return err;
 
2819
}
 
2820
 
 
2821
/**
 
2822
 * initialize_secure
 
2823
 *
 
2824
 * initializes $Secure's $SDH and $SII indexes from $SDS datastream
 
2825
 */
 
2826
static int initialize_secure(char *sds, u32 sds_size, MFT_RECORD *m)
 
2827
{
 
2828
        int err, sdh_size, sii_size;
 
2829
        SECURITY_DESCRIPTOR_HEADER *sds_header;
 
2830
        INDEX_ENTRY *idx_entry_sdh, *idx_entry_sii;
 
2831
        SDH_INDEX_DATA *sdh_data;
 
2832
        SII_INDEX_DATA *sii_data;
 
2833
 
 
2834
        sds_header = (SECURITY_DESCRIPTOR_HEADER*)sds;
 
2835
        sdh_size  = sizeof(INDEX_ENTRY_HEADER);
 
2836
        sdh_size += sizeof(SDH_INDEX_KEY) + sizeof(SDH_INDEX_DATA);
 
2837
        sii_size  = sizeof(INDEX_ENTRY_HEADER);
 
2838
        sii_size += sizeof(SII_INDEX_KEY) + sizeof(SII_INDEX_DATA);
 
2839
        idx_entry_sdh = ntfs_calloc(sizeof(INDEX_ENTRY));
 
2840
        if (!idx_entry_sdh)
 
2841
                return -errno;
 
2842
        idx_entry_sii = ntfs_calloc(sizeof(INDEX_ENTRY));
 
2843
        if (!idx_entry_sii) {
 
2844
                free(idx_entry_sdh);
 
2845
                return -errno;
 
2846
        }
 
2847
        err = 0;
 
2848
 
 
2849
        while ((char*)sds_header < (char*)sds + sds_size) {
 
2850
                if (!sds_header->length)
 
2851
                        break;
 
2852
                /* SDH index entry */
 
2853
                idx_entry_sdh->data_offset = const_cpu_to_le16(0x18);
 
2854
                idx_entry_sdh->data_length = const_cpu_to_le16(0x14);
 
2855
                idx_entry_sdh->reservedV = const_cpu_to_le32(0x00);
 
2856
                idx_entry_sdh->length = const_cpu_to_le16(0x30);
 
2857
                idx_entry_sdh->key_length = const_cpu_to_le16(0x08);
 
2858
                idx_entry_sdh->ie_flags = const_cpu_to_le16(0x00);
 
2859
                idx_entry_sdh->reserved = const_cpu_to_le16(0x00);
 
2860
                idx_entry_sdh->key.sdh.hash = sds_header->hash;
 
2861
                idx_entry_sdh->key.sdh.security_id = sds_header->security_id;
 
2862
                sdh_data = (SDH_INDEX_DATA*)((u8*)idx_entry_sdh +
 
2863
                                le16_to_cpu(idx_entry_sdh->data_offset));
 
2864
                sdh_data->hash = sds_header->hash;
 
2865
                sdh_data->security_id = sds_header->security_id;
 
2866
                sdh_data->offset = sds_header->offset;
 
2867
                sdh_data->length = sds_header->length;
 
2868
                sdh_data->reserved_II = const_cpu_to_le32(0x00490049);
 
2869
 
 
2870
                /* SII index entry */
 
2871
                idx_entry_sii->data_offset = const_cpu_to_le16(0x14);
 
2872
                idx_entry_sii->data_length = const_cpu_to_le16(0x14);
 
2873
                idx_entry_sii->reservedV = const_cpu_to_le32(0x00);
 
2874
                idx_entry_sii->length = const_cpu_to_le16(0x28);
 
2875
                idx_entry_sii->key_length = const_cpu_to_le16(0x04);
 
2876
                idx_entry_sii->ie_flags = const_cpu_to_le16(0x00);
 
2877
                idx_entry_sii->reserved = const_cpu_to_le16(0x00);
 
2878
                idx_entry_sii->key.sii.security_id = sds_header->security_id;
 
2879
                sii_data = (SII_INDEX_DATA*)((u8*)idx_entry_sii +
 
2880
                                le16_to_cpu(idx_entry_sii->data_offset));
 
2881
                sii_data->hash = sds_header->hash;
 
2882
                sii_data->security_id = sds_header->security_id;
 
2883
                sii_data->offset = sds_header->offset;
 
2884
                sii_data->length = sds_header->length;
 
2885
                if ((err = insert_index_entry_in_res_dir_index(idx_entry_sdh,
 
2886
                                sdh_size, m, NTFS_INDEX_SDH, 4, AT_UNUSED)))
 
2887
                        break;
 
2888
                if ((err = insert_index_entry_in_res_dir_index(idx_entry_sii,
 
2889
                                sii_size, m, NTFS_INDEX_SII, 4, AT_UNUSED)))
 
2890
                        break;
 
2891
                sds_header = (SECURITY_DESCRIPTOR_HEADER*)((u8*)sds_header +
 
2892
                                ((le32_to_cpu(sds_header->length) + 15) & ~15));
 
2893
        }
 
2894
        free(idx_entry_sdh);
 
2895
        free(idx_entry_sii);
 
2896
        return err;
 
2897
}
 
2898
 
 
2899
/**
 
2900
 * initialize_quota
 
2901
 *
 
2902
 * initialize $Quota with the default quota index-entries.
 
2903
 */
 
2904
static int initialize_quota(MFT_RECORD *m)
 
2905
{
 
2906
        int o_size, q1_size, q2_size, err, i;
 
2907
        INDEX_ENTRY *idx_entry_o, *idx_entry_q1, *idx_entry_q2;
 
2908
        QUOTA_O_INDEX_DATA *idx_entry_o_data;
 
2909
        QUOTA_CONTROL_ENTRY *idx_entry_q1_data, *idx_entry_q2_data;
 
2910
 
 
2911
        err = 0;
 
2912
        /* q index entry num 1 */
 
2913
        q1_size = 0x48;
 
2914
        idx_entry_q1 = ntfs_calloc(q1_size);
 
2915
        if (!idx_entry_q1)
 
2916
                return errno;
 
2917
        idx_entry_q1->data_offset = const_cpu_to_le16(0x14);
 
2918
        idx_entry_q1->data_length = const_cpu_to_le16(0x30);
 
2919
        idx_entry_q1->reservedV = const_cpu_to_le32(0x00);
 
2920
        idx_entry_q1->length = const_cpu_to_le16(0x48);
 
2921
        idx_entry_q1->key_length = const_cpu_to_le16(0x04);
 
2922
        idx_entry_q1->ie_flags = const_cpu_to_le16(0x00);
 
2923
        idx_entry_q1->reserved = const_cpu_to_le16(0x00);
 
2924
        idx_entry_q1->key.owner_id = const_cpu_to_le32(0x01);
 
2925
        idx_entry_q1_data = (QUOTA_CONTROL_ENTRY*)((char*)idx_entry_q1
 
2926
                        + le16_to_cpu(idx_entry_q1->data_offset));
 
2927
        idx_entry_q1_data->version = const_cpu_to_le32(0x02);
 
2928
        idx_entry_q1_data->flags = QUOTA_FLAG_DEFAULT_LIMITS;
 
2929
        idx_entry_q1_data->bytes_used = const_cpu_to_le64(0x00);
 
2930
        idx_entry_q1_data->change_time = mkntfs_time();
 
2931
        idx_entry_q1_data->threshold = cpu_to_sle64(-1);
 
2932
        idx_entry_q1_data->limit = cpu_to_sle64(-1);
 
2933
        idx_entry_q1_data->exceeded_time = const_cpu_to_le64(0);
 
2934
        err = insert_index_entry_in_res_dir_index(idx_entry_q1, q1_size, m,
 
2935
                        NTFS_INDEX_Q, 2, AT_UNUSED);
 
2936
        free(idx_entry_q1);
 
2937
        if (err)
 
2938
                return err;
 
2939
        /* q index entry num 2 */
 
2940
        q2_size = 0x58;
 
2941
        idx_entry_q2 = ntfs_calloc(q2_size);
 
2942
        if (!idx_entry_q2)
 
2943
                return errno;
 
2944
        idx_entry_q2->data_offset = const_cpu_to_le16(0x14);
 
2945
        idx_entry_q2->data_length = const_cpu_to_le16(0x40);
 
2946
        idx_entry_q2->reservedV = const_cpu_to_le32(0x00);
 
2947
        idx_entry_q2->length = const_cpu_to_le16(0x58);
 
2948
        idx_entry_q2->key_length = const_cpu_to_le16(0x04);
 
2949
        idx_entry_q2->ie_flags = const_cpu_to_le16(0x00);
 
2950
        idx_entry_q2->reserved = const_cpu_to_le16(0x00);
 
2951
        idx_entry_q2->key.owner_id = QUOTA_FIRST_USER_ID;
 
2952
        idx_entry_q2_data = (QUOTA_CONTROL_ENTRY*)((char*)idx_entry_q2
 
2953
                        + le16_to_cpu(idx_entry_q2->data_offset));
 
2954
        idx_entry_q2_data->version = const_cpu_to_le32(0x02);
 
2955
        idx_entry_q2_data->flags = QUOTA_FLAG_DEFAULT_LIMITS;
 
2956
        idx_entry_q2_data->bytes_used = const_cpu_to_le64(0x00);
 
2957
        idx_entry_q2_data->change_time = mkntfs_time();
 
2958
        idx_entry_q2_data->threshold = cpu_to_sle64(-1);
 
2959
        idx_entry_q2_data->limit = cpu_to_sle64(-1);
 
2960
        idx_entry_q2_data->exceeded_time = const_cpu_to_le64(0);
 
2961
        idx_entry_q2_data->sid.revision = 1;
 
2962
        idx_entry_q2_data->sid.sub_authority_count = 2;
 
2963
        for (i = 0; i < 5; i++)
 
2964
                idx_entry_q2_data->sid.identifier_authority.value[i] = 0;
 
2965
        idx_entry_q2_data->sid.identifier_authority.value[5] = 0x05;
 
2966
        idx_entry_q2_data->sid.sub_authority[0] =
 
2967
                        const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID);
 
2968
        idx_entry_q2_data->sid.sub_authority[1] =
 
2969
                        const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS);
 
2970
        err = insert_index_entry_in_res_dir_index(idx_entry_q2, q2_size, m,
 
2971
                        NTFS_INDEX_Q, 2, AT_UNUSED);
 
2972
        free(idx_entry_q2);
 
2973
        if (err)
 
2974
                return err;
 
2975
        o_size = 0x28;
 
2976
        idx_entry_o = ntfs_calloc(o_size);
 
2977
        if (!idx_entry_o)
 
2978
                return errno;
 
2979
        idx_entry_o->data_offset = const_cpu_to_le16(0x20);
 
2980
        idx_entry_o->data_length = const_cpu_to_le16(0x04);
 
2981
        idx_entry_o->reservedV = const_cpu_to_le32(0x00);
 
2982
        idx_entry_o->length = const_cpu_to_le16(0x28);
 
2983
        idx_entry_o->key_length = const_cpu_to_le16(0x10);
 
2984
        idx_entry_o->ie_flags = const_cpu_to_le16(0x00);
 
2985
        idx_entry_o->reserved = const_cpu_to_le16(0x00);
 
2986
        idx_entry_o->key.sid.revision = 0x01;
 
2987
        idx_entry_o->key.sid.sub_authority_count = 0x02;
 
2988
        for (i = 0; i < 5; i++)
 
2989
                idx_entry_o->key.sid.identifier_authority.value[i] = 0;
 
2990
        idx_entry_o->key.sid.identifier_authority.value[5] = 0x05;
 
2991
        idx_entry_o->key.sid.sub_authority[0] =
 
2992
                        const_cpu_to_le32(SECURITY_BUILTIN_DOMAIN_RID);
 
2993
        idx_entry_o->key.sid.sub_authority[1] =
 
2994
                        const_cpu_to_le32(DOMAIN_ALIAS_RID_ADMINS);
 
2995
        idx_entry_o_data = (QUOTA_O_INDEX_DATA*)((char*)idx_entry_o
 
2996
                        + le16_to_cpu(idx_entry_o->data_offset));
 
2997
        idx_entry_o_data->owner_id  = QUOTA_FIRST_USER_ID;
 
2998
        /* 20 00 00 00 padding after here on ntfs 3.1. 3.0 is unchecked. */
 
2999
        idx_entry_o_data->unknown = const_cpu_to_le32(32);
 
3000
        err = insert_index_entry_in_res_dir_index(idx_entry_o, o_size, m,
 
3001
                        NTFS_INDEX_O, 2, AT_UNUSED);
 
3002
        free(idx_entry_o);
 
3003
 
 
3004
        return err;
 
3005
}
 
3006
 
 
3007
/**
 
3008
 * insert_file_link_in_dir_index
 
3009
 *
 
3010
 * Insert the fully completed FILE_NAME_ATTR @file_name which is inside
 
3011
 * the file with mft reference @file_ref into the index (allocation) block
 
3012
 * @idx (which belongs to @file_ref's parent directory).
 
3013
 *
 
3014
 * Return 0 on success or -errno on error.
 
3015
 */
 
3016
static int insert_file_link_in_dir_index(INDEX_BLOCK *idx, leMFT_REF file_ref,
 
3017
                FILE_NAME_ATTR *file_name, u32 file_name_size)
 
3018
{
 
3019
        int err, i;
 
3020
        INDEX_ENTRY *ie;
 
3021
        char *index_end;
 
3022
 
 
3023
        /*
 
3024
         * Lookup dir entry @file_name in dir @idx to determine correct
 
3025
         * insertion location. FIXME: Using a very oversimplified lookup
 
3026
         * method which is sufficient for mkntfs but no good whatsoever in
 
3027
         * real world scenario. (AIA)
 
3028
         */
 
3029
 
 
3030
        index_end = (char*)&idx->index + le32_to_cpu(idx->index.index_length);
 
3031
        ie = (INDEX_ENTRY*)((char*)&idx->index +
 
3032
                        le32_to_cpu(idx->index.entries_offset));
 
3033
        /*
 
3034
         * Loop until we exceed valid memory (corruption case) or until we
 
3035
         * reach the last entry.
 
3036
         */
 
3037
        while ((char*)ie < index_end && !(ie->ie_flags & INDEX_ENTRY_END)) {
 
3038
#if 0
 
3039
#ifdef DEBUG
 
3040
                ntfs_log_debug("file_name_attr1->file_name_length = %i\n",
 
3041
                                file_name->file_name_length);
 
3042
                if (file_name->file_name_length) {
 
3043
                        char *__buf = NULL;
 
3044
                        i = ntfs_ucstombs((ntfschar*)&file_name->file_name,
 
3045
                                file_name->file_name_length, &__buf, 0);
 
3046
                        if (i < 0)
 
3047
                                ntfs_log_debug("Name contains non-displayable "
 
3048
                                                "Unicode characters.\n");
 
3049
                        ntfs_log_debug("file_name_attr1->file_name = %s\n",
 
3050
                                        __buf);
 
3051
                        free(__buf);
 
3052
                }
 
3053
                ntfs_log_debug("file_name_attr2->file_name_length = %i\n",
 
3054
                                ie->key.file_name.file_name_length);
 
3055
                if (ie->key.file_name.file_name_length) {
 
3056
                        char *__buf = NULL;
 
3057
                        i = ntfs_ucstombs(ie->key.file_name.file_name,
 
3058
                                ie->key.file_name.file_name_length + 1, &__buf,
 
3059
                                0);
 
3060
                        if (i < 0)
 
3061
                                ntfs_log_debug("Name contains non-displayable "
 
3062
                                                "Unicode characters.\n");
 
3063
                        ntfs_log_debug("file_name_attr2->file_name = %s\n",
 
3064
                                        __buf);
 
3065
                        free(__buf);
 
3066
                }
 
3067
#endif
 
3068
#endif
 
3069
                /*
 
3070
                i = ntfs_file_values_compare(file_name,
 
3071
                                (FILE_NAME_ATTR*)&ie->key.file_name, 1,
 
3072
                                IGNORE_CASE, g_vol->upcase, g_vol->upcase_len);
 
3073
                */
 
3074
                i = ntfs_names_full_collate(file_name->file_name, file_name->file_name_length,
 
3075
                                ((FILE_NAME_ATTR*)&ie->key.file_name)->file_name, ((FILE_NAME_ATTR*)&ie->key.file_name)->file_name_length,
 
3076
                                IGNORE_CASE, g_vol->upcase, g_vol->upcase_len);
 
3077
                /*
 
3078
                 * If @file_name collates before ie->key.file_name, there is no
 
3079
                 * matching index entry.
 
3080
                 */
 
3081
                if (i == -1)
 
3082
                        break;
 
3083
                /* If file names are not equal, continue search. */
 
3084
                if (i)
 
3085
                        goto do_next;
 
3086
                /* File names are equal when compared ignoring case. */
 
3087
                /*
 
3088
                 * If BOTH file names are in the POSIX namespace, do a case
 
3089
                 * sensitive comparison as well. Otherwise the names match so
 
3090
                 * we return -EEXIST. FIXME: There are problems with this in a
 
3091
                 * real world scenario, when one is POSIX and one isn't, but
 
3092
                 * fine for mkntfs where we don't use POSIX namespace at all
 
3093
                 * and hence this following code is luxury. (AIA)
 
3094
                 */
 
3095
                if (file_name->file_name_type != FILE_NAME_POSIX ||
 
3096
                    ie->key.file_name.file_name_type != FILE_NAME_POSIX)
 
3097
                        return -EEXIST;
 
3098
                /*
 
3099
                i = ntfs_file_values_compare(file_name,
 
3100
                                (FILE_NAME_ATTR*)&ie->key.file_name, 1,
 
3101
                                CASE_SENSITIVE, g_vol->upcase,
 
3102
                                g_vol->upcase_len);
 
3103
                */
 
3104
                i = ntfs_names_full_collate(file_name->file_name, file_name->file_name_length,
 
3105
                                ((FILE_NAME_ATTR*)&ie->key.file_name)->file_name, ((FILE_NAME_ATTR*)&ie->key.file_name)->file_name_length,
 
3106
                                CASE_SENSITIVE, g_vol->upcase, g_vol->upcase_len);
 
3107
                if (i == -1)
 
3108
                        break;
 
3109
                /* Complete match. Bugger. Can't insert. */
 
3110
                if (!i)
 
3111
                        return -EEXIST;
 
3112
do_next:
 
3113
#ifdef DEBUG
 
3114
                /* Next entry. */
 
3115
                if (!ie->length) {
 
3116
                        ntfs_log_debug("BUG: ie->length is zero, breaking out "
 
3117
                                        "of loop.\n");
 
3118
                        break;
 
3119
                }
 
3120
#endif
 
3121
                ie = (INDEX_ENTRY*)((char*)ie + le16_to_cpu(ie->length));
 
3122
        };
 
3123
        i = (sizeof(INDEX_ENTRY_HEADER) + file_name_size + 7) & ~7;
 
3124
        err = make_room_for_index_entry_in_index_block(idx, ie, i);
 
3125
        if (err) {
 
3126
                ntfs_log_error("make_room_for_index_entry_in_index_block "
 
3127
                                "failed: %s\n", strerror(-err));
 
3128
                return err;
 
3129
        }
 
3130
        /* Create entry in place and copy file name attribute value. */
 
3131
        ie->indexed_file = file_ref;
 
3132
        ie->length = cpu_to_le16(i);
 
3133
        ie->key_length = cpu_to_le16(file_name_size);
 
3134
        ie->ie_flags = cpu_to_le16(0);
 
3135
        ie->reserved = cpu_to_le16(0);
 
3136
        memcpy((char*)&ie->key.file_name, (char*)file_name, file_name_size);
 
3137
        return 0;
 
3138
}
 
3139
 
 
3140
/**
 
3141
 * create_hardlink_res
 
3142
 *
 
3143
 * Create a file_name_attribute in the mft record @m_file which points to the
 
3144
 * parent directory with mft reference @ref_parent.
 
3145
 *
 
3146
 * Then, insert an index entry with this file_name_attribute in the index
 
3147
 * root @idx of the index_root attribute of the parent directory.
 
3148
 *
 
3149
 * @ref_file is the mft reference of @m_file.
 
3150
 *
 
3151
 * Return 0 on success or -errno on error.
 
3152
 */
 
3153
static int create_hardlink_res(MFT_RECORD *m_parent, const leMFT_REF ref_parent,
 
3154
                MFT_RECORD *m_file, const leMFT_REF ref_file,
 
3155
                const s64 allocated_size, const s64 data_size,
 
3156
                const FILE_ATTR_FLAGS flags, const u16 packed_ea_size,
 
3157
                const u32 reparse_point_tag, const char *file_name,
 
3158
                const FILE_NAME_TYPE_FLAGS file_name_type)
 
3159
{
 
3160
        FILE_NAME_ATTR *fn;
 
3161
        int i, fn_size, idx_size;
 
3162
        INDEX_ENTRY *idx_entry_new;
 
3163
        ntfschar *uname;
 
3164
 
 
3165
        /* Create the file_name attribute. */
 
3166
        i = (strlen(file_name) + 1) * sizeof(ntfschar);
 
3167
        fn_size = sizeof(FILE_NAME_ATTR) + i;
 
3168
        fn = ntfs_malloc(fn_size);
 
3169
        if (!fn)
 
3170
                return -errno;
 
3171
        fn->parent_directory = ref_parent;
 
3172
        fn->creation_time = stdinfo_time(m_file);
 
3173
        fn->last_data_change_time = fn->creation_time;
 
3174
        fn->last_mft_change_time = fn->creation_time;
 
3175
        fn->last_access_time = fn->creation_time;
 
3176
        fn->allocated_size = cpu_to_sle64(allocated_size);
 
3177
        fn->data_size = cpu_to_sle64(data_size);
 
3178
        fn->file_attributes = flags;
 
3179
        /* These are in a union so can't have both. */
 
3180
        if (packed_ea_size && reparse_point_tag) {
 
3181
                free(fn);
 
3182
                return -EINVAL;
 
3183
        }
 
3184
        if (packed_ea_size) {
 
3185
                free(fn);
 
3186
                return -EINVAL;
 
3187
        }
 
3188
        if (packed_ea_size) {
 
3189
                fn->packed_ea_size = cpu_to_le16(packed_ea_size);
 
3190
                fn->reserved = cpu_to_le16(0);
 
3191
        } else {
 
3192
                fn->reparse_point_tag = cpu_to_le32(reparse_point_tag);
 
3193
        }
 
3194
        fn->file_name_type = file_name_type;
 
3195
        uname = fn->file_name;
 
3196
        i = ntfs_mbstoucs_libntfscompat(file_name, &uname, i);
 
3197
        if (i < 1) {
 
3198
                free(fn);
 
3199
                return -EINVAL;
 
3200
        }
 
3201
        if (i > 0xff) {
 
3202
                free(fn);
 
3203
                return -ENAMETOOLONG;
 
3204
        }
 
3205
        /* No terminating null in file names. */
 
3206
        fn->file_name_length = i;
 
3207
        fn_size = sizeof(FILE_NAME_ATTR) + i * sizeof(ntfschar);
 
3208
        /* Increment the link count of @m_file. */
 
3209
        i = le16_to_cpu(m_file->link_count);
 
3210
        if (i == 0xffff) {
 
3211
                ntfs_log_error("Too many hardlinks present already.\n");
 
3212
                free(fn);
 
3213
                return -EINVAL;
 
3214
        }
 
3215
        m_file->link_count = cpu_to_le16(i + 1);
 
3216
        /* Add the file_name to @m_file. */
 
3217
        i = insert_resident_attr_in_mft_record(m_file, AT_FILE_NAME, NULL, 0,
 
3218
                        CASE_SENSITIVE, const_cpu_to_le16(0),
 
3219
                        RESIDENT_ATTR_IS_INDEXED, (u8*)fn, fn_size);
 
3220
        if (i < 0) {
 
3221
                ntfs_log_error("create_hardlink failed adding file name "
 
3222
                                "attribute: %s\n", strerror(-i));
 
3223
                free(fn);
 
3224
                /* Undo link count increment. */
 
3225
                m_file->link_count = cpu_to_le16(
 
3226
                                le16_to_cpu(m_file->link_count) - 1);
 
3227
                return i;
 
3228
        }
 
3229
        /* Insert the index entry for file_name in @idx. */
 
3230
        idx_size = (fn_size + 7)  & ~7;
 
3231
        idx_entry_new = ntfs_calloc(idx_size + 0x10);
 
3232
        if (!idx_entry_new)
 
3233
                return -errno;
 
3234
        idx_entry_new->indexed_file = ref_file;
 
3235
        idx_entry_new->length = cpu_to_le16(idx_size + 0x10);
 
3236
        idx_entry_new->key_length = cpu_to_le16(fn_size);
 
3237
        memcpy((u8*)idx_entry_new + 0x10, (u8*)fn, fn_size);
 
3238
        i = insert_index_entry_in_res_dir_index(idx_entry_new, idx_size + 0x10,
 
3239
                        m_parent, NTFS_INDEX_I30, 4, AT_FILE_NAME);
 
3240
        if (i < 0) {
 
3241
                ntfs_log_error("create_hardlink failed inserting index entry: "
 
3242
                                "%s\n", strerror(-i));
 
3243
                /* FIXME: Remove the file name attribute from @m_file. */
 
3244
                free(idx_entry_new);
 
3245
                free(fn);
 
3246
                /* Undo link count increment. */
 
3247
                m_file->link_count = cpu_to_le16(
 
3248
                                le16_to_cpu(m_file->link_count) - 1);
 
3249
                return i;
 
3250
        }
 
3251
        free(idx_entry_new);
 
3252
        free(fn);
 
3253
        return 0;
 
3254
}
 
3255
 
 
3256
/**
 
3257
 * create_hardlink
 
3258
 *
 
3259
 * Create a file_name_attribute in the mft record @m_file which points to the
 
3260
 * parent directory with mft reference @ref_parent.
 
3261
 *
 
3262
 * Then, insert an index entry with this file_name_attribute in the index
 
3263
 * block @idx of the index allocation attribute of the parent directory.
 
3264
 *
 
3265
 * @ref_file is the mft reference of @m_file.
 
3266
 *
 
3267
 * Return 0 on success or -errno on error.
 
3268
 */
 
3269
static int create_hardlink(INDEX_BLOCK *idx, const leMFT_REF ref_parent,
 
3270
                MFT_RECORD *m_file, const leMFT_REF ref_file,
 
3271
                const s64 allocated_size, const s64 data_size,
 
3272
                const FILE_ATTR_FLAGS flags, const u16 packed_ea_size,
 
3273
                const u32 reparse_point_tag, const char *file_name,
 
3274
                const FILE_NAME_TYPE_FLAGS file_name_type)
 
3275
{
 
3276
        FILE_NAME_ATTR *fn;
 
3277
        int i, fn_size;
 
3278
        ntfschar *uname;
 
3279
 
 
3280
        /* Create the file_name attribute. */
 
3281
        i = (strlen(file_name) + 1) * sizeof(ntfschar);
 
3282
        fn_size = sizeof(FILE_NAME_ATTR) + i;
 
3283
        fn = ntfs_malloc(fn_size);
 
3284
        if (!fn)
 
3285
                return -errno;
 
3286
        fn->parent_directory = ref_parent;
 
3287
        fn->creation_time = stdinfo_time(m_file);
 
3288
        fn->last_data_change_time = fn->creation_time;
 
3289
        fn->last_mft_change_time = fn->creation_time;
 
3290
        fn->last_access_time = fn->creation_time;
 
3291
                /* allocated size depends on unnamed data being resident */
 
3292
        if (allocated_size && non_resident_unnamed_data(m_file))
 
3293
                fn->allocated_size = cpu_to_sle64(allocated_size);
 
3294
        else
 
3295
                fn->allocated_size = cpu_to_sle64((data_size + 7) & -8);
 
3296
        fn->data_size = cpu_to_sle64(data_size);
 
3297
        fn->file_attributes = flags;
 
3298
        /* These are in a union so can't have both. */
 
3299
        if (packed_ea_size && reparse_point_tag) {
 
3300
                free(fn);
 
3301
                return -EINVAL;
 
3302
        }
 
3303
        if (packed_ea_size) {
 
3304
                fn->packed_ea_size = cpu_to_le16(packed_ea_size);
 
3305
                fn->reserved = cpu_to_le16(0);
 
3306
        } else {
 
3307
                fn->reparse_point_tag = cpu_to_le32(reparse_point_tag);
 
3308
        }
 
3309
        fn->file_name_type = file_name_type;
 
3310
        uname = fn->file_name;
 
3311
        i = ntfs_mbstoucs_libntfscompat(file_name, &uname, i);
 
3312
        if (i < 1) {
 
3313
                free(fn);
 
3314
                return -EINVAL;
 
3315
        }
 
3316
        if (i > 0xff) {
 
3317
                free(fn);
 
3318
                return -ENAMETOOLONG;
 
3319
        }
 
3320
        /* No terminating null in file names. */
 
3321
        fn->file_name_length = i;
 
3322
        fn_size = sizeof(FILE_NAME_ATTR) + i * sizeof(ntfschar);
 
3323
        /* Increment the link count of @m_file. */
 
3324
        i = le16_to_cpu(m_file->link_count);
 
3325
        if (i == 0xffff) {
 
3326
                ntfs_log_error("Too many hardlinks present already.\n");
 
3327
                free(fn);
 
3328
                return -EINVAL;
 
3329
        }
 
3330
        m_file->link_count = cpu_to_le16(i + 1);
 
3331
        /* Add the file_name to @m_file. */
 
3332
        i = insert_resident_attr_in_mft_record(m_file, AT_FILE_NAME, NULL, 0,
 
3333
                        CASE_SENSITIVE, cpu_to_le16(0),
 
3334
                        RESIDENT_ATTR_IS_INDEXED, (u8*)fn, fn_size);
 
3335
        if (i < 0) {
 
3336
                ntfs_log_error("create_hardlink failed adding file name attribute: "
 
3337
                                "%s\n", strerror(-i));
 
3338
                free(fn);
 
3339
                /* Undo link count increment. */
 
3340
                m_file->link_count = cpu_to_le16(
 
3341
                                le16_to_cpu(m_file->link_count) - 1);
 
3342
                return i;
 
3343
        }
 
3344
        /* Insert the index entry for file_name in @idx. */
 
3345
        i = insert_file_link_in_dir_index(idx, ref_file, fn, fn_size);
 
3346
        if (i < 0) {
 
3347
                ntfs_log_error("create_hardlink failed inserting index entry: %s\n",
 
3348
                                strerror(-i));
 
3349
                /* FIXME: Remove the file name attribute from @m_file. */
 
3350
                free(fn);
 
3351
                /* Undo link count increment. */
 
3352
                m_file->link_count = cpu_to_le16(
 
3353
                                le16_to_cpu(m_file->link_count) - 1);
 
3354
                return i;
 
3355
        }
 
3356
        free(fn);
 
3357
        return 0;
 
3358
}
 
3359
 
 
3360
/**
 
3361
 * index_obj_id_insert
 
3362
 *
 
3363
 * Insert an index entry with the key @guid and data pointing to the mft record
 
3364
 * @ref in the $O index root of the mft record @m (which must be the mft record
 
3365
 * for $ObjId).
 
3366
 *
 
3367
 * Return 0 on success or -errno on error.
 
3368
 */
 
3369
static int index_obj_id_insert(MFT_RECORD *m, const GUID *guid,
 
3370
                const leMFT_REF ref)
 
3371
{
 
3372
        INDEX_ENTRY *idx_entry_new;
 
3373
        int data_ofs, idx_size, err;
 
3374
        OBJ_ID_INDEX_DATA *oi;
 
3375
 
 
3376
        /*
 
3377
         * Insert the index entry for the object id in the index.
 
3378
         *
 
3379
         * First determine the size of the index entry to be inserted.  This
 
3380
         * consists of the index entry header, followed by the index key, i.e.
 
3381
         * the GUID, followed by the index data, i.e. OBJ_ID_INDEX_DATA.
 
3382
         */
 
3383
        data_ofs = (sizeof(INDEX_ENTRY_HEADER) + sizeof(GUID) + 7) & ~7;
 
3384
        idx_size = (data_ofs + sizeof(OBJ_ID_INDEX_DATA) + 7) & ~7;
 
3385
        idx_entry_new = ntfs_calloc(idx_size);
 
3386
        if (!idx_entry_new)
 
3387
                return -errno;
 
3388
        idx_entry_new->data_offset = cpu_to_le16(data_ofs);
 
3389
        idx_entry_new->data_length = cpu_to_le16(sizeof(OBJ_ID_INDEX_DATA));
 
3390
        idx_entry_new->length = cpu_to_le16(idx_size);
 
3391
        idx_entry_new->key_length = cpu_to_le16(sizeof(GUID));
 
3392
        idx_entry_new->key.object_id = *guid;
 
3393
        oi = (OBJ_ID_INDEX_DATA*)((u8*)idx_entry_new + data_ofs);
 
3394
        oi->mft_reference = ref;
 
3395
        err = insert_index_entry_in_res_dir_index(idx_entry_new, idx_size, m,
 
3396
                        NTFS_INDEX_O, 2, AT_UNUSED);
 
3397
        free(idx_entry_new);
 
3398
        if (err < 0) {
 
3399
                ntfs_log_error("index_obj_id_insert failed inserting index "
 
3400
                                "entry: %s\n", strerror(-err));
 
3401
                return err;
 
3402
        }
 
3403
        return 0;
 
3404
}
 
3405
 
 
3406
/**
 
3407
 * mkntfs_cleanup
 
3408
 */
 
3409
static void mkntfs_cleanup(void)
 
3410
{
 
3411
        struct BITMAP_ALLOCATION *p, *q;
 
3412
 
 
3413
        /* Close the volume */
 
3414
        if (g_vol) {
 
3415
                if (g_vol->dev) {
 
3416
                        if (NDevOpen(g_vol->dev) && g_vol->dev->d_ops->close(g_vol->dev))
 
3417
                                ntfs_log_perror("Warning: Could not close %s", g_vol->dev->d_name);
 
3418
                        ntfs_device_free(g_vol->dev);
 
3419
                }
 
3420
                free(g_vol->vol_name);
 
3421
                free(g_vol->attrdef);
 
3422
                free(g_vol->upcase);
 
3423
                free(g_vol);
 
3424
                g_vol = NULL;
 
3425
        }
 
3426
 
 
3427
        /* Free any memory we've used */
 
3428
        free(g_bad_blocks);     g_bad_blocks    = NULL;
 
3429
        free(g_buf);            g_buf           = NULL;
 
3430
        free(g_index_block);    g_index_block   = NULL;
 
3431
        free(g_dynamic_buf);    g_dynamic_buf   = NULL;
 
3432
        free(g_mft_bitmap);     g_mft_bitmap    = NULL;
 
3433
        free(g_rl_bad);         g_rl_bad        = NULL;
 
3434
        free(g_rl_boot);        g_rl_boot       = NULL;
 
3435
        free(g_rl_logfile);     g_rl_logfile    = NULL;
 
3436
        free(g_rl_mft);         g_rl_mft        = NULL;
 
3437
        free(g_rl_mft_bmp);     g_rl_mft_bmp    = NULL;
 
3438
        free(g_rl_mftmirr);     g_rl_mftmirr    = NULL;
 
3439
 
 
3440
        p = g_allocation;
 
3441
        while (p) {
 
3442
                q = p->next;
 
3443
                free(p);
 
3444
                p = q;
 
3445
        }
 
3446
}
 
3447
 
 
3448
 
 
3449
/**
 
3450
 * mkntfs_open_partition -
 
3451
 */
 
3452
static BOOL mkntfs_open_partition(ntfs_volume *vol)
 
3453
{
 
3454
        BOOL result = FALSE;
 
3455
        int i;
 
3456
        struct stat sbuf;
 
3457
        unsigned long mnt_flags;
 
3458
 
 
3459
        /*
 
3460
         * Allocate and initialize an ntfs device structure and attach it to
 
3461
         * the volume.
 
3462
         */
 
3463
        vol->dev = ntfs_device_alloc(opts.dev_name, 0, &ntfs_device_default_io_ops, NULL);
 
3464
        if (!vol->dev) {
 
3465
                ntfs_log_perror("Could not create device");
 
3466
                goto done;
 
3467
        }
 
3468
 
 
3469
        /* Open the device for reading or reading and writing. */
 
3470
        if (opts.no_action) {
 
3471
                ntfs_log_quiet("Running in READ-ONLY mode!\n");
 
3472
                i = O_RDONLY;
 
3473
        } else {
 
3474
                i = O_RDWR;
 
3475
        }
 
3476
        if (vol->dev->d_ops->open(vol->dev, i)) {
 
3477
                if (errno == ENOENT)
 
3478
                        ntfs_log_error("The device doesn't exist; did you specify it correctly?\n");
 
3479
                else
 
3480
                        ntfs_log_perror("Could not open %s", vol->dev->d_name);
 
3481
                goto done;
 
3482
        }
 
3483
        /* Verify we are dealing with a block device. */
 
3484
        if (vol->dev->d_ops->stat(vol->dev, &sbuf)) {
 
3485
                ntfs_log_perror("Error getting information about %s", vol->dev->d_name);
 
3486
                goto done;
 
3487
        }
 
3488
 
 
3489
        if (!S_ISBLK(sbuf.st_mode)) {
 
3490
                ntfs_log_error("%s is not a block device.\n", vol->dev->d_name);
 
3491
                if (!opts.force) {
 
3492
                        ntfs_log_error("Refusing to make a filesystem here!\n");
 
3493
                        goto done;
 
3494
                }
 
3495
                if (!opts.num_sectors) {
 
3496
                        if (!sbuf.st_size && !sbuf.st_blocks) {
 
3497
                                ntfs_log_error("You must specify the number of sectors.\n");
 
3498
                                goto done;
 
3499
                        }
 
3500
                        if (opts.sector_size) {
 
3501
                                if (sbuf.st_size)
 
3502
                                        opts.num_sectors = sbuf.st_size / opts.sector_size;
 
3503
                                else
 
3504
                                        opts.num_sectors = ((s64)sbuf.st_blocks << 9) / opts.sector_size;
 
3505
                        } else {
 
3506
                                if (sbuf.st_size)
 
3507
                                        opts.num_sectors = sbuf.st_size / 512;
 
3508
                                else
 
3509
                                        opts.num_sectors = sbuf.st_blocks;
 
3510
                                opts.sector_size = 512;
 
3511
                        }
 
3512
                }
 
3513
                ntfs_log_warning("mkntfs forced anyway.\n");
 
3514
#ifdef HAVE_LINUX_MAJOR_H
 
3515
        } else if ((IDE_DISK_MAJOR(MAJOR(sbuf.st_rdev)) &&
 
3516
                        MINOR(sbuf.st_rdev) % 64 == 0) ||
 
3517
                        (SCSI_DISK_MAJOR(MAJOR(sbuf.st_rdev)) &&
 
3518
                        MINOR(sbuf.st_rdev) % 16 == 0)) {
 
3519
                ntfs_log_error("%s is entire device, not just one partition.\n", vol->dev->d_name);
 
3520
                if (!opts.force) {
 
3521
                        ntfs_log_error("Refusing to make a filesystem here!\n");
 
3522
                        goto done;
 
3523
                }
 
3524
                ntfs_log_warning("mkntfs forced anyway.\n");
 
3525
#endif
 
3526
        }
 
3527
        /* Make sure the file system is not mounted. */
 
3528
        if (ntfs_check_if_mounted(vol->dev->d_name, &mnt_flags)) {
 
3529
                ntfs_log_perror("Failed to determine whether %s is mounted", vol->dev->d_name);
 
3530
        } else if (mnt_flags & NTFS_MF_MOUNTED) {
 
3531
                ntfs_log_error("%s is mounted.\n", vol->dev->d_name);
 
3532
                if (!opts.force) {
 
3533
                        ntfs_log_error("Refusing to make a filesystem here!\n");
 
3534
                        goto done;
 
3535
                }
 
3536
                ntfs_log_warning("mkntfs forced anyway. Hope /etc/mtab is incorrect.\n");
 
3537
        }
 
3538
        result = TRUE;
 
3539
done:
 
3540
        return result;
 
3541
}
 
3542
 
 
3543
/**
 
3544
 * mkntfs_get_page_size - detect the system's memory page size.
 
3545
 */
 
3546
static long mkntfs_get_page_size(void)
 
3547
{
 
3548
        long page_size;
 
3549
#ifdef _SC_PAGESIZE
 
3550
        page_size = sysconf(_SC_PAGESIZE);
 
3551
        if (page_size < 0)
 
3552
#endif
 
3553
        {
 
3554
                ntfs_log_warning("Failed to determine system page size.  "
 
3555
                                "Assuming safe default of 4096 bytes.\n");
 
3556
                return 4096;
 
3557
        }
 
3558
        ntfs_log_debug("System page size is %li bytes.\n", page_size);
 
3559
        return page_size;
 
3560
}
 
3561
 
 
3562
/**
 
3563
 * mkntfs_override_vol_params -
 
3564
 */
 
3565
static BOOL mkntfs_override_vol_params(ntfs_volume *vol)
 
3566
{
 
3567
        s64 volume_size;
 
3568
        long page_size;
 
3569
        int i;
 
3570
        BOOL winboot = TRUE;
 
3571
 
 
3572
        /* If user didn't specify the sector size, determine it now. */
 
3573
        if (opts.sector_size < 0) {
 
3574
                opts.sector_size = ntfs_device_sector_size_get(vol->dev);
 
3575
                if (opts.sector_size < 0) {
 
3576
                        ntfs_log_warning("The sector size was not specified "
 
3577
                                "for %s and it could not be obtained "
 
3578
                                "automatically.  It has been set to 512 "
 
3579
                                "bytes.\n", vol->dev->d_name);
 
3580
                        opts.sector_size = 512;
 
3581
                }
 
3582
        }
 
3583
        /* Validate sector size. */
 
3584
        if ((opts.sector_size - 1) & opts.sector_size) {
 
3585
                ntfs_log_error("The sector size is invalid.  It must be a "
 
3586
                        "power of two, e.g. 512, 1024.\n");
 
3587
                return FALSE;
 
3588
        }
 
3589
        if (opts.sector_size < 256 || opts.sector_size > 4096) {
 
3590
                ntfs_log_error("The sector size is invalid.  The minimum size "
 
3591
                        "is 256 bytes and the maximum is 4096 bytes.\n");
 
3592
                return FALSE;
 
3593
        }
 
3594
        ntfs_log_debug("sector size = %ld bytes\n", opts.sector_size);
 
3595
        /* Now set the device block size to the sector size. */
 
3596
        if (ntfs_device_block_size_set(vol->dev, opts.sector_size))
 
3597
                ntfs_log_debug("Failed to set the device block size to the "
 
3598
                                "sector size.  This may cause problems when "
 
3599
                                "creating the backup boot sector and also may "
 
3600
                                "affect performance but should be harmless "
 
3601
                                "otherwise.  Error: %s\n", strerror(errno));
 
3602
        /* If user didn't specify the number of sectors, determine it now. */
 
3603
        if (opts.num_sectors < 0) {
 
3604
                opts.num_sectors = ntfs_device_size_get(vol->dev,
 
3605
                                opts.sector_size);
 
3606
                if (opts.num_sectors <= 0) {
 
3607
                        ntfs_log_error("Couldn't determine the size of %s.  "
 
3608
                                "Please specify the number of sectors "
 
3609
                                "manually.\n", vol->dev->d_name);
 
3610
                        return FALSE;
 
3611
                }
 
3612
        }
 
3613
        ntfs_log_debug("number of sectors = %lld (0x%llx)\n", opts.num_sectors,
 
3614
                        opts.num_sectors);
 
3615
        /*
 
3616
         * Reserve the last sector for the backup boot sector unless the
 
3617
         * sector size is less than 512 bytes in which case reserve 512 bytes
 
3618
         * worth of sectors.
 
3619
         */
 
3620
        i = 1;
 
3621
        if (opts.sector_size < 512)
 
3622
                i = 512 / opts.sector_size;
 
3623
        opts.num_sectors -= i;
 
3624
        /* If user didn't specify the partition start sector, determine it. */
 
3625
        if (opts.part_start_sect < 0) {
 
3626
                opts.part_start_sect = ntfs_device_partition_start_sector_get(
 
3627
                                vol->dev);
 
3628
                if (opts.part_start_sect < 0) {
 
3629
                        ntfs_log_warning("The partition start sector was not "
 
3630
                                "specified for %s and it could not be obtained "
 
3631
                                "automatically.  It has been set to 0.\n",
 
3632
                                vol->dev->d_name);
 
3633
                        opts.part_start_sect = 0;
 
3634
                        winboot = FALSE;
 
3635
                } else if (opts.part_start_sect >> 32) {
 
3636
                        ntfs_log_warning("The partition start sector specified "
 
3637
                                "for %s and the automatically determined value "
 
3638
                                "is too large.  It has been set to 0.\n",
 
3639
                                vol->dev->d_name);
 
3640
                        opts.part_start_sect = 0;
 
3641
                        winboot = FALSE;
 
3642
                }
 
3643
        } else if (opts.part_start_sect >> 32) {
 
3644
                ntfs_log_error("Invalid partition start sector.  Maximum is "
 
3645
                        "4294967295 (2^32-1).\n");
 
3646
                return FALSE;
 
3647
        }
 
3648
        /* If user didn't specify the sectors per track, determine it now. */
 
3649
        if (opts.sectors_per_track < 0) {
 
3650
                opts.sectors_per_track = ntfs_device_sectors_per_track_get(
 
3651
                                vol->dev);
 
3652
                if (opts.sectors_per_track < 0) {
 
3653
                        ntfs_log_warning("The number of sectors per track was "
 
3654
                                "not specified for %s and it could not be "
 
3655
                                "obtained automatically.  It has been set to "
 
3656
                                "0.\n", vol->dev->d_name);
 
3657
                        opts.sectors_per_track = 0;
 
3658
                        winboot = FALSE;
 
3659
                } else if (opts.sectors_per_track > 65535) {
 
3660
                        ntfs_log_warning("The number of sectors per track was "
 
3661
                                "not specified for %s and the automatically "
 
3662
                                "determined value is too large.  It has been "
 
3663
                                "set to 0.\n", vol->dev->d_name);
 
3664
                        opts.sectors_per_track = 0;
 
3665
                        winboot = FALSE;
 
3666
                }
 
3667
        } else if (opts.sectors_per_track > 65535) {
 
3668
                ntfs_log_error("Invalid number of sectors per track.  Maximum "
 
3669
                        "is 65535.\n");
 
3670
                return FALSE;
 
3671
        }
 
3672
        /* If user didn't specify the number of heads, determine it now. */
 
3673
        if (opts.heads < 0) {
 
3674
                opts.heads = ntfs_device_heads_get(vol->dev);
 
3675
                if (opts.heads < 0) {
 
3676
                        ntfs_log_warning("The number of heads was not "
 
3677
                                "specified for %s and it could not be obtained "
 
3678
                                "automatically.  It has been set to 0.\n",
 
3679
                                vol->dev->d_name);
 
3680
                        opts.heads = 0;
 
3681
                        winboot = FALSE;
 
3682
                } else if (opts.heads > 65535) {
 
3683
                        ntfs_log_warning("The number of heads was not "
 
3684
                                "specified for %s and the automatically "
 
3685
                                "determined value is too large.  It has been "
 
3686
                                "set to 0.\n", vol->dev->d_name);
 
3687
                        opts.heads = 0;
 
3688
                        winboot = FALSE;
 
3689
                }
 
3690
        } else if (opts.heads > 65535) {
 
3691
                ntfs_log_error("Invalid number of heads.  Maximum is 65535.\n");
 
3692
                return FALSE;
 
3693
        }
 
3694
        volume_size = opts.num_sectors * opts.sector_size;
 
3695
        /* Validate volume size. */
 
3696
        if (volume_size < (1 << 20)) {                  /* 1MiB */
 
3697
                ntfs_log_error("Device is too small (%llikiB).  Minimum NTFS "
 
3698
                                "volume size is 1MiB.\n",
 
3699
                                (long long)(volume_size / 1024));
 
3700
                return FALSE;
 
3701
        }
 
3702
        ntfs_log_debug("volume size = %llikiB\n", volume_size / 1024);
 
3703
        /* If user didn't specify the cluster size, determine it now. */
 
3704
        if (!vol->cluster_size) {
 
3705
                /*
 
3706
                 * Windows Vista always uses 4096 bytes as the default cluster
 
3707
                 * size regardless of the volume size so we do it, too.
 
3708
                 */
 
3709
                vol->cluster_size = 4096;
 
3710
                /* For small volumes on devices with large sector sizes. */
 
3711
                if (vol->cluster_size < (u32)opts.sector_size)
 
3712
                        vol->cluster_size = opts.sector_size;
 
3713
                /*
 
3714
                 * For huge volumes, grow the cluster size until the number of
 
3715
                 * clusters fits into 32 bits or the cluster size exceeds the
 
3716
                 * maximum limit of 64kiB.
 
3717
                 */
 
3718
                while (volume_size >> (ffs(vol->cluster_size) - 1 + 32)) {
 
3719
                        vol->cluster_size <<= 1;
 
3720
                        if (vol->cluster_size > 65535) {
 
3721
                                ntfs_log_error("Device is too large to hold an "
 
3722
                                                "NTFS volume (maximum size is "
 
3723
                                                "256TiB).\n");
 
3724
                                return FALSE;
 
3725
                        }
 
3726
                }
 
3727
                ntfs_log_quiet("Cluster size has been automatically set to %u "
 
3728
                                "bytes.\n", (unsigned)vol->cluster_size);
 
3729
        }
 
3730
        /* Validate cluster size. */
 
3731
        if (vol->cluster_size & (vol->cluster_size - 1)) {
 
3732
                ntfs_log_error("The cluster size is invalid.  It must be a "
 
3733
                                "power of two, e.g. 1024, 4096.\n");
 
3734
                return FALSE;
 
3735
        }
 
3736
        if (vol->cluster_size < (u32)opts.sector_size) {
 
3737
                ntfs_log_error("The cluster size is invalid.  It must be equal "
 
3738
                                "to, or larger than, the sector size.\n");
 
3739
                return FALSE;
 
3740
        }
 
3741
        if (vol->cluster_size > 128 * (u32)opts.sector_size) {
 
3742
                ntfs_log_error("The cluster size is invalid.  It cannot be "
 
3743
                                "more that 128 times the size of the sector "
 
3744
                                "size.\n");
 
3745
                return FALSE;
 
3746
        }
 
3747
        if (vol->cluster_size > 65536) {
 
3748
                ntfs_log_error("The cluster size is invalid.  The maximum "
 
3749
                        "cluster size is 65536 bytes (64kiB).\n");
 
3750
                return FALSE;
 
3751
        }
 
3752
        vol->cluster_size_bits = ffs(vol->cluster_size) - 1;
 
3753
        ntfs_log_debug("cluster size = %u bytes\n",
 
3754
                        (unsigned int)vol->cluster_size);
 
3755
        if (vol->cluster_size > 4096) {
 
3756
                if (opts.enable_compression) {
 
3757
                        if (!opts.force) {
 
3758
                                ntfs_log_error("Windows cannot use compression "
 
3759
                                                "when the cluster size is "
 
3760
                                                "larger than 4096 bytes.\n");
 
3761
                                return FALSE;
 
3762
                        }
 
3763
                        opts.enable_compression = 0;
 
3764
                }
 
3765
                ntfs_log_warning("Windows cannot use compression when the "
 
3766
                                "cluster size is larger than 4096 bytes.  "
 
3767
                                "Compression has been disabled for this "
 
3768
                                "volume.\n");
 
3769
        }
 
3770
        vol->nr_clusters = volume_size / vol->cluster_size;
 
3771
        /*
 
3772
         * Check the cluster_size and num_sectors for consistency with
 
3773
         * sector_size and num_sectors. And check both of these for consistency
 
3774
         * with volume_size.
 
3775
         */
 
3776
        if ((vol->nr_clusters != ((opts.num_sectors * opts.sector_size) /
 
3777
                        vol->cluster_size) ||
 
3778
                        (volume_size / opts.sector_size) != opts.num_sectors ||
 
3779
                        (volume_size / vol->cluster_size) !=
 
3780
                        vol->nr_clusters)) {
 
3781
                /* XXX is this code reachable? */
 
3782
                ntfs_log_error("Illegal combination of volume/cluster/sector "
 
3783
                                "size and/or cluster/sector number.\n");
 
3784
                return FALSE;
 
3785
        }
 
3786
        ntfs_log_debug("number of clusters = %llu (0x%llx)\n",
 
3787
                        vol->nr_clusters, vol->nr_clusters);
 
3788
        /* Number of clusters must fit within 32 bits (Win2k limitation). */
 
3789
        if (vol->nr_clusters >> 32) {
 
3790
                if (vol->cluster_size >= 65536) {
 
3791
                        ntfs_log_error("Device is too large to hold an NTFS "
 
3792
                                        "volume (maximum size is 256TiB).\n");
 
3793
                        return FALSE;
 
3794
                }
 
3795
                ntfs_log_error("Number of clusters exceeds 32 bits.  Please "
 
3796
                                "try again with a larger\ncluster size or "
 
3797
                                "leave the cluster size unspecified and the "
 
3798
                                "smallest possible cluster size for the size "
 
3799
                                "of the device will be used.\n");
 
3800
                return FALSE;
 
3801
        }
 
3802
        page_size = mkntfs_get_page_size();
 
3803
        /*
 
3804
         * Set the mft record size.  By default this is 1024 but it has to be
 
3805
         * at least as big as a sector and not bigger than a page on the system
 
3806
         * or the NTFS kernel driver will not be able to mount the volume.
 
3807
         * TODO: The mft record size should be user specifiable just like the
 
3808
         * "inode size" can be specified on other Linux/Unix file systems.
 
3809
         */
 
3810
        vol->mft_record_size = 1024;
 
3811
        if (vol->mft_record_size < (u32)opts.sector_size)
 
3812
                vol->mft_record_size = opts.sector_size;
 
3813
        if (vol->mft_record_size > (unsigned long)page_size)
 
3814
                ntfs_log_warning("Mft record size (%u bytes) exceeds system "
 
3815
                                "page size (%li bytes).  You will not be able "
 
3816
                                "to mount this volume using the NTFS kernel "
 
3817
                                "driver.\n", (unsigned)vol->mft_record_size,
 
3818
                                page_size);
 
3819
        vol->mft_record_size_bits = ffs(vol->mft_record_size) - 1;
 
3820
        ntfs_log_debug("mft record size = %u bytes\n",
 
3821
                        (unsigned)vol->mft_record_size);
 
3822
        /*
 
3823
         * Set the index record size.  By default this is 4096 but it has to be
 
3824
         * at least as big as a sector and not bigger than a page on the system
 
3825
         * or the NTFS kernel driver will not be able to mount the volume.
 
3826
         * FIXME: Should we make the index record size to be user specifiable?
 
3827
         */
 
3828
        vol->indx_record_size = 4096;
 
3829
        if (vol->indx_record_size < (u32)opts.sector_size)
 
3830
                vol->indx_record_size = opts.sector_size;
 
3831
        if (vol->indx_record_size > (unsigned long)page_size)
 
3832
                ntfs_log_warning("Index record size (%u bytes) exceeds system "
 
3833
                                "page size (%li bytes).  You will not be able "
 
3834
                                "to mount this volume using the NTFS kernel "
 
3835
                                "driver.\n", (unsigned)vol->indx_record_size,
 
3836
                                page_size);
 
3837
        vol->indx_record_size_bits = ffs(vol->indx_record_size) - 1;
 
3838
        ntfs_log_debug("index record size = %u bytes\n",
 
3839
                        (unsigned)vol->indx_record_size);
 
3840
        if (!winboot) {
 
3841
                ntfs_log_warning("To boot from a device, Windows needs the "
 
3842
                                "'partition start sector', the 'sectors per "
 
3843
                                "track' and the 'number of heads' to be "
 
3844
                                "set.\n");
 
3845
                ntfs_log_warning("Windows will not be able to boot from this "
 
3846
                                "device.\n");
 
3847
        }
 
3848
        return TRUE;
 
3849
}
 
3850
 
 
3851
/**
 
3852
 * mkntfs_initialize_bitmaps -
 
3853
 */
 
3854
static BOOL mkntfs_initialize_bitmaps(void)
 
3855
{
 
3856
        u64 i;
 
3857
        int mft_bitmap_size;
 
3858
 
 
3859
        /* Determine lcn bitmap byte size and allocate it. */
 
3860
        g_lcn_bitmap_byte_size = (g_vol->nr_clusters + 7) >> 3;
 
3861
        /* Needs to be multiple of 8 bytes. */
 
3862
        g_lcn_bitmap_byte_size = (g_lcn_bitmap_byte_size + 7) & ~7;
 
3863
        i = (g_lcn_bitmap_byte_size + g_vol->cluster_size - 1) &
 
3864
                        ~(g_vol->cluster_size - 1);
 
3865
        ntfs_log_debug("g_lcn_bitmap_byte_size = %i, allocated = %llu\n",
 
3866
                        g_lcn_bitmap_byte_size, i);
 
3867
        g_dynamic_buf_size = mkntfs_get_page_size();
 
3868
        g_dynamic_buf = (u8*)ntfs_calloc(g_dynamic_buf_size);
 
3869
        if (!g_dynamic_buf)
 
3870
                return FALSE;
 
3871
        /*
 
3872
         * $Bitmap can overlap the end of the volume. Any bits in this region
 
3873
         * must be set. This region also encompasses the backup boot sector.
 
3874
         */
 
3875
        if (!bitmap_allocate(g_vol->nr_clusters,
 
3876
                    ((s64)g_lcn_bitmap_byte_size << 3) - g_vol->nr_clusters))
 
3877
                return (FALSE);
 
3878
        /*
 
3879
         * Mft size is 27 (NTFS 3.0+) mft records or one cluster, whichever is
 
3880
         * bigger.
 
3881
         */
 
3882
        g_mft_size = 27;
 
3883
        g_mft_size *= g_vol->mft_record_size;
 
3884
        if (g_mft_size < (s32)g_vol->cluster_size)
 
3885
                g_mft_size = g_vol->cluster_size;
 
3886
        ntfs_log_debug("MFT size = %i (0x%x) bytes\n", g_mft_size, g_mft_size);
 
3887
        /* Determine mft bitmap size and allocate it. */
 
3888
        mft_bitmap_size = g_mft_size / g_vol->mft_record_size;
 
3889
        /* Convert to bytes, at least one. */
 
3890
        g_mft_bitmap_byte_size = (mft_bitmap_size + 7) >> 3;
 
3891
        /* Mft bitmap is allocated in multiples of 8 bytes. */
 
3892
        g_mft_bitmap_byte_size = (g_mft_bitmap_byte_size + 7) & ~7;
 
3893
        ntfs_log_debug("mft_bitmap_size = %i, g_mft_bitmap_byte_size = %i\n",
 
3894
                        mft_bitmap_size, g_mft_bitmap_byte_size);
 
3895
        g_mft_bitmap = ntfs_calloc(g_mft_bitmap_byte_size);
 
3896
        if (!g_mft_bitmap)
 
3897
                return FALSE;
 
3898
        /* Create runlist for mft bitmap. */
 
3899
        g_rl_mft_bmp = ntfs_malloc(2 * sizeof(runlist));
 
3900
        if (!g_rl_mft_bmp)
 
3901
                return FALSE;
 
3902
 
 
3903
        g_rl_mft_bmp[0].vcn = 0LL;
 
3904
        /* Mft bitmap is right after $Boot's data. */
 
3905
        i = (8192 + g_vol->cluster_size - 1) / g_vol->cluster_size;
 
3906
        g_rl_mft_bmp[0].lcn = i;
 
3907
        /*
 
3908
         * Size is always one cluster, even though valid data size and
 
3909
         * initialized data size are only 8 bytes.
 
3910
         */
 
3911
        g_rl_mft_bmp[1].vcn = 1LL;
 
3912
        g_rl_mft_bmp[0].length = 1LL;
 
3913
        g_rl_mft_bmp[1].lcn = -1LL;
 
3914
        g_rl_mft_bmp[1].length = 0LL;
 
3915
        /* Allocate cluster for mft bitmap. */
 
3916
        return (bitmap_allocate(i,1));
 
3917
}
 
3918
 
 
3919
/**
 
3920
 * mkntfs_initialize_rl_mft -
 
3921
 */
 
3922
static BOOL mkntfs_initialize_rl_mft(void)
 
3923
{
 
3924
        int j;
 
3925
        BOOL done;
 
3926
 
 
3927
        /* If user didn't specify the mft lcn, determine it now. */
 
3928
        if (!g_mft_lcn) {
 
3929
                /*
 
3930
                 * We start at the higher value out of 16kiB and just after the
 
3931
                 * mft bitmap.
 
3932
                 */
 
3933
                g_mft_lcn = g_rl_mft_bmp[0].lcn + g_rl_mft_bmp[0].length;
 
3934
                if (g_mft_lcn * g_vol->cluster_size < 16 * 1024)
 
3935
                        g_mft_lcn = (16 * 1024 + g_vol->cluster_size - 1) /
 
3936
                                        g_vol->cluster_size;
 
3937
        }
 
3938
        ntfs_log_debug("$MFT logical cluster number = 0x%llx\n", g_mft_lcn);
 
3939
        /* Determine MFT zone size. */
 
3940
        g_mft_zone_end = g_vol->nr_clusters;
 
3941
        switch (opts.mft_zone_multiplier) {  /* % of volume size in clusters */
 
3942
        case 4:
 
3943
                g_mft_zone_end = g_mft_zone_end >> 1;   /* 50%   */
 
3944
                break;
 
3945
        case 3:
 
3946
                g_mft_zone_end = g_mft_zone_end * 3 >> 3;/* 37.5% */
 
3947
                break;
 
3948
        case 2:
 
3949
                g_mft_zone_end = g_mft_zone_end >> 2;   /* 25%   */
 
3950
                break;
 
3951
        case 1:
 
3952
        default:
 
3953
                g_mft_zone_end = g_mft_zone_end >> 3;   /* 12.5% */
 
3954
                break;
 
3955
        }
 
3956
        ntfs_log_debug("MFT zone size = %lldkiB\n", g_mft_zone_end <<
 
3957
                        g_vol->cluster_size_bits >> 10 /* >> 10 == / 1024 */);
 
3958
        /*
 
3959
         * The mft zone begins with the mft data attribute, not at the beginning
 
3960
         * of the device.
 
3961
         */
 
3962
        g_mft_zone_end += g_mft_lcn;
 
3963
        /* Create runlist for mft. */
 
3964
        g_rl_mft = ntfs_malloc(2 * sizeof(runlist));
 
3965
        if (!g_rl_mft)
 
3966
                return FALSE;
 
3967
 
 
3968
        g_rl_mft[0].vcn = 0LL;
 
3969
        g_rl_mft[0].lcn = g_mft_lcn;
 
3970
        /* rounded up division by cluster size */
 
3971
        j = (g_mft_size + g_vol->cluster_size - 1) / g_vol->cluster_size;
 
3972
        g_rl_mft[1].vcn = j;
 
3973
        g_rl_mft[0].length = j;
 
3974
        g_rl_mft[1].lcn = -1LL;
 
3975
        g_rl_mft[1].length = 0LL;
 
3976
        /* Allocate clusters for mft. */
 
3977
        bitmap_allocate(g_mft_lcn,j);
 
3978
        /* Determine mftmirr_lcn (middle of volume). */
 
3979
        g_mftmirr_lcn = (opts.num_sectors * opts.sector_size >> 1)
 
3980
                        / g_vol->cluster_size;
 
3981
        ntfs_log_debug("$MFTMirr logical cluster number = 0x%llx\n",
 
3982
                        g_mftmirr_lcn);
 
3983
        /* Create runlist for mft mirror. */
 
3984
        g_rl_mftmirr = ntfs_malloc(2 * sizeof(runlist));
 
3985
        if (!g_rl_mftmirr)
 
3986
                return FALSE;
 
3987
 
 
3988
        g_rl_mftmirr[0].vcn = 0LL;
 
3989
        g_rl_mftmirr[0].lcn = g_mftmirr_lcn;
 
3990
        /*
 
3991
         * The mft mirror is either 4kb (the first four records) or one cluster
 
3992
         * in size, which ever is bigger. In either case, it contains a
 
3993
         * byte-for-byte identical copy of the beginning of the mft (i.e. either
 
3994
         * the first four records (4kb) or the first cluster worth of records,
 
3995
         * whichever is bigger).
 
3996
         */
 
3997
        j = (4 * g_vol->mft_record_size + g_vol->cluster_size - 1) / g_vol->cluster_size;
 
3998
        g_rl_mftmirr[1].vcn = j;
 
3999
        g_rl_mftmirr[0].length = j;
 
4000
        g_rl_mftmirr[1].lcn = -1LL;
 
4001
        g_rl_mftmirr[1].length = 0LL;
 
4002
        /* Allocate clusters for mft mirror. */
 
4003
        done = bitmap_allocate(g_mftmirr_lcn,j);
 
4004
        g_logfile_lcn = g_mftmirr_lcn + j;
 
4005
        ntfs_log_debug("$LogFile logical cluster number = 0x%llx\n",
 
4006
                        g_logfile_lcn);
 
4007
        return (done);
 
4008
}
 
4009
 
 
4010
/**
 
4011
 * mkntfs_initialize_rl_logfile -
 
4012
 */
 
4013
static BOOL mkntfs_initialize_rl_logfile(void)
 
4014
{
 
4015
        int j;
 
4016
        u64 volume_size;
 
4017
 
 
4018
        /* Create runlist for log file. */
 
4019
        g_rl_logfile = ntfs_malloc(2 * sizeof(runlist));
 
4020
        if (!g_rl_logfile)
 
4021
                return FALSE;
 
4022
 
 
4023
 
 
4024
        volume_size = g_vol->nr_clusters << g_vol->cluster_size_bits;
 
4025
 
 
4026
        g_rl_logfile[0].vcn = 0LL;
 
4027
        g_rl_logfile[0].lcn = g_logfile_lcn;
 
4028
        /*
 
4029
         * Determine logfile_size from volume_size (rounded up to a cluster),
 
4030
         * making sure it does not overflow the end of the volume.
 
4031
         */
 
4032
        if (volume_size < 2048LL * 1024)                /* < 2MiB       */
 
4033
                g_logfile_size = 256LL * 1024;          /*   -> 256kiB  */
 
4034
        else if (volume_size < 4000000LL)               /* < 4MB        */
 
4035
                g_logfile_size = 512LL * 1024;          /*   -> 512kiB  */
 
4036
        else if (volume_size <= 200LL * 1024 * 1024)    /* < 200MiB     */
 
4037
                g_logfile_size = 2048LL * 1024;         /*   -> 2MiB    */
 
4038
        else    {
 
4039
                /*
 
4040
                 * FIXME: The $LogFile size is 64 MiB upwards from 12GiB but
 
4041
                 * the "200" divider below apparently approximates "100" or
 
4042
                 * some other value as the volume size decreases. For example:
 
4043
                 *      Volume size   LogFile size    Ratio
 
4044
                 *        8799808        46048       191.100
 
4045
                 *        8603248        45072       190.877
 
4046
                 *        7341704        38768       189.375
 
4047
                 *        6144828        32784       187.433
 
4048
                 *        4192932        23024       182.111
 
4049
                 */
 
4050
                if (volume_size >= 12LL << 30)          /* > 12GiB      */
 
4051
                        g_logfile_size = 64 << 20;      /*   -> 64MiB   */
 
4052
                else
 
4053
                        g_logfile_size = (volume_size / 200) &
 
4054
                                        ~(g_vol->cluster_size - 1);
 
4055
        }
 
4056
        j = g_logfile_size / g_vol->cluster_size;
 
4057
        while (g_rl_logfile[0].lcn + j >= g_vol->nr_clusters) {
 
4058
                /*
 
4059
                 * $Logfile would overflow volume. Need to make it smaller than
 
4060
                 * the standard size. It's ok as we are creating a non-standard
 
4061
                 * volume anyway if it is that small.
 
4062
                 */
 
4063
                g_logfile_size >>= 1;
 
4064
                j = g_logfile_size / g_vol->cluster_size;
 
4065
        }
 
4066
        g_logfile_size = (g_logfile_size + g_vol->cluster_size - 1) &
 
4067
                        ~(g_vol->cluster_size - 1);
 
4068
        ntfs_log_debug("$LogFile (journal) size = %ikiB\n",
 
4069
                        g_logfile_size / 1024);
 
4070
        /*
 
4071
         * FIXME: The 256kiB limit is arbitrary. Should find out what the real
 
4072
         * minimum requirement for Windows is so it doesn't blue screen.
 
4073
         */
 
4074
        if (g_logfile_size < 256 << 10) {
 
4075
                ntfs_log_error("$LogFile would be created with invalid size. "
 
4076
                                "This is not allowed as it would cause Windows "
 
4077
                                "to blue screen and during boot.\n");
 
4078
                return FALSE;
 
4079
        }
 
4080
        g_rl_logfile[1].vcn = j;
 
4081
        g_rl_logfile[0].length = j;
 
4082
        g_rl_logfile[1].lcn = -1LL;
 
4083
        g_rl_logfile[1].length = 0LL;
 
4084
        /* Allocate clusters for log file. */
 
4085
        return (bitmap_allocate(g_logfile_lcn,j));
 
4086
}
 
4087
 
 
4088
/**
 
4089
 * mkntfs_initialize_rl_boot -
 
4090
 */
 
4091
static BOOL mkntfs_initialize_rl_boot(void)
 
4092
{
 
4093
        int j;
 
4094
        /* Create runlist for $Boot. */
 
4095
        g_rl_boot = ntfs_malloc(2 * sizeof(runlist));
 
4096
        if (!g_rl_boot)
 
4097
                return FALSE;
 
4098
 
 
4099
        g_rl_boot[0].vcn = 0LL;
 
4100
        g_rl_boot[0].lcn = 0LL;
 
4101
        /*
 
4102
         * $Boot is always 8192 (0x2000) bytes or 1 cluster, whichever is
 
4103
         * bigger.
 
4104
         */
 
4105
        j = (8192 + g_vol->cluster_size - 1) / g_vol->cluster_size;
 
4106
        g_rl_boot[1].vcn = j;
 
4107
        g_rl_boot[0].length = j;
 
4108
        g_rl_boot[1].lcn = -1LL;
 
4109
        g_rl_boot[1].length = 0LL;
 
4110
        /* Allocate clusters for $Boot. */
 
4111
        return (bitmap_allocate(0,j));
 
4112
}
 
4113
 
 
4114
/**
 
4115
 * mkntfs_initialize_rl_bad -
 
4116
 */
 
4117
static BOOL mkntfs_initialize_rl_bad(void)
 
4118
{
 
4119
        /* Create runlist for $BadClus, $DATA named stream $Bad. */
 
4120
        g_rl_bad = ntfs_malloc(2 * sizeof(runlist));
 
4121
        if (!g_rl_bad)
 
4122
                return FALSE;
 
4123
 
 
4124
        g_rl_bad[0].vcn = 0LL;
 
4125
        g_rl_bad[0].lcn = -1LL;
 
4126
        /*
 
4127
         * $BadClus named stream $Bad contains the whole volume as a single
 
4128
         * sparse runlist entry.
 
4129
         */
 
4130
        g_rl_bad[1].vcn = g_vol->nr_clusters;
 
4131
        g_rl_bad[0].length = g_vol->nr_clusters;
 
4132
        g_rl_bad[1].lcn = -1LL;
 
4133
        g_rl_bad[1].length = 0LL;
 
4134
 
 
4135
        /* TODO: Mark bad blocks as such. */
 
4136
        return TRUE;
 
4137
}
 
4138
 
 
4139
/**
 
4140
 * mkntfs_fill_device_with_zeroes -
 
4141
 */
 
4142
static BOOL mkntfs_fill_device_with_zeroes(void)
 
4143
{
 
4144
        /*
 
4145
         * If not quick format, fill the device with 0s.
 
4146
         * FIXME: Except bad blocks! (AIA)
 
4147
         */
 
4148
        int i;
 
4149
        ssize_t bw;
 
4150
        unsigned long long position;
 
4151
        float progress_inc = (float)g_vol->nr_clusters / 100;
 
4152
        u64 volume_size;
 
4153
 
 
4154
        volume_size = g_vol->nr_clusters << g_vol->cluster_size_bits;
 
4155
 
 
4156
        ntfs_log_progress("Initializing device with zeroes:   0%%");
 
4157
        for (position = 0; position < (unsigned long long)g_vol->nr_clusters;
 
4158
                        position++) {
 
4159
                if (!(position % (int)(progress_inc+1))) {
 
4160
                        ntfs_log_progress("\b\b\b\b%3.0f%%", position /
 
4161
                                        progress_inc);
 
4162
                }
 
4163
                bw = mkntfs_write(g_vol->dev, g_buf, g_vol->cluster_size);
 
4164
                if (bw != (ssize_t)g_vol->cluster_size) {
 
4165
                        if (bw != -1 || errno != EIO) {
 
4166
                                ntfs_log_error("This should not happen.\n");
 
4167
                                return FALSE;
 
4168
                        }
 
4169
                        if (!position) {
 
4170
                                ntfs_log_error("Error: Cluster zero is bad. "
 
4171
                                        "Cannot create NTFS file "
 
4172
                                        "system.\n");
 
4173
                                return FALSE;
 
4174
                        }
 
4175
                        /* Add the baddie to our bad blocks list. */
 
4176
                        if (!append_to_bad_blocks(position))
 
4177
                                return FALSE;
 
4178
                        ntfs_log_quiet("\nFound bad cluster (%lld). Adding to "
 
4179
                                "list of bad blocks.\nInitializing "
 
4180
                                "device with zeroes: %3.0f%%", position,
 
4181
                                position / progress_inc);
 
4182
                        /* Seek to next cluster. */
 
4183
                        g_vol->dev->d_ops->seek(g_vol->dev,
 
4184
                                        ((off_t)position + 1) *
 
4185
                                        g_vol->cluster_size, SEEK_SET);
 
4186
                }
 
4187
        }
 
4188
        ntfs_log_progress("\b\b\b\b100%%");
 
4189
        position = (volume_size & (g_vol->cluster_size - 1)) /
 
4190
                        opts.sector_size;
 
4191
        for (i = 0; (unsigned long)i < position; i++) {
 
4192
                bw = mkntfs_write(g_vol->dev, g_buf, opts.sector_size);
 
4193
                if (bw != opts.sector_size) {
 
4194
                        if (bw != -1 || errno != EIO) {
 
4195
                                ntfs_log_error("This should not happen.\n");
 
4196
                                return FALSE;
 
4197
                        } else if (i + 1ull == position) {
 
4198
                                ntfs_log_error("Error: Bad cluster found in "
 
4199
                                        "location reserved for system "
 
4200
                                        "file $Boot.\n");
 
4201
                                return FALSE;
 
4202
                        }
 
4203
                        /* Seek to next sector. */
 
4204
                        g_vol->dev->d_ops->seek(g_vol->dev,
 
4205
                                        opts.sector_size, SEEK_CUR);
 
4206
                }
 
4207
        }
 
4208
        ntfs_log_progress(" - Done.\n");
 
4209
        return TRUE;
 
4210
}
 
4211
 
 
4212
/**
 
4213
 * mkntfs_sync_index_record
 
4214
 *
 
4215
 * (ERSO) made a function out of this, but the reason for doing that
 
4216
 * disappeared during coding....
 
4217
 */
 
4218
static BOOL mkntfs_sync_index_record(INDEX_ALLOCATION* idx, MFT_RECORD* m,
 
4219
                ntfschar* name, u32 name_len)
 
4220
{
 
4221
        int i, err;
 
4222
        ntfs_attr_search_ctx *ctx;
 
4223
        ATTR_RECORD *a;
 
4224
        long long lw;
 
4225
        runlist *rl_index = NULL;
 
4226
 
 
4227
        i = 5 * sizeof(ntfschar);
 
4228
        ctx = ntfs_attr_get_search_ctx(NULL, m);
 
4229
        if (!ctx) {
 
4230
                ntfs_log_perror("Failed to allocate attribute search context");
 
4231
                return FALSE;
 
4232
        }
 
4233
        /* FIXME: This should be IGNORE_CASE! */
 
4234
        if (mkntfs_attr_lookup(AT_INDEX_ALLOCATION, name, name_len,
 
4235
                        CASE_SENSITIVE, 0, NULL, 0, ctx)) {
 
4236
                ntfs_attr_put_search_ctx(ctx);
 
4237
                ntfs_log_error("BUG: $INDEX_ALLOCATION attribute not found.\n");
 
4238
                return FALSE;
 
4239
        }
 
4240
        a = ctx->attr;
 
4241
        rl_index = ntfs_mapping_pairs_decompress(g_vol, a, NULL);
 
4242
        if (!rl_index) {
 
4243
                ntfs_attr_put_search_ctx(ctx);
 
4244
                ntfs_log_error("Failed to decompress runlist of $INDEX_ALLOCATION "
 
4245
                                "attribute.\n");
 
4246
                return FALSE;
 
4247
        }
 
4248
        if (sle64_to_cpu(a->initialized_size) < i) {
 
4249
                ntfs_attr_put_search_ctx(ctx);
 
4250
                free(rl_index);
 
4251
                ntfs_log_error("BUG: $INDEX_ALLOCATION attribute too short.\n");
 
4252
                return FALSE;
 
4253
        }
 
4254
        ntfs_attr_put_search_ctx(ctx);
 
4255
        i = sizeof(INDEX_BLOCK) - sizeof(INDEX_HEADER) +
 
4256
                        le32_to_cpu(idx->index.allocated_size);
 
4257
        err = ntfs_mst_pre_write_fixup((NTFS_RECORD*)idx, i);
 
4258
        if (err) {
 
4259
                free(rl_index);
 
4260
                ntfs_log_error("ntfs_mst_pre_write_fixup() failed while "
 
4261
                        "syncing index block.\n");
 
4262
                return FALSE;
 
4263
        }
 
4264
        lw = ntfs_rlwrite(g_vol->dev, rl_index, (u8*)idx, i, NULL,
 
4265
                                WRITE_STANDARD);
 
4266
        free(rl_index);
 
4267
        if (lw != i) {
 
4268
                ntfs_log_error("Error writing $INDEX_ALLOCATION.\n");
 
4269
                return FALSE;
 
4270
        }
 
4271
        /* No more changes to @idx below here so no need for fixup: */
 
4272
        /* ntfs_mst_post_write_fixup((NTFS_RECORD*)idx); */
 
4273
        return TRUE;
 
4274
}
 
4275
 
 
4276
/**
 
4277
 * create_file_volume -
 
4278
 */
 
4279
static BOOL create_file_volume(MFT_RECORD *m, leMFT_REF root_ref,
 
4280
                VOLUME_FLAGS fl, const GUID *volume_guid)
 
4281
{
 
4282
        int i, err;
 
4283
        u8 *sd;
 
4284
 
 
4285
        ntfs_log_verbose("Creating $Volume (mft record 3)\n");
 
4286
        m = (MFT_RECORD*)(g_buf + 3 * g_vol->mft_record_size);
 
4287
        err = create_hardlink(g_index_block, root_ref, m,
 
4288
                        MK_LE_MREF(FILE_Volume, FILE_Volume), 0LL, 0LL,
 
4289
                        FILE_ATTR_HIDDEN | FILE_ATTR_SYSTEM, 0, 0,
 
4290
                        "$Volume", FILE_NAME_WIN32_AND_DOS);
 
4291
        if (!err) {
 
4292
                init_system_file_sd(FILE_Volume, &sd, &i);
 
4293
                err = add_attr_sd(m, sd, i);
 
4294
        }
 
4295
        if (!err)
 
4296
                err = add_attr_data(m, NULL, 0, CASE_SENSITIVE,
 
4297
                                const_cpu_to_le16(0), NULL, 0);
 
4298
        if (!err)
 
4299
                err = add_attr_vol_name(m, g_vol->vol_name, g_vol->vol_name ?
 
4300
                                strlen(g_vol->vol_name) : 0);
 
4301
        if (!err) {
 
4302
                if (fl & VOLUME_IS_DIRTY)
 
4303
                        ntfs_log_quiet("Setting the volume dirty so check "
 
4304
                                        "disk runs on next reboot into "
 
4305
                                        "Windows.\n");
 
4306
                err = add_attr_vol_info(m, fl, g_vol->major_ver,
 
4307
                                g_vol->minor_ver);
 
4308
        }
 
4309
        if (!err && opts.with_uuid)
 
4310
                err = add_attr_object_id(m, volume_guid);
 
4311
        if (err < 0) {
 
4312
                ntfs_log_error("Couldn't create $Volume: %s\n",
 
4313
                                strerror(-err));
 
4314
                return FALSE;
 
4315
        }
 
4316
        return TRUE;
 
4317
}
 
4318
 
 
4319
/**
 
4320
 * create_backup_boot_sector
 
4321
 *
 
4322
 * Return 0 on success or -1 if it couldn't be created.
 
4323
 */
 
4324
static int create_backup_boot_sector(u8 *buff)
 
4325
{
 
4326
        const char *s;
 
4327
        ssize_t bw;
 
4328
        int size, e;
 
4329
 
 
4330
        ntfs_log_verbose("Creating backup boot sector.\n");
 
4331
        /*
 
4332
         * Write the first max(512, opts.sector_size) bytes from buf to the
 
4333
         * last sector, but limit that to 8192 bytes of written data since that
 
4334
         * is how big $Boot is (and how big our buffer is)..
 
4335
         */
 
4336
        size = 512;
 
4337
        if (size < opts.sector_size)
 
4338
                size = opts.sector_size;
 
4339
        if (g_vol->dev->d_ops->seek(g_vol->dev, (opts.num_sectors + 1) *
 
4340
                        opts.sector_size - size, SEEK_SET) == (off_t)-1) {
 
4341
                ntfs_log_perror("Seek failed");
 
4342
                goto bb_err;
 
4343
        }
 
4344
        if (size > 8192)
 
4345
                size = 8192;
 
4346
        bw = mkntfs_write(g_vol->dev, buff, size);
 
4347
        if (bw == size)
 
4348
                return 0;
 
4349
        e = errno;
 
4350
        if (bw == -1LL)
 
4351
                s = strerror(e);
 
4352
        else
 
4353
                s = "unknown error";
 
4354
        /* At least some 2.4 kernels return EIO instead of ENOSPC. */
 
4355
        if (bw != -1LL || (bw == -1LL && e != ENOSPC && e != EIO)) {
 
4356
                ntfs_log_critical("Couldn't write backup boot sector: %s\n", s);
 
4357
                return -1;
 
4358
        }
 
4359
bb_err:
 
4360
        ntfs_log_error("Couldn't write backup boot sector. This is due to a "
 
4361
                        "limitation in the\nLinux kernel. This is not a major "
 
4362
                        "problem as Windows check disk will create the\n"
 
4363
                        "backup boot sector when it is run on your next boot "
 
4364
                        "into Windows.\n");
 
4365
        return -1;
 
4366
}
 
4367
 
 
4368
/**
 
4369
 * mkntfs_create_root_structures -
 
4370
 */
 
4371
static BOOL mkntfs_create_root_structures(void)
 
4372
{
 
4373
        NTFS_BOOT_SECTOR *bs;
 
4374
        MFT_RECORD *m;
 
4375
        leMFT_REF root_ref;
 
4376
        leMFT_REF extend_ref;
 
4377
        int i;
 
4378
        int j;
 
4379
        int err;
 
4380
        u8 *sd;
 
4381
        FILE_ATTR_FLAGS extend_flags;
 
4382
        VOLUME_FLAGS volume_flags = const_cpu_to_le16(0);
 
4383
        int nr_sysfiles;
 
4384
        int buf_sds_first_size;
 
4385
        char *buf_sds;
 
4386
        GUID vol_guid;
 
4387
 
 
4388
        ntfs_log_quiet("Creating NTFS volume structures.\n");
 
4389
        nr_sysfiles = 27;
 
4390
        /*
 
4391
         * Setup an empty mft record.  Note, we can just give 0 as the mft
 
4392
         * reference as we are creating an NTFS 1.2 volume for which the mft
 
4393
         * reference is ignored by ntfs_mft_record_layout().
 
4394
         *
 
4395
         * Copy the mft record onto all 16 records in the buffer and setup the
 
4396
         * sequence numbers of each system file to equal the mft record number
 
4397
         * of that file (only for $MFT is the sequence number 1 rather than 0).
 
4398
         */
 
4399
        for (i = 0; i < nr_sysfiles; i++) {
 
4400
                if (ntfs_mft_record_layout(g_vol, 0, m = (MFT_RECORD *)(g_buf +
 
4401
                                i * g_vol->mft_record_size))) {
 
4402
                        ntfs_log_error("Failed to layout system mft records."
 
4403
                                        "\n");
 
4404
                        return FALSE;
 
4405
                }
 
4406
                if (i == 0 || i > 23)
 
4407
                        m->sequence_number = cpu_to_le16(1);
 
4408
                else
 
4409
                        m->sequence_number = cpu_to_le16(i);
 
4410
        }
 
4411
        /*
 
4412
         * If only one cluster contains all system files then
 
4413
         * fill the rest of it with empty, formatted records.
 
4414
         */
 
4415
        if (nr_sysfiles * (s32)g_vol->mft_record_size < g_mft_size) {
 
4416
                for (i = nr_sysfiles;
 
4417
                      i * (s32)g_vol->mft_record_size < g_mft_size; i++) {
 
4418
                        m = (MFT_RECORD *)(g_buf + i * g_vol->mft_record_size);
 
4419
                        if (ntfs_mft_record_layout(g_vol, 0, m)) {
 
4420
                                ntfs_log_error("Failed to layout mft record."
 
4421
                                                "\n");
 
4422
                                return FALSE;
 
4423
                        }
 
4424
                        m->flags = cpu_to_le16(0);
 
4425
                        m->sequence_number = cpu_to_le16(i);
 
4426
                }
 
4427
        }
 
4428
        /*
 
4429
         * Create the 16 system files, adding the system information attribute
 
4430
         * to each as well as marking them in use in the mft bitmap.
 
4431
         */
 
4432
        for (i = 0; i < nr_sysfiles; i++) {
 
4433
                le32 file_attrs;
 
4434
 
 
4435
                m = (MFT_RECORD*)(g_buf + i * g_vol->mft_record_size);
 
4436
                if (i < 16 || i > 23) {
 
4437
                        m->mft_record_number = cpu_to_le32(i);
 
4438
                        m->flags |= MFT_RECORD_IN_USE;
 
4439
                        ntfs_bit_set(g_mft_bitmap, 0LL + i, 1);
 
4440
                }
 
4441
                file_attrs = FILE_ATTR_HIDDEN | FILE_ATTR_SYSTEM;
 
4442
                if (i == FILE_root) {
 
4443
                        file_attrs |= FILE_ATTR_ARCHIVE;
 
4444
                        if (opts.disable_indexing)
 
4445
                                file_attrs |= FILE_ATTR_NOT_CONTENT_INDEXED;
 
4446
                        if (opts.enable_compression)
 
4447
                                file_attrs |= FILE_ATTR_COMPRESSED;
 
4448
                }
 
4449
                /* setting specific security_id flag and */
 
4450
                /* file permissions for ntfs 3.x */
 
4451
                if (i == 0 || i == 1 || i == 2 || i == 6 || i == 8 ||
 
4452
                                i == 10) {
 
4453
                        add_attr_std_info(m, file_attrs,
 
4454
                                cpu_to_le32(0x0100));
 
4455
                } else if (i == 9) {
 
4456
                        file_attrs |= FILE_ATTR_VIEW_INDEX_PRESENT;
 
4457
                        add_attr_std_info(m, file_attrs,
 
4458
                                cpu_to_le32(0x0101));
 
4459
                } else if (i == 11) {
 
4460
                        add_attr_std_info(m, file_attrs,
 
4461
                                cpu_to_le32(0x0101));
 
4462
                } else if (i == 24 || i == 25 || i == 26) {
 
4463
                        file_attrs |= FILE_ATTR_ARCHIVE;
 
4464
                        file_attrs |= FILE_ATTR_VIEW_INDEX_PRESENT;
 
4465
                        add_attr_std_info(m, file_attrs,
 
4466
                                cpu_to_le32(0x0101));
 
4467
                } else {
 
4468
                        add_attr_std_info(m, file_attrs,
 
4469
                                cpu_to_le32(0x00));
 
4470
                }
 
4471
        }
 
4472
        /* The root directory mft reference. */
 
4473
        root_ref = MK_LE_MREF(FILE_root, FILE_root);
 
4474
        extend_ref = MK_LE_MREF(11,11);
 
4475
        ntfs_log_verbose("Creating root directory (mft record 5)\n");
 
4476
        m = (MFT_RECORD*)(g_buf + 5 * g_vol->mft_record_size);
 
4477
        m->flags |= MFT_RECORD_IS_DIRECTORY;
 
4478
        m->link_count = cpu_to_le16(le16_to_cpu(m->link_count) + 1);
 
4479
        err = add_attr_file_name(m, root_ref, 0LL, 0LL,
 
4480
                        FILE_ATTR_HIDDEN | FILE_ATTR_SYSTEM |
 
4481
                        FILE_ATTR_I30_INDEX_PRESENT, 0, 0, ".",
 
4482
                        FILE_NAME_WIN32_AND_DOS);
 
4483
        if (!err) {
 
4484
                init_root_sd(&sd, &i);
 
4485
                err = add_attr_sd(m, sd, i);
 
4486
        }
 
4487
        /* FIXME: This should be IGNORE_CASE */
 
4488
        if (!err)
 
4489
                err = add_attr_index_root(m, "$I30", 4, CASE_SENSITIVE,
 
4490
                                AT_FILE_NAME, COLLATION_FILE_NAME,
 
4491
                                g_vol->indx_record_size);
 
4492
        /* FIXME: This should be IGNORE_CASE */
 
4493
        if (!err)
 
4494
                err = upgrade_to_large_index(m, "$I30", 4, CASE_SENSITIVE,
 
4495
                                &g_index_block);
 
4496
        if (!err) {
 
4497
                ntfs_attr_search_ctx *ctx;
 
4498
                ATTR_RECORD *a;
 
4499
                ctx = ntfs_attr_get_search_ctx(NULL, m);
 
4500
                if (!ctx) {
 
4501
                        ntfs_log_perror("Failed to allocate attribute search "
 
4502
                                        "context");
 
4503
                        return FALSE;
 
4504
                }
 
4505
                /* There is exactly one file name so this is ok. */
 
4506
                if (mkntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0,
 
4507
                                CASE_SENSITIVE, 0, NULL, 0, ctx)) {
 
4508
                        ntfs_attr_put_search_ctx(ctx);
 
4509
                        ntfs_log_error("BUG: $FILE_NAME attribute not found."
 
4510
                                        "\n");
 
4511
                        return FALSE;
 
4512
                }
 
4513
                a = ctx->attr;
 
4514
                err = insert_file_link_in_dir_index(g_index_block, root_ref,
 
4515
                                (FILE_NAME_ATTR*)((char*)a +
 
4516
                                le16_to_cpu(a->value_offset)),
 
4517
                                le32_to_cpu(a->value_length));
 
4518
                ntfs_attr_put_search_ctx(ctx);
 
4519
        }
 
4520
        if (err) {
 
4521
                ntfs_log_error("Couldn't create root directory: %s\n",
 
4522
                        strerror(-err));
 
4523
                return FALSE;
 
4524
        }
 
4525
        /* Add all other attributes, on a per-file basis for clarity. */
 
4526
        ntfs_log_verbose("Creating $MFT (mft record 0)\n");
 
4527
        m = (MFT_RECORD*)g_buf;
 
4528
        err = add_attr_data_positioned(m, NULL, 0, CASE_SENSITIVE,
 
4529
                        const_cpu_to_le16(0), g_rl_mft, g_buf, g_mft_size);
 
4530
        if (!err)
 
4531
                err = create_hardlink(g_index_block, root_ref, m,
 
4532
                                MK_LE_MREF(FILE_MFT, 1),
 
4533
                                ((g_mft_size - 1)
 
4534
                                        | (g_vol->cluster_size - 1)) + 1,
 
4535
                                g_mft_size, FILE_ATTR_HIDDEN |
 
4536
                                FILE_ATTR_SYSTEM, 0, 0, "$MFT",
 
4537
                                FILE_NAME_WIN32_AND_DOS);
 
4538
        /* mft_bitmap is not modified in mkntfs; no need to sync it later. */
 
4539
        if (!err)
 
4540
                err = add_attr_bitmap_positioned(m, NULL, 0, CASE_SENSITIVE,
 
4541
                                g_rl_mft_bmp,
 
4542
                                g_mft_bitmap, g_mft_bitmap_byte_size);
 
4543
        if (err < 0) {
 
4544
                ntfs_log_error("Couldn't create $MFT: %s\n", strerror(-err));
 
4545
                return FALSE;
 
4546
        }
 
4547
        ntfs_log_verbose("Creating $MFTMirr (mft record 1)\n");
 
4548
        m = (MFT_RECORD*)(g_buf + 1 * g_vol->mft_record_size);
 
4549
        err = add_attr_data_positioned(m, NULL, 0, CASE_SENSITIVE,
 
4550
                        const_cpu_to_le16(0), g_rl_mftmirr, g_buf,
 
4551
                        g_rl_mftmirr[0].length * g_vol->cluster_size);
 
4552
        if (!err)
 
4553
                err = create_hardlink(g_index_block, root_ref, m,
 
4554
                                MK_LE_MREF(FILE_MFTMirr, FILE_MFTMirr),
 
4555
                                g_rl_mftmirr[0].length * g_vol->cluster_size,
 
4556
                                g_rl_mftmirr[0].length * g_vol->cluster_size,
 
4557
                                FILE_ATTR_HIDDEN | FILE_ATTR_SYSTEM, 0, 0,
 
4558
                                "$MFTMirr", FILE_NAME_WIN32_AND_DOS);
 
4559
        if (err < 0) {
 
4560
                ntfs_log_error("Couldn't create $MFTMirr: %s\n",
 
4561
                                strerror(-err));
 
4562
                return FALSE;
 
4563
        }
 
4564
        ntfs_log_verbose("Creating $LogFile (mft record 2)\n");
 
4565
        m = (MFT_RECORD*)(g_buf + 2 * g_vol->mft_record_size);
 
4566
        err = add_attr_data_positioned(m, NULL, 0, CASE_SENSITIVE,
 
4567
                        const_cpu_to_le16(0), g_rl_logfile,
 
4568
                        (const u8*)NULL, g_logfile_size);
 
4569
        if (!err)
 
4570
                err = create_hardlink(g_index_block, root_ref, m,
 
4571
                                MK_LE_MREF(FILE_LogFile, FILE_LogFile),
 
4572
                                g_logfile_size, g_logfile_size,
 
4573
                                FILE_ATTR_HIDDEN | FILE_ATTR_SYSTEM, 0, 0,
 
4574
                                "$LogFile", FILE_NAME_WIN32_AND_DOS);
 
4575
        if (err < 0) {
 
4576
                ntfs_log_error("Couldn't create $LogFile: %s\n",
 
4577
                                strerror(-err));
 
4578
                return FALSE;
 
4579
        }
 
4580
        ntfs_log_verbose("Creating $AttrDef (mft record 4)\n");
 
4581
        m = (MFT_RECORD*)(g_buf + 4 * g_vol->mft_record_size);
 
4582
        err = add_attr_data(m, NULL, 0, CASE_SENSITIVE, const_cpu_to_le16(0),
 
4583
                        (u8*)g_vol->attrdef, g_vol->attrdef_len);
 
4584
        if (!err)
 
4585
                err = create_hardlink(g_index_block, root_ref, m,
 
4586
                                MK_LE_MREF(FILE_AttrDef, FILE_AttrDef),
 
4587
                                (g_vol->attrdef_len + g_vol->cluster_size - 1) &
 
4588
                                ~(g_vol->cluster_size - 1), g_vol->attrdef_len,
 
4589
                                FILE_ATTR_HIDDEN | FILE_ATTR_SYSTEM, 0, 0,
 
4590
                                "$AttrDef", FILE_NAME_WIN32_AND_DOS);
 
4591
        if (!err) {
 
4592
                init_system_file_sd(FILE_AttrDef, &sd, &i);
 
4593
                err = add_attr_sd(m, sd, i);
 
4594
        }
 
4595
        if (err < 0) {
 
4596
                ntfs_log_error("Couldn't create $AttrDef: %s\n",
 
4597
                                strerror(-err));
 
4598
                return FALSE;
 
4599
        }
 
4600
        ntfs_log_verbose("Creating $Bitmap (mft record 6)\n");
 
4601
        m = (MFT_RECORD*)(g_buf + 6 * g_vol->mft_record_size);
 
4602
        /* the data attribute of $Bitmap must be non-resident or otherwise */
 
4603
        /* windows 2003 will regard the volume as corrupt (ERSO) */
 
4604
        if (!err)
 
4605
                err = insert_non_resident_attr_in_mft_record(m,
 
4606
                        AT_DATA,  NULL, 0, CASE_SENSITIVE,
 
4607
                        const_cpu_to_le16(0), (const u8*)NULL,
 
4608
                        g_lcn_bitmap_byte_size, WRITE_BITMAP);
 
4609
 
 
4610
 
 
4611
        if (!err)
 
4612
                err = create_hardlink(g_index_block, root_ref, m,
 
4613
                                MK_LE_MREF(FILE_Bitmap, FILE_Bitmap),
 
4614
                                (g_lcn_bitmap_byte_size + g_vol->cluster_size -
 
4615
                                1) & ~(g_vol->cluster_size - 1),
 
4616
                                g_lcn_bitmap_byte_size,
 
4617
                                FILE_ATTR_HIDDEN | FILE_ATTR_SYSTEM, 0, 0,
 
4618
                                "$Bitmap", FILE_NAME_WIN32_AND_DOS);
 
4619
        if (err < 0) {
 
4620
                ntfs_log_error("Couldn't create $Bitmap: %s\n", strerror(-err));
 
4621
                return FALSE;
 
4622
        }
 
4623
        ntfs_log_verbose("Creating $Boot (mft record 7)\n");
 
4624
        m = (MFT_RECORD*)(g_buf + 7 * g_vol->mft_record_size);
 
4625
        bs = ntfs_calloc(8192);
 
4626
        if (!bs)
 
4627
                return FALSE;
 
4628
        memcpy(bs, boot_array, sizeof(boot_array));
 
4629
        /*
 
4630
         * Create the boot sector in bs. Note, that bs is already zeroed
 
4631
         * in the boot sector section and that it has the NTFS OEM id/magic
 
4632
         * already inserted, so no need to worry about these things.
 
4633
         */
 
4634
        bs->bpb.bytes_per_sector = cpu_to_le16(opts.sector_size);
 
4635
        bs->bpb.sectors_per_cluster = (u8)(g_vol->cluster_size /
 
4636
                        opts.sector_size);
 
4637
        bs->bpb.media_type = 0xf8; /* hard disk */
 
4638
        bs->bpb.sectors_per_track = cpu_to_le16(opts.sectors_per_track);
 
4639
        ntfs_log_debug("sectors per track = %ld (0x%lx)\n",
 
4640
                        opts.sectors_per_track, opts.sectors_per_track);
 
4641
        bs->bpb.heads = cpu_to_le16(opts.heads);
 
4642
        ntfs_log_debug("heads = %ld (0x%lx)\n", opts.heads, opts.heads);
 
4643
        bs->bpb.hidden_sectors = cpu_to_le32(opts.part_start_sect);
 
4644
        ntfs_log_debug("hidden sectors = %llu (0x%llx)\n", opts.part_start_sect,
 
4645
                        opts.part_start_sect);
 
4646
        bs->physical_drive = 0x80;          /* boot from hard disk */
 
4647
        bs->extended_boot_signature = 0x80; /* everybody sets this, so we do */
 
4648
        bs->number_of_sectors = cpu_to_sle64(opts.num_sectors);
 
4649
        bs->mft_lcn = cpu_to_sle64(g_mft_lcn);
 
4650
        bs->mftmirr_lcn = cpu_to_sle64(g_mftmirr_lcn);
 
4651
        if (g_vol->mft_record_size >= g_vol->cluster_size) {
 
4652
                bs->clusters_per_mft_record = g_vol->mft_record_size /
 
4653
                        g_vol->cluster_size;
 
4654
        } else {
 
4655
                bs->clusters_per_mft_record = -(ffs(g_vol->mft_record_size) -
 
4656
                                1);
 
4657
                if ((u32)(1 << -bs->clusters_per_mft_record) !=
 
4658
                                g_vol->mft_record_size) {
 
4659
                        free(bs);
 
4660
                        ntfs_log_error("BUG: calculated clusters_per_mft_record"
 
4661
                                        " is wrong (= 0x%x)\n",
 
4662
                                        bs->clusters_per_mft_record);
 
4663
                        return FALSE;
 
4664
                }
 
4665
        }
 
4666
        ntfs_log_debug("clusters per mft record = %i (0x%x)\n",
 
4667
                        bs->clusters_per_mft_record,
 
4668
                        bs->clusters_per_mft_record);
 
4669
        if (g_vol->indx_record_size >= g_vol->cluster_size) {
 
4670
                bs->clusters_per_index_record = g_vol->indx_record_size /
 
4671
                        g_vol->cluster_size;
 
4672
        } else {
 
4673
                bs->clusters_per_index_record = -g_vol->indx_record_size_bits;
 
4674
                if ((1 << -bs->clusters_per_index_record) !=
 
4675
                                (s32)g_vol->indx_record_size) {
 
4676
                        free(bs);
 
4677
                        ntfs_log_error("BUG: calculated "
 
4678
                                        "clusters_per_index_record is wrong "
 
4679
                                        "(= 0x%x)\n",
 
4680
                                        bs->clusters_per_index_record);
 
4681
                        return FALSE;
 
4682
                }
 
4683
        }
 
4684
        ntfs_log_debug("clusters per index block = %i (0x%x)\n",
 
4685
                        bs->clusters_per_index_record,
 
4686
                        bs->clusters_per_index_record);
 
4687
        /* Generate a 64-bit random number for the serial number. */
 
4688
        bs->volume_serial_number = cpu_to_le64(((u64)random() << 32) |
 
4689
                        ((u64)random() & 0xffffffff));
 
4690
        /*
 
4691
         * Leave zero for now as NT4 leaves it zero, too. If want it later, see
 
4692
         * ../libntfs/bootsect.c for how to calculate it.
 
4693
         */
 
4694
        bs->checksum = cpu_to_le32(0);
 
4695
        /* Make sure the bootsector is ok. */
 
4696
        if (!ntfs_boot_sector_is_ntfs(bs)) {
 
4697
                free(bs);
 
4698
                ntfs_log_error("FATAL: Generated boot sector is invalid!\n");
 
4699
                return FALSE;
 
4700
        }
 
4701
        err = add_attr_data_positioned(m, NULL, 0, CASE_SENSITIVE,
 
4702
                        const_cpu_to_le16(0), g_rl_boot, (u8*)bs, 8192);
 
4703
        if (!err)
 
4704
                err = create_hardlink(g_index_block, root_ref, m,
 
4705
                                MK_LE_MREF(FILE_Boot, FILE_Boot),
 
4706
                                (8192 + g_vol->cluster_size - 1) &
 
4707
                                ~(g_vol->cluster_size - 1), 8192,
 
4708
                                FILE_ATTR_HIDDEN | FILE_ATTR_SYSTEM, 0, 0,
 
4709
                                "$Boot", FILE_NAME_WIN32_AND_DOS);
 
4710
        if (!err) {
 
4711
                init_system_file_sd(FILE_Boot, &sd, &i);
 
4712
                err = add_attr_sd(m, sd, i);
 
4713
        }
 
4714
        if (err < 0) {
 
4715
                free(bs);
 
4716
                ntfs_log_error("Couldn't create $Boot: %s\n", strerror(-err));
 
4717
                return FALSE;
 
4718
        }
 
4719
        if (create_backup_boot_sector((u8*)bs)) {
 
4720
                /*
 
4721
                 * Pre-2.6 kernels couldn't access the last sector if it was
 
4722
                 * odd and we failed to set the device block size to the sector
 
4723
                 * size, hence we schedule chkdsk to create it.
 
4724
                 */
 
4725
                volume_flags |= VOLUME_IS_DIRTY;
 
4726
        }
 
4727
        free(bs);
 
4728
        /*
 
4729
         * We cheat a little here and if the user has requested all times to be
 
4730
         * set to zero then we set the GUID to zero as well.  This options is
 
4731
         * only used for development purposes so that should be fine.
 
4732
         */
 
4733
        if (!opts.use_epoch_time) {
 
4734
                /* Generate a GUID for the volume. */
 
4735
#ifdef ENABLE_UUID
 
4736
                uuid_generate((void*)&vol_guid);
 
4737
#else
 
4738
                ntfs_generate_guid(&vol_guid);
 
4739
#endif
 
4740
        } else
 
4741
                memset(&vol_guid, 0, sizeof(vol_guid));
 
4742
        if (!create_file_volume(m, root_ref, volume_flags, &vol_guid))
 
4743
                return FALSE;
 
4744
        ntfs_log_verbose("Creating $BadClus (mft record 8)\n");
 
4745
        m = (MFT_RECORD*)(g_buf + 8 * g_vol->mft_record_size);
 
4746
        /* FIXME: This should be IGNORE_CASE */
 
4747
        /* Create a sparse named stream of size equal to the volume size. */
 
4748
        err = add_attr_data_positioned(m, "$Bad", 4, CASE_SENSITIVE,
 
4749
                        const_cpu_to_le16(0), g_rl_bad, NULL,
 
4750
                        g_vol->nr_clusters * g_vol->cluster_size);
 
4751
        if (!err) {
 
4752
                err = add_attr_data(m, NULL, 0, CASE_SENSITIVE,
 
4753
                                const_cpu_to_le16(0), NULL, 0);
 
4754
        }
 
4755
        if (!err) {
 
4756
                err = create_hardlink(g_index_block, root_ref, m,
 
4757
                                MK_LE_MREF(FILE_BadClus, FILE_BadClus),
 
4758
                                0LL, 0LL, FILE_ATTR_HIDDEN | FILE_ATTR_SYSTEM,
 
4759
                                0, 0, "$BadClus", FILE_NAME_WIN32_AND_DOS);
 
4760
        }
 
4761
        if (err < 0) {
 
4762
                ntfs_log_error("Couldn't create $BadClus: %s\n",
 
4763
                                strerror(-err));
 
4764
                return FALSE;
 
4765
        }
 
4766
        /* create $Secure (NTFS 3.0+) */
 
4767
        ntfs_log_verbose("Creating $Secure (mft record 9)\n");
 
4768
        m = (MFT_RECORD*)(g_buf + 9 * g_vol->mft_record_size);
 
4769
        m->flags |= MFT_RECORD_IS_VIEW_INDEX;
 
4770
        if (!err)
 
4771
                err = create_hardlink(g_index_block, root_ref, m,
 
4772
                                MK_LE_MREF(9, 9), 0LL, 0LL,
 
4773
                                FILE_ATTR_HIDDEN | FILE_ATTR_SYSTEM |
 
4774
                                FILE_ATTR_VIEW_INDEX_PRESENT, 0, 0,
 
4775
                                "$Secure", FILE_NAME_WIN32_AND_DOS);
 
4776
        buf_sds = NULL;
 
4777
        buf_sds_first_size = 0;
 
4778
        if (!err) {
 
4779
                int buf_sds_size;
 
4780
 
 
4781
                buf_sds_first_size = 0xfc;
 
4782
                buf_sds_size = 0x40000 + buf_sds_first_size;
 
4783
                buf_sds = ntfs_calloc(buf_sds_size);
 
4784
                if (!buf_sds)
 
4785
                        return FALSE;
 
4786
                init_secure_sds(buf_sds);
 
4787
                memcpy(buf_sds + 0x40000, buf_sds, buf_sds_first_size);
 
4788
                err = add_attr_data(m, "$SDS", 4, CASE_SENSITIVE,
 
4789
                                const_cpu_to_le16(0), (u8*)buf_sds,
 
4790
                                buf_sds_size);
 
4791
        }
 
4792
        /* FIXME: This should be IGNORE_CASE */
 
4793
        if (!err)
 
4794
                err = add_attr_index_root(m, "$SDH", 4, CASE_SENSITIVE,
 
4795
                        AT_UNUSED, COLLATION_NTOFS_SECURITY_HASH,
 
4796
                        g_vol->indx_record_size);
 
4797
        /* FIXME: This should be IGNORE_CASE */
 
4798
        if (!err)
 
4799
                err = add_attr_index_root(m, "$SII", 4, CASE_SENSITIVE,
 
4800
                        AT_UNUSED, COLLATION_NTOFS_ULONG,
 
4801
                        g_vol->indx_record_size);
 
4802
        if (!err)
 
4803
                err = initialize_secure(buf_sds, buf_sds_first_size, m);
 
4804
        free(buf_sds);
 
4805
        if (err < 0) {
 
4806
                ntfs_log_error("Couldn't create $Secure: %s\n",
 
4807
                        strerror(-err));
 
4808
                return FALSE;
 
4809
        }
 
4810
        ntfs_log_verbose("Creating $UpCase (mft record 0xa)\n");
 
4811
        m = (MFT_RECORD*)(g_buf + 0xa * g_vol->mft_record_size);
 
4812
        err = add_attr_data(m, NULL, 0, CASE_SENSITIVE, const_cpu_to_le16(0),
 
4813
                        (u8*)g_vol->upcase, g_vol->upcase_len << 1);
 
4814
        /*
 
4815
         * The $Info only exists since Windows 8, but it apparently
 
4816
         * does not disturb chkdsk from earlier versions.
 
4817
         */
 
4818
        if (!err)
 
4819
                err = add_attr_data(m, "$Info", 5, CASE_SENSITIVE,
 
4820
                        const_cpu_to_le16(0),
 
4821
                        (u8*)g_upcaseinfo, sizeof(struct UPCASEINFO));
 
4822
        if (!err)
 
4823
                err = create_hardlink(g_index_block, root_ref, m,
 
4824
                                MK_LE_MREF(FILE_UpCase, FILE_UpCase),
 
4825
                                ((g_vol->upcase_len << 1) +
 
4826
                                g_vol->cluster_size - 1) &
 
4827
                                ~(g_vol->cluster_size - 1),
 
4828
                                g_vol->upcase_len << 1,
 
4829
                                FILE_ATTR_HIDDEN | FILE_ATTR_SYSTEM, 0, 0,
 
4830
                                "$UpCase", FILE_NAME_WIN32_AND_DOS);
 
4831
        if (err < 0) {
 
4832
                ntfs_log_error("Couldn't create $UpCase: %s\n", strerror(-err));
 
4833
                return FALSE;
 
4834
        }
 
4835
        ntfs_log_verbose("Creating $Extend (mft record 11)\n");
 
4836
        /*
 
4837
         * $Extend index must be resident.  Otherwise, w2k3 will regard the
 
4838
         * volume as corrupt. (ERSO)
 
4839
         */
 
4840
        m = (MFT_RECORD*)(g_buf + 11 * g_vol->mft_record_size);
 
4841
        m->flags |= MFT_RECORD_IS_DIRECTORY;
 
4842
        if (!err)
 
4843
                err = create_hardlink(g_index_block, root_ref, m,
 
4844
                                MK_LE_MREF(11, 11), 0LL, 0LL,
 
4845
                                FILE_ATTR_HIDDEN | FILE_ATTR_SYSTEM |
 
4846
                                FILE_ATTR_I30_INDEX_PRESENT, 0, 0,
 
4847
                                "$Extend", FILE_NAME_WIN32_AND_DOS);
 
4848
        /* FIXME: This should be IGNORE_CASE */
 
4849
        if (!err)
 
4850
                err = add_attr_index_root(m, "$I30", 4, CASE_SENSITIVE,
 
4851
                        AT_FILE_NAME, COLLATION_FILE_NAME,
 
4852
                        g_vol->indx_record_size);
 
4853
        if (err < 0) {
 
4854
                ntfs_log_error("Couldn't create $Extend: %s\n",
 
4855
                        strerror(-err));
 
4856
                return FALSE;
 
4857
        }
 
4858
        /* NTFS reserved system files (mft records 0xc-0xf) */
 
4859
        for (i = 0xc; i < 0x10; i++) {
 
4860
                ntfs_log_verbose("Creating system file (mft record 0x%x)\n", i);
 
4861
                m = (MFT_RECORD*)(g_buf + i * g_vol->mft_record_size);
 
4862
                err = add_attr_data(m, NULL, 0, CASE_SENSITIVE,
 
4863
                                const_cpu_to_le16(0), NULL, 0);
 
4864
                if (!err) {
 
4865
                        init_system_file_sd(i, &sd, &j);
 
4866
                        err = add_attr_sd(m, sd, j);
 
4867
                }
 
4868
                if (err < 0) {
 
4869
                        ntfs_log_error("Couldn't create system file %i (0x%x): "
 
4870
                                        "%s\n", i, i, strerror(-err));
 
4871
                        return FALSE;
 
4872
                }
 
4873
        }
 
4874
        /* create systemfiles for ntfs volumes (3.1) */
 
4875
        /* starting with file 24 (ignoring file 16-23) */
 
4876
        extend_flags = FILE_ATTR_HIDDEN | FILE_ATTR_SYSTEM |
 
4877
                FILE_ATTR_ARCHIVE | FILE_ATTR_VIEW_INDEX_PRESENT;
 
4878
        ntfs_log_verbose("Creating $Quota (mft record 24)\n");
 
4879
        m = (MFT_RECORD*)(g_buf + 24 * g_vol->mft_record_size);
 
4880
        m->flags |= MFT_RECORD_IS_4;
 
4881
        m->flags |= MFT_RECORD_IS_VIEW_INDEX;
 
4882
        if (!err)
 
4883
                err = create_hardlink_res((MFT_RECORD*)(g_buf +
 
4884
                        11 * g_vol->mft_record_size), extend_ref, m,
 
4885
                        MK_LE_MREF(24, 1), 0LL, 0LL, extend_flags,
 
4886
                        0, 0, "$Quota", FILE_NAME_WIN32_AND_DOS);
 
4887
        /* FIXME: This should be IGNORE_CASE */
 
4888
        if (!err)
 
4889
                err = add_attr_index_root(m, "$Q", 2, CASE_SENSITIVE, AT_UNUSED,
 
4890
                        COLLATION_NTOFS_ULONG, g_vol->indx_record_size);
 
4891
        /* FIXME: This should be IGNORE_CASE */
 
4892
        if (!err)
 
4893
                err = add_attr_index_root(m, "$O", 2, CASE_SENSITIVE, AT_UNUSED,
 
4894
                        COLLATION_NTOFS_SID, g_vol->indx_record_size);
 
4895
        if (!err)
 
4896
                err = initialize_quota(m);
 
4897
        if (err < 0) {
 
4898
                ntfs_log_error("Couldn't create $Quota: %s\n", strerror(-err));
 
4899
                return FALSE;
 
4900
        }
 
4901
        ntfs_log_verbose("Creating $ObjId (mft record 25)\n");
 
4902
        m = (MFT_RECORD*)(g_buf + 25 * g_vol->mft_record_size);
 
4903
        m->flags |= MFT_RECORD_IS_4;
 
4904
        m->flags |= MFT_RECORD_IS_VIEW_INDEX;
 
4905
        if (!err)
 
4906
                err = create_hardlink_res((MFT_RECORD*)(g_buf +
 
4907
                                11 * g_vol->mft_record_size), extend_ref,
 
4908
                                m, MK_LE_MREF(25, 1), 0LL, 0LL,
 
4909
                                extend_flags, 0, 0, "$ObjId",
 
4910
                                FILE_NAME_WIN32_AND_DOS);
 
4911
 
 
4912
        /* FIXME: This should be IGNORE_CASE */
 
4913
        if (!err)
 
4914
                err = add_attr_index_root(m, "$O", 2, CASE_SENSITIVE, AT_UNUSED,
 
4915
                        COLLATION_NTOFS_ULONGS,
 
4916
                        g_vol->indx_record_size);
 
4917
        if (!err && opts.with_uuid)
 
4918
                err = index_obj_id_insert(m, &vol_guid,
 
4919
                                MK_LE_MREF(FILE_Volume, FILE_Volume));
 
4920
        if (err < 0) {
 
4921
                ntfs_log_error("Couldn't create $ObjId: %s\n",
 
4922
                                strerror(-err));
 
4923
                return FALSE;
 
4924
        }
 
4925
        ntfs_log_verbose("Creating $Reparse (mft record 26)\n");
 
4926
        m = (MFT_RECORD*)(g_buf + 26 * g_vol->mft_record_size);
 
4927
        m->flags |= MFT_RECORD_IS_4;
 
4928
        m->flags |= MFT_RECORD_IS_VIEW_INDEX;
 
4929
        if (!err)
 
4930
                err = create_hardlink_res((MFT_RECORD*)(g_buf +
 
4931
                                11 * g_vol->mft_record_size),
 
4932
                                extend_ref, m, MK_LE_MREF(26, 1),
 
4933
                                0LL, 0LL, extend_flags, 0, 0,
 
4934
                                "$Reparse", FILE_NAME_WIN32_AND_DOS);
 
4935
        /* FIXME: This should be IGNORE_CASE */
 
4936
        if (!err)
 
4937
                err = add_attr_index_root(m, "$R", 2, CASE_SENSITIVE, AT_UNUSED,
 
4938
                        COLLATION_NTOFS_ULONGS, g_vol->indx_record_size);
 
4939
        if (err < 0) {
 
4940
                ntfs_log_error("Couldn't create $Reparse: %s\n",
 
4941
                        strerror(-err));
 
4942
                return FALSE;
 
4943
        }
 
4944
        return TRUE;
 
4945
}
 
4946
 
 
4947
/**
 
4948
 * mkntfs_redirect
 
4949
 */
 
4950
static int mkntfs_redirect(struct mkntfs_options *opts2)
 
4951
{
 
4952
        u64 upcase_crc;
 
4953
        int result = 1;
 
4954
        ntfs_attr_search_ctx *ctx = NULL;
 
4955
        long long lw, pos;
 
4956
        ATTR_RECORD *a;
 
4957
        MFT_RECORD *m;
 
4958
        int i, err;
 
4959
 
 
4960
        if (!opts2) {
 
4961
                ntfs_log_error("Internal error: invalid parameters to mkntfs_options.\n");
 
4962
                goto done;
 
4963
        }
 
4964
        /* Initialize the random number generator with the current time. */
 
4965
        srandom(le64_to_cpu(mkntfs_time())/10000000);
 
4966
        /* Allocate and initialize ntfs_volume structure g_vol. */
 
4967
        g_vol = ntfs_volume_alloc();
 
4968
        if (!g_vol) {
 
4969
                ntfs_log_perror("Could not create volume");
 
4970
                goto done;
 
4971
        }
 
4972
        /* Create NTFS 3.1 (Windows XP/Vista) volumes. */
 
4973
        g_vol->major_ver = 3;
 
4974
        g_vol->minor_ver = 1;
 
4975
        /* Transfer some options to the volume. */
 
4976
        if (opts.label) {
 
4977
                g_vol->vol_name = strdup(opts.label);
 
4978
                if (!g_vol->vol_name) {
 
4979
                        ntfs_log_perror("Could not copy volume name");
 
4980
                        goto done;
 
4981
                }
 
4982
        }
 
4983
        if (opts.cluster_size >= 0)
 
4984
                g_vol->cluster_size = opts.cluster_size;
 
4985
        /* Length is in unicode characters. */
 
4986
        g_vol->upcase_len = ntfs_upcase_build_default(&g_vol->upcase);
 
4987
        /* Since Windows 8, there is a $Info stream in $UpCase */
 
4988
        g_upcaseinfo =
 
4989
                (struct UPCASEINFO*)ntfs_malloc(sizeof(struct UPCASEINFO));
 
4990
        if (!g_vol->upcase_len || !g_upcaseinfo)
 
4991
                goto done;
 
4992
        /* If the CRC is correct, chkdsk does not warn about obsolete table */
 
4993
        crc64(0,(byte*)NULL,0); /* initialize the crc computation */
 
4994
        upcase_crc = crc64(0,(byte*)g_vol->upcase,
 
4995
                        g_vol->upcase_len * sizeof(ntfschar));
 
4996
        /* keep the version fields as zero */
 
4997
        memset(g_upcaseinfo, 0, sizeof(struct UPCASEINFO));
 
4998
        g_upcaseinfo->len = cpu_to_le32(sizeof(struct UPCASEINFO));
 
4999
        g_upcaseinfo->crc = cpu_to_le64(upcase_crc);
 
5000
        g_vol->attrdef = ntfs_malloc(sizeof(attrdef_ntfs3x_array));
 
5001
        if (!g_vol->attrdef) {
 
5002
                ntfs_log_perror("Could not create attrdef structure");
 
5003
                goto done;
 
5004
        }
 
5005
        memcpy(g_vol->attrdef, attrdef_ntfs3x_array,
 
5006
                        sizeof(attrdef_ntfs3x_array));
 
5007
        g_vol->attrdef_len = sizeof(attrdef_ntfs3x_array);
 
5008
        /* Open the partition. */
 
5009
        if (!mkntfs_open_partition(g_vol))
 
5010
                goto done;
 
5011
        /*
 
5012
         * Decide on the sector size, cluster size, mft record and index record
 
5013
         * sizes as well as the number of sectors/tracks/heads/size, etc.
 
5014
         */
 
5015
        if (!mkntfs_override_vol_params(g_vol))
 
5016
                goto done;
 
5017
        /* Initialize $Bitmap and $MFT/$BITMAP related stuff. */
 
5018
        if (!mkntfs_initialize_bitmaps())
 
5019
                goto done;
 
5020
        /* Initialize MFT & set g_logfile_lcn. */
 
5021
        if (!mkntfs_initialize_rl_mft())
 
5022
                goto done;
 
5023
        /* Initialize $LogFile. */
 
5024
        if (!mkntfs_initialize_rl_logfile())
 
5025
                goto done;
 
5026
        /* Initialize $Boot. */
 
5027
        if (!mkntfs_initialize_rl_boot())
 
5028
                goto done;
 
5029
        /* Allocate a buffer large enough to hold the mft. */
 
5030
        g_buf = ntfs_calloc(g_mft_size);
 
5031
        if (!g_buf)
 
5032
                goto done;
 
5033
        /* Create runlist for $BadClus, $DATA named stream $Bad. */
 
5034
        if (!mkntfs_initialize_rl_bad())
 
5035
                goto done;
 
5036
        /* If not quick format, fill the device with 0s. */
 
5037
        if (!opts.quick_format) {
 
5038
                if (!mkntfs_fill_device_with_zeroes())
 
5039
                        goto done;
 
5040
        }
 
5041
        /* Create NTFS volume structures. */
 
5042
        if (!mkntfs_create_root_structures())
 
5043
                goto done;
 
5044
        /*
 
5045
         * - Do not step onto bad blocks!!!
 
5046
         * - If any bad blocks were specified or found, modify $BadClus,
 
5047
         *   allocating the bad clusters in $Bitmap.
 
5048
         * - C&w bootsector backup bootsector (backup in last sector of the
 
5049
         *   partition).
 
5050
         * - If NTFS 3.0+, c&w $Secure file and $Extend directory with the
 
5051
         *   corresponding special files in it, i.e. $ObjId, $Quota, $Reparse,
 
5052
         *   and $UsnJrnl. And others? Or not all necessary?
 
5053
         * - RE: Populate $root with the system files (and $Extend directory if
 
5054
         *   applicable). Possibly should move this as far to the top as
 
5055
         *   possible and update during each subsequent c&w of each system file.
 
5056
         */
 
5057
        ntfs_log_verbose("Syncing root directory index record.\n");
 
5058
        if (!mkntfs_sync_index_record(g_index_block, (MFT_RECORD*)(g_buf + 5 *
 
5059
                        g_vol->mft_record_size), NTFS_INDEX_I30, 4))
 
5060
                goto done;
 
5061
 
 
5062
        ntfs_log_verbose("Syncing $Bitmap.\n");
 
5063
        m = (MFT_RECORD*)(g_buf + 6 * g_vol->mft_record_size);
 
5064
 
 
5065
        ctx = ntfs_attr_get_search_ctx(NULL, m);
 
5066
        if (!ctx) {
 
5067
                ntfs_log_perror("Could not create an attribute search context");
 
5068
                goto done;
 
5069
        }
 
5070
 
 
5071
        if (mkntfs_attr_lookup(AT_DATA, AT_UNNAMED, 0, CASE_SENSITIVE,
 
5072
                                0, NULL, 0, ctx)) {
 
5073
                ntfs_log_error("BUG: $DATA attribute not found.\n");
 
5074
                goto done;
 
5075
        }
 
5076
 
 
5077
        a = ctx->attr;
 
5078
        if (a->non_resident) {
 
5079
                runlist *rl = ntfs_mapping_pairs_decompress(g_vol, a, NULL);
 
5080
                if (!rl) {
 
5081
                        ntfs_log_error("ntfs_mapping_pairs_decompress() failed\n");
 
5082
                        goto done;
 
5083
                }
 
5084
                lw = ntfs_rlwrite(g_vol->dev, rl, (const u8*)NULL,
 
5085
                         g_lcn_bitmap_byte_size, NULL, WRITE_BITMAP);
 
5086
                err = errno;
 
5087
                free(rl);
 
5088
                if (lw != g_lcn_bitmap_byte_size) {
 
5089
                        ntfs_log_error("ntfs_rlwrite: %s\n", lw == -1 ?
 
5090
                                       strerror(err) : "unknown error");
 
5091
                        goto done;
 
5092
                }
 
5093
        } else {
 
5094
                /* Error : the bitmap must be created non resident */
 
5095
                ntfs_log_error("Error : the global bitmap is resident\n");
 
5096
                goto done;
 
5097
        }
 
5098
 
 
5099
        /*
 
5100
         * No need to sync $MFT/$BITMAP as that has never been modified since
 
5101
         * its creation.
 
5102
         */
 
5103
        ntfs_log_verbose("Syncing $MFT.\n");
 
5104
        pos = g_mft_lcn * g_vol->cluster_size;
 
5105
        lw = 1;
 
5106
        for (i = 0; i < g_mft_size / (s32)g_vol->mft_record_size; i++) {
 
5107
                if (!opts.no_action)
 
5108
                        lw = ntfs_mst_pwrite(g_vol->dev, pos, 1, g_vol->mft_record_size, g_buf + i * g_vol->mft_record_size);
 
5109
                if (lw != 1) {
 
5110
                        ntfs_log_error("ntfs_mst_pwrite: %s\n", lw == -1 ?
 
5111
                                       strerror(errno) : "unknown error");
 
5112
                        goto done;
 
5113
                }
 
5114
                pos += g_vol->mft_record_size;
 
5115
        }
 
5116
        ntfs_log_verbose("Updating $MFTMirr.\n");
 
5117
        pos = g_mftmirr_lcn * g_vol->cluster_size;
 
5118
        lw = 1;
 
5119
        for (i = 0; i < g_rl_mftmirr[0].length * g_vol->cluster_size / g_vol->mft_record_size; i++) {
 
5120
                m = (MFT_RECORD*)(g_buf + i * g_vol->mft_record_size);
 
5121
                /*
 
5122
                 * Decrement the usn by one, so it becomes the same as the one
 
5123
                 * in $MFT once it is mst protected. - This is as we need the
 
5124
                 * $MFTMirr to have the exact same byte by byte content as
 
5125
                 * $MFT, rather than just equivalent meaning content.
 
5126
                 */
 
5127
                if (ntfs_mft_usn_dec(m)) {
 
5128
                        ntfs_log_error("ntfs_mft_usn_dec");
 
5129
                        goto done;
 
5130
                }
 
5131
                if (!opts.no_action)
 
5132
                        lw = ntfs_mst_pwrite(g_vol->dev, pos, 1, g_vol->mft_record_size, g_buf + i * g_vol->mft_record_size);
 
5133
                if (lw != 1) {
 
5134
                        ntfs_log_error("ntfs_mst_pwrite: %s\n", lw == -1 ?
 
5135
                                       strerror(errno) : "unknown error");
 
5136
                        goto done;
 
5137
                }
 
5138
                pos += g_vol->mft_record_size;
 
5139
        }
 
5140
        ntfs_log_verbose("Syncing device.\n");
 
5141
        if (g_vol->dev->d_ops->sync(g_vol->dev)) {
 
5142
                ntfs_log_error("Syncing device. FAILED");
 
5143
                goto done;
 
5144
        }
 
5145
        ntfs_log_quiet("mkntfs completed successfully. Have a nice day.\n");
 
5146
        result = 0;
 
5147
done:
 
5148
        ntfs_attr_put_search_ctx(ctx);
 
5149
        mkntfs_cleanup();       /* Device is unlocked and closed here */
 
5150
        return result;
 
5151
}
 
5152
 
 
5153
 
 
5154
/**
 
5155
 * main - Begin here
 
5156
 *
 
5157
 * Start from here.
 
5158
 *
 
5159
 * Return:  0  Success, the program worked
 
5160
 *          1  Error, something went wrong
 
5161
 */
 
5162
int main(int argc, char *argv[])
 
5163
{
 
5164
        int result = 1;
 
5165
 
 
5166
        ntfs_log_set_handler(ntfs_log_handler_outerr);
 
5167
        utils_set_locale();
 
5168
 
 
5169
        mkntfs_init_options(&opts);                     /* Set up the options */
 
5170
 
 
5171
        if (!mkntfs_parse_options(argc, argv, &opts))   /* Read the command line options */
 
5172
                goto done;
 
5173
 
 
5174
        result = mkntfs_redirect(&opts);
 
5175
done:
 
5176
        return result;
 
5177
}