~ubuntu-branches/ubuntu/dapper/linux-ntfs/dapper

« back to all changes in this revision

Viewing changes to ntfsprogs/mkntfs.c

  • Committer: Bazaar Package Importer
  • Author(s): David Martínez Moreno
  • Date: 2005-11-08 20:20:23 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20051108202023-dpn4lutm8o0div8g
Tags: 1.12.1-1
* New upstream release (closes: #332930):
  - Fixed lots of memory leaks in the tools.
  - ntfsmount now uses the new API, and it has several fixes.
  - Support journals which have been modified by chkdsk.
  - New API for creating hard links, index handling, high-level creation and
    deletion of files and directories.
  - New utility ntfscmp (make extra) which compares two NTFS volumes and
    tell the differences. It's used for development, debugging, testing, etc.
  - Added robustness to several tools.
  - ntfsclone: fix saving by sectors during --rescue.
  - ntfsmount: Add 'locale' option and change interface to 'ntfsmount device
    mount_point'.
  - Fixed problem with kernel 2.4 and mkntfs.
  - Change ALL utilities to display the libntfs version they are running on.
    This should make debugging easier in the case that people are running
    mismatched utilities/library.
* This new release fixes problems with libfuse 2.4.0 (closes: #336357).
* Fixed a lot of typos in the manpages, kindly submitted by A Costa. Thanks!
  (closes: #336143, #336144, #336145, #336147, #336148).
* Fixed a couple of typos by me.
* debian/control: The SONAME of libntfs was bumped. Created new package
  (libntfs8) and removed the old one.
* debian/copyright: Updated the FSF postal address.
* Added debian/ntfsprogs.links in order to ship mkfs.ntfs and
  mount.ntfs-fuse.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/**
2
2
 * mkntfs - Part of the Linux-NTFS project.
3
3
 *
4
 
 * Copyright (c) 2000-2004 Anton Altaparmakov
 
4
 * Copyright (c) 2000-2005 Anton Altaparmakov
5
5
 * Copyright (c) 2001-2003 Richard Russon
6
6
 *
7
7
 * This utility will create an NTFS 1.2 (Windows NT 4.0) volume on a user
62
62
#ifdef HAVE_ERRNO_H
63
63
#       include <errno.h>
64
64
#endif
 
65
#ifdef HAVE_TIME_H
65
66
#include <time.h>
 
67
#endif
66
68
#ifdef HAVE_GETOPT_H
67
69
#       include <getopt.h>
68
70
#else
69
71
        extern char *optarg;
70
72
        extern int optind;
71
73
#endif
 
74
#ifdef HAVE_SYS_STAT_H
72
75
#include <sys/stat.h>
 
76
#endif
 
77
#ifdef HAVE_SYS_IOCTL_H
73
78
#include <sys/ioctl.h>
 
79
#endif
 
80
#ifdef HAVE_FCNTL_H
74
81
#include <fcntl.h>
 
82
#endif
75
83
#ifdef HAVE_LINUX_MAJOR_H
76
84
#       include <linux/major.h>
77
85
#       ifndef MAJOR
110
118
                                (M) <= SCSI_DISK7_MAJOR))
111
119
#       endif
112
120
#endif
 
121
#ifdef HAVE_LIMITS_H
113
122
#include <limits.h>
 
123
#endif
114
124
 
115
125
#if defined(linux) && defined(_IO) && !defined(BLKSSZGET)
116
 
#       define BLKSSZGET _IO(0x12,104) /* Get device sector size in bytse. */
 
126
#       define BLKSSZGET _IO(0x12,104) /* Get device sector size in bytes. */
117
127
#endif
118
128
 
119
129
#include "types.h"
 
130
#include "attrib.h"
 
131
#include "bitmap.h"
120
132
#include "bootsect.h"
121
133
#include "device.h"
122
 
#include "attrib.h"
123
 
#include "bitmap.h"
 
134
#include "dir.h"
 
135
#include "mft.h"
124
136
#include "mst.h"
125
 
#include "dir.h"
126
137
#include "runlist.h"
127
 
#include "mft.h"
128
138
#include "utils.h"
 
139
#include "ntfstime.h"
 
140
#include "version.h"
129
141
 
130
142
#ifdef NO_NTFS_DEVICE_DEFAULT_IO_OPS
131
143
#       error "No default device io operations!  Cannot build mkntfs.  \
135
147
 
136
148
extern const unsigned char attrdef_ntfs12_array[2400];
137
149
extern const unsigned char boot_array[3429];
138
 
extern void init_system_file_sd(int sys_file_no, char **sd_val,
139
 
                int *sd_val_len);
 
150
extern void init_system_file_sd(int sys_file_no, u8 **sd_val, int *sd_val_len);
140
151
extern void init_upcase_table(ntfschar *uc, u32 uc_len);
141
152
 
142
153
/* Page size on ia32. Can change to 8192 on Alpha. */
145
156
const char *EXEC_NAME = "mkntfs";
146
157
 
147
158
/* Need these global so mkntfs_exit can access them. */
148
 
char *buf = NULL;
149
 
char *buf2 = NULL;
 
159
u8 *buf = NULL;
 
160
u8 *buf2 = NULL;
150
161
int buf2_size = 0;
151
162
int mft_bitmap_size, mft_bitmap_byte_size;
152
 
unsigned char *mft_bitmap = NULL;
 
163
u8 *mft_bitmap = NULL;
153
164
int lcn_bitmap_byte_size;
154
 
unsigned char *lcn_bitmap = NULL;
 
165
u8 *lcn_bitmap = NULL;
155
166
runlist *rl_mft = NULL, *rl_mft_bmp = NULL, *rl_mftmirr = NULL;
156
167
runlist *rl_logfile = NULL, *rl_boot = NULL, *rl_bad = NULL, *rl_index;
157
168
INDEX_ALLOCATION *index_block = NULL;
159
170
char *dev_name;
160
171
 
161
172
struct {
162
 
        long long part_start_sect;      /* start sector of partition on parent
163
 
                                           device */
 
173
        long long part_start_sect;      /* -p, start sector of partition on
 
174
                                           parent device */
164
175
        long long nr_sectors;           /* size of device in sectors */
165
176
        long long nr_clusters;          /* Note: Win2k treats clusters as
166
177
                                           32-bit entities! */
174
185
        long long logfile_lcn;          /* lcn of $LogFile, $DATA. */
175
186
        int logfile_size;               /* in bytes, determined from
176
187
                                           volume_size. */
177
 
        int mft_zone_multiplier;        /* -z, value from 1 to 4. Default is 
 
188
        int mft_zone_multiplier;        /* -z, value from 1 to 4. Default is
178
189
                                           1. */
179
190
        long long mft_zone_end;         /* Determined from volume_size and
180
191
                                           mft_zone_multiplier, in clusters. */
188
199
        u32 upcase_len;                 /* Determined automatically. */
189
200
        int sector_size;                /* -s, in bytes, power of 2, default is
190
201
                                           512 bytes. */
191
 
        int sectors_per_track;          /* number of sectors per track on
 
202
        int sectors_per_track;          /* -S, number of sectors per track on
192
203
                                           device */
193
 
        int heads;                      /* number of heads on device */
 
204
        int heads;                      /* -H, number of heads on device */
194
205
        int quiet;                      /* -q, quiet execution. */
195
206
        int verbose;                    /* -v, verbose execution, given twice,
196
207
                                         * really verbose execution (debug
207
218
        char disable_indexing;          /* -I, disables indexing of file
208
219
                                           contents on the volume by default. */
209
220
                                        /* -V, print version and exit. */
 
221
        char use_epoch_time;            /* -T, fake the time to be
 
222
                                           00:00:00 UTC, Jan 1, 1970. */
210
223
} opts;
211
224
 
212
225
/**
213
 
 * Dprintf - debugging output (-vv); overriden by quiet (-q)
 
226
 * mkDprintf - debugging output (-vv); overridden by quiet (-q)
214
227
 */
215
 
static void Dprintf(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
216
 
static void Dprintf(const char *fmt, ...)
 
228
static void mkDprintf(const char *fmt, ...)
 
229
                __attribute__((format(printf, 1, 2)));
 
230
static void mkDprintf(const char *fmt, ...)
217
231
{
218
232
        va_list ap;
219
233
 
248
262
/**
249
263
 * err_exit - error output and terminate; ignores quiet (-q)
250
264
 */
251
 
static void err_exit(const char *fmt, ...) 
 
265
static void err_exit(const char *fmt, ...)
252
266
                __attribute__((noreturn))
253
267
                __attribute__((format(printf, 1, 2)));
254
268
static void err_exit(const char *fmt, ...)
269
283
 */
270
284
static void copyright(void)
271
285
{
272
 
        fprintf(stderr, "Copyright (c) 2000-2004 Anton Altaparmakov\n"
 
286
        fprintf(stderr, "Copyright (c) 2000-2005 Anton Altaparmakov\n"
273
287
                        "Copyright (c) 2001-2003 Richard Russon\n"
274
288
                        "Create an NTFS volume on a user specified (block) "
275
289
                        "device.\n");
314
328
                        "    -n                       Do not write to disk\n"
315
329
                        "    -F                       Force execution despite "
316
330
                        "errors\n"
 
331
                        "    -T                       Fake the time to be "
 
332
                        "00:00:00 UTC, Jan 1, 1970\n"
317
333
                        "    -q                       Quiet execution\n"
318
334
                        "    -v                       Verbose execution\n"
319
335
                        "    -vv                      Very verbose execution\n"
327
343
        exit(1);
328
344
}
329
345
 
 
346
#include "version.h"
330
347
/**
331
348
 * parse_options
332
349
 */
341
358
//               logfile size, list of bad blocks, check for bad blocks, ...
342
359
        if (argc && *argv)
343
360
                EXEC_NAME = *argv;
344
 
        fprintf(stderr, "%s v%s\n", EXEC_NAME, VERSION);
345
 
        while ((c = getopt(argc, argv, "c:fh?np:qs:vz:CFIL:QVl")) != EOF)
 
361
        fprintf(stderr, "%s v%s (libntfs %s)\n", EXEC_NAME, VERSION,
 
362
                        ntfs_libntfs_version());
 
363
        while ((c = getopt(argc, argv, "c:fH:h?np:qS:s:vz:CFTIL:QVl")) != EOF)
346
364
                switch (c) {
347
365
                case 'n':
348
366
                        opts.no_action = 1;
400
418
                case 'F':
401
419
                        opts.force = 1;
402
420
                        break;
 
421
                case 'T':
 
422
                        opts.use_epoch_time = 1;
 
423
                        break;
403
424
                case 'I':
404
425
                        opts.disable_indexing = 1;
405
426
                        break;
433
454
}
434
455
 
435
456
/**
 
457
 * mkntfs_time
 
458
 */
 
459
static time_t mkntfs_time(void)
 
460
{
 
461
        if (!opts.use_epoch_time)
 
462
                return time(NULL);
 
463
        return 0;
 
464
}
 
465
 
 
466
/**
436
467
 * append_to_bad_blocks
437
468
 *
438
469
 * Note: Might not return.
439
470
 */
440
 
static void append_to_bad_blocks(unsigned long block)
 
471
static void append_to_bad_blocks(unsigned long long block)
441
472
{
442
473
        long long *new_buf;
443
474
 
502
533
 * Note: Might not return.
503
534
 */
504
535
static s64 ntfs_rlwrite(struct ntfs_device *dev, const runlist *rl,
505
 
                const char *val, const s64 val_len, s64 *inited_size)
 
536
                const u8 *val, const s64 val_len, s64 *inited_size)
506
537
{
507
538
        s64 bytes_written, total, length, delta;
508
539
        int retry, i;
522
553
                        // TODO: Check that *val is really zero at pos and len.
523
554
                        continue;
524
555
                }
 
556
                /*
 
557
                 * Break up the write into the real data write and then a write
 
558
                 * of zeroes between the end of the real data and the end of
 
559
                 * the (last) run.
 
560
                 */
 
561
                if (total + length > val_len) {
 
562
                        delta = length;
 
563
                        length = val_len - total;
 
564
                        delta -= length;
 
565
                }
525
566
                if (dev->d_ops->seek(dev, rl[i].lcn * vol->cluster_size,
526
567
                                SEEK_SET) == (off_t)-1)
527
568
                        return -1LL;
528
569
                retry = 0;
529
570
                do {
530
 
                        if (total + length > val_len) {
531
 
                                delta = length;
532
 
                                length = val_len - total;
533
 
                                delta -= length;
534
 
                        }
535
571
                        bytes_written = dev->d_ops->write(dev, val + total,
536
572
                                        length);
537
573
                        if (bytes_written == -1LL) {
557
593
                }
558
594
        }
559
595
        if (delta) {
 
596
                int eo;
560
597
                char *b = (char*)calloc(1, delta);
561
598
                if (!b)
562
599
                        err_exit("Error allocating internal buffer: "
563
600
                                        "%s\n", strerror(errno));
564
601
                bytes_written = mkntfs_write(dev, b, delta);
 
602
                eo = errno;
565
603
                free(b);
 
604
                errno = eo;
566
605
                if (bytes_written == -1LL)
567
606
                        return bytes_written;
568
607
        }
803
842
/**
804
843
 * dump_mapping_pairs_array
805
844
 */
806
 
static void dump_mapping_pairs_array(char *b, unsigned int max_len)
 
845
static void dump_mapping_pairs_array(char *b __attribute__((unused)),
 
846
                unsigned int max_len __attribute__((unused)))
807
847
{
808
848
        // TODO
809
849
        return;
1154
1194
}
1155
1195
 
1156
1196
/**
 
1197
 * Internal:
 
1198
 *
 
1199
 * ntfs_attr_find - find (next) attribute in mft record
 
1200
 * @type:       attribute type to find
 
1201
 * @name:       attribute name to find (optional, i.e. NULL means don't care)
 
1202
 * @name_len:   attribute name length (only needed if @name present)
 
1203
 * @ic:         IGNORE_CASE or CASE_SENSITIVE (ignored if @name not present)
 
1204
 * @val:        attribute value to find (optional, resident attributes only)
 
1205
 * @val_len:    attribute value length
 
1206
 * @ctx:        search context with mft record and attribute to search from
 
1207
 *
 
1208
 * You shouldn't need to call this function directly. Use lookup_attr() instead.
 
1209
 *
 
1210
 * ntfs_attr_find() takes a search context @ctx as parameter and searches the
 
1211
 * mft record specified by @ctx->mrec, beginning at @ctx->attr, for an
 
1212
 * attribute of @type, optionally @name and @val. If found, ntfs_attr_find()
 
1213
 * returns 0 and @ctx->attr will point to the found attribute.
 
1214
 *
 
1215
 * If not found, ntfs_attr_find() returns -1, with errno set to ENOENT and
 
1216
 * @ctx->attr will point to the attribute before which the attribute being
 
1217
 * searched for would need to be inserted if such an action were to be desired.
 
1218
 *
 
1219
 * On actual error, ntfs_attr_find() returns -1 with errno set to the error
 
1220
 * code but not to ENOENT.  In this case @ctx->attr is undefined and in
 
1221
 * particular do not rely on it not changing.
 
1222
 *
 
1223
 * If @ctx->is_first is TRUE, the search begins with @ctx->attr itself. If it
 
1224
 * is FALSE, the search begins after @ctx->attr.
 
1225
 *
 
1226
 * If @type is AT_UNUSED, return the first found attribute, i.e. one can
 
1227
 * enumerate all attributes by setting @type to AT_UNUSED and then calling
 
1228
 * ntfs_attr_find() repeatedly until it returns -1 with errno set to ENOENT to
 
1229
 * indicate that there are no more entries. During the enumeration, each
 
1230
 * successful call of ntfs_attr_find() will return the next attribute in the
 
1231
 * mft record @ctx->mrec.
 
1232
 *
 
1233
 * If @type is AT_END, seek to the end and return -1 with errno set to ENOENT.
 
1234
 * AT_END is not a valid attribute, its length is zero for example, thus it is
 
1235
 * safer to return error instead of success in this case. This also allows us
 
1236
 * to interoperate cleanly with ntfs_external_attr_find().
 
1237
 *
 
1238
 * If @name is AT_UNNAMED search for an unnamed attribute. If @name is present
 
1239
 * but not AT_UNNAMED search for a named attribute matching @name. Otherwise,
 
1240
 * match both named and unnamed attributes.
 
1241
 *
 
1242
 * If @ic is IGNORE_CASE, the @name comparison is not case sensitive and
 
1243
 * @ctx->ntfs_ino must be set to the ntfs inode to which the mft record
 
1244
 * @ctx->mrec belongs. This is so we can get at the ntfs volume and hence at
 
1245
 * the upcase table. If @ic is CASE_SENSITIVE, the comparison is case
 
1246
 * sensitive. When @name is present, @name_len is the @name length in Unicode
 
1247
 * characters.
 
1248
 *
 
1249
 * If @name is not present (NULL), we assume that the unnamed attribute is
 
1250
 * being searched for.
 
1251
 *
 
1252
 * Finally, the resident attribute value @val is looked for, if present.
 
1253
 * If @val is not present (NULL), @val_len is ignored.
 
1254
 *
 
1255
 * ntfs_attr_find() only searches the specified mft record and it ignores the
 
1256
 * presence of an attribute list attribute (unless it is the one being searched
 
1257
 * for, obviously). If you need to take attribute lists into consideration, use
 
1258
 * ntfs_attr_lookup() instead (see below). This also means that you cannot use
 
1259
 * ntfs_attr_find() to search for extent records of non-resident attributes, as
 
1260
 * extents with lowest_vcn != 0 are usually described by the attribute list
 
1261
 * attribute only. - Note that it is possible that the first extent is only in
 
1262
 * the attribute list while the last extent is in the base mft record, so don't
 
1263
 * rely on being able to find the first extent in the base mft record.
 
1264
 *
 
1265
 * Warning: Never use @val when looking for attribute types which can be
 
1266
 *          non-resident as this most likely will result in a crash!
 
1267
 */
 
1268
static int mkntfs_attr_find(const ATTR_TYPES type, const ntfschar *name,
 
1269
                const u32 name_len, const IGNORE_CASE_BOOL ic,
 
1270
                const u8 *val, const u32 val_len, ntfs_attr_search_ctx *ctx)
 
1271
{
 
1272
        ATTR_RECORD *a;
 
1273
        ntfschar *upcase = vol->upcase;
 
1274
        u32 upcase_len = vol->upcase_len;
 
1275
 
 
1276
        /*
 
1277
         * Iterate over attributes in mft record starting at @ctx->attr, or the
 
1278
         * attribute following that, if @ctx->is_first is TRUE.
 
1279
         */
 
1280
        if (ctx->is_first) {
 
1281
                a = ctx->attr;
 
1282
                ctx->is_first = FALSE;
 
1283
        } else
 
1284
                a = (ATTR_RECORD*)((char*)ctx->attr +
 
1285
                                le32_to_cpu(ctx->attr->length));
 
1286
        for (;; a = (ATTR_RECORD*)((char*)a + le32_to_cpu(a->length))) {
 
1287
                if (p2n(a) < p2n(ctx->mrec) || (char*)a > (char*)ctx->mrec +
 
1288
                                le32_to_cpu(ctx->mrec->bytes_allocated))
 
1289
                        break;
 
1290
                ctx->attr = a;
 
1291
                if (((type != AT_UNUSED) && (le32_to_cpu(a->type) >
 
1292
                                le32_to_cpu(type))) ||
 
1293
                                (a->type == AT_END)) {
 
1294
                        errno = ENOENT;
 
1295
                        return -1;
 
1296
                }
 
1297
                if (!a->length)
 
1298
                        break;
 
1299
                /* If this is an enumeration return this attribute. */
 
1300
                if (type == AT_UNUSED)
 
1301
                        return 0;
 
1302
                if (a->type != type)
 
1303
                        continue;
 
1304
                /*
 
1305
                 * If @name is AT_UNNAMED we want an unnamed attribute.
 
1306
                 * If @name is present, compare the two names.
 
1307
                 * Otherwise, match any attribute.
 
1308
                 */
 
1309
                if (name == AT_UNNAMED) {
 
1310
                        /* The search failed if the found attribute is named. */
 
1311
                        if (a->name_length) {
 
1312
                                errno = ENOENT;
 
1313
                                return -1;
 
1314
                        }
 
1315
                } else if (name && !ntfs_names_are_equal(name, name_len,
 
1316
                            (ntfschar*)((char*)a + le16_to_cpu(a->name_offset)),
 
1317
                            a->name_length, ic, upcase, upcase_len)) {
 
1318
                        register int rc;
 
1319
 
 
1320
                        rc = ntfs_names_collate(name, name_len,
 
1321
                                        (ntfschar*)((char*)a +
 
1322
                                        le16_to_cpu(a->name_offset)),
 
1323
                                        a->name_length, 1, IGNORE_CASE,
 
1324
                                        upcase, upcase_len);
 
1325
                        /*
 
1326
                         * If @name collates before a->name, there is no
 
1327
                         * matching attribute.
 
1328
                         */
 
1329
                        if (rc == -1) {
 
1330
                                errno = ENOENT;
 
1331
                                return -1;
 
1332
                        }
 
1333
                        /* If the strings are not equal, continue search. */
 
1334
                        if (rc)
 
1335
                                continue;
 
1336
                        rc = ntfs_names_collate(name, name_len,
 
1337
                                        (ntfschar*)((char*)a +
 
1338
                                        le16_to_cpu(a->name_offset)),
 
1339
                                        a->name_length, 1, CASE_SENSITIVE,
 
1340
                                        upcase, upcase_len);
 
1341
                        if (rc == -1) {
 
1342
                                errno = ENOENT;
 
1343
                                return -1;
 
1344
                        }
 
1345
                        if (rc)
 
1346
                                continue;
 
1347
                }
 
1348
                /*
 
1349
                 * The names match or @name not present and attribute is
 
1350
                 * unnamed. If no @val specified, we have found the attribute
 
1351
                 * and are done.
 
1352
                 */
 
1353
                if (!val)
 
1354
                        return 0;
 
1355
                /* @val is present; compare values. */
 
1356
                else {
 
1357
                        register int rc;
 
1358
 
 
1359
                        rc = memcmp(val, (char*)a +le16_to_cpu(a->value_offset),
 
1360
                                        min(val_len,
 
1361
                                        le32_to_cpu(a->value_length)));
 
1362
                        /*
 
1363
                         * If @val collates before the current attribute's
 
1364
                         * value, there is no matching attribute.
 
1365
                         */
 
1366
                        if (!rc) {
 
1367
                                register u32 avl;
 
1368
                                avl = le32_to_cpu(a->value_length);
 
1369
                                if (val_len == avl)
 
1370
                                        return 0;
 
1371
                                if (val_len < avl) {
 
1372
                                        errno = ENOENT;
 
1373
                                        return -1;
 
1374
                                }
 
1375
                        } else if (rc < 0) {
 
1376
                                errno = ENOENT;
 
1377
                                return -1;
 
1378
                        }
 
1379
                }
 
1380
        }
 
1381
        Dputs("mkntfs_attr_find(): File is corrupt. Run chkdsk.");
 
1382
        errno = EIO;
 
1383
        return -1;
 
1384
}
 
1385
 
 
1386
/**
 
1387
 * ntfs_attr_lookup - find an attribute in an ntfs inode
 
1388
 * @type:       attribute type to find
 
1389
 * @name:       attribute name to find (optional, i.e. NULL means don't care)
 
1390
 * @name_len:   attribute name length (only needed if @name present)
 
1391
 * @ic:         IGNORE_CASE or CASE_SENSITIVE (ignored if @name not present)
 
1392
 * @lowest_vcn: lowest vcn to find (optional, non-resident attributes only)
 
1393
 * @val:        attribute value to find (optional, resident attributes only)
 
1394
 * @val_len:    attribute value length
 
1395
 * @ctx:        search context with mft record and attribute to search from
 
1396
 *
 
1397
 * Find an attribute in an ntfs inode. On first search @ctx->ntfs_ino must
 
1398
 * be the base mft record and @ctx must have been obtained from a call to
 
1399
 * ntfs_attr_get_search_ctx().
 
1400
 *
 
1401
 * This function transparently handles attribute lists and @ctx is used to
 
1402
 * continue searches where they were left off at.
 
1403
 *
 
1404
 * If @type is AT_UNUSED, return the first found attribute, i.e. one can
 
1405
 * enumerate all attributes by setting @type to AT_UNUSED and then calling
 
1406
 * ntfs_attr_lookup() repeatedly until it returns -1 with errno set to ENOENT
 
1407
 * to indicate that there are no more entries. During the enumeration, each
 
1408
 * successful call of ntfs_attr_lookup() will return the next attribute, with
 
1409
 * the current attribute being described by the search context @ctx.
 
1410
 *
 
1411
 * If @type is AT_END, seek to the end of the base mft record ignoring the
 
1412
 * attribute list completely and return -1 with errno set to ENOENT.  AT_END is
 
1413
 * not a valid attribute, its length is zero for example, thus it is safer to
 
1414
 * return error instead of success in this case.  It should never ne needed to
 
1415
 * do this, but we implement the functionality because it allows for simpler
 
1416
 * code inside ntfs_external_attr_find().
 
1417
 *
 
1418
 * If @name is AT_UNNAMED search for an unnamed attribute. If @name is present
 
1419
 * but not AT_UNNAMED search for a named attribute matching @name. Otherwise,
 
1420
 * match both named and unnamed attributes.
 
1421
 *
 
1422
 * After finishing with the attribute/mft record you need to call
 
1423
 * ntfs_attr_put_search_ctx() to cleanup the search context (unmapping any
 
1424
 * mapped extent inodes, etc).
 
1425
 *
 
1426
 * Return 0 if the search was successful and -1 if not, with errno set to the
 
1427
 * error code.
 
1428
 *
 
1429
 * On success, @ctx->attr is the found attribute, it is in mft record
 
1430
 * @ctx->mrec, and @ctx->al_entry is the attribute list entry for this
 
1431
 * attribute with @ctx->base_* being the base mft record to which @ctx->attr
 
1432
 * belongs.  If no attribute list attribute is present @ctx->al_entry and
 
1433
 * @ctx->base_* are NULL.
 
1434
 *
 
1435
 * On error ENOENT, i.e. attribute not found, @ctx->attr is set to the
 
1436
 * attribute which collates just after the attribute being searched for in the
 
1437
 * base ntfs inode, i.e. if one wants to add the attribute to the mft record
 
1438
 * this is the correct place to insert it into, and if there is not enough
 
1439
 * space, the attribute should be placed in an extent mft record.
 
1440
 * @ctx->al_entry points to the position within @ctx->base_ntfs_ino->attr_list
 
1441
 * at which the new attribute's attribute list entry should be inserted.  The
 
1442
 * other @ctx fields, base_ntfs_ino, base_mrec, and base_attr are set to NULL.
 
1443
 * The only exception to this is when @type is AT_END, in which case
 
1444
 * @ctx->al_entry is set to NULL also (see above).
 
1445
 *
 
1446
 *
 
1447
 * The following error codes are defined:
 
1448
 *      ENOENT  Attribute not found, not an error as such.
 
1449
 *      EINVAL  Invalid arguments.
 
1450
 *      EIO     I/O error or corrupt data structures found.
 
1451
 *      ENOMEM  Not enough memory to allocate necessary buffers.
 
1452
 */
 
1453
static int mkntfs_attr_lookup(const ATTR_TYPES type, const ntfschar *name,
 
1454
                const u32 name_len, const IGNORE_CASE_BOOL ic,
 
1455
                const VCN lowest_vcn __attribute__ ((unused)), const u8 *val,
 
1456
                const u32 val_len, ntfs_attr_search_ctx *ctx)
 
1457
{
 
1458
        ntfs_inode *base_ni;
 
1459
 
 
1460
        if (!ctx || !ctx->mrec || !ctx->attr) {
 
1461
                errno = EINVAL;
 
1462
                return -1;
 
1463
        }
 
1464
        if (ctx->base_ntfs_ino)
 
1465
                base_ni = ctx->base_ntfs_ino;
 
1466
        else
 
1467
                base_ni = ctx->ntfs_ino;
 
1468
        if (!base_ni || !NInoAttrList(base_ni) || type == AT_ATTRIBUTE_LIST)
 
1469
                return mkntfs_attr_find(type, name, name_len, ic, val, val_len,
 
1470
                                ctx);
 
1471
        errno = EOPNOTSUPP;
 
1472
        return -1;
 
1473
}
 
1474
 
 
1475
/**
1157
1476
 * insert_positioned_attr_in_mft_record
1158
1477
 * Create a non-resident attribute with a predefined on disk location
1159
1478
 * specified by the runlist @rl. The clusters specified by @rl are assumed to
1164
1483
static int insert_positioned_attr_in_mft_record(MFT_RECORD *m,
1165
1484
                const ATTR_TYPES type, const char *name, u32 name_len,
1166
1485
                const IGNORE_CASE_BOOL ic, const ATTR_FLAGS flags,
1167
 
                const runlist *rl, const char *val, const s64 val_len)
 
1486
                const runlist *rl, const u8 *val, const s64 val_len)
1168
1487
{
1169
1488
        ntfs_attr_search_ctx *ctx;
1170
1489
        ATTR_RECORD *a;
1199
1518
        }
1200
1519
        if (ic == IGNORE_CASE) {
1201
1520
                Eprintf("FIXME: Hit unimplemented code path #1.\n");
1202
 
                err = -ENOTSUP;
 
1521
                err = -EOPNOTSUPP;
1203
1522
                goto err_out;
1204
1523
        }
1205
 
        if (!ntfs_attr_lookup(type, uname, name_len, ic, 0, NULL, 0, ctx)) {
 
1524
        if (!mkntfs_attr_lookup(type, uname, name_len, ic, 0, NULL, 0, ctx)) {
1206
1525
                err = -EEXIST;
1207
1526
                goto err_out;
1208
1527
        }
1216
1535
                Eprintf("Compressed attributes not supported yet.\n");
1217
1536
                // FIXME: Compress attribute into a temporary buffer, set
1218
1537
                // val accordingly and save the compressed size.
1219
 
                err = -ENOTSUP;
 
1538
                err = -EOPNOTSUPP;
1220
1539
                goto err_out;
1221
1540
        }
1222
1541
        if (flags & (ATTR_IS_ENCRYPTED || ATTR_IS_SPARSE)) {
1223
1542
                Eprintf("Encrypted/sparse attributes not supported yet.\n");
1224
 
                err = -ENOTSUP;
 
1543
                err = -EOPNOTSUPP;
1225
1544
                goto err_out;
1226
1545
        }
1227
1546
        if (flags & ATTR_COMPRESSION_MASK) {
1235
1554
        } else {
1236
1555
                hdr_size = 64;
1237
1556
                if (val_len) {
1238
 
                        mpa_size = ntfs_get_size_for_mapping_pairs(vol, rl);
 
1557
                        mpa_size = ntfs_get_size_for_mapping_pairs(vol, rl, 0);
1239
1558
                        if (mpa_size < 0) {
1240
1559
                                err = -errno;
1241
1560
                                Eprintf("Failed to get size for mapping "
1272
1591
                // record.
1273
1592
                // FIXME: the check for needing extension records should be
1274
1593
                // earlier on as it is very quick: asize > m->bytes_allocated?
1275
 
                err = -ENOTSUP;
 
1594
                err = -EOPNOTSUPP;
1276
1595
                goto err_out;
1277
1596
        }
1278
1597
#ifdef DEBUG
1314
1633
                a->compressed_size = cpu_to_le64(0);
1315
1634
                // FIXME: Write out the compressed data.
1316
1635
                // FIXME: err = build_mapping_pairs_compressed();
1317
 
                err = -ENOTSUP;
 
1636
                err = -EOPNOTSUPP;
1318
1637
        } else {
1319
1638
                a->compression_unit = 0;
1320
1639
                bw = ntfs_rlwrite(vol->dev, rl, val, val_len, &inited_size);
1321
1640
                if (bw != val_len)
1322
1641
                        Eprintf("Error writing non-resident attribute value."
1323
1642
                                "\n");
1324
 
                err = ntfs_mapping_pairs_build(vol, (s8*)a + hdr_size +
1325
 
                                ((name_len + 7) & ~7), mpa_size, rl);
 
1643
                err = ntfs_mapping_pairs_build(vol, (u8*)a + hdr_size +
 
1644
                                ((name_len + 7) & ~7), mpa_size, rl, 0, NULL);
1326
1645
        }
1327
1646
        a->initialized_size = cpu_to_le64(inited_size);
1328
1647
        if (err < 0 || bw != val_len) {
1349
1668
static int insert_non_resident_attr_in_mft_record(MFT_RECORD *m,
1350
1669
                const ATTR_TYPES type, const char *name, u32 name_len,
1351
1670
                const IGNORE_CASE_BOOL ic, const ATTR_FLAGS flags,
1352
 
                const char *val, const s64 val_len)
 
1671
                const u8 *val, const s64 val_len)
1353
1672
{
1354
1673
        ntfs_attr_search_ctx *ctx;
1355
1674
        ATTR_RECORD *a;
1384
1703
        }
1385
1704
        if (ic == IGNORE_CASE) {
1386
1705
                Eprintf("FIXME: Hit unimplemented code path #2.\n");
1387
 
                err = -ENOTSUP;
 
1706
                err = -EOPNOTSUPP;
1388
1707
                goto err_out;
1389
1708
        }
1390
 
        if (!ntfs_attr_lookup(type, uname, name_len, ic, 0, NULL, 0, ctx)) {
 
1709
        if (!mkntfs_attr_lookup(type, uname, name_len, ic, 0, NULL, 0, ctx)) {
1391
1710
                err = -EEXIST;
1392
1711
                goto err_out;
1393
1712
        }
1401
1720
                Eprintf("Compressed attributes not supported yet.\n");
1402
1721
                // FIXME: Compress attribute into a temporary buffer, set
1403
1722
                // val accordingly and save the compressed size.
1404
 
                err = -ENOTSUP;
 
1723
                err = -EOPNOTSUPP;
1405
1724
                goto err_out;
1406
1725
        }
1407
1726
        if (flags & (ATTR_IS_ENCRYPTED || ATTR_IS_SPARSE)) {
1408
1727
                Eprintf("Encrypted/sparse attributes not supported yet.\n");
1409
 
                err = -ENOTSUP;
 
1728
                err = -EOPNOTSUPP;
1410
1729
                goto err_out;
1411
1730
        }
1412
1731
        if (val_len) {
1431
1750
        } else {
1432
1751
                hdr_size = 64;
1433
1752
                if (val_len) {
1434
 
                        mpa_size = ntfs_get_size_for_mapping_pairs(vol, rl);
 
1753
                        mpa_size = ntfs_get_size_for_mapping_pairs(vol, rl, 0);
1435
1754
                        if (mpa_size < 0) {
1436
1755
                                err = -errno;
1437
1756
                                Eprintf("Failed to get size for mapping "
1459
1778
                // record.
1460
1779
                // FIXME: the check for needing extension records should be
1461
1780
                // earlier on as it is very quick: asize > m->bytes_allocated?
1462
 
                err = -ENOTSUP;
 
1781
                err = -EOPNOTSUPP;
1463
1782
                goto err_out;
1464
1783
        }
1465
1784
#ifdef DEBUG
1504
1823
                a->compressed_size = cpu_to_le64(0);
1505
1824
                // FIXME: Write out the compressed data.
1506
1825
                // FIXME: err = build_mapping_pairs_compressed();
1507
 
                err = -ENOTSUP;
 
1826
                err = -EOPNOTSUPP;
1508
1827
        } else {
1509
1828
                a->compression_unit = 0;
1510
1829
                bw = ntfs_rlwrite(vol->dev, rl, val, val_len, NULL);
1511
1830
                if (bw != val_len)
1512
1831
                        Eprintf("Error writing non-resident attribute value."
1513
1832
                                "\n");
1514
 
                err = ntfs_mapping_pairs_build(vol, (s8*)a + hdr_size +
1515
 
                                ((name_len + 7) & ~7), mpa_size, rl);
 
1833
                err = ntfs_mapping_pairs_build(vol, (u8*)a + hdr_size +
 
1834
                                ((name_len + 7) & ~7), mpa_size, rl, 0, NULL);
1516
1835
        }
1517
1836
        if (err < 0 || bw != val_len) {
1518
1837
                // FIXME: Handle error.
1541
1860
                const ATTR_TYPES type, const char *name, u32 name_len,
1542
1861
                const IGNORE_CASE_BOOL ic, const ATTR_FLAGS flags,
1543
1862
                const RESIDENT_ATTR_FLAGS res_flags,
1544
 
                const char *val, const u32 val_len)
 
1863
                const u8 *val, const u32 val_len)
1545
1864
{
1546
1865
        ntfs_attr_search_ctx *ctx;
1547
1866
        ATTR_RECORD *a;
1549
1868
        ntfschar *uname;
1550
1869
/*
1551
1870
        if (base record)
1552
 
                ntfs_attr_lookup();
 
1871
                mkntfs_attr_lookup();
1553
1872
        else
1554
1873
*/
1555
1874
        if (name_len) {
1573
1892
        }
1574
1893
        if (ic == IGNORE_CASE) {
1575
1894
                Eprintf("FIXME: Hit unimplemented code path #3.\n");
1576
 
                err = -ENOTSUP;
 
1895
                err = -EOPNOTSUPP;
1577
1896
                goto err_out;
1578
1897
        }
1579
 
        if (!ntfs_attr_lookup(type, uname, name_len, ic, 0, val, val_len,
 
1898
        if (!mkntfs_attr_lookup(type, uname, name_len, ic, 0, val, val_len,
1580
1899
                        ctx)) {
1581
1900
                err = -EEXIST;
1582
1901
                goto err_out;
1605
1924
                // record.
1606
1925
                // FIXME: the check for needing extension records should be
1607
1926
                // earlier on as it is very quick: asize > m->bytes_allocated?
1608
 
                err = -ENOTSUP;
 
1927
                err = -EOPNOTSUPP;
1609
1928
                goto err_out;
1610
1929
        }
1611
1930
#ifdef DEBUG
1650
1969
        STANDARD_INFORMATION si;
1651
1970
        int err;
1652
1971
 
1653
 
        si.creation_time = utc2ntfs(time(NULL));
 
1972
        si.creation_time = utc2ntfs(mkntfs_time());
1654
1973
        si.last_data_change_time = si.creation_time;
1655
1974
        si.last_mft_change_time = si.creation_time;
1656
1975
        si.last_access_time = si.creation_time;
1671
1990
        }
1672
1991
        /* NTFS 1.2: size of si = 48, NTFS 3.0: size of si = 72 */
1673
1992
        err = insert_resident_attr_in_mft_record(m, AT_STANDARD_INFORMATION,
1674
 
                        NULL, 0, 0, 0, 0, (char*)&si,
 
1993
                        NULL, 0, 0, 0, 0, (u8*)&si,
1675
1994
                        vol->major_ver < 3 ? 48 : 72);
1676
1995
        if (err < 0)
1677
1996
                Eprintf("add_attr_std_info failed: %s\n", strerror(-err));
1699
2018
                Eprintf("Failed to allocate attribute search context.\n");
1700
2019
                return -ENOMEM;
1701
2020
        }
1702
 
        if (ntfs_attr_lookup(AT_STANDARD_INFORMATION, AT_UNNAMED, 0, 0, 0, NULL, 0,
 
2021
        if (mkntfs_attr_lookup(AT_STANDARD_INFORMATION, AT_UNNAMED, 0, 0, 0, NULL, 0,
1703
2022
                        ctx)) {
1704
2023
                int eo = errno;
1705
2024
                Eprintf("BUG: Standard information attribute not present in "
1751
2070
        fn->file_name_length = i;
1752
2071
        fn_size = sizeof(FILE_NAME_ATTR) + i * sizeof(ntfschar);
1753
2072
        i = insert_resident_attr_in_mft_record(m, AT_FILE_NAME, NULL, 0, 0,
1754
 
                        0, RESIDENT_ATTR_IS_INDEXED, (char*)fn, fn_size);
 
2073
                        0, RESIDENT_ATTR_IS_INDEXED, (u8*)fn, fn_size);
1755
2074
        free(fn);
1756
2075
        if (i < 0)
1757
2076
                Eprintf("add_attr_file_name failed: %s\n", strerror(-i));
1765
2084
 *
1766
2085
 * Return 0 on success or -errno on error.
1767
2086
 */
1768
 
static int add_attr_sd(MFT_RECORD *m, const char *sd, const s64 sd_len)
 
2087
static int add_attr_sd(MFT_RECORD *m, const u8 *sd, const s64 sd_len)
1769
2088
{
1770
2089
        int err;
1771
2090
 
1790
2109
 */
1791
2110
static int add_attr_data(MFT_RECORD *m, const char *name, const u32 name_len,
1792
2111
                const IGNORE_CASE_BOOL ic, const ATTR_FLAGS flags,
1793
 
                const char *val, const s64 val_len)
 
2112
                const u8 *val, const s64 val_len)
1794
2113
{
1795
2114
        int err;
1796
2115
 
1830
2149
static int add_attr_data_positioned(MFT_RECORD *m, const char *name,
1831
2150
                const u32 name_len, const IGNORE_CASE_BOOL ic,
1832
2151
                const ATTR_FLAGS flags, const runlist *rl,
1833
 
                const char *val, const s64 val_len)
 
2152
                const u8 *val, const s64 val_len)
1834
2153
{
1835
2154
        int err;
1836
2155
 
1877
2196
                len = 0;
1878
2197
        }
1879
2198
        i = insert_resident_attr_in_mft_record(m, AT_VOLUME_NAME, NULL, 0, 0,
1880
 
                        0, 0, (char*)uname, len);
 
2199
                        0, 0, (u8*)uname, len);
1881
2200
        if (uname)
1882
2201
                free(uname);
1883
2202
        if (i < 0)
1900
2219
        vi.minor_ver = minor_ver;
1901
2220
        vi.flags = flags & VOLUME_FLAGS_MASK;
1902
2221
        err = insert_resident_attr_in_mft_record(m, AT_VOLUME_INFORMATION, NULL,
1903
 
                        0, 0, 0, 0, (char*)&vi, sizeof(vi));
 
2222
                        0, 0, 0, 0, (u8*)&vi, sizeof(vi));
1904
2223
        if (err < 0)
1905
2224
                Eprintf("add_attr_vol_info failed: %s\n", strerror(-err));
1906
2225
        return err;
1979
2298
        e->flags = INDEX_ENTRY_END;
1980
2299
        e->reserved = cpu_to_le16(0);
1981
2300
        err = insert_resident_attr_in_mft_record(m, AT_INDEX_ROOT, name,
1982
 
                                name_len, ic, 0, 0, (char*)r, val_len);
 
2301
                                name_len, ic, 0, 0, (u8*)r, val_len);
1983
2302
        free(r);
1984
2303
        if (err < 0)
1985
2304
                Eprintf("add_attr_index_root failed: %s\n", strerror(-err));
1992
2311
 */
1993
2312
static int add_attr_index_alloc(MFT_RECORD *m, const char *name,
1994
2313
                const u32 name_len, const IGNORE_CASE_BOOL ic,
1995
 
                const char *index_alloc_val, const u32 index_alloc_val_len)
 
2314
                const u8 *index_alloc_val, const u32 index_alloc_val_len)
1996
2315
{
1997
2316
        int err;
1998
2317
 
2009
2328
 * Return 0 on success or -errno on error.
2010
2329
 */
2011
2330
static int add_attr_bitmap(MFT_RECORD *m, const char *name, const u32 name_len,
2012
 
                const IGNORE_CASE_BOOL ic, const char *bitmap,
 
2331
                const IGNORE_CASE_BOOL ic, const u8 *bitmap,
2013
2332
                const u32 bitmap_len)
2014
2333
{
2015
2334
        int err;
2038
2357
 */
2039
2358
static int add_attr_bitmap_positioned(MFT_RECORD *m, const char *name,
2040
2359
                const u32 name_len, const IGNORE_CASE_BOOL ic,
2041
 
                const runlist *rl, const char *bitmap, const u32 bitmap_len)
 
2360
                const runlist *rl, const u8 *bitmap, const u32 bitmap_len)
2042
2361
{
2043
2362
        int err;
2044
2363
 
2068
2387
        INDEX_ENTRY *re;
2069
2388
        INDEX_ALLOCATION *ia_val = NULL;
2070
2389
        ntfschar *uname;
2071
 
        char bmp[8];
 
2390
        u8 bmp[8];
2072
2391
        char *re_start, *re_end;
2073
2392
        int i, err, index_block_size;
2074
2393
 
2094
2413
        }
2095
2414
        if (ic == IGNORE_CASE) {
2096
2415
                Eprintf("FIXME: Hit unimplemented code path #4.\n");
2097
 
                err = -ENOTSUP;
 
2416
                err = -EOPNOTSUPP;
2098
2417
                if (uname)
2099
2418
                        free(uname);
2100
2419
                goto err_out;
2101
2420
        }
2102
 
        err = ntfs_attr_lookup(AT_INDEX_ROOT, uname, name_len, ic, 0, NULL, 0,
 
2421
        err = mkntfs_attr_lookup(AT_INDEX_ROOT, uname, name_len, ic, 0, NULL, 0,
2103
2422
                        ctx);
2104
2423
        if (uname)
2105
2424
                free(uname);
2120
2439
        memset(bmp, 0, sizeof(bmp));
2121
2440
        ntfs_bit_set(bmp, 0ULL, 1);
2122
2441
        /* Bitmap has to be at least 8 bytes in size. */
2123
 
        err = add_attr_bitmap(m, name, name_len, ic, (char*)&bmp, sizeof(bmp));
 
2442
        err = add_attr_bitmap(m, name, name_len, ic, bmp, sizeof(bmp));
2124
2443
        if (err)
2125
2444
                goto err_out;
2126
2445
        ia_val = calloc(1, index_block_size);
2131
2450
        /* Setup header. */
2132
2451
        ia_val->magic = magic_INDX;
2133
2452
        ia_val->usa_ofs = cpu_to_le16(sizeof(INDEX_ALLOCATION));
2134
 
        if (index_block_size >= NTFS_SECTOR_SIZE)
 
2453
        if (index_block_size >= NTFS_BLOCK_SIZE)
2135
2454
                ia_val->usa_count = cpu_to_le16(index_block_size /
2136
 
                                NTFS_SECTOR_SIZE + 1);
 
2455
                                NTFS_BLOCK_SIZE + 1);
2137
2456
        else {
2138
2457
                ia_val->usa_count = cpu_to_le16(1);
2139
2458
                Qprintf("Sector size is bigger than index block size. Setting "
2197
2516
                                "upgrade_to_large_index.\n");
2198
2517
                goto err_out;
2199
2518
        }
2200
 
        err = add_attr_index_alloc(m, name, name_len, ic, (char*)ia_val,
 
2519
        err = add_attr_index_alloc(m, name, name_len, ic, (u8*)ia_val,
2201
2520
                        index_block_size);
2202
2521
        ntfs_mst_post_write_fixup((NTFS_RECORD*)ia_val);
2203
2522
        if (err) {
2297
2616
        while ((char*)ie < index_end && !(ie->flags & INDEX_ENTRY_END)) {
2298
2617
/*
2299
2618
#ifdef DEBUG
2300
 
                Dprintf("file_name_attr1->file_name_length = %i\n",
 
2619
                mkDprintf("file_name_attr1->file_name_length = %i\n",
2301
2620
                                file_name->file_name_length);
2302
2621
                if (file_name->file_name_length) {
2303
2622
                        char *__buf;
2309
2628
                        i = ucstos(__buf, (ntfschar*)&file_name->file_name,
2310
2629
                                        file_name->file_name_length + 1);
2311
2630
                        if (i == -1)
2312
 
                                Dprintf("Name contains non-displayable "
 
2631
                                mkDprintf("Name contains non-displayable "
2313
2632
                                                "Unicode characters.\n");
2314
 
                        Dprintf("file_name_attr1->file_name = %s\n", __buf);
 
2633
                        mkDprintf("file_name_attr1->file_name = %s\n", __buf);
2315
2634
                        free(__buf);
2316
2635
                }
2317
 
                Dprintf("file_name_attr2->file_name_length = %i\n",
 
2636
                mkDprintf("file_name_attr2->file_name_length = %i\n",
2318
2637
                                ie->key.file_name.file_name_length);
2319
2638
                if (ie->key.file_name.file_name_length) {
2320
2639
                        char *__buf;
2326
2645
                        i = ucstos(__buf, ie->key.file_name.file_name,
2327
2646
                                        ie->key.file_name.file_name_length + 1);
2328
2647
                        if (i == -1)
2329
 
                                Dprintf("Name contains non-displayable "
 
2648
                                mkDprintf("Name contains non-displayable "
2330
2649
                                                "Unicode characters.\n");
2331
 
                        Dprintf("file_name_attr2->file_name = %s\n", __buf);
 
2650
                        mkDprintf("file_name_attr2->file_name = %s\n", __buf);
2332
2651
                        free(__buf);
2333
2652
                }
2334
2653
#endif
2369
2688
#ifdef DEBUG
2370
2689
                /* Next entry. */
2371
2690
                if (!ie->length) {
2372
 
                        Dprintf("BUG: ie->length is zero, breaking out of "
 
2691
                        mkDprintf("BUG: ie->length is zero, breaking out of "
2373
2692
                                        "loop.\n");
2374
2693
                        break;
2375
2694
                }
2424
2743
        fn->parent_directory = ref_parent;
2425
2744
        // FIXME: Is this correct? Or do we have to copy the creation_time
2426
2745
        // from the std info?
2427
 
        fn->creation_time = utc2ntfs(time(NULL));
 
2746
        fn->creation_time = utc2ntfs(mkntfs_time());
2428
2747
        fn->last_data_change_time = fn->creation_time;
2429
2748
        fn->last_mft_change_time = fn->creation_time;
2430
2749
        fn->last_access_time = fn->creation_time;
2464
2783
        m_file->link_count = cpu_to_le16(i + 1);
2465
2784
        /* Add the file_name to @m_file. */
2466
2785
        i = insert_resident_attr_in_mft_record(m_file, AT_FILE_NAME, NULL, 0, 0,
2467
 
                        0, RESIDENT_ATTR_IS_INDEXED, (char*)fn, fn_size);
 
2786
                        0, RESIDENT_ATTR_IS_INDEXED, (u8*)fn, fn_size);
2468
2787
        if (i < 0) {
2469
2788
                Eprintf("create_hardlink failed adding file name attribute: "
2470
2789
                                "%s\n", strerror(-i));
2502
2821
        opts.index_block_size = 4096;
2503
2822
        opts.attr_defs = (ATTR_DEF*)&attrdef_ntfs12_array;
2504
2823
        opts.attr_defs_len = sizeof(attrdef_ntfs12_array);
2505
 
        //Dprintf("Attr_defs table length = %u\n", opts.attr_defs_len);
 
2824
        //mkDprintf("Attr_defs table length = %u\n", opts.attr_defs_len);
2506
2825
}
2507
2826
 
2508
2827
/**
2644
2963
 */
2645
2964
static void mkntfs_override_phys_params(void)
2646
2965
{
 
2966
        int i;
 
2967
 
2647
2968
        /* If user didn't specify the sector size, determine it now. */
2648
2969
        if (!opts.sector_size) {
2649
2970
#ifdef BLKSSZGET
2668
2989
                err_exit("sector_size is invalid. It must be a power "
2669
2990
                         "of two, and it must be\n greater or equal 256 and "
2670
2991
                         "less than or equal 4096 bytes.\n");
2671
 
        Dprintf("sector size = %i bytes\n", opts.sector_size);
 
2992
        mkDprintf("sector size = %i bytes\n", opts.sector_size);
2672
2993
        /* If user didn't specify the number of sectors, determine it now. */
2673
2994
        if (!opts.nr_sectors) {
2674
2995
                opts.nr_sectors = ntfs_device_size_get(vol->dev,
2678
2999
                                        "specify it manually.\n",
2679
3000
                                        vol->dev->d_name);
2680
3001
        }
2681
 
        Dprintf("number of sectors = %lld (0x%llx)\n", opts.nr_sectors,
 
3002
        mkDprintf("number of sectors = %lld (0x%llx)\n", opts.nr_sectors,
2682
3003
                        opts.nr_sectors);
2683
 
        /* Reserve the last sector for the backup boot sector. */
2684
 
        opts.nr_sectors--;
 
3004
        /*
 
3005
         * Reserve the last sector for the backup boot sector unless the
 
3006
         * sector size is less than 512 bytes in which case reserve 512 bytes
 
3007
         * worth of secstors.
 
3008
         */
 
3009
        i = 1;
 
3010
        if (opts.sector_size < 512)
 
3011
                i = 512 / opts.sector_size;
 
3012
        opts.nr_sectors -= i;
2685
3013
        /* If user didn't specify the partition start sector, determine it. */
2686
3014
        if (opts.part_start_sect < 0) {
2687
3015
                opts.part_start_sect = ntfs_device_partition_start_sector_get(
2763
3091
        if (opts.volume_size < 1 << 20 /* 1MiB */)
2764
3092
                err_exit("Device is too small (%llikiB). Minimum NTFS volume "
2765
3093
                         "size is 1MiB.\n", opts.volume_size / 1024);
2766
 
        Dprintf("volume size = %llikiB\n", opts.volume_size / 1024);
 
3094
        mkDprintf("volume size = %llikiB\n", opts.volume_size / 1024);
2767
3095
        /* If user didn't specify the cluster size, determine it now. */
2768
3096
        if (!vol->cluster_size) {
2769
3097
                if (opts.volume_size <= 512LL << 20)    /* <= 512MB */
2801
3129
                         "to fit inside eight bits. (We do not support larger "
2802
3130
                         "cluster sizes yet.)\n");
2803
3131
        vol->cluster_size_bits = ffs(vol->cluster_size) - 1;
2804
 
        Dprintf("cluster size = %u bytes\n", (unsigned int)vol->cluster_size);
 
3132
        mkDprintf("cluster size = %u bytes\n", (unsigned int)vol->cluster_size);
2805
3133
        if (vol->cluster_size > 4096) {
2806
3134
                if (opts.enable_compression) {
2807
3135
                        if (!opts.force)
2833
3161
            opts.volume_size / vol->cluster_size != opts.nr_clusters)
2834
3162
                err_exit("Illegal combination of volume/cluster/sector size "
2835
3163
                         "and/or cluster/sector number.\n");
2836
 
        Dprintf("number of clusters = %llu (0x%llx)\n", opts.nr_clusters,
 
3164
        mkDprintf("number of clusters = %llu (0x%llx)\n", opts.nr_clusters,
2837
3165
                        opts.nr_clusters);
2838
3166
        /* Number of clusters must fit within 32 bits (Win2k limitation). */
2839
3167
        if (opts.nr_clusters >> 32) {
2856
3184
static void mkntfs_initialize_bitmaps(void)
2857
3185
{
2858
3186
        int i, j;
2859
 
        
 
3187
 
2860
3188
        /* Determine lcn bitmap byte size and allocate it. */
2861
3189
        lcn_bitmap_byte_size = (opts.nr_clusters + 7) >> 3;
2862
3190
        /* Needs to be multiple of 8 bytes. */
2863
3191
        lcn_bitmap_byte_size = (lcn_bitmap_byte_size + 7) & ~7;
2864
3192
        i = (lcn_bitmap_byte_size + vol->cluster_size - 1) &
2865
3193
                        ~(vol->cluster_size - 1);
2866
 
        Dprintf("lcn_bitmap_byte_size = %i, allocated = %i\n",
 
3194
        mkDprintf("lcn_bitmap_byte_size = %i, allocated = %i\n",
2867
3195
                        lcn_bitmap_byte_size, i);
2868
3196
        lcn_bitmap = (unsigned char *)calloc(1, lcn_bitmap_byte_size);
2869
3197
        if (!lcn_bitmap)
2881
3209
         */
2882
3210
        opts.mft_size = (16 * vol->mft_record_size + vol->cluster_size - 1)
2883
3211
                        & ~(vol->cluster_size - 1);
2884
 
        Dprintf("MFT size = %i (0x%x) bytes\n", opts.mft_size, opts.mft_size);
 
3212
        mkDprintf("MFT size = %i (0x%x) bytes\n", opts.mft_size, opts.mft_size);
2885
3213
        /* Determine mft bitmap size and allocate it. */
2886
3214
        mft_bitmap_size = opts.mft_size / vol->mft_record_size;
2887
3215
        /* Convert to bytes, at least one. */
2888
3216
        mft_bitmap_byte_size = (mft_bitmap_size + 7) >> 3;
2889
3217
        /* Mft bitmap is allocated in multiples of 8 bytes. */
2890
3218
        mft_bitmap_byte_size = (mft_bitmap_byte_size + 7) & ~7;
2891
 
        Dprintf("mft_bitmap_size = %i, mft_bitmap_byte_size = %i\n",
 
3219
        mkDprintf("mft_bitmap_size = %i, mft_bitmap_byte_size = %i\n",
2892
3220
                        mft_bitmap_size, mft_bitmap_byte_size);
2893
3221
        mft_bitmap = (unsigned char *)calloc(1, mft_bitmap_byte_size);
2894
3222
        if (!mft_bitmap)
2922
3250
static void mkntfs_initialize_rl_mft(void)
2923
3251
{
2924
3252
        int i, j;
2925
 
        
 
3253
 
2926
3254
        /* If user didn't specify the mft lcn, determine it now. */
2927
3255
        if (!opts.mft_lcn) {
2928
3256
                /*
2934
3262
                        opts.mft_lcn = (16 * 1024 + vol->cluster_size - 1) /
2935
3263
                                        vol->cluster_size;
2936
3264
        }
2937
 
        Dprintf("$MFT logical cluster number = 0x%llx\n", opts.mft_lcn);
 
3265
        mkDprintf("$MFT logical cluster number = 0x%llx\n", opts.mft_lcn);
2938
3266
        /* Determine MFT zone size. */
2939
3267
        opts.mft_zone_end = opts.nr_clusters;
2940
3268
        switch (opts.mft_zone_multiplier) {  /* % of volume size in clusters */
2952
3280
                opts.mft_zone_end = opts.mft_zone_end >> 3;     /* 12.5% */
2953
3281
                break;
2954
3282
        }
2955
 
        Dprintf("MFT zone size = %lldkiB\n", opts.mft_zone_end / 1024);
 
3283
        mkDprintf("MFT zone size = %lldkiB\n", opts.mft_zone_end / 1024);
2956
3284
        /*
2957
3285
         * The mft zone begins with the mft data attribute, not at the beginning
2958
3286
         * of the device.
2975
3303
                ntfs_bit_set(lcn_bitmap, opts.mft_lcn + i, 1);
2976
3304
        /* Determine mftmirr_lcn (middle of volume). */
2977
3305
        opts.mftmirr_lcn = (opts.nr_sectors * opts.sector_size >> 1)
2978
 
                                                        / vol->cluster_size;
2979
 
        Dprintf("$MFTMirr logical cluster number = 0x%llx\n", opts.mftmirr_lcn);
 
3306
                        / vol->cluster_size;
 
3307
        mkDprintf("$MFTMirr logical cluster number = 0x%llx\n",
 
3308
                        opts.mftmirr_lcn);
2980
3309
        /* Create runlist for mft mirror. */
2981
3310
        rl_mftmirr = (runlist *)malloc(2 * sizeof(runlist));
2982
3311
        if (!rl_mftmirr)
2988
3317
         * The mft mirror is either 4kb (the first four records) or one cluster
2989
3318
         * in size, which ever is bigger. In either case, it contains a
2990
3319
         * byte-for-byte identical copy of the beginning of the mft (i.e. either
2991
 
         * ther first four records (4kb) or the first cluster worth of records,
 
3320
         * the first four records (4kb) or the first cluster worth of records,
2992
3321
         * whichever is bigger).
2993
3322
         */
2994
3323
        j = (4 * vol->mft_record_size + vol->cluster_size - 1) / vol->cluster_size;
2999
3328
        for (i = 0; i < j; i++)
3000
3329
                ntfs_bit_set(lcn_bitmap, opts.mftmirr_lcn + i, 1);
3001
3330
        opts.logfile_lcn = opts.mftmirr_lcn + j;
3002
 
        Dprintf("$LogFile logical cluster number = 0x%llx\n", opts.logfile_lcn);
 
3331
        mkDprintf("$LogFile logical cluster number = 0x%llx\n",
 
3332
                        opts.logfile_lcn);
3003
3333
}
3004
3334
 
3005
3335
/**
3045
3375
        }
3046
3376
        opts.logfile_size = (opts.logfile_size + vol->cluster_size - 1) &
3047
3377
                        ~(vol->cluster_size - 1);
3048
 
        Dprintf("$LogFile (journal) size = %ikiB\n", opts.logfile_size / 1024);
 
3378
        mkDprintf("$LogFile (journal) size = %ikiB\n",
 
3379
                        opts.logfile_size / 1024);
3049
3380
        /*
3050
3381
         * FIXME: The 256kiB limit is arbitrary. Should find out what the real
3051
3382
         * minimum requirement for Windows is so it doesn't blue screen.
3128
3459
         */
3129
3460
        int i;
3130
3461
        ssize_t bw;
3131
 
        unsigned long position;
3132
 
        unsigned long mid_clust;
 
3462
        unsigned long long position, mid_clust;
3133
3463
        float progress_inc = (float)opts.nr_clusters / 100;
3134
3464
 
3135
3465
        Qprintf("Initialising device with zeroes:   0%%");
3136
3466
        fflush(stdout);
3137
3467
        mid_clust = (opts.volume_size >> 1) / vol->cluster_size;
3138
 
        for (position = 0; position < opts.nr_clusters; position++) {
 
3468
        for (position = 0; position < (unsigned long long)opts.nr_clusters;
 
3469
                        position++) {
3139
3470
                if (!(position % (int)(progress_inc+1))) {
3140
3471
                        Qprintf("\b\b\b\b%3.0f%%", position /
3141
3472
                                        progress_inc);
3158
3489
                                        "file $Boot.\n");
3159
3490
                        /* Add the baddie to our bad blocks list. */
3160
3491
                        append_to_bad_blocks(position);
3161
 
                        Qprintf("\nFound bad cluster (%ld). Adding to "
 
3492
                        Qprintf("\nFound bad cluster (%lld). Adding to "
3162
3493
                                "list of bad blocks.\nInitialising "
3163
3494
                                "device with zeroes: %3.0f%%", position,
3164
3495
                                position / progress_inc);
3176
3507
                if (bw != opts.sector_size) {
3177
3508
                        if (bw != -1 || errno != EIO)
3178
3509
                                err_exit("This should not happen.\n");
3179
 
                        else if (i + 1UL == position &&
 
3510
                        else if (i + 1ull == position &&
3180
3511
                                        (vol->major_ver >= 2 ||
3181
3512
                                         (vol->major_ver == 1 &&
3182
3513
                                          vol->minor_ver >= 2)))
3192
3523
}
3193
3524
 
3194
3525
/**
 
3526
 * create_file_volume -
 
3527
 */
 
3528
static void create_file_volume(MFT_RECORD *m, MFT_REF root_ref, VOLUME_FLAGS fl)
 
3529
{
 
3530
        int i, err;
 
3531
        u8 *sd;
 
3532
 
 
3533
        Vprintf("Creating $Volume (mft record 3)\n");
 
3534
        m = (MFT_RECORD*)(buf + 3 * vol->mft_record_size);
 
3535
        err = create_hardlink(index_block, root_ref, m,
 
3536
                        MK_LE_MREF(FILE_Volume, FILE_Volume), 0LL, 0LL,
 
3537
                        FILE_ATTR_HIDDEN | FILE_ATTR_SYSTEM, 0, 0,
 
3538
                        "$Volume", FILE_NAME_WIN32_AND_DOS);
 
3539
        if (!err) {
 
3540
                init_system_file_sd(FILE_Volume, &sd, &i);
 
3541
                err = add_attr_sd(m, sd, i);
 
3542
        }
 
3543
        if (!err)
 
3544
                err = add_attr_data(m, NULL, 0, 0, 0, NULL, 0);
 
3545
        if (!err)
 
3546
                err = add_attr_vol_name(m, vol->vol_name, vol->vol_name ?
 
3547
                                strlen(vol->vol_name) : 0);
 
3548
        if (!err) {
 
3549
                if (fl & VOLUME_IS_DIRTY)
 
3550
                        Qprintf("Setting the volume dirty so check disk runs "
 
3551
                                        "on next reboot into Windows.\n");
 
3552
                err = add_attr_vol_info(m, fl, vol->major_ver, vol->minor_ver);
 
3553
        }
 
3554
        if (err < 0)
 
3555
                err_exit("Couldn't create $Volume: %s\n", strerror(-err));
 
3556
}
 
3557
 
 
3558
/**
 
3559
 * create_backup_boot_sector
 
3560
 *
 
3561
 * Return 0 on success or -1 if it couldn't be created.
 
3562
 */
 
3563
static int create_backup_boot_sector(u8 *buff)
 
3564
{
 
3565
        const char *_s;
 
3566
        ssize_t bw;
 
3567
        int size, _e;
 
3568
 
 
3569
        Vprintf("Creating backup boot sector.\n");
 
3570
        /*
 
3571
         * Write the first max(512, opts.sector_size) bytes from buf to the
 
3572
         * last sector, but limit that to 8192 bytes of written data since that
 
3573
         * is how big $Boot is (and how big our buffer is)..
 
3574
         */
 
3575
        size = 512;
 
3576
        if (size < opts.sector_size)
 
3577
                size = opts.sector_size;
 
3578
        if (vol->dev->d_ops->seek(vol->dev, (opts.nr_sectors + 1) *
 
3579
                        opts.sector_size - size, SEEK_SET) == (off_t)-1)
 
3580
                goto bb_err;
 
3581
        if (size > 8192)
 
3582
                size = 8192;
 
3583
        bw = mkntfs_write(vol->dev, buff, size);
 
3584
        if (bw == size)
 
3585
                return 0;
 
3586
        _e = errno;
 
3587
        if (bw == -1LL)
 
3588
                _s = strerror(_e);
 
3589
        else
 
3590
                _s = "unknown error";
 
3591
        if (bw != -1LL || (bw == -1LL && _e != ENOSPC)) {
 
3592
                err_exit("Couldn't write backup boot sector: %s\n", _s);
 
3593
bb_err:
 
3594
                Eprintf("Seek failed: %s\n", strerror(errno));
 
3595
        }
 
3596
        Eprintf("Couldn't write backup boot sector. This is due to a "
 
3597
                        "limitation in the\nLinux kernel. This is not "
 
3598
                        "a major problem as Windows check disk will "
 
3599
                        "create the\nbackup boot sector when it "
 
3600
                        "is run on your next boot into Windows.\n");
 
3601
        return -1;
 
3602
}
 
3603
 
 
3604
/**
3195
3605
 * mkntfs_create_root_structures -
3196
3606
 *
3197
3607
 * Note: Might not return.
3202
3612
        ATTR_RECORD *a;
3203
3613
        MFT_RECORD *m;
3204
3614
        MFT_REF root_ref;
3205
 
        ssize_t bw;
3206
3615
        int i, j, err;
3207
 
        char *sd;
 
3616
        u8 *sd;
 
3617
        VOLUME_FLAGS volume_flags = 0;
3208
3618
 
3209
3619
        Qprintf("Creating NTFS volume structures.\n");
3210
3620
        /*
3285
3695
                        err_exit("Failed to allocate attribute search "
3286
3696
                                        "context: %s\n", strerror(errno));
3287
3697
                /* There is exactly one file name so this is ok. */
3288
 
                if (ntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0, 0, 0, NULL, 0,
 
3698
                if (mkntfs_attr_lookup(AT_FILE_NAME, AT_UNNAMED, 0, 0, 0, NULL, 0,
3289
3699
                                ctx)) {
3290
3700
                        ntfs_attr_put_search_ctx(ctx);
3291
3701
                        err_exit("BUG: $FILE_NAME attribute not found.\n");
3365
3775
        if (err < 0)
3366
3776
                err_exit("Couldn't create $LogFile: %s\n", strerror(-err));
3367
3777
        //dump_mft_record(m);
3368
 
        Vprintf("Creating $Volume (mft record 3)\n");
3369
 
        m = (MFT_RECORD*)(buf + 3 * vol->mft_record_size);
3370
 
        err = create_hardlink(index_block, root_ref, m,
3371
 
                        MK_LE_MREF(FILE_Volume, FILE_Volume), 0LL, 0LL,
3372
 
                        FILE_ATTR_HIDDEN | FILE_ATTR_SYSTEM, 0, 0,
3373
 
                        "$Volume", FILE_NAME_WIN32_AND_DOS);
3374
 
        if (!err) {
3375
 
                init_system_file_sd(FILE_Volume, &sd, &i);
3376
 
                err = add_attr_sd(m, sd, i);
3377
 
        }
3378
 
        if (!err)
3379
 
                err = add_attr_data(m, NULL, 0, 0, 0, NULL, 0);
3380
 
        if (!err)
3381
 
                err = add_attr_vol_name(m, vol->vol_name, vol->vol_name ?
3382
 
                                strlen(vol->vol_name) : 0);
3383
 
        if (!err) {
3384
 
                Qprintf("Setting the volume dirty so check disk runs on next "
3385
 
                                "reboot into Windows.\n");
3386
 
                err = add_attr_vol_info(m, VOLUME_IS_DIRTY, vol->major_ver,
3387
 
                                vol->minor_ver);
3388
 
        }
3389
 
        if (err < 0)
3390
 
                err_exit("Couldn't create $Volume: %s\n", strerror(-err));
3391
 
        //dump_mft_record(m);
 
3778
 
3392
3779
        Vprintf("Creating $AttrDef (mft record 4)\n");
3393
3780
        m = (MFT_RECORD*)(buf + 4 * vol->mft_record_size);
3394
3781
        if (vol->major_ver < 3)
3395
3782
                buf2_size = 36000;
3396
3783
        else
3397
3784
                buf2_size = opts.attr_defs_len;
3398
 
        buf2 = (char*)calloc(1, buf2_size);
 
3785
        buf2 = calloc(1, buf2_size);
3399
3786
        if (!buf2)
3400
3787
                err_exit("Failed to allocate internal buffer: %s\n",
3401
3788
                                strerror(errno));
3453
3840
                        opts.sector_size);
3454
3841
        bs->bpb.media_type = 0xf8; /* hard disk */
3455
3842
        bs->bpb.sectors_per_track = cpu_to_le16(opts.sectors_per_track);
3456
 
        Dprintf("sectors per track = %u (0x%x)\n", opts.sectors_per_track,
 
3843
        mkDprintf("sectors per track = %u (0x%x)\n", opts.sectors_per_track,
3457
3844
                        opts.sectors_per_track);
3458
3845
        bs->bpb.heads = cpu_to_le16(opts.heads);
3459
 
        Dprintf("heads = %u (0x%x)\n", opts.heads, opts.heads);
 
3846
        mkDprintf("heads = %u (0x%x)\n", opts.heads, opts.heads);
3460
3847
        bs->bpb.hidden_sectors = cpu_to_le32(opts.part_start_sect);
3461
 
        Dprintf("hidden sectors = %llu (0x%llx)\n", opts.part_start_sect,
 
3848
        mkDprintf("hidden sectors = %llu (0x%llx)\n", opts.part_start_sect,
3462
3849
                        opts.part_start_sect);
3463
3850
        /*
3464
3851
         * If there are problems go back to bs->unused[0-3] and set them. See
3465
3852
         * ../include/layout.h for details.
3466
3853
         */
3467
 
        bs->number_of_sectors = scpu_to_le64(opts.nr_sectors);
3468
 
        bs->mft_lcn = scpu_to_le64(opts.mft_lcn);
3469
 
        bs->mftmirr_lcn = scpu_to_le64(opts.mftmirr_lcn);
 
3854
        bs->number_of_sectors = cpu_to_sle64(opts.nr_sectors);
 
3855
        bs->mft_lcn = cpu_to_sle64(opts.mft_lcn);
 
3856
        bs->mftmirr_lcn = cpu_to_sle64(opts.mftmirr_lcn);
3470
3857
        if (vol->mft_record_size >= vol->cluster_size)
3471
3858
                bs->clusters_per_mft_record = vol->mft_record_size /
3472
3859
                        vol->cluster_size;
3478
3865
                                        "is wrong (= 0x%x)\n",
3479
3866
                                        bs->clusters_per_mft_record);
3480
3867
        }
3481
 
        Dprintf("clusters per mft record = %i (0x%x)\n",
 
3868
        mkDprintf("clusters per mft record = %i (0x%x)\n",
3482
3869
                        bs->clusters_per_mft_record,
3483
3870
                        bs->clusters_per_mft_record);
3484
3871
        if (opts.index_block_size >= (int)vol->cluster_size)
3492
3879
                                        "is wrong (= 0x%x)\n",
3493
3880
                                        bs->clusters_per_index_record);
3494
3881
        }
3495
 
        Dprintf("clusters per index block = %i (0x%x)\n",
 
3882
        mkDprintf("clusters per index block = %i (0x%x)\n",
3496
3883
                        bs->clusters_per_index_record,
3497
3884
                        bs->clusters_per_index_record);
3498
3885
        /* Generate a 64-bit random number for the serial number. */
3499
 
        bs->volume_serial_number = scpu_to_le64(((s64)random() << 32) |
 
3886
        bs->volume_serial_number = cpu_to_sle64(((s64)random() << 32) |
3500
3887
                        ((s64)random() & 0xffffffff));
3501
3888
        /*
3502
3889
         * Leave zero for now as NT4 leaves it zero, too. If want it later, see
3520
3907
        }
3521
3908
        if (err < 0)
3522
3909
                err_exit("Couldn't create $Boot: %s\n", strerror(-err));
3523
 
        Vprintf("Creating backup boot sector.\n");
3524
 
        /*
3525
 
         * Write the first max(512, opts.sector_size) bytes from buf2 to the
3526
 
         * last sector.
3527
 
         */
3528
 
        if (vol->dev->d_ops->seek(vol->dev, (opts.nr_sectors + 1) *
3529
 
                        opts.sector_size - i, SEEK_SET) == (off_t)-1)
3530
 
                goto bb_err;
3531
 
        bw = mkntfs_write(vol->dev, buf2, i);
 
3910
 
 
3911
        if (create_backup_boot_sector(buf2)) {
 
3912
                /*
 
3913
                 *   Pre-2.6 kernels couldn't  access  the  last  sector
 
3914
                 *   if it was odd hence we schedule chkdsk to create it.
 
3915
                 */
 
3916
                volume_flags |= VOLUME_IS_DIRTY;
 
3917
        }
 
3918
 
3532
3919
        free(buf2);
3533
3920
        buf2 = NULL;
3534
 
        if (bw != i) {
3535
 
                int _e = errno;
3536
 
                const char *_s;
3537
 
 
3538
 
                if (bw == -1LL)
3539
 
                        _s = strerror(_e);
3540
 
                else
3541
 
                        _s = "unknown error";
3542
 
                if (bw != -1LL || (bw == -1LL && _e != ENOSPC)) {
3543
 
                        err_exit("Couldn't write backup boot sector: %s\n", _s);
3544
 
bb_err:
3545
 
                        Eprintf("Seek failed: %s\n", strerror(errno));
3546
 
                }
3547
 
                Eprintf("Couldn't write backup boot sector. This is due to a "
3548
 
                                "limitation in the\nLinux kernel. This is not "
3549
 
                                "a major problem as Windows check disk will "
3550
 
                                "create the\nbackup boot sector when it "
3551
 
                                "is run on your next boot into Windows.\n");
3552
 
        }
3553
 
        //dump_mft_record(m);
 
3921
 
 
3922
        create_file_volume(m, root_ref, volume_flags);
 
3923
 
3554
3924
        Vprintf("Creating $BadClus (mft record 8)\n");
3555
3925
        m = (MFT_RECORD*)(buf + 8 * vol->mft_record_size);
3556
3926
        // FIXME: This should be IGNORE_CASE
3590
3960
        //dump_mft_record(m);
3591
3961
        Vprintf("Creating $UpCase (mft record 0xa)\n");
3592
3962
        m = (MFT_RECORD*)(buf + 0xa * vol->mft_record_size);
3593
 
        err = add_attr_data(m, NULL, 0, 0, 0, (char*)vol->upcase,
 
3963
        err = add_attr_data(m, NULL, 0, 0, 0, (u8*)vol->upcase,
3594
3964
                        vol->upcase_len << 1);
3595
3965
        if (!err)
3596
3966
                err = create_hardlink(index_block, root_ref, m,
3636
4006
        /* Setup the correct locale for string output and conversion. */
3637
4007
        utils_set_locale();
3638
4008
        /* Initialize the random number generator with the current time. */
3639
 
        srandom(time(NULL));
 
4009
        srandom(mkntfs_time());
3640
4010
        /* Allocate and initialize ntfs_volume structure vol. */
3641
4011
        vol = ntfs_volume_alloc();
3642
4012
        if (!vol)
3671
4041
        mkntfs_initialize_bitmaps();
3672
4042
        /* Initialize MFT & set opts.logfile_lcn. */
3673
4043
        mkntfs_initialize_rl_mft();
3674
 
        /* Initlialize $LogFile. */
 
4044
        /* Initialise $LogFile. */
3675
4045
        mkntfs_initialize_rl_logfile();
3676
4046
        /* Initialize $Boot. */
3677
4047
        mkntfs_initialize_rl_boot();
3706
4076
                err_exit("Failed to allocate attribute search context: %s\n",
3707
4077
                                strerror(errno));
3708
4078
        // FIXME: This should be IGNORE_CASE!
3709
 
        if (ntfs_attr_lookup(AT_INDEX_ALLOCATION, I30, 4, 0, 0,
 
4079
        if (mkntfs_attr_lookup(AT_INDEX_ALLOCATION, I30, 4, 0, 0,
3710
4080
                        NULL, 0, ctx)) {
3711
4081
                ntfs_attr_put_search_ctx(ctx);
3712
4082
                err_exit("BUG: $INDEX_ALLOCATION attribute not found.\n");
3729
4099
        if (err)
3730
4100
                err_exit("ntfs_mst_pre_write_fixup() failed while syncing "
3731
4101
                                "root directory index block.\n");
3732
 
        lw = ntfs_rlwrite(vol->dev, rl_index, (char*)index_block, i, NULL);
 
4102
        lw = ntfs_rlwrite(vol->dev, rl_index, (u8*)index_block, i, NULL);
3733
4103
        if (lw != i)
3734
4104
                err_exit("Error writing $INDEX_ALLOCATION.\n");
3735
4105
        /* No more changes to @index_block below here so no need for fixup: */
3740
4110
        if (!ctx)
3741
4111
                err_exit("Failed to allocate attribute search context: %s\n",
3742
4112
                                strerror(errno));
3743
 
        if (ntfs_attr_lookup(AT_DATA, AT_UNNAMED, 0, 0, 0, NULL, 0, ctx)) {
 
4113
        if (mkntfs_attr_lookup(AT_DATA, AT_UNNAMED, 0, 0, 0, NULL, 0, ctx)) {
3744
4114
                ntfs_attr_put_search_ctx(ctx);
3745
4115
                err_exit("BUG: $DATA attribute not found.\n");
3746
4116
        }