2 * Copyright (c) 1999-2001 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
23 Copyright (c) 2002 Apple Computer, Inc.
26 This file contains the routine to make an HFS+ volume journaled
27 and a corresponding routine to turn it off.
31 #include <sys/types.h>
35 #include <sys/sysctl.h>
36 #include <sys/resource.h>
37 #include <sys/vmmeter.h>
38 #include <sys/mount.h>
40 #include <sys/ioctl.h>
43 #include <sys/loadable_fs.h>
44 #include <hfs/hfs_format.h>
45 #include <hfs/hfs_mount.h> /* for hfs sysctl values */
56 #include <architecture/byte_order.h>
58 // just in case these aren't in <hfs/hfs_mount.h> yet
59 #ifndef HFS_ENABLE_JOURNALING
60 #define HFS_ENABLE_JOURNALING 0x082969
62 #ifndef HFS_DISABLE_JOURNALING
63 #define HFS_DISABLE_JOURNALING 0x031272
65 #ifndef HFS_GET_JOURNAL_INFO
66 #define HFS_GET_JOURNAL_INFO 0x6a6e6c69
69 /* getattrlist buffers start with an extra length field */
70 struct ExtentsAttrBuf
{
71 unsigned long infoLength
;
72 HFSPlusExtentRecord extents
;
74 typedef struct ExtentsAttrBuf ExtentsAttrBuf
;
78 #define kIsInvisible 0x4000
81 * Generic Finder file/dir data
84 u_int32_t opaque_1
[2];
85 u_int16_t fdFlags
; /* Finder flags */
88 typedef struct FinderInfo FinderInfo
;
90 /* getattrlist buffers start with an extra length field */
91 struct FinderAttrBuf
{
92 unsigned long infoLength
;
93 FinderInfo finderInfo
;
95 typedef struct FinderAttrBuf FinderAttrBuf
;
98 int hide_file(const char * file
)
100 struct attrlist alist
= {0};
101 FinderAttrBuf finderInfoBuf
= {0};
104 alist
.bitmapcount
= ATTR_BIT_MAP_COUNT
;
105 alist
.commonattr
= ATTR_CMN_FNDRINFO
;
107 result
= getattrlist(file
, &alist
, &finderInfoBuf
, sizeof(finderInfoBuf
), 0);
112 if (finderInfoBuf
.finderInfo
.fdFlags
& kIsInvisible
) {
113 printf("hide: %s is alreadly invisible\n", file
);
117 finderInfoBuf
.finderInfo
.fdFlags
|= kIsInvisible
;
119 result
= setattrlist(file
, &alist
, &finderInfoBuf
.finderInfo
, sizeof(FinderInfo
), 0);
121 return (result
== -1 ? errno
: result
);
125 get_start_block(const char *file
, uint32_t fs_block_size
)
127 off_t cur_pos
, phys_start
, len
;
132 fd
= open(file
, O_RDONLY
);
137 if (fstat(fd
, &st
) < 0) {
138 fprintf(stderr
, "can't stat %s (%s)\n", file
, strerror(errno
));
143 fs_block_size
= st
.st_blksize
; // XXXdbg quick hack for now
145 phys_start
= len
= 0;
146 for(cur_pos
=0; cur_pos
< st
.st_size
; cur_pos
+= fs_block_size
) {
147 memset(&l2p
, 0, sizeof(l2p
));
148 lseek(fd
, cur_pos
, SEEK_SET
);
149 err
= fcntl(fd
, F_LOG2PHYS
, &l2p
);
151 if (phys_start
== 0) {
152 phys_start
= l2p
.l2p_devoffset
;
154 } else if (l2p
.l2p_devoffset
!= (phys_start
+ len
)) {
155 // printf(" %lld : %lld - %lld\n", cur_pos, phys_start / fs_block_size, len / fs_block_size);
156 fprintf(stderr
, "%s : is not contiguous!\n", file
);
159 // phys_start = l2p.l2p_devoffset;
160 // len = fs_block_size;
162 len
+= fs_block_size
;
168 //printf("%s start offset %lld; byte len %lld (blksize %d)\n",
169 // file, phys_start, len, fs_block_size);
171 if ((phys_start
/ (unsigned)fs_block_size
) & 0xffffffff00000000LL
) {
172 fprintf(stderr
, "%s : starting block is > 32bits!\n", file
);
181 // Get the embedded offset (if any) for an hfs+ volume.
182 // This is pretty skanky that we have to do this but
185 #include <sys/disk.h>
186 #include <hfs/hfs_format.h>
188 #include <machine/endian.h>
190 #define HFS_PRI_SECTOR(blksize) (1024 / (blksize))
191 #define HFS_PRI_OFFSET(blksize) ((blksize) > 1024 ? 1024 : 0)
193 #define SWAP_BE16(x) ntohs(x)
194 #define SWAP_BE32(x) ntohl(x)
198 get_embedded_offset(char *devname
)
202 char *buff
= NULL
, rawdev
[256];
205 HFSMasterDirectoryBlock
*mdbp
;
206 off_t embeddedOffset
;
211 if (stat(devname
, &st
) != 0) {
212 fprintf(stderr
, "Could not access %s (%s)\n", devname
, strerror(errno
));
217 if (S_ISCHR(st
.st_mode
) == 0) {
218 // hmmm, it's not the character special raw device so we
219 // should try to figure out the real device.
220 if (statfs(devname
, &sfs
) != 0) {
221 fprintf(stderr
, "Can't find out any info about the fs for path %s (%s)\n",
222 devname
, strerror(errno
));
228 strncpy(rawdev
, sfs
.f_mntfromname
, 5);
230 strcpy(&rawdev
[6], &sfs
.f_mntfromname
[5]);
231 devname
= &rawdev
[0];
235 fd
= open(devname
, O_RDONLY
);
237 fprintf(stderr
, "can't open: %s (%s)\n", devname
, strerror(errno
));
242 /* Get the real physical block size. */
243 if (ioctl(fd
, DKIOCGETBLOCKSIZE
, (caddr_t
)&blksize
) != 0) {
244 fprintf(stderr
, "can't get the device block size (%s). assuming 512\n", strerror(errno
));
250 /* Get the number of physical blocks. */
251 if (ioctl(fd
, DKIOCGETBLOCKCOUNT
, (caddr_t
)&blkcnt
)) {
253 fprintf(stderr
, "failed to get block count. trying stat().\n");
254 if (fstat(fd
, &st
) != 0) {
259 blkcnt
= st
.st_size
/ blksize
;
264 * blksize has our prefered physical block size
265 * blkcnt has the total number of physical blocks
268 buff
= (char *)malloc(blksize
);
270 if (pread(fd
, buff
, blksize
, HFS_PRI_SECTOR(blksize
)*blksize
) != blksize
) {
271 fprintf(stderr
, "failed to read volume header @ offset %d (%s)\n",
272 HFS_PRI_SECTOR(blksize
), strerror(errno
));
277 mdbp
= (HFSMasterDirectoryBlock
*)buff
;
278 if ( (SWAP_BE16(mdbp
->drSigWord
) != kHFSSigWord
)
279 && (SWAP_BE16(mdbp
->drSigWord
) != kHFSPlusSigWord
)
280 && (SWAP_BE16(mdbp
->drSigWord
) != kHFSXSigWord
)) {
285 if ((SWAP_BE16(mdbp
->drSigWord
) == kHFSSigWord
) && (SWAP_BE16(mdbp
->drEmbedSigWord
) != kHFSPlusSigWord
)) {
288 } else if (SWAP_BE16(mdbp
->drEmbedSigWord
) == kHFSPlusSigWord
) {
289 /* Get the embedded Volume Header */
290 embeddedOffset
= SWAP_BE16(mdbp
->drAlBlSt
) * 512;
291 embeddedOffset
+= (u_int64_t
)SWAP_BE16(mdbp
->drEmbedExtent
.startBlock
) *
292 (u_int64_t
)SWAP_BE32(mdbp
->drAlBlkSiz
);
295 * If the embedded volume doesn't start on a block
296 * boundary, then switch the device to a 512-byte
297 * block size so everything will line up on a block
300 if ((embeddedOffset
% blksize
) != 0) {
301 fprintf(stderr
, "HFS Mount: embedded volume offset not"
302 " a multiple of physical block size (%d);"
303 " switching to 512\n", blksize
);
305 blkcnt
*= (blksize
/ 512);
309 } else { /* pure HFS+ */
313 ret
= embeddedOffset
;
327 static const char *journal_fname
= ".journal";
328 static const char *jib_fname
= ".journal_info_block";
331 DoMakeJournaled(char *volname
, int jsize
)
333 int fd
, i
, block_size
, journal_size
= 8*1024*1024;
337 int32_t jstart_block
, jinfo_block
;
339 JournalInfoBlock jib
;
341 static char tmpname
[MAXPATHLEN
];
342 off_t start_block
, embedded_offset
;
344 if (statfs(volname
, &sfs
) != 0) {
345 fprintf(stderr
, "Can't stat volume %s (%s).\n", volname
, strerror(errno
));
349 // Make sure that we're HFS+. First we check the fstypename.
350 // If that's ok then we try to create a symlink (which won't
351 // work on plain hfs volumes but will work on hfs+ volumes).
353 sprintf(tmpname
, "%s/is_vol_hfs_plus", volname
);
354 if (strcmp(sfs
.f_fstypename
, "hfs") != 0 ||
355 ((ret
= symlink(tmpname
, tmpname
)) != 0 && errno
== ENOTSUP
)) {
356 fprintf(stderr
, "%s is not an HFS+ volume. Journaling only works on HFS+ volumes.\n",
362 if (sfs
.f_flags
& MNT_JOURNALED
) {
363 fprintf(stderr
, "Volume %s is already journaled.\n", volname
);
368 journal_size
= jsize
;
373 // we want at least 8 megs of journal for each 100 gigs of
374 // disk space. We cap the size at 512 megs though.
376 scale
= ((long long)sfs
.f_bsize
* (long long)((unsigned)sfs
.f_blocks
)) / (100*1024*1024*1024ULL);
377 journal_size
*= (scale
+ 1);
378 if (journal_size
> 512 * 1024 * 1024) {
379 journal_size
= 512 * 1024 * 1024;
383 if (chdir(volname
) != 0) {
384 fprintf(stderr
, "Can't locate volume %s to make it journaled (%s).\n",
385 volname
, strerror(errno
));
390 embedded_offset
= get_embedded_offset(volname
);
391 if (embedded_offset
< 0) {
392 fprintf(stderr
, "Can't calculate the embedded offset (if any) for %s.\n", volname
);
393 fprintf(stderr
, "Journal creation failure.\n");
396 // printf("Embedded offset == 0x%llx\n", embedded_offset);
398 fd
= open(journal_fname
, O_CREAT
|O_TRUNC
|O_RDWR
, 000);
400 fprintf(stderr
, "Can't create journal file on volume %s (%s)\n",
401 volname
, strerror(errno
));
405 // make sure that it has no r/w/x privs (only could happen if
406 // the file already existed since open() doesn't reset the mode
411 block_size
= sfs
.f_bsize
;
412 if ((journal_size
% block_size
) != 0) {
413 fprintf(stderr
, "Journal size %dk is not a multiple of volume %s block size (%d).\n",
414 journal_size
/1024, volname
, block_size
);
416 unlink(journal_fname
);
421 memset(&fst
, 0, sizeof(fst
));
422 fst
.fst_flags
= F_ALLOCATECONTIG
|F_ALLOCATEALL
;
423 fst
.fst_length
= journal_size
;
424 fst
.fst_posmode
= F_PEOFPOSMODE
;
426 ret
= fcntl(fd
, F_PREALLOCATE
, &fst
);
428 if (journal_size
>= 2*1024*1024) {
429 fprintf(stderr
, "Not enough contiguous space for a %d k journal. Retrying.\n",
432 ftruncate(fd
, 0); // make sure the file is zero bytes long.
435 fprintf(stderr
, "Disk too fragmented to enable journaling.\n");
436 fprintf(stderr
, "Please run a defragmenter on %s.\n", volname
);
438 unlink(journal_fname
);
443 printf("Allocated %lldK for journal file.\n", fst
.fst_bytesalloc
/1024LL);
444 buf
= (char *)calloc(block_size
, 1);
446 for(i
=0; i
< journal_size
/block_size
; i
++) {
447 ret
= write(fd
, buf
, block_size
);
448 if (ret
!= block_size
) {
453 if (i
*block_size
!= journal_size
) {
454 fprintf(stderr
, "Failed to write %dk to journal on volume %s (%s)\n",
455 journal_size
/1024, volname
, strerror(errno
));
458 printf("Could not allocate memory to write to the journal on volume %s (%s)\n",
459 volname
, strerror(errno
));
464 hide_file(journal_fname
);
466 start_block
= get_start_block(journal_fname
, block_size
);
467 if (start_block
== (off_t
)-1) {
468 fprintf(stderr
, "Failed to get start block for %s (%s)\n",
469 journal_fname
, strerror(errno
));
470 unlink(journal_fname
);
473 jstart_block
= (start_block
/ block_size
) - (embedded_offset
/ block_size
);
475 memset(&jib
, 'Z', sizeof(jib
));
476 jib
.flags
= kJIJournalInFSMask
;
477 jib
.offset
= (off_t
)((unsigned)jstart_block
) * (off_t
)((unsigned)block_size
);
478 jib
.size
= (off_t
)((unsigned)journal_size
);
480 fd
= open(jib_fname
, O_CREAT
|O_TRUNC
|O_RDWR
, 000);
482 fprintf(stderr
, "Could not create journal info block file on volume %s (%s)\n",
483 volname
, strerror(errno
));
484 unlink(journal_fname
);
488 // swap the data before we copy it
489 jib
.flags
= OSSwapBigToHostInt32(jib
.flags
);
490 jib
.offset
= OSSwapBigToHostInt64(jib
.offset
);
491 jib
.size
= OSSwapBigToHostInt64(jib
.size
);
493 memcpy(buf
, &jib
, sizeof(jib
));
495 // now put it back the way it was
496 jib
.size
= OSSwapBigToHostInt64(jib
.size
);
497 jib
.offset
= OSSwapBigToHostInt64(jib
.offset
);
498 jib
.flags
= OSSwapBigToHostInt32(jib
.flags
);
500 if (write(fd
, buf
, block_size
) != block_size
) {
501 fprintf(stderr
, "Failed to write journal info block on volume %s (%s)!\n",
502 volname
, strerror(errno
));
503 unlink(journal_fname
);
509 hide_file(jib_fname
);
511 start_block
= get_start_block(jib_fname
, block_size
);
512 if (start_block
== (off_t
)-1) {
513 fprintf(stderr
, "Failed to get start block for %s (%s)\n",
514 jib_fname
, strerror(errno
));
515 unlink(journal_fname
);
519 jinfo_block
= (start_block
/ block_size
) - (embedded_offset
/ block_size
);
523 // Now make the volume journaled!
525 memset(sysctl_info
, 0, sizeof(sysctl_info
));
526 sysctl_info
[0] = CTL_VFS
;
527 sysctl_info
[1] = sfs
.f_fsid
.val
[1];
528 sysctl_info
[2] = HFS_ENABLE_JOURNALING
;
529 sysctl_info
[3] = jinfo_block
;
530 sysctl_info
[4] = jstart_block
;
531 sysctl_info
[5] = journal_size
;
533 //printf("fs type: 0x%x\n", sysctl_info[1]);
534 //printf("jinfo block : 0x%x\n", jinfo_block);
535 //printf("jstart block: 0x%x\n", jstart_block);
536 //printf("journal size: 0x%x\n", journal_size);
538 ret
= sysctl((void *)sysctl_info
, 6, NULL
, NULL
, NULL
, 0);
540 fprintf(stderr
, "Failed to make volume %s journaled (%s)\n",
541 volname
, strerror(errno
));
542 unlink(journal_fname
);
552 DoUnJournal(char *volname
)
557 char jbuf
[MAXPATHLEN
];
559 if (statfs(volname
, &sfs
) != 0) {
560 fprintf(stderr
, "Can't stat volume %s (%s).\n", volname
, strerror(errno
));
564 if ((sfs
.f_flags
& MNT_JOURNALED
) == 0) {
565 fprintf(stderr
, "Volume %s is not journaled.\n", volname
);
569 if (chdir(volname
) != 0) {
570 fprintf(stderr
, "Can't locate volume %s to turn off journaling (%s).\n",
571 volname
, strerror(errno
));
575 memset(sysctl_info
, 0, sizeof(sysctl_info
));
576 sysctl_info
[0] = CTL_VFS
;
577 sysctl_info
[1] = sfs
.f_fsid
.val
[1];
578 sysctl_info
[2] = HFS_DISABLE_JOURNALING
;
580 result
= sysctl((void *)sysctl_info
, 3, NULL
, NULL
, NULL
, 0);
582 fprintf(stderr
, "Failed to make volume %s UN-journaled (%s)\n",
583 volname
, strerror(errno
));
587 sprintf(jbuf
, "%s/%s", volname
, journal_fname
);
588 if (unlink(jbuf
) != 0) {
589 fprintf(stderr
, "Failed to remove the journal %s (%s)\n",
590 jbuf
, strerror(errno
));
593 sprintf(jbuf
, "%s/%s", volname
, jib_fname
);
594 if (unlink(jbuf
) != 0) {
595 fprintf(stderr
, "Failed to remove the journal info block %s (%s)\n",
596 jbuf
, strerror(errno
));
599 printf("Journaling disabled on %s\n", volname
);
606 DoGetJournalInfo(char *volname
)
613 if (statfs(volname
, &sfs
) != 0) {
614 fprintf(stderr
, "Can't stat volume %s (%s).\n", volname
, strerror(errno
));
618 if ((sfs
.f_flags
& MNT_JOURNALED
) == 0) {
619 fprintf(stderr
, "Volume %s is not journaled.\n", volname
);
623 if (chdir(volname
) != 0) {
624 fprintf(stderr
, "Can't cd to volume %s to get journal info (%s).\n",
625 volname
, strerror(errno
));
629 memset(sysctl_info
, 0, sizeof(sysctl_info
));
630 sysctl_info
[0] = CTL_VFS
;
631 sysctl_info
[1] = sfs
.f_fsid
.val
[1];
632 sysctl_info
[2] = HFS_GET_JOURNAL_INFO
;
633 sysctl_info
[3] = (int)&jstart
;
634 sysctl_info
[4] = (int)&jsize
;
636 result
= sysctl((void *)sysctl_info
, 5, NULL
, NULL
, NULL
, 0);
638 fprintf(stderr
, "Failed to get journal info for volume %s (%s)\n",
639 volname
, strerror(errno
));
644 printf("%s : not journaled.\n", volname
);
646 printf("%s : journal size %lld k at offset 0x%llx\n", volname
, jsize
/1024, jstart
);
654 RawDisableJournaling(char *devname
)
656 int fd
= -1, ret
= 0;
657 char *buff
= NULL
, rawdev
[256];
662 HFSMasterDirectoryBlock
*mdbp
;
663 HFSPlusVolumeHeader
*vhp
;
664 off_t embeddedOffset
, hdr_offset
;
669 if (stat(devname
, &st
) != 0) {
670 fprintf(stderr
, "Could not access %s (%s)\n", devname
, strerror(errno
));
675 if (S_ISCHR(st
.st_mode
) == 0) {
676 // hmmm, it's not the character special raw device so we
677 // should try to figure out the real device.
678 if (S_ISBLK(st
.st_mode
)) {
679 strcpy(rawdev
, "/dev/r");
680 strcat(rawdev
, devname
+ 5);
682 if (statfs(devname
, &sfs
) != 0) {
683 fprintf(stderr
, "Can't find out any info about the fs for path %s (%s)\n",
684 devname
, strerror(errno
));
690 strncpy(rawdev
, sfs
.f_mntfromname
, 5);
692 strcpy(&rawdev
[6], &sfs
.f_mntfromname
[5]);
695 devname
= &rawdev
[0];
699 fd
= open(devname
, O_RDWR
);
701 fprintf(stderr
, "can't open: %s (%s)\n", devname
, strerror(errno
));
706 /* Get the real physical block size. */
707 if (ioctl(fd
, DKIOCGETBLOCKSIZE
, (caddr_t
)&blksize
) != 0) {
708 fprintf(stderr
, "can't get the device block size (%s). assuming 512\n", strerror(errno
));
714 /* Get the number of physical blocks. */
715 if (ioctl(fd
, DKIOCGETBLOCKCOUNT
, (caddr_t
)&blkcnt
)) {
718 if (fstat(fd
, &st
) != 0) {
723 blkcnt
= st
.st_size
/ blksize
;
726 /* Compute an accurate disk size */
727 disksize
= blkcnt
* (u_int64_t
)blksize
;
730 * There are only 31 bits worth of block count in
731 * the buffer cache. So for large volumes a 4K
732 * physical block size is needed.
734 if (blksize
== 512 && blkcnt
> (u_int64_t
)0x000000007fffffff) {
740 * blksize has our prefered physical block size
741 * blkcnt has the total number of physical blocks
744 buff
= (char *)malloc(blksize
);
746 hdr_offset
= HFS_PRI_SECTOR(blksize
)*blksize
;
747 if (pread(fd
, buff
, blksize
, hdr_offset
) != blksize
) {
748 fprintf(stderr
, "failed to read volume header @ offset %lld (%s)\n",
749 hdr_offset
, strerror(errno
));
754 // if we read in an empty bunch of junk at location zero, then
755 // retry at offset 0x400 which is where the header normally is.
756 if (*(int *)buff
== 0 && hdr_offset
== 0) {
758 if (pread(fd
, buff
, blksize
, hdr_offset
) != blksize
) {
759 fprintf(stderr
, "failed to read volume header @ offset %lld (%s)\n",
760 hdr_offset
, strerror(errno
));
768 mdbp
= (HFSMasterDirectoryBlock
*)buff
;
769 if ((SWAP_BE16(mdbp
->drSigWord
) == kHFSSigWord
) && (SWAP_BE16(mdbp
->drEmbedSigWord
) != kHFSPlusSigWord
)) {
770 // normal hfs can not ever be journaled
771 fprintf(stderr
, "disable_journaling: volume is only regular HFS, not HFS+\n");
775 /* Get the embedded Volume Header */
776 if (SWAP_BE16(mdbp
->drEmbedSigWord
) == kHFSPlusSigWord
) {
777 embeddedOffset
= SWAP_BE16(mdbp
->drAlBlSt
) * 512;
778 embeddedOffset
+= (u_int64_t
)SWAP_BE16(mdbp
->drEmbedExtent
.startBlock
) * (u_int64_t
)SWAP_BE32(mdbp
->drAlBlkSiz
);
781 * If the embedded volume doesn't start on a block
782 * boundary, then switch the device to a 512-byte
783 * block size so everything will line up on a block
786 if ((embeddedOffset
% blksize
) != 0) {
787 fprintf(stderr
, "HFS Mount: embedded volume offset not"
788 " a multiple of physical block size (%d);"
789 " switching to 512\n", blksize
);
791 blkcnt
*= (blksize
/ 512);
795 disksize
= (u_int64_t
)SWAP_BE16(mdbp
->drEmbedExtent
.blockCount
) * (u_int64_t
)SWAP_BE32(mdbp
->drAlBlkSiz
);
797 mdb_offset
= (embeddedOffset
/ blksize
) + HFS_PRI_SECTOR(blksize
);
798 hdr_offset
= mdb_offset
* blksize
;
799 if (pread(fd
, buff
, blksize
, hdr_offset
) != blksize
) {
800 fprintf(stderr
, "failed to read the embedded vhp @ offset %d\n", mdb_offset
* blksize
);
805 vhp
= (HFSPlusVolumeHeader
*) buff
;
806 } else /* pure HFS+ */ {
808 vhp
= (HFSPlusVolumeHeader
*) mdbp
;
812 if ((SWAP_BE32(vhp
->attributes
) & kHFSVolumeJournaledMask
) != 0) {
813 unsigned int tmp
= SWAP_BE32(vhp
->attributes
);
815 tmp
&= ~kHFSVolumeJournaledMask
;
816 vhp
->attributes
= SWAP_BE32(tmp
);
817 if ((tmp
= pwrite(fd
, buff
, blksize
, hdr_offset
)) != blksize
) {
818 fprintf(stderr
, "Update of super-block on %s failed! (%d != %d, %s)\n",
819 devname
, tmp
, blksize
, strerror(errno
));
821 fprintf(stderr
, "Turned off the journaling bit for %s\n", devname
);
824 fprintf(stderr
, "disable_journaling: volume was not journaled.\n");