]> git.saurik.com Git - apple/hfs.git/blame - hfs_util/hfsutil_jnl.c
hfs-195.tar.gz
[apple/hfs.git] / hfs_util / hfsutil_jnl.c
CommitLineData
08cdaae8 1/*
04a16b11 2 * Copyright (c) 1999-2009 Apple Inc. All rights reserved.
08cdaae8
A
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
635a1ee0
A
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.2 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
08cdaae8 11 *
635a1ee0
A
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
08cdaae8
A
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
635a1ee0
A
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
08cdaae8
A
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22/*
23 Copyright (c) 2002 Apple Computer, Inc.
24 All Rights Reserved.
25
26 This file contains the routine to make an HFS+ volume journaled
27 and a corresponding routine to turn it off.
28
29 */
30
31#include <sys/types.h>
32#include <sys/attr.h>
33#include <sys/stat.h>
34#include <sys/time.h>
35#include <sys/sysctl.h>
36#include <sys/resource.h>
37#include <sys/vmmeter.h>
38#include <sys/mount.h>
39#include <sys/wait.h>
16f263f5 40#include <sys/ioctl.h>
08cdaae8 41
19348fcb 42#include <sys/disk.h>
08cdaae8
A
43#include <sys/loadable_fs.h>
44#include <hfs/hfs_format.h>
19348fcb 45#include <hfs/hfs_mount.h> /* for hfs sysctl values */
08cdaae8 46
ab40a2da
A
47#include <System/hfs/hfs_fsctl.h>
48
08cdaae8
A
49#include <errno.h>
50#include <fcntl.h>
51#include <libgen.h>
52#include <pwd.h>
53#include <stdio.h>
54#include <stdlib.h>
55#include <string.h>
56#include <unistd.h>
57
58#include <architecture/byte_order.h>
59
19348fcb
A
60// just in case these aren't in <hfs/hfs_mount.h> yet
61#ifndef HFS_ENABLE_JOURNALING
62#define HFS_ENABLE_JOURNALING 0x082969
63#endif
64#ifndef HFS_DISABLE_JOURNALING
65#define HFS_DISABLE_JOURNALING 0x031272
66#endif
67#ifndef HFS_GET_JOURNAL_INFO
68#define HFS_GET_JOURNAL_INFO 0x6a6e6c69
69#endif
08cdaae8
A
70
71/* getattrlist buffers start with an extra length field */
72struct ExtentsAttrBuf {
73 unsigned long infoLength;
74 HFSPlusExtentRecord extents;
75};
76typedef struct ExtentsAttrBuf ExtentsAttrBuf;
77
ab40a2da
A
78#ifndef HFSIOC_GET_JOURNAL_INFO
79# include <sys/ioctl.h>
80struct hfs_journal_info {
81 off_t jstart;
82 off_t jsize;
83};
84# define HFSIOC_GET_JOURNAL_INFO _IOR('h', 17, struct hfs_journal_info)
85#endif
08cdaae8
A
86
87
88#define kIsInvisible 0x4000
89
90/*
91 * Generic Finder file/dir data
92 */
93struct FinderInfo {
94 u_int32_t opaque_1[2];
95 u_int16_t fdFlags; /* Finder flags */
96 int16_t opaque_2[11];
97};
98typedef struct FinderInfo FinderInfo;
99
100/* getattrlist buffers start with an extra length field */
101struct FinderAttrBuf {
102 unsigned long infoLength;
103 FinderInfo finderInfo;
104};
105typedef struct FinderAttrBuf FinderAttrBuf;
106
107
108int hide_file(const char * file)
109{
110 struct attrlist alist = {0};
111 FinderAttrBuf finderInfoBuf = {0};
112 int result;
113
114 alist.bitmapcount = ATTR_BIT_MAP_COUNT;
115 alist.commonattr = ATTR_CMN_FNDRINFO;
116
117 result = getattrlist(file, &alist, &finderInfoBuf, sizeof(finderInfoBuf), 0);
118 if (result) {
19348fcb
A
119 return (errno);
120 }
08cdaae8
A
121
122 if (finderInfoBuf.finderInfo.fdFlags & kIsInvisible) {
19348fcb
A
123 printf("hide: %s is alreadly invisible\n", file);
124 return (0);
08cdaae8
A
125 }
126
127 finderInfoBuf.finderInfo.fdFlags |= kIsInvisible;
128
129 result = setattrlist(file, &alist, &finderInfoBuf.finderInfo, sizeof(FinderInfo), 0);
130
131 return (result == -1 ? errno : result);
132}
133
16f263f5
A
134off_t
135get_start_block(const char *file, uint32_t fs_block_size)
08cdaae8 136{
16f263f5
A
137 off_t cur_pos, phys_start, len;
138 int fd, err;
139 struct log2phys l2p;
140 struct stat st;
08cdaae8 141
16f263f5
A
142 fd = open(file, O_RDONLY);
143 if (fd < 0) {
144 return -1;
145 }
08cdaae8 146
16f263f5
A
147 if (fstat(fd, &st) < 0) {
148 fprintf(stderr, "can't stat %s (%s)\n", file, strerror(errno));
149 close(fd);
19348fcb 150 return -1;
08cdaae8
A
151 }
152
16f263f5
A
153 fs_block_size = st.st_blksize; // XXXdbg quick hack for now
154
155 phys_start = len = 0;
156 for(cur_pos=0; cur_pos < st.st_size; cur_pos += fs_block_size) {
157 memset(&l2p, 0, sizeof(l2p));
158 lseek(fd, cur_pos, SEEK_SET);
159 err = fcntl(fd, F_LOG2PHYS, &l2p);
160
161 if (phys_start == 0) {
162 phys_start = l2p.l2p_devoffset;
163 len = fs_block_size;
164 } else if (l2p.l2p_devoffset != (phys_start + len)) {
165 // printf(" %lld : %lld - %lld\n", cur_pos, phys_start / fs_block_size, len / fs_block_size);
166 fprintf(stderr, "%s : is not contiguous!\n", file);
167 close(fd);
168 return -1;
169 // phys_start = l2p.l2p_devoffset;
170 // len = fs_block_size;
171 } else {
172 len += fs_block_size;
173 }
174 }
175
176 close(fd);
177
178 //printf("%s start offset %lld; byte len %lld (blksize %d)\n",
179 // file, phys_start, len, fs_block_size);
180
ab40a2da 181 if ((phys_start / (unsigned int)fs_block_size) & 0xffffffff00000000LL) {
16f263f5 182 fprintf(stderr, "%s : starting block is > 32bits!\n", file);
19348fcb 183 return -1;
08cdaae8 184 }
16f263f5
A
185
186 return phys_start;
187}
188
189
190//
191// Get the embedded offset (if any) for an hfs+ volume.
192// This is pretty skanky that we have to do this but
193// that's life...
194//
195#include <sys/disk.h>
196#include <hfs/hfs_format.h>
197
198#include <machine/endian.h>
199
200#define HFS_PRI_SECTOR(blksize) (1024 / (blksize))
201#define HFS_PRI_OFFSET(blksize) ((blksize) > 1024 ? 1024 : 0)
202
ab40a2da
A
203#include <libkern/OSByteOrder.h>
204
16f263f5
A
205#define SWAP_BE16(x) ntohs(x)
206#define SWAP_BE32(x) ntohl(x)
ab40a2da 207#define SWAP_BE64(x) OSSwapConstInt64(x)
16f263f5
A
208
209
210off_t
211get_embedded_offset(char *devname)
212{
213 int fd = -1;
214 off_t ret = 0;
215 char *buff = NULL, rawdev[256];
216 u_int64_t blkcnt;
217 u_int32_t blksize;
218 HFSMasterDirectoryBlock *mdbp;
219 off_t embeddedOffset;
220 struct statfs sfs;
221 struct stat st;
222
223 restart:
224 if (stat(devname, &st) != 0) {
225 fprintf(stderr, "Could not access %s (%s)\n", devname, strerror(errno));
226 ret = -1;
227 goto out;
228 }
229
230 if (S_ISCHR(st.st_mode) == 0) {
231 // hmmm, it's not the character special raw device so we
232 // should try to figure out the real device.
233 if (statfs(devname, &sfs) != 0) {
234 fprintf(stderr, "Can't find out any info about the fs for path %s (%s)\n",
235 devname, strerror(errno));
236 ret = -1;
237 goto out;
238 }
239
ab40a2da
A
240 // This assumes it begins with "/dev/". The old code assumed
241 // it began with five characters. Should probably use strrchr or equivalent.
242 snprintf(rawdev, sizeof(rawdev), "/dev/r%s", &sfs.f_mntfromname[5]);
16f263f5
A
243 devname = &rawdev[0];
244 goto restart;
245 }
08cdaae8 246
16f263f5
A
247 fd = open(devname, O_RDONLY);
248 if (fd < 0) {
249 fprintf(stderr, "can't open: %s (%s)\n", devname, strerror(errno));
250 ret = -1;
251 goto out;
252 }
253
254 /* Get the real physical block size. */
255 if (ioctl(fd, DKIOCGETBLOCKSIZE, (caddr_t)&blksize) != 0) {
256 fprintf(stderr, "can't get the device block size (%s). assuming 512\n", strerror(errno));
257 blksize = 512;
258 ret = -1;
259 goto out;
260 }
261
262 /* Get the number of physical blocks. */
263 if (ioctl(fd, DKIOCGETBLOCKCOUNT, (caddr_t)&blkcnt)) {
264 struct stat st;
265 fprintf(stderr, "failed to get block count. trying stat().\n");
266 if (fstat(fd, &st) != 0) {
267 ret = -1;
268 goto out;
269 }
270
271 blkcnt = st.st_size / blksize;
272 }
273
16f263f5
A
274 /*
275 * At this point:
276 * blksize has our prefered physical block size
277 * blkcnt has the total number of physical blocks
278 */
279
280 buff = (char *)malloc(blksize);
281
282 if (pread(fd, buff, blksize, HFS_PRI_SECTOR(blksize)*blksize) != blksize) {
04a16b11
A
283 fprintf(stderr, "failed to read volume header @ offset %d (%s)\n",
284 HFS_PRI_SECTOR(blksize), strerror(errno));
285 ret = -1;
286 goto out;
16f263f5
A
287 }
288
04a16b11
A
289 mdbp = (HFSMasterDirectoryBlock *)(buff + HFS_PRI_OFFSET(blksize));
290 if ( (SWAP_BE16(mdbp->drSigWord) != kHFSSigWord)
291 && (SWAP_BE16(mdbp->drSigWord) != kHFSPlusSigWord)
292 && (SWAP_BE16(mdbp->drSigWord) != kHFSXSigWord)) {
293 printf ("get_embedded_offset: invalid volume signature \n");
294 ret = -1;
295 goto out;
296 }
16f263f5
A
297
298 if ((SWAP_BE16(mdbp->drSigWord) == kHFSSigWord) && (SWAP_BE16(mdbp->drEmbedSigWord) != kHFSPlusSigWord)) {
299 ret = -1;
300 goto out;
301 } else if (SWAP_BE16(mdbp->drEmbedSigWord) == kHFSPlusSigWord) {
302 /* Get the embedded Volume Header */
303 embeddedOffset = SWAP_BE16(mdbp->drAlBlSt) * 512;
304 embeddedOffset += (u_int64_t)SWAP_BE16(mdbp->drEmbedExtent.startBlock) *
305 (u_int64_t)SWAP_BE32(mdbp->drAlBlkSiz);
306
307 /*
308 * If the embedded volume doesn't start on a block
309 * boundary, then switch the device to a 512-byte
310 * block size so everything will line up on a block
311 * boundary.
312 */
313 if ((embeddedOffset % blksize) != 0) {
314 fprintf(stderr, "HFS Mount: embedded volume offset not"
315 " a multiple of physical block size (%d);"
316 " switching to 512\n", blksize);
317
318 blkcnt *= (blksize / 512);
319 blksize = 512;
320 }
321
322 } else { /* pure HFS+ */
323 embeddedOffset = 0;
324 }
325
326 ret = embeddedOffset;
327
328 out:
329 if (buff) {
330 free(buff);
331 }
332 if (fd >= 0)
333 close(fd);
334
335 return ret;
08cdaae8
A
336}
337
16f263f5
A
338
339
08cdaae8
A
340static const char *journal_fname = ".journal";
341static const char *jib_fname = ".journal_info_block";
342
343int
344DoMakeJournaled(char *volname, int jsize)
345{
346 int fd, i, block_size, journal_size = 8*1024*1024;
347 char *buf;
348 int ret;
349 fstore_t fst;
16f263f5
A
350 int32_t jstart_block, jinfo_block;
351 int sysctl_info[8];
08cdaae8 352 JournalInfoBlock jib;
19348fcb
A
353 struct statfs sfs;
354 static char tmpname[MAXPATHLEN];
16f263f5 355 off_t start_block, embedded_offset;
08cdaae8 356
19348fcb
A
357 if (statfs(volname, &sfs) != 0) {
358 fprintf(stderr, "Can't stat volume %s (%s).\n", volname, strerror(errno));
359 return 10;
360 }
08cdaae8 361
19348fcb
A
362 // Make sure that we're HFS+. First we check the fstypename.
363 // If that's ok then we try to create a symlink (which won't
364 // work on plain hfs volumes but will work on hfs+ volumes).
365 //
ab40a2da
A
366 if (strcmp(sfs.f_fstypename, "devfs") == 0) {
367 fprintf (stderr, "%s is a device node. Journal enable only works on a mounted HFS+ volume.\n", volname);
368 return 10;
369 }
370 snprintf(tmpname, sizeof(tmpname), "%s/is_vol_hfs_plus", volname);
19348fcb
A
371 if (strcmp(sfs.f_fstypename, "hfs") != 0 ||
372 ((ret = symlink(tmpname, tmpname)) != 0 && errno == ENOTSUP)) {
373 fprintf(stderr, "%s is not an HFS+ volume. Journaling only works on HFS+ volumes.\n",
374 volname);
375 return 10;
376 }
377 unlink(tmpname);
08cdaae8 378
19348fcb
A
379 if (sfs.f_flags & MNT_JOURNALED) {
380 fprintf(stderr, "Volume %s is already journaled.\n", volname);
381 return 1;
382 }
383
384 if (jsize != 0) {
385 journal_size = jsize;
386 } else {
387 int scale;
08cdaae8 388
19348fcb
A
389 //
390 // we want at least 8 megs of journal for each 100 gigs of
391 // disk space. We cap the size at 512 megs though.
392 //
ab40a2da 393 scale = ((long long)sfs.f_bsize * (long long)((unsigned int)sfs.f_blocks)) / (100*1024*1024*1024ULL);
19348fcb
A
394 journal_size *= (scale + 1);
395 if (journal_size > 512 * 1024 * 1024) {
396 journal_size = 512 * 1024 * 1024;
08cdaae8 397 }
19348fcb 398 }
08cdaae8
A
399
400 if (chdir(volname) != 0) {
19348fcb
A
401 fprintf(stderr, "Can't locate volume %s to make it journaled (%s).\n",
402 volname, strerror(errno));
403 return 10;
404 }
08cdaae8 405
16f263f5
A
406
407 embedded_offset = get_embedded_offset(volname);
408 if (embedded_offset < 0) {
409 fprintf(stderr, "Can't calculate the embedded offset (if any) for %s.\n", volname);
410 fprintf(stderr, "Journal creation failure.\n");
411 return 15;
412 }
413 // printf("Embedded offset == 0x%llx\n", embedded_offset);
414
08cdaae8
A
415 fd = open(journal_fname, O_CREAT|O_TRUNC|O_RDWR, 000);
416 if (fd < 0) {
19348fcb
A
417 fprintf(stderr, "Can't create journal file on volume %s (%s)\n",
418 volname, strerror(errno));
419 return 5;
08cdaae8
A
420 }
421
19348fcb
A
422 // make sure that it has no r/w/x privs (only could happen if
423 // the file already existed since open() doesn't reset the mode
424 // bits).
425 //
426 fchmod(fd, 0);
08cdaae8
A
427
428 block_size = sfs.f_bsize;
429 if ((journal_size % block_size) != 0) {
19348fcb
A
430 fprintf(stderr, "Journal size %dk is not a multiple of volume %s block size (%d).\n",
431 journal_size/1024, volname, block_size);
432 close(fd);
433 unlink(journal_fname);
434 return 5;
08cdaae8
A
435 }
436
19348fcb 437 retry:
08cdaae8
A
438 memset(&fst, 0, sizeof(fst));
439 fst.fst_flags = F_ALLOCATECONTIG|F_ALLOCATEALL;
440 fst.fst_length = journal_size;
441 fst.fst_posmode = F_PEOFPOSMODE;
442
443 ret = fcntl(fd, F_PREALLOCATE, &fst);
444 if (ret < 0) {
19348fcb
A
445 if (journal_size >= 2*1024*1024) {
446 fprintf(stderr, "Not enough contiguous space for a %d k journal. Retrying.\n",
447 journal_size/1024);
448 journal_size /= 2;
449 ftruncate(fd, 0); // make sure the file is zero bytes long.
450 goto retry;
451 } else {
452 fprintf(stderr, "Disk too fragmented to enable journaling.\n");
453 fprintf(stderr, "Please run a defragmenter on %s.\n", volname);
454 close(fd);
455 unlink(journal_fname);
456 return 10;
457 }
08cdaae8
A
458 }
459
460 printf("Allocated %lldK for journal file.\n", fst.fst_bytesalloc/1024LL);
461 buf = (char *)calloc(block_size, 1);
462 if (buf) {
19348fcb
A
463 for(i=0; i < journal_size/block_size; i++) {
464 ret = write(fd, buf, block_size);
465 if (ret != block_size) {
466 break;
467 }
468 }
08cdaae8 469
19348fcb
A
470 if (i*block_size != journal_size) {
471 fprintf(stderr, "Failed to write %dk to journal on volume %s (%s)\n",
472 journal_size/1024, volname, strerror(errno));
473 }
08cdaae8 474 } else {
19348fcb
A
475 printf("Could not allocate memory to write to the journal on volume %s (%s)\n",
476 volname, strerror(errno));
08cdaae8
A
477 }
478
479 fsync(fd);
480 close(fd);
481 hide_file(journal_fname);
482
16f263f5
A
483 start_block = get_start_block(journal_fname, block_size);
484 if (start_block == (off_t)-1) {
485 fprintf(stderr, "Failed to get start block for %s (%s)\n",
486 journal_fname, strerror(errno));
487 unlink(journal_fname);
488 return 20;
489 }
490 jstart_block = (start_block / block_size) - (embedded_offset / block_size);
08cdaae8 491
16f263f5 492 memset(&jib, 'Z', sizeof(jib));
08cdaae8 493 jib.flags = kJIJournalInFSMask;
ab40a2da
A
494 jib.offset = (off_t)((unsigned int)jstart_block) * (off_t)((unsigned int)block_size);
495 jib.size = (off_t)((unsigned int)journal_size);
08cdaae8
A
496
497 fd = open(jib_fname, O_CREAT|O_TRUNC|O_RDWR, 000);
498 if (fd < 0) {
19348fcb
A
499 fprintf(stderr, "Could not create journal info block file on volume %s (%s)\n",
500 volname, strerror(errno));
501 unlink(journal_fname);
502 return 5;
08cdaae8
A
503 }
504
19348fcb 505 // swap the data before we copy it
e74bfeef
A
506 jib.flags = OSSwapBigToHostInt32(jib.flags);
507 jib.offset = OSSwapBigToHostInt64(jib.offset);
508 jib.size = OSSwapBigToHostInt64(jib.size);
19348fcb 509
08cdaae8 510 memcpy(buf, &jib, sizeof(jib));
19348fcb
A
511
512 // now put it back the way it was
e74bfeef
A
513 jib.size = OSSwapBigToHostInt64(jib.size);
514 jib.offset = OSSwapBigToHostInt64(jib.offset);
515 jib.flags = OSSwapBigToHostInt32(jib.flags);
19348fcb 516
08cdaae8 517 if (write(fd, buf, block_size) != block_size) {
19348fcb
A
518 fprintf(stderr, "Failed to write journal info block on volume %s (%s)!\n",
519 volname, strerror(errno));
520 unlink(journal_fname);
521 return 10;
08cdaae8
A
522 }
523
524 fsync(fd);
525 close(fd);
526 hide_file(jib_fname);
527
16f263f5
A
528 start_block = get_start_block(jib_fname, block_size);
529 if (start_block == (off_t)-1) {
530 fprintf(stderr, "Failed to get start block for %s (%s)\n",
531 jib_fname, strerror(errno));
532 unlink(journal_fname);
533 unlink(jib_fname);
534 return 20;
535 }
536 jinfo_block = (start_block / block_size) - (embedded_offset / block_size);
08cdaae8
A
537
538
539 //
540 // Now make the volume journaled!
541 //
542 memset(sysctl_info, 0, sizeof(sysctl_info));
543 sysctl_info[0] = CTL_VFS;
544 sysctl_info[1] = sfs.f_fsid.val[1];
19348fcb 545 sysctl_info[2] = HFS_ENABLE_JOURNALING;
08cdaae8
A
546 sysctl_info[3] = jinfo_block;
547 sysctl_info[4] = jstart_block;
548 sysctl_info[5] = journal_size;
549
550 //printf("fs type: 0x%x\n", sysctl_info[1]);
551 //printf("jinfo block : 0x%x\n", jinfo_block);
552 //printf("jstart block: 0x%x\n", jstart_block);
553 //printf("journal size: 0x%x\n", journal_size);
554
555 ret = sysctl((void *)sysctl_info, 6, NULL, NULL, NULL, 0);
556 if (ret != 0) {
19348fcb
A
557 fprintf(stderr, "Failed to make volume %s journaled (%s)\n",
558 volname, strerror(errno));
559 unlink(journal_fname);
560 unlink(jib_fname);
561 return 20;
08cdaae8 562 }
19348fcb
A
563
564 return 0;
08cdaae8
A
565}
566
567
568int
569DoUnJournal(char *volname)
570{
19348fcb 571 int result;
08cdaae8 572 int sysctl_info[8];
19348fcb
A
573 struct statfs sfs;
574 char jbuf[MAXPATHLEN];
08cdaae8 575
19348fcb
A
576 if (statfs(volname, &sfs) != 0) {
577 fprintf(stderr, "Can't stat volume %s (%s).\n", volname, strerror(errno));
578 return 10;
579 }
08cdaae8 580
ab40a2da
A
581 if (strcmp(sfs.f_fstypename, "hfs") != 0) {
582 fprintf(stderr, "Volume %s (%s) is not a HFS volume.\n", volname, sfs.f_mntfromname);
583 return 1;
584 }
585
19348fcb 586 if ((sfs.f_flags & MNT_JOURNALED) == 0) {
ab40a2da 587 fprintf(stderr, "Volume %s (%s) is not journaled.\n", volname, sfs.f_mntfromname);
19348fcb
A
588 return 1;
589 }
08cdaae8 590
19348fcb
A
591 if (chdir(volname) != 0) {
592 fprintf(stderr, "Can't locate volume %s to turn off journaling (%s).\n",
593 volname, strerror(errno));
594 return 10;
595 }
08cdaae8 596
19348fcb
A
597 memset(sysctl_info, 0, sizeof(sysctl_info));
598 sysctl_info[0] = CTL_VFS;
599 sysctl_info[1] = sfs.f_fsid.val[1];
600 sysctl_info[2] = HFS_DISABLE_JOURNALING;
08cdaae8 601
19348fcb
A
602 result = sysctl((void *)sysctl_info, 3, NULL, NULL, NULL, 0);
603 if (result != 0) {
604 fprintf(stderr, "Failed to make volume %s UN-journaled (%s)\n",
605 volname, strerror(errno));
606 return 20;
607 }
08cdaae8 608
ab40a2da 609 snprintf(jbuf, sizeof(jbuf), "%s/%s", volname, journal_fname);
19348fcb
A
610 if (unlink(jbuf) != 0) {
611 fprintf(stderr, "Failed to remove the journal %s (%s)\n",
612 jbuf, strerror(errno));
613 }
08cdaae8 614
ab40a2da 615 snprintf(jbuf, sizeof(jbuf), "%s/%s", volname, jib_fname);
19348fcb
A
616 if (unlink(jbuf) != 0) {
617 fprintf(stderr, "Failed to remove the journal info block %s (%s)\n",
618 jbuf, strerror(errno));
619 }
08cdaae8 620
ab40a2da 621 printf("Journaling disabled on %s mounted at %s.\n", sfs.f_mntfromname, volname);
08cdaae8 622
19348fcb
A
623 return 0;
624}
625
626
ab40a2da
A
627
628
629int
630get_journal_info(char *devname, struct JournalInfoBlock *jib)
631{
632 int fd = -1, ret = 0;
633 char *buff = NULL, *buff2 = NULL;
634 u_int64_t disksize;
635 u_int64_t blkcnt;
636 u_int32_t blksize;
637 daddr_t mdb_offset;
638 HFSMasterDirectoryBlock *mdbp;
639 HFSPlusVolumeHeader *vhp;
640 off_t embeddedOffset, pos;
641 struct JournalInfoBlock *myjib;
642
643 fd = open(devname, O_RDONLY);
644 if (fd < 0) {
645 printf("can't open: %s (%s)\n", devname, strerror(errno));
646 ret = -5;
647 goto out;
648 }
649
650 /* Get the real physical block size. */
651 if (ioctl(fd, DKIOCGETBLOCKSIZE, (caddr_t)&blksize) != 0) {
652 printf("can't get the device block size (%s). assuming 512\n", strerror(errno));
653 blksize = 512;
654 ret = -1;
655 goto out;
656 }
657
658 /* Get the number of physical blocks. */
659 if (ioctl(fd, DKIOCGETBLOCKCOUNT, (caddr_t)&blkcnt)) {
660 struct stat st;
661 printf("failed to get block count. trying stat().\n");
662 if (fstat(fd, &st) != 0) {
663 ret = -1;
664 goto out;
665 }
666
667 blkcnt = st.st_size / blksize;
668 }
669
670 /* Compute an accurate disk size */
671 disksize = blkcnt * (u_int64_t)blksize;
672
673 /*
674 * There are only 31 bits worth of block count in
675 * the buffer cache. So for large volumes a 4K
676 * physical block size is needed.
677 */
678 if (blksize == 512 && blkcnt > (u_int64_t)0x000000007fffffff) {
679 blksize = 4096;
680 }
681
682 /*
683 * At this point:
684 * blksize has our prefered physical block size
685 * blkcnt has the total number of physical blocks
686 */
687
688 buff = (char *)malloc(blksize);
689 buff2 = (char *)malloc(blksize);
690
691 if (pread(fd, buff, blksize, HFS_PRI_SECTOR(blksize)*blksize) != blksize) {
692 printf("failed to read volume header @ offset %d (%s)\n",
693 HFS_PRI_SECTOR(blksize), strerror(errno));
694 ret = -1;
695 goto out;
696 }
697
04a16b11
A
698 mdbp = (HFSMasterDirectoryBlock *)(buff + HFS_PRI_OFFSET(blksize));
699
700 if ( (SWAP_BE16(mdbp->drSigWord) != kHFSSigWord)
701 && (SWAP_BE16(mdbp->drSigWord) != kHFSPlusSigWord)
702 && (SWAP_BE16(mdbp->drSigWord) != kHFSXSigWord)) {
703 ret = -1;
704 printf("get_journal_info: invalid volume signature\n");
705 goto out;
ab40a2da
A
706 }
707
708 mdbp->drSigWord = SWAP_BE16(mdbp->drSigWord);
709 mdbp->drEmbedSigWord = SWAP_BE16(mdbp->drEmbedSigWord);
710 mdbp->drAlBlSt = SWAP_BE16(mdbp->drAlBlSt);
711 mdbp->drEmbedExtent.startBlock = SWAP_BE16(mdbp->drEmbedExtent.startBlock);
712 mdbp->drAlBlkSiz = SWAP_BE32(mdbp->drAlBlkSiz);
713 mdbp->drEmbedExtent.blockCount = SWAP_BE16(mdbp->drEmbedExtent.blockCount);
ab40a2da 714
ab40a2da
A
715
716 if ((mdbp->drSigWord == kHFSSigWord) && (mdbp->drEmbedSigWord != kHFSPlusSigWord)) {
717 // normal hfs can not ever be journaled
718 goto out;
719 }
720
721 /* Get the embedded Volume Header */
722 if (mdbp->drEmbedSigWord == kHFSPlusSigWord) {
723 embeddedOffset = mdbp->drAlBlSt * 512;
724 embeddedOffset += (u_int64_t)mdbp->drEmbedExtent.startBlock *
725 (u_int64_t)mdbp->drAlBlkSiz;
726
727 /*
728 * If the embedded volume doesn't start on a block
729 * boundary, then switch the device to a 512-byte
730 * block size so everything will line up on a block
731 * boundary.
732 */
733 if ((embeddedOffset % blksize) != 0) {
734 printf("HFS Mount: embedded volume offset not"
735 " a multiple of physical block size (%d);"
736 " switching to 512\n", blksize);
737
738 blkcnt *= (blksize / 512);
739 blksize = 512;
740 }
741
742 disksize = (u_int64_t)mdbp->drEmbedExtent.blockCount *
743 (u_int64_t)mdbp->drAlBlkSiz;
744
745 mdb_offset = (embeddedOffset / blksize) + HFS_PRI_SECTOR(blksize);
746 if (pread(fd, buff, blksize, mdb_offset * blksize) != blksize) {
747 printf("failed to read the embedded vhp @ offset %d\n", mdb_offset * blksize);
748 ret = -1;
749 goto out;
750 }
751
04a16b11
A
752 vhp = (HFSPlusVolumeHeader*) (buff + HFS_PRI_OFFSET(blksize));
753
754 mdbp = (HFSMasterDirectoryBlock *)vhp;
755 if ( (SWAP_BE16(mdbp->drSigWord) != kHFSSigWord)
756 && (SWAP_BE16(mdbp->drSigWord) != kHFSPlusSigWord)
757 && (SWAP_BE16(mdbp->drSigWord) != kHFSXSigWord)) {
758 ret = -1;
759
760 printf("get_journal_info: invalid embedded volume signature \n");
761 goto out;
762 }
763
ab40a2da
A
764 } else /* pure HFS+ */ {
765 embeddedOffset = 0;
766 vhp = (HFSPlusVolumeHeader*) mdbp;
767 }
768
769 if ((SWAP_BE32(vhp->attributes) & kHFSVolumeJournaledMask) == 0) {
770 ret = 0;
771 goto out;
772 }
773
774 //
775 // Now read the journal info block... (when calculating the
776 // position, make sure to cast to unsigned first, then to
777 // off_t so that things don't get sign-extended improperly
778 // or truncated).
779 //
780 pos = (off_t)((off_t)embeddedOffset +
781 (off_t)((unsigned int)SWAP_BE32(vhp->journalInfoBlock))*(off_t)((unsigned int)SWAP_BE32(vhp->blockSize)));
782
783 if (pread(fd, buff2, blksize, pos) != blksize) {
784 printf("failed to read the journal info block (%s).\n", strerror(errno));
785 ret = -1;
786 goto out;
787 }
788
789 myjib = (struct JournalInfoBlock *)buff2;
790 myjib->flags = SWAP_BE32(myjib->flags);
791 myjib->offset = SWAP_BE64(myjib->offset);
792 myjib->size = SWAP_BE64(myjib->size);
793
794 memcpy(jib, myjib, sizeof(*myjib));
795
796 ret = 1;
797
798out:
799 if (buff)
800 free(buff);
801 if (buff2)
802 free(buff2);
803 if (fd >= 0)
804 close(fd);
805
806 return ret;
807}
808
809
19348fcb
A
810int
811DoGetJournalInfo(char *volname)
812{
19348fcb 813 struct statfs sfs;
ab40a2da 814 struct hfs_journal_info jinfo;
19348fcb 815
ab40a2da
A
816 if (strncmp(volname, "/dev/", 5) == 0 || strncmp(volname, "disk", 4) == 0 || strncmp(volname, "rdisk", 5) == 0) {
817 struct JournalInfoBlock jib;
818 int ret;
819 char fulldevname[256];
820
821 if (strncmp(volname, "disk", 4) == 0 || strncmp(volname, "rdisk", 5) == 0) {
822 snprintf(fulldevname, sizeof(fulldevname), "/dev/%s", volname);
823 volname = &fulldevname[0];
824 }
825
826 // try the name as a device name...
827 ret = get_journal_info(volname, &jib);
828 if (ret == 0) {
829 printf("Volume %s is not journaled.\n", volname);
830 return 0;
831 } else if (ret < 0) {
832 printf("Volume %s does not appear to be an HFS+ volume.\n", volname);
833 return 10;
834 } else {
835 if (jib.flags & kJIJournalInFSMask) {
836 printf("%s : journal size %lld k at offset 0x%llx\n", volname, jib.size/1024, jib.offset);
837 } else {
838 printf("%s: external journal stored on partition with uuid %s on machine w/serial number %s\n",
839 volname, jib.ext_jnl_uuid, jib.machine_serial_num);
840 }
841
842 return 0;
843 }
844
845 }
846
19348fcb 847 if (statfs(volname, &sfs) != 0) {
ab40a2da
A
848 fprintf(stderr, "Unable to get fs info for %s\n", volname);
849 return 10;
19348fcb
A
850 }
851
852 if ((sfs.f_flags & MNT_JOURNALED) == 0) {
853 fprintf(stderr, "Volume %s is not journaled.\n", volname);
854 return 1;
855 }
856
ab40a2da 857 if (fsctl(volname, HFSIOC_GET_JOURNAL_INFO, &jinfo, 0) != 0) {
19348fcb
A
858 fprintf(stderr, "Failed to get journal info for volume %s (%s)\n",
859 volname, strerror(errno));
860 return 20;
861 }
862
ab40a2da
A
863 if (jinfo.jstart == 0) {
864 char rawdev[256];
865
866 snprintf(rawdev, sizeof(rawdev), "/dev/r%s", &sfs.f_mntfromname[5]);
867
868 // it's an external journal so get the info the
869 // other way.
870 return DoGetJournalInfo(&rawdev[0]);
871 }
872
873 if (jinfo.jsize == 0) {
19348fcb
A
874 printf("%s : not journaled.\n", volname);
875 } else {
ab40a2da 876 printf("%s : journal size %lld k at offset 0x%llx\n", volname, jinfo.jsize/1024, jinfo.jstart);
19348fcb
A
877 }
878
879 return 0;
08cdaae8 880}
e74bfeef
A
881
882
883int
884RawDisableJournaling(char *devname)
885{
886 int fd = -1, ret = 0;
ab40a2da 887 char *buff = NULL, rawdev[256], unrawdev[256];
e74bfeef
A
888 u_int64_t disksize;
889 u_int64_t blkcnt;
890 u_int32_t blksize;
891 daddr_t mdb_offset;
892 HFSMasterDirectoryBlock *mdbp;
893 HFSPlusVolumeHeader *vhp;
894 off_t embeddedOffset, hdr_offset;
e74bfeef 895 struct stat st;
ab40a2da 896 struct statfs *fsinfo;
e74bfeef 897
ab40a2da
A
898 // assume that the name provided is a raw device name
899 strlcpy(rawdev, devname, sizeof(rawdev));
e74bfeef 900
ab40a2da
A
901restart:
902 if (stat(rawdev, &st) != 0) {
903 fprintf(stderr, "Could not access %s (%s)\n", devname, strerror(errno));
904 ret = -1;
905 goto out;
906 }
907
908 if (S_ISCHR(st.st_mode) == 0) {
909 if (S_ISBLK(st.st_mode)) {
910 // this is a block device, convert the name to
911 // raw character device and try again
912 snprintf(rawdev, sizeof(rawdev), "/dev/r%s", devname + 5);
913 goto restart;
914 } else {
915 // probably it is a mount point
916 return DoUnJournal(devname);
917 }
e74bfeef 918 } else {
ab40a2da
A
919 // convert the character raw device name to
920 // block device name to compare with getmntinfo output
921 snprintf(unrawdev, sizeof(unrawdev), "/dev/%s", rawdev + 6);
922 }
923
924 // make sure that the file system on the device node is not mounted
925 ret = getmntinfo(&fsinfo, MNT_NOWAIT);
926 if (ret == 0) {
927 fprintf (stderr, "Error getting list of mounted filesystems\n");
e74bfeef
A
928 ret = -1;
929 goto out;
ab40a2da
A
930 }
931
932 while (ret--) {
933 // the file system on this device node is currently mounted
934 if (strcmp(unrawdev, fsinfo[ret].f_mntfromname) == 0) {
935 return DoUnJournal(fsinfo[ret].f_mntonname);
936 }
e74bfeef
A
937 }
938
ab40a2da 939 fd = open(rawdev, O_RDWR);
e74bfeef
A
940 if (fd < 0) {
941 fprintf(stderr, "can't open: %s (%s)\n", devname, strerror(errno));
942 ret = -1;
943 goto out;
944 }
945
946 /* Get the real physical block size. */
947 if (ioctl(fd, DKIOCGETBLOCKSIZE, (caddr_t)&blksize) != 0) {
948 fprintf(stderr, "can't get the device block size (%s). assuming 512\n", strerror(errno));
949 blksize = 512;
950 ret = -1;
951 goto out;
952 }
953
954 /* Get the number of physical blocks. */
955 if (ioctl(fd, DKIOCGETBLOCKCOUNT, (caddr_t)&blkcnt)) {
956 struct stat st;
957
958 if (fstat(fd, &st) != 0) {
959 ret = -1;
960 goto out;
961 }
962
963 blkcnt = st.st_size / blksize;
964 }
965
966 /* Compute an accurate disk size */
967 disksize = blkcnt * (u_int64_t)blksize;
968
969 /*
970 * There are only 31 bits worth of block count in
971 * the buffer cache. So for large volumes a 4K
972 * physical block size is needed.
973 */
974 if (blksize == 512 && blkcnt > (u_int64_t)0x000000007fffffff) {
975 blksize = 4096;
976 }
977
978 /*
979 * At this point:
980 * blksize has our prefered physical block size
981 * blkcnt has the total number of physical blocks
982 */
983
984 buff = (char *)malloc(blksize);
985
986 hdr_offset = HFS_PRI_SECTOR(blksize)*blksize;
987 if (pread(fd, buff, blksize, hdr_offset) != blksize) {
04a16b11
A
988 fprintf(stderr, "RawDisableJournaling: failed to read volume header @ offset %lld (%s)\n",
989 hdr_offset, strerror(errno));
990 ret = -1;
991 goto out;
e74bfeef
A
992 }
993
04a16b11
A
994 mdbp = (HFSMasterDirectoryBlock *)(buff + HFS_PRI_OFFSET(blksize));
995 if ( (SWAP_BE16(mdbp->drSigWord) != kHFSSigWord)
996 && (SWAP_BE16(mdbp->drSigWord) != kHFSPlusSigWord)
997 && (SWAP_BE16(mdbp->drSigWord) != kHFSXSigWord)) {
998 ret = -1;
999 printf("RawDisableJournaling: Invalid Volume Signature \n");
1000 goto out;
e74bfeef 1001 }
04a16b11 1002
e74bfeef
A
1003 if ((SWAP_BE16(mdbp->drSigWord) == kHFSSigWord) && (SWAP_BE16(mdbp->drEmbedSigWord) != kHFSPlusSigWord)) {
1004 // normal hfs can not ever be journaled
1005 fprintf(stderr, "disable_journaling: volume is only regular HFS, not HFS+\n");
1006 goto out;
1007 }
1008
1009 /* Get the embedded Volume Header */
1010 if (SWAP_BE16(mdbp->drEmbedSigWord) == kHFSPlusSigWord) {
04a16b11
A
1011 embeddedOffset = SWAP_BE16(mdbp->drAlBlSt) * 512;
1012 embeddedOffset += (u_int64_t)SWAP_BE16(mdbp->drEmbedExtent.startBlock) * (u_int64_t)SWAP_BE32(mdbp->drAlBlkSiz);
1013
1014 /*
1015 * If the embedded volume doesn't start on a block
1016 * boundary, then switch the device to a 512-byte
1017 * block size so everything will line up on a block
1018 * boundary.
1019 */
1020 if ((embeddedOffset % blksize) != 0) {
1021 fprintf(stderr, "HFS Mount: embedded volume offset not"
1022 " a multiple of physical block size (%d);"
1023 " switching to 512\n", blksize);
1024
1025 blkcnt *= (blksize / 512);
1026 blksize = 512;
1027 }
1028
1029 disksize = (u_int64_t)SWAP_BE16(mdbp->drEmbedExtent.blockCount) * (u_int64_t)SWAP_BE32(mdbp->drAlBlkSiz);
1030
1031 mdb_offset = (embeddedOffset / blksize) + HFS_PRI_SECTOR(blksize);
1032 hdr_offset = mdb_offset * blksize;
1033 if (pread(fd, buff, blksize, hdr_offset) != blksize) {
1034 fprintf(stderr, "failed to read the embedded vhp @ offset %d\n", mdb_offset * blksize);
1035 ret = -1;
1036 goto out;
1037 }
1038
1039 vhp = (HFSPlusVolumeHeader*) (buff + HFS_PRI_OFFSET(blksize));
1040
1041 mdbp = (HFSMasterDirectoryBlock *)vhp;
1042 if ( (SWAP_BE16(mdbp->drSigWord) != kHFSSigWord)
1043 && (SWAP_BE16(mdbp->drSigWord) != kHFSPlusSigWord)
1044 && (SWAP_BE16(mdbp->drSigWord) != kHFSXSigWord)) {
1045 ret = -1;
1046
1047 printf("RawDisableJournaling: invalid embedded volume signature \n");
1048 goto out;
1049 }
e74bfeef 1050
e74bfeef 1051 } else /* pure HFS+ */ {
04a16b11
A
1052 embeddedOffset = 0;
1053 vhp = (HFSPlusVolumeHeader*) mdbp;
e74bfeef
A
1054 }
1055
1056
1057 if ((SWAP_BE32(vhp->attributes) & kHFSVolumeJournaledMask) != 0) {
04a16b11
A
1058 unsigned int tmp = SWAP_BE32(vhp->attributes);
1059
1060 tmp &= ~kHFSVolumeJournaledMask;
1061 vhp->attributes = SWAP_BE32(tmp);
1062 if ((tmp = pwrite(fd, buff, blksize, hdr_offset)) != blksize) {
1063 fprintf(stderr, "Update of super-block on %s failed! (%d != %d, %s)\n",
1064 devname, tmp, blksize, strerror(errno));
1065 } else {
1066 fprintf(stderr, "Turned off the journaling bit for %s\n", devname);
1067 }
e74bfeef 1068 } else {
04a16b11 1069 fprintf(stderr, "disable_journaling: %s is not journaled.\n", devname);
e74bfeef 1070 }
04a16b11 1071
e74bfeef
A
1072
1073 out:
1074 if (buff)
1075 free(buff);
1076 if (fd >= 0)
1077 close(fd);
1078
1079 return ret;
1080}
ab40a2da
A
1081
1082
1083
1084int
1085SetJournalInFSState(const char *devname, int journal_in_fs)
1086{
1087 int fd = -1, ret = 0;
1088 char *buff = NULL, *buff2 = NULL;
1089 u_int64_t blkcnt;
1090 u_int32_t blksize;
1091 daddr_t mdb_offset;
1092 HFSMasterDirectoryBlock *mdbp;
1093 HFSPlusVolumeHeader *vhp;
1094 off_t embeddedOffset, pos;
1095 struct JournalInfoBlock *myjib;
1096
1097 fd = open(devname, O_RDWR);
1098 if (fd < 0) {
1099 printf("can't open: %s (%s)\n", devname, strerror(errno));
1100 ret = -1;
1101 goto out;
1102 }
1103
1104 /* Get the real physical block size. */
1105 if (ioctl(fd, DKIOCGETBLOCKSIZE, (caddr_t)&blksize) != 0) {
1106 printf("can't get the device block size (%s). assuming 512\n", strerror(errno));
1107 blksize = 512;
1108 ret = -1;
1109 goto out;
1110 }
1111
1112 /* Get the number of physical blocks. */
1113 if (ioctl(fd, DKIOCGETBLOCKCOUNT, (caddr_t)&blkcnt)) {
1114 struct stat st;
1115 printf("failed to get block count. trying stat().\n");
1116 if (fstat(fd, &st) != 0) {
1117 ret = -1;
1118 goto out;
1119 }
1120
1121 blkcnt = st.st_size / blksize;
1122 }
1123
1124 /*
1125 * There used to only be 31 bits worth of block count in
1126 * the buffer cache. So for large volumes a 4K
1127 * physical block size is needed.
1128 */
1129 if (blksize == 512 && blkcnt > (u_int64_t)0x000000007fffffff) {
1130 blksize = 4096;
1131 }
1132
1133 /*
1134 * At this point:
1135 * blksize has our prefered physical block size
1136 * blkcnt has the total number of physical blocks
1137 */
1138
1139 buff = (char *)malloc(blksize);
1140 buff2 = (char *)malloc(blksize);
1141
1142 if (pread(fd, buff, blksize, HFS_PRI_SECTOR(blksize)*blksize) != blksize) {
1143 printf("failed to read volume header @ offset %d (%s)\n",
1144 HFS_PRI_SECTOR(blksize), strerror(errno));
1145 ret = -1;
1146 goto out;
1147 }
1148
04a16b11 1149 mdbp = (HFSMasterDirectoryBlock *)(buff + HFS_PRI_OFFSET(blksize));
ab40a2da 1150
ab40a2da 1151
04a16b11
A
1152 if ( (SWAP_BE16(mdbp->drSigWord) != kHFSSigWord)
1153 && (SWAP_BE16(mdbp->drSigWord) != kHFSPlusSigWord)
1154 && (SWAP_BE16(mdbp->drSigWord) != kHFSXSigWord)) {
1155 ret = -1;
1156 printf ("SetJournalInFSState: Invalid Volume Signature \n");
1157 goto out;
ab40a2da
A
1158 }
1159
1160 if ((SWAP_BE16(mdbp->drSigWord) == kHFSSigWord) && (SWAP_BE16(mdbp->drEmbedSigWord) != kHFSPlusSigWord)) {
1161 // normal hfs can not ever be journaled
1162 goto out;
1163 }
1164
1165 /* Get the embedded Volume Header */
1166 if (SWAP_BE16(mdbp->drEmbedSigWord) == kHFSPlusSigWord) {
1167 embeddedOffset = SWAP_BE16(mdbp->drAlBlSt) * 512;
1168 embeddedOffset += (u_int64_t)SWAP_BE16(mdbp->drEmbedExtent.startBlock) *
1169 (u_int64_t)SWAP_BE32(mdbp->drAlBlkSiz);
1170
1171 /*
1172 * If the embedded volume doesn't start on a block
1173 * boundary, then switch the device to a 512-byte
1174 * block size so everything will line up on a block
1175 * boundary.
1176 */
1177 if ((embeddedOffset % blksize) != 0) {
1178 printf("HFS Mount: embedded volume offset not"
1179 " a multiple of physical block size (%d);"
1180 " switching to 512\n", blksize);
1181
1182 blkcnt *= (blksize / 512);
1183 blksize = 512;
1184 }
1185
1186 mdb_offset = (embeddedOffset / blksize) + HFS_PRI_SECTOR(blksize);
1187 if (pread(fd, buff, blksize, mdb_offset * blksize) != blksize) {
1188 printf("failed to read the embedded vhp @ offset %d\n", mdb_offset * blksize);
1189 ret = -1;
1190 goto out;
1191 }
1192
04a16b11
A
1193 vhp = (HFSPlusVolumeHeader*) (buff + HFS_PRI_OFFSET(blksize));
1194
1195 mdbp = (HFSMasterDirectoryBlock *)(vhp);
1196 if ( (SWAP_BE16(mdbp->drSigWord) != kHFSSigWord)
1197 && (SWAP_BE16(mdbp->drSigWord) != kHFSPlusSigWord)
1198 && (SWAP_BE16(mdbp->drSigWord) != kHFSXSigWord)) {
1199 ret = -1;
1200 printf("SetJournalInFSState: Invalid Embedded Volume Signature \n");
1201 goto out;
1202 }
1203
1204
ab40a2da
A
1205 } else /* pure HFS+ */ {
1206 embeddedOffset = 0;
1207 vhp = (HFSPlusVolumeHeader*) mdbp;
1208 }
1209
1210 //printf("vol header attributes: 0x%x\n", SWAP_BE32(vhp->attributes));
1211 if ((SWAP_BE32(vhp->attributes) & kHFSVolumeJournaledMask) == 0) {
1212 ret = 0;
1213 goto out;
1214 }
1215
1216 //
1217 // Now read the journal info block... (when calculating the
1218 // position, make sure to cast to unsigned first, then to
1219 // off_t so that things don't get sign-extended improperly
1220 // or truncated).
1221 //
1222 pos = (off_t)((off_t)embeddedOffset +
1223 (off_t)((unsigned int )SWAP_BE32(vhp->journalInfoBlock))*(off_t)((unsigned int)SWAP_BE32(vhp->blockSize)));
1224
1225 if (pread(fd, buff2, blksize, pos) != blksize) {
1226 printf("failed to read the journal info block (%s).\n", strerror(errno));
1227 ret = -1;
1228 goto out;
1229 }
1230
1231 myjib = (struct JournalInfoBlock *)buff2;
1232
1233 // swap this to host native format so we can diddle with the bits
1234 myjib->flags = SWAP_BE32(myjib->flags);
1235
1236 if (journal_in_fs) {
1237 myjib->flags |= kJIJournalInFSMask;
1238 } else {
1239 myjib->flags &= ~kJIJournalInFSMask;
1240 }
1241 myjib->flags |= kJIJournalNeedInitMask;
1242
1243 // and now swap back before writing it out
1244 myjib->flags = SWAP_BE32(myjib->flags);
1245
1246 if (pwrite(fd, buff2, blksize, pos) != blksize) {
1247 printf("failed to re-write the journal info block (%s).\n", strerror(errno));
1248 ret = -1;
1249 goto out;
1250 }
1251
1252 ret = 0;
1253
1254 out:
1255 if (buff)
1256 free(buff);
1257 if (buff2)
1258 free(buff2);
1259 if (fd >= 0)
1260 close(fd);
1261
1262 return ret;
1263}