Bug Summary

File:src/gnu/usr.sbin/mkhybrid/mkhybrid/../src/libhfs_iso/hfs.c
Warning:line 317, column 5
Use of memory after it is freed

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name hfs.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/gnu/usr.sbin/mkhybrid/mkhybrid/obj -resource-dir /usr/local/lib/clang/13.0.0 -D SYSTEM_ID_DEFAULT="OpenBSD" -D APPLE_HYB -D VANILLA_AUTOCONF -I /usr/src/gnu/usr.sbin/mkhybrid/mkhybrid/../src -I /usr/src/gnu/usr.sbin/mkhybrid/mkhybrid/../src/include -I /usr/src/gnu/usr.sbin/mkhybrid/mkhybrid/../src/libhfs_iso -I /usr/src/gnu/usr.sbin/mkhybrid/mkhybrid/../src/libfile -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/gnu/usr.sbin/mkhybrid/mkhybrid/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/gnu/usr.sbin/mkhybrid/mkhybrid/../src/libhfs_iso/hfs.c
1/*
2 * hfsutils - tools for reading and writing Macintosh HFS volumes
3 * Copyright (C) 1996, 1997 Robert Leslie
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20/* APPLE_HYB James Pearson j.pearson@ps.ucl.ac.uk 16/7/97 */
21
22# include <stdlib.h>
23# include <unistd.h>
24# include <fcntl.h>
25# include <errno(*__errno()).h>
26# include <string.h>
27# include <time.h>
28# include <ctype.h>
29# include <sys/stat.h>
30
31# include "internal.h"
32# include "data.h"
33# include "block.h"
34# include "low.h"
35# include "file.h"
36# include "btree.h"
37# include "node.h"
38# include "record.h"
39# include "volume.h"
40
41char *hfs_error = "no error"; /* static error string */
42
43hfsvol *hfs_mounts; /* linked list of mounted volumes */
44hfsvol *hfs_curvol; /* current volume */
45
46/* High-Level Volume Routines ============================================== */
47
48/*
49 * NAME: hfs->mount()
50 * DESCRIPTION: open an HFS volume; return volume descriptor or 0 (error)
51 */
52#ifdef APPLE_HYB1
53hfsvol *hfs_mount(hce_mem *hce, int pnum, int flags)
54#else
55hfsvol *hfs_mount(char *path, int pnum, int flags)
56#endif /* APPLE_HYB */
57{
58 hfsvol *vol = 0;
59
60#ifndef APPLE_HYB1
61
62 struct stat dev;
63 /* see if the volume is already mounted */
64
65 if (stat(path, &dev) >= 0)
66 {
67 struct stat mdev;
68 hfsvol *check;
69
70 for (check = hfs_mounts; check; check = check->next)
71 {
72 if (fstat(check->fd, &mdev) >= 0 &&
73 mdev.st_dev == dev.st_dev &&
74 mdev.st_ino == dev.st_ino &&
75 (check->pnum == 0 || check->pnum == pnum))
76 {
77 /* verify compatible read/write mode */
78
79 if (((check->flags & HFS_READONLY0x01) &&
80 ! (flags & O_WRONLY0x0001)) ||
81 (! (check->flags & HFS_READONLY0x01) &&
82 (flags & (O_WRONLY0x0001 | O_RDWR0x0002))))
83 {
84 vol = check;
85 break;
86 }
87 }
88 }
89 }
90#endif /* APPLE_HYB */
91 if (vol == 0)
92 {
93 vol = ALLOC(hfsvol, 1)((hfsvol *) malloc(((size_t) (sizeof(hfsvol) * (1)))));
94 if (vol == 0)
95 {
96 ERROR(ENOMEM, 0)(hfs_error = (0), (*__errno()) = (12));
97 return 0;
98 }
99
100 vol->flags = 0;
101 vol->pnum = pnum;
102 vol->vstart = 0;
103 vol->vlen = 0;
104 vol->lpa = 0;
105 vol->vbm = 0;
106 vol->cwd = HFS_CNID_ROOTDIR2;
107
108 vol->refs = 0;
109 vol->files = 0;
110 vol->dirs = 0;
111 vol->prev = 0;
112 vol->next = 0;
113
114 vol->ext.map = 0;
115 vol->ext.mapsz = 0;
116 vol->ext.flags = 0;
117 vol->ext.compare = r_compareextkeys;
118
119 vol->cat.map = 0;
120 vol->cat.mapsz = 0;
121 vol->cat.flags = 0;
122 vol->cat.compare = r_comparecatkeys;
123
124 /* open and lock the device */
125
126#ifdef APPLE_HYB1
127 vol->fd = 3; /* any +ve number will do? */
128 vol->hce = hce; /* store the extra with the vol info */
129#else
130 if (flags & (O_WRONLY0x0001 | O_RDWR0x0002))
131 {
132 vol->fd = open(path, O_RDWR0x0002);
133 if (vol->fd >= 0 && l_lockvol(vol) < 0)
134 {
135 close(vol->fd);
136 vol->fd = -2;
137 }
138 }
139
140 if (! (flags & (O_WRONLY0x0001 | O_RDWR0x0002)) ||
141 (vol->fd < 0 &&
142 (errno(*__errno()) == EROFS30 || errno(*__errno()) == EACCES13 || errno(*__errno()) == EAGAIN35) &&
143 (flags & O_RDWR0x0002)))
144 {
145 vol->flags |= HFS_READONLY0x01;
146 vol->fd = open(path, O_RDONLY0x0000);
147 if (vol->fd >= 0 && l_lockvol(vol) < 0)
148 {
149 close(vol->fd);
150 vol->fd = -2;
151 }
152 }
153
154 if (vol->fd < 0)
155 {
156 if (vol->fd != -2)
157 ERROR(errno, "error opening device")(hfs_error = ("error opening device"), (*__errno()) = ((*__errno
())))
;
158
159 v_destruct(vol);
160
161 return 0;
162 }
163#endif /* APPLE_HYB */
164
165 /* find out what kind of media this is and read the MDB */
166
167 if (l_readblock0(vol) < 0 ||
168 l_readmdb(vol) < 0)
169 {
170#ifndef APPLE_HYB1
171 close(vol->fd);
172 v_destruct(vol);
173#endif /* APPLE_HYB */
174 return 0;
175 }
176
177 /* verify this is an HFS volume */
178
179 if (vol->mdb.drSigWord != 0x4244)
180 {
181#ifndef APPLE_HYB1
182 close(vol->fd);
183#endif /* APPLE_HYB */
184 v_destruct(vol);
185
186 ERROR(EINVAL, "not a Macintosh HFS volume")(hfs_error = ("not a Macintosh HFS volume"), (*__errno()) = (
22))
;
187 return 0;
188 }
189
190 /* do minimal consistency checks */
191
192 if (vol->mdb.drAlBlkSiz % HFS_BLOCKSZ512 != 0)
193 {
194#ifndef APPLE_HYB1
195 close(vol->fd);
196#endif /* APPLE_HYB */
197 v_destruct(vol);
198
199 ERROR(EINVAL, "bad volume allocation block size")(hfs_error = ("bad volume allocation block size"), (*__errno(
)) = (22))
;
200 return 0;
201 }
202
203 if (vol->vlen == 0)
204 vol->vlen = vol->mdb.drAlBlSt +
205 vol->mdb.drNmAlBlks * (vol->mdb.drAlBlkSiz / HFS_BLOCKSZ512) + 2;
206
207 /* read the volume bitmap and extents/catalog B*-tree headers */
208
209 if (l_readvbm(vol) < 0 ||
210 bt_readhdr(&vol->ext) < 0 ||
211 bt_readhdr(&vol->cat) < 0)
212 {
213#ifndef APPLE_HYB1
214 close(vol->fd);
215#endif /* APPLE_HYB */
216 v_destruct(vol);
217 return 0;
218 }
219
220 if (! (vol->mdb.drAtrb & HFS_ATRB_UMOUNTED(1 << 8)))
221 {
222 /* volume was not cleanly unmounted; scavenge free-space */
223
224 if (v_scavenge(vol) < 0)
225 {
226#ifndef APPLE_HYB1
227 close(vol->fd);
228#endif /* APPLE_HYB */
229 v_destruct(vol);
230 return 0;
231 }
232 }
233
234 if (vol->flags & HFS_READONLY0x01)
235 vol->mdb.drAtrb |= HFS_ATRB_HLOCKED(1 << 7);
236 else
237 vol->mdb.drAtrb &= ~HFS_ATRB_HLOCKED(1 << 7);
238
239 vol->prev = 0;
240 vol->next = hfs_mounts;
241
242 if (hfs_mounts)
243 hfs_mounts->prev = vol;
244
245 hfs_mounts = vol;
246 }
247
248 ++vol->refs;
249
250 return hfs_curvol = vol;
251}
252
253/*
254 * NAME: hfs->flush()
255 * DESCRIPTION: flush all pending changes to an HFS volume
256 */
257int hfs_flush(hfsvol *vol)
258{
259 hfsfile *file;
260
261 if (v_getvol(&vol) < 0)
262 return -1;
263
264 for (file = vol->files; file; file = file->next)
265 {
266 if (f_flush(file) < 0)
267 return -1;
268 }
269
270 if (v_flush(vol, 0) < 0)
271 return -1;
272
273 return 0;
274}
275
276/*
277 * NAME: hfs->flushall()
278 * DESCRIPTION: flush all pending changes to all mounted HFS volumes
279 */
280void hfs_flushall(void)
281{
282 hfsvol *vol;
283
284 for (vol = hfs_mounts; vol; vol = vol->next)
285 hfs_flush(vol);
286}
287
288/*
289 * NAME: hfs->umount()
290 * DESCRIPTION: close an HFS volume
291 */
292#ifdef APPLE_HYB1
293/* extra argument used to alter the position of the extents/catalog files */
294int hfs_umount(hfsvol *vol, long end)
295#else
296int hfs_umount(hfsvol *vol)
297#endif /* APPLE_HYB */
298{
299 int result = 0;
300
301 if (v_getvol(&vol) < 0)
1
Assuming the condition is false
2
Taking false branch
302 return -1;
303
304 if (--vol->refs)
3
Assuming the condition is false
4
Taking false branch
305 return v_flush(vol, 0);
306
307 /* close all open files and directories */
308
309 while (vol->files)
5
Loop condition is false. Execution continues on line 316
310#ifdef APPLE_HYB1
311 hfs_close(vol->files, 0, 0);
312#else
313 hfs_close(vol->files);
314#endif /* APPLE_HYB */
315
316 while (vol->dirs)
6
Loop condition is true. Entering loop body
17
Loop condition is true. Entering loop body
317 hfs_closedir(vol->dirs);
7
Calling 'hfs_closedir'
16
Returning; memory was released via 1st parameter
18
Use of memory after it is freed
318
319#ifdef APPLE_HYB1
320 if (end)
321 {
322 /* move extents and catalog to end of volume ... */
323 long vbmsz = (vol->vlen / vol->lpa + 4095) / 4096;
324
325 /* we are adding this "files" to the end of the ISO volume,
326 so calculate this address in HFS speak ... */
327/* end -= vol->mdb.drAlBlSt; */
328 end -= (vol->mdb.drAlBlSt + vol->hce->hfs_map_size);
329 end /= vol->lpa;
330
331 /* catalog file ... */
332 vol->ext.f.cat.u.fil.filExtRec[0].xdrStABN = end;
333 vol->mdb.drXTExtRec[0].xdrStABN = end;
334
335 /* move postition to start of extents file */
336 end += vol->cat.f.cat.u.fil.filExtRec[0].xdrStABN;
337
338 /* extents file ... */
339 vol->cat.f.cat.u.fil.filExtRec[0].xdrStABN = end;
340 vol->mdb.drCTExtRec[0].xdrStABN = end;
341
342 /* the volume bitmap is wrong as we have "moved" files
343 about - simple just set the whole lot (it's a readonly volume
344 anyway!) */
345 memset(vol->vbm, 0xff, vbmsz*HFS_BLOCKSZ512);
346
347 /* set the free blocks to zero */
348 vol->mdb.drFreeBks = 0;
349
350 /* flag changes for flushing later */
351 vol->flags |= HFS_UPDATE_VBM0x40;
352 vol->flags |= HFS_UPDATE_MDB0x10;
353 vol->mdb.drAtrb |= HFS_ATRB_HLOCKED(1 << 7);
354 vol->ext.flags |= HFS_UPDATE_BTHDR0x01;
355 vol->cat.flags |= HFS_UPDATE_BTHDR0x01;
356 }
357#endif /* APPLE_HYB */
358
359 if (v_flush(vol, 1) < 0)
360 result = -1;
361
362#ifndef APPLE_HYB1
363 if (close(vol->fd) < 0 && result == 0)
364 {
365 ERROR(errno, "error closing device")(hfs_error = ("error closing device"), (*__errno()) = ((*__errno
())))
;
366 result = -1;
367 }
368#endif /* APPLE_HYB */
369
370 if (vol->prev)
371 vol->prev->next = vol->next;
372 if (vol->next)
373 vol->next->prev = vol->prev;
374
375 if (vol == hfs_mounts)
376 hfs_mounts = vol->next;
377 if (vol == hfs_curvol)
378 hfs_curvol = 0;
379
380 v_destruct(vol);
381
382 return result;
383}
384
385/*
386 * NAME: hfs->umountall()
387 * DESCRIPTION: unmount all mounted volumes
388 */
389void hfs_umountall(void)
390{
391 while (hfs_mounts)
392#ifdef APPLE_HYB1
393 continue;
394#else
395 hfs_umount(hfs_mounts);
396#endif /* APPLE_HYB */
397}
398
399/*
400 * NAME: hfs->getvol()
401 * DESCRIPTION: return a pointer to a mounted volume
402 */
403hfsvol *hfs_getvol(char *name)
404{
405 hfsvol *vol;
406
407 if (name == 0)
408 return hfs_curvol;
409
410 for (vol = hfs_mounts; vol; vol = vol->next)
411 {
412 if (d_relstring(name, vol->mdb.drVN) == 0)
413 return vol;
414 }
415
416 return 0;
417}
418
419/*
420 * NAME: hfs->setvol()
421 * DESCRIPTION: change the current volume
422 */
423void hfs_setvol(hfsvol *vol)
424{
425 hfs_curvol = vol;
426}
427
428/*
429 * NAME: hfs->vstat()
430 * DESCRIPTION: return volume statistics
431 */
432int hfs_vstat(hfsvol *vol, hfsvolent *ent)
433{
434 if (v_getvol(&vol) < 0)
435 return -1;
436
437 strcpy(ent->name, vol->mdb.drVN);
438
439 ent->flags = (vol->flags & HFS_READONLY0x01) ? HFS_ISLOCKED0x02 : 0;
440 ent->totbytes = vol->mdb.drNmAlBlks * vol->mdb.drAlBlkSiz;
441 ent->freebytes = vol->mdb.drFreeBks * vol->mdb.drAlBlkSiz;
442 ent->crdate = d_toutime(vol->mdb.drCrDate);
443 ent->mddate = d_toutime(vol->mdb.drLsMod);
444
445 return 0;
446}
447
448/*
449 * NAME: hfs->format()
450 * DESCRIPTION: write a new filesystem
451 */
452#ifdef APPLE_HYB1
453int hfs_format(hce_mem *hce, int pnum, char *vname)
454#else
455int hfs_format(char *path, int pnum, char *vname)
456#endif /* APPLE_HYB */
457{
458 hfsvol vol;
459 btree *ext = &vol.ext;
460 btree *cat = &vol.cat;
461 unsigned int vbmsz;
462 int i, result = 0;
463 block vbm[16];
464 char *map;
465
466 if (strchr(vname, ':'))
467 {
468 ERROR(EINVAL, "volume name may not contain colons")(hfs_error = ("volume name may not contain colons"), (*__errno
()) = (22))
;
469 return -1;
470 }
471
472 i = strlen(vname);
473 if (i < 1 || i > HFS_MAX_VLEN27)
474 {
475 ERROR(EINVAL, "volume name must be 1-27 chars")(hfs_error = ("volume name must be 1-27 chars"), (*__errno())
= (22))
;
476 return -1;
477 }
478
479 vol.flags = 0;
480 vol.pnum = pnum;
481 vol.vstart = 0;
482 vol.vlen = 0;
483 vol.lpa = 0;
484 vol.vbm = vbm;
485 vol.cwd = HFS_CNID_ROOTDIR2;
486
487 vol.refs = 0;
488 vol.files = 0;
489 vol.dirs = 0;
490 vol.prev = 0;
491 vol.next = 0;
492
493#ifndef APPLE_HYB1
494 vol.fd = open(path, O_RDWR0x0002);
495 if (vol.fd < 0)
496 {
497 ERROR(errno, "error opening device for writing")(hfs_error = ("error opening device for writing"), (*__errno(
)) = ((*__errno())))
;
498 return -1;
499 }
500
501 if (l_lockvol(&vol) < 0)
502 {
503 close(vol.fd);
504 return -1;
505 }
506#endif /* APPLE_HYB */
507 if (pnum > 0)
508 {
509 if (l_readpm(&vol) < 0)
510 {
511 close(vol.fd);
512 return -1;
513 }
514 }
515 else /* determine size of entire device */
516 {
517#ifdef APPLE_HYB1
518 vol.vlen = hce->hfs_vol_size/HFS_BLOCKSZ512;
519#else
520 unsigned long low, high, mid;
521 block b;
522
523 for (low = 0, high = 2879; b_readlb(&vol, high, &b) >= 0; high *= 2)
524 low = high;
525
526 while (low < high - 1)
527 {
528 mid = (low + high) / 2;
529
530 if (b_readlb(&vol, mid, &b) < 0)
531 high = mid;
532 else
533 low = mid;
534 }
535
536 vol.vlen = low + 1;
537#endif /* APPLE_HYB */
538 }
539
540 if (vol.vlen < 800 * 1024 / HFS_BLOCKSZ512)
541 {
542#ifndef APPLE_HYB1
543 close(vol.fd);
544#endif /* APPLE_HYB */
545
546 ERROR(EINVAL, "volume size must be >= 800K")(hfs_error = ("volume size must be >= 800K"), (*__errno())
= (22))
;
547 return -1;
548 }
549
550 /* initialize volume geometry */
551
552#ifdef APPLE_HYB1
553 /* force lpa to be a multiple of 4 (i.e. 2048/512) - as calculated
554 earlier */
555 vol.lpa = hce->Csize/HFS_BLOCKSZ512;
556#else
557 vol.lpa = 1 + vol.vlen / 65536;
558#endif /* APPLE_HYB */
559
560 vbmsz = (vol.vlen / vol.lpa + 4095) / 4096;
561
562 vol.mdb.drSigWord = 0x4244;
563 vol.mdb.drCrDate = d_tomtime(time(0));
564 vol.mdb.drLsMod = vol.mdb.drCrDate;
565 vol.mdb.drAtrb = 0;
566 vol.mdb.drNmFls = 0;
567 vol.mdb.drVBMSt = 3;
568 vol.mdb.drAllocPtr = 0;
569 vol.mdb.drNmAlBlks = (vol.vlen - 5 - vbmsz) / vol.lpa;
570 vol.mdb.drAlBlkSiz = vol.lpa * HFS_BLOCKSZ512;
571 vol.mdb.drClpSiz = vol.mdb.drAlBlkSiz * 4;
572 vol.mdb.drAlBlSt = 3 + vbmsz;
573#ifdef APPLE_HYB1
574 /* round up start block to a muliple of lpa - important later */
575/*vol.mdb.drAlBlSt = ((vol.mdb.drAlBlSt + vol.lpa - 1) / vol.lpa) * vol.lpa;
576*/
577 /* take in accout alignment of files wrt HFS volume start i.e we want
578 drAlBlSt plus hfs_map_size to me a multiple of lpa */
579 vol.mdb.drAlBlSt = ((vol.mdb.drAlBlSt + hce->hfs_map_size + vol.lpa - 1) / vol.lpa) * vol.lpa;
580 vol.mdb.drAlBlSt -= hce->hfs_map_size;
581#endif /* APPLE_HYB */
582 vol.mdb.drNxtCNID = HFS_CNID_ROOTDIR2; /* modified later */
583 vol.mdb.drFreeBks = vol.mdb.drNmAlBlks;
584
585 strcpy(vol.mdb.drVN, vname);
586
587 vol.mdb.drVolBkUp = 0;
588 vol.mdb.drVSeqNum = 0;
589 vol.mdb.drWrCnt = 0;
590 vol.mdb.drXTClpSiz = vol.mdb.drNmAlBlks / 128 * vol.mdb.drAlBlkSiz;
591#ifdef APPLE_HYB1
592 /* adjust size of extents/catalog upwards as we may have rounded up
593 allocation size */
594 i = 1 + vol.vlen / 65536;
595
596 vol.mdb.drXTClpSiz = (vol.mdb.drXTClpSiz * vol.lpa) / i;
597
598 /* round up to lpa size */
599 vol.mdb.drXTClpSiz = ((vol.mdb.drXTClpSiz + vol.mdb.drAlBlkSiz - 1) /
600 vol.mdb.drAlBlkSiz) * vol.mdb.drAlBlkSiz;
601
602 /* ignore above, use what we have already calculated ... */
603 vol.mdb.drXTClpSiz = hce->XTCsize;
604
605 /* make Catalog file CTC (default twice) as big - prevents further allocation
606 later which we don't want - this seems to work OK ... */
607/*vol.mdb.drCTClpSiz = vol.mdb.drXTClpSiz * CTC; */
608 vol.mdb.drCTClpSiz = vol.mdb.drXTClpSiz * hce->ctc_size;
609
610 /* we want to put things at the end of the volume later, so we'll
611 cheat here ... shouldn't matter, as we only need the volume read
612 only anyway (we won't be adding files later!) - leave some extra
613 space for the alternative MDB (in the last allocation block) */
614
615 vol.mdb.drNmAlBlks = vol.mdb.drFreeBks = vol.vlen / vol.lpa - 1;
616#else
617 vol.mdb.drCTClpSiz = vol.mdb.drXTClpSiz;
618#endif /* APPLE_HYB */
619 vol.mdb.drNmRtDirs = 0;
620 vol.mdb.drFilCnt = 0;
621 vol.mdb.drDirCnt = -1; /* incremented when root folder is created */
622
623 for (i = 0; i < 8; ++i)
624 vol.mdb.drFndrInfo[i] = 0;
625
626 vol.mdb.drVCSize = 0;
627 vol.mdb.drVBMCSize = 0;
628 vol.mdb.drCtlCSize = 0;
629
630 vol.mdb.drXTFlSize = 0;
631 vol.mdb.drCTFlSize = 0;
632
633 for (i = 0; i < 3; ++i)
634 {
635 vol.mdb.drXTExtRec[i].xdrStABN = 0;
636 vol.mdb.drXTExtRec[i].xdrNumABlks = 0;
637
638 vol.mdb.drCTExtRec[i].xdrStABN = 0;
639 vol.mdb.drCTExtRec[i].xdrNumABlks = 0;
640 }
641
642 /* initialize volume bitmap */
643
644 memset(vol.vbm, 0, sizeof(vbm));
645
646#ifdef APPLE_HYB1
647 /* We don't want to write anything out at the moment, so we allocate
648 memory to hold the HFS "header" info and extents/catalog files.
649 Any reads/writes from/to these parts of the volume are trapped and
650 stored in memory. */
651
652 /* blocks up to the first unallocated block == HFS "header" info
653 This will be placed in the first 32kb of the ISO volume later */
654 hce->hfs_hdr_size = vol.mdb.drAlBlSt;
655
656 /* size of the extents and catalog files. This will be added
657 to the end of the ISO volume later */
658 hce->hfs_ce_size = vol.mdb.drXTClpSiz + vol.mdb.drCTClpSiz;
659
660 /* we also allocate space for the Desktop file and the alternative
661 MDB while we're here */
662 FREE(hce->hfs_ce)((hce->hfs_ce) ? (void) free((void *) hce->hfs_ce) : (void
) 0)
;
663 hce->hfs_ce = ALLOC(unsigned char, (hce->hfs_ce_size + vol.mdb.drClpSiz((unsigned char *) malloc(((size_t) (sizeof(unsigned char) * (
(hce->hfs_ce_size + vol.mdb.drClpSiz + vol.mdb.drAlBlkSiz)
)))))
664 + vol.mdb.drAlBlkSiz))((unsigned char *) malloc(((size_t) (sizeof(unsigned char) * (
(hce->hfs_ce_size + vol.mdb.drClpSiz + vol.mdb.drAlBlkSiz)
)))))
;
665
666 /* allocate memory for the map and hdr */
667 FREE(hce->hfs_map)((hce->hfs_map) ? (void) free((void *) hce->hfs_map) : (
void) 0)
;
668 hce->hfs_map = ALLOC(unsigned char, ((hce->hfs_hdr_size + hce->hfs_map_size)((unsigned char *) malloc(((size_t) (sizeof(unsigned char) * (
((hce->hfs_hdr_size + hce->hfs_map_size) *512))))))
669 *HFS_BLOCKSZ))((unsigned char *) malloc(((size_t) (sizeof(unsigned char) * (
((hce->hfs_hdr_size + hce->hfs_map_size) *512))))))
;
670
671 if (hce->hfs_ce == 0 || hce->hfs_map == 0)
672 {
673 ERROR(ENOMEM, 0)(hfs_error = (0), (*__errno()) = (12));
674 result = -1;
675 }
676
677 /* hfs_hdr is immediately after the hfs_map */
678 hce->hfs_hdr = hce->hfs_map + hce->hfs_map_size*HFS_BLOCKSZ512;
679
680 /* size needed in HFS_BLOCKSZ blocks for later use */
681 hce->hfs_ce_size /= HFS_BLOCKSZ512;
682
683 /* note size of Desktop file */
684 hce->hfs_dt_size = vol.mdb.drClpSiz/HFS_BLOCKSZ512;
685
686 /* total size of catalog/extents and desktop */
687 hce->hfs_tot_size = hce->hfs_ce_size + hce->hfs_dt_size;
688
689 /* alternative MDB in the last alocation block */
690 hce->hfs_alt_mdb = hce->hfs_ce + hce->hfs_tot_size*HFS_BLOCKSZ512;
691
692 /* add the MDB to the total size */
693 hce->hfs_tot_size += vol.lpa;
694
695 /* store this info in the volume info */
696 vol.hce = hce;
697
698#endif /* APPLE_HYB */
699
700 /* create extents overflow file */
701
702 ext->f.vol = &vol;
703 ext->f.parid = 0;
704 strcpy(ext->f.name, "extents overflow");
705
706 ext->f.cat.cdrType = cdrFilRec;
707 /* ext->f.cat.cdrResrv2 */
708 ext->f.cat.u.fil.filFlags = 0;
709 ext->f.cat.u.fil.filTyp = 0;
710 /* ext->f.cat.u.fil.filUsrWds */
711 ext->f.cat.u.fil.filFlNum = HFS_CNID_EXT3;
712 ext->f.cat.u.fil.filStBlk = 0;
713 ext->f.cat.u.fil.filLgLen = 0;
714 ext->f.cat.u.fil.filPyLen = 0;
715 ext->f.cat.u.fil.filRStBlk = 0;
716 ext->f.cat.u.fil.filRLgLen = 0;
717 ext->f.cat.u.fil.filRPyLen = 0;
718 ext->f.cat.u.fil.filCrDat = vol.mdb.drCrDate;
719 ext->f.cat.u.fil.filMdDat = vol.mdb.drLsMod;
720 ext->f.cat.u.fil.filBkDat = 0;
721 /* ext->f.cat.u.fil.filFndrInfo */
722 ext->f.cat.u.fil.filClpSize = 0;
723
724 for (i = 0; i < 3; ++i)
725 {
726 ext->f.cat.u.fil.filExtRec[i].xdrStABN = 0;
727 ext->f.cat.u.fil.filExtRec[i].xdrNumABlks = 0;
728
729 ext->f.cat.u.fil.filRExtRec[i].xdrStABN = 0;
730 ext->f.cat.u.fil.filRExtRec[i].xdrNumABlks = 0;
731 }
732 /* ext->f.cat.u.fil.filResrv */
733 f_selectfork(&ext->f, 0);
734
735 ext->f.clump = vol.mdb.drXTClpSiz;
736 ext->f.flags = 0;
737
738 ext->f.prev = ext->f.next = 0;
739
740 n_init(&ext->hdrnd, ext, ndHdrNode, 0);
741
742 ext->hdrnd.nnum = 0;
743 ext->hdrnd.nd.ndNRecs = 3;
744 ext->hdrnd.roff[1] = 0x078;
745 ext->hdrnd.roff[2] = 0x0f8;
746 ext->hdrnd.roff[3] = 0x1f8;
747
748 memset(HFS_NODEREC(ext->hdrnd, 1)((ext->hdrnd).data + (ext->hdrnd).roff[1]), 0, 128);
749
750 ext->hdr.bthDepth = 0;
751 ext->hdr.bthRoot = 0;
752 ext->hdr.bthNRecs = 0;
753 ext->hdr.bthFNode = 0;
754 ext->hdr.bthLNode = 0;
755 ext->hdr.bthNodeSize = HFS_BLOCKSZ512;
756 ext->hdr.bthKeyLen = 0x07;
757 ext->hdr.bthNNodes = 0;
758 ext->hdr.bthFree = 0;
759 for (i = 0; i < 76; ++i)
760 ext->hdr.bthResv[i] = 0;
761
762 map = ALLOC(char, HFS_MAP1SZ)((char *) malloc(((size_t) (sizeof(char) * (256)))));
763 if (map == 0)
764 {
765 if (result == 0)
766 {
767 ERROR(ENOMEM, 0)(hfs_error = (0), (*__errno()) = (12));
768 result = -1;
769 }
770 }
771 else
772 {
773 memset(map, 0, HFS_MAP1SZ256);
774 BMSET(map, 0)(((char *) (map))[(0) >> 3] |= (0x80 >> ((0) &
0x07)))
;
775 }
776
777 ext->map = map;
778 ext->mapsz = HFS_MAP1SZ256;
779 ext->flags = HFS_UPDATE_BTHDR0x01;
780 ext->compare = r_compareextkeys;
781
782 if (result == 0 && bt_space(ext, 1) < 0)
783 result = -1;
784
785 --ext->hdr.bthFree;
786
787 /* create catalog file */
788
789 cat->f.vol = &vol;
790 cat->f.parid = 0;
791 strcpy(cat->f.name, "catalog");
792
793 cat->f.cat.cdrType = cdrFilRec;
794 /* cat->f.cat.cdrResrv2 */
795 cat->f.cat.u.fil.filFlags = 0;
796 cat->f.cat.u.fil.filTyp = 0;
797 /* cat->f.cat.u.fil.filUsrWds */
798 cat->f.cat.u.fil.filFlNum = HFS_CNID_CAT4;
799 cat->f.cat.u.fil.filStBlk = 0;
800 cat->f.cat.u.fil.filLgLen = 0;
801 cat->f.cat.u.fil.filPyLen = 0;
802 cat->f.cat.u.fil.filRStBlk = 0;
803 cat->f.cat.u.fil.filRLgLen = 0;
804 cat->f.cat.u.fil.filRPyLen = 0;
805 cat->f.cat.u.fil.filCrDat = vol.mdb.drCrDate;
806 cat->f.cat.u.fil.filMdDat = vol.mdb.drLsMod;
807 cat->f.cat.u.fil.filBkDat = 0;
808 /* cat->f.cat.u.fil.filFndrInfo */
809 cat->f.cat.u.fil.filClpSize = 0;
810
811 for (i = 0; i < 3; ++i)
812 {
813 cat->f.cat.u.fil.filExtRec[i].xdrStABN = 0;
814 cat->f.cat.u.fil.filExtRec[i].xdrNumABlks = 0;
815
816 cat->f.cat.u.fil.filRExtRec[i].xdrStABN = 0;
817 cat->f.cat.u.fil.filRExtRec[i].xdrNumABlks = 0;
818 }
819 /* cat->f.cat.u.fil.filResrv */
820 f_selectfork(&cat->f, 0);
821
822 cat->f.clump = vol.mdb.drCTClpSiz;
823 cat->f.flags = 0;
824
825 cat->f.prev = cat->f.next = 0;
826
827 n_init(&cat->hdrnd, cat, ndHdrNode, 0);
828
829 cat->hdrnd.nnum = 0;
830 cat->hdrnd.nd.ndNRecs = 3;
831 cat->hdrnd.roff[1] = 0x078;
832 cat->hdrnd.roff[2] = 0x0f8;
833 cat->hdrnd.roff[3] = 0x1f8;
834
835 memset(HFS_NODEREC(cat->hdrnd, 1)((cat->hdrnd).data + (cat->hdrnd).roff[1]), 0, 128);
836
837 cat->hdr.bthDepth = 0;
838 cat->hdr.bthRoot = 0;
839 cat->hdr.bthNRecs = 0;
840 cat->hdr.bthFNode = 0;
841 cat->hdr.bthLNode = 0;
842 cat->hdr.bthNodeSize = HFS_BLOCKSZ512;
843 cat->hdr.bthKeyLen = 0x25;
844 cat->hdr.bthNNodes = 0;
845 cat->hdr.bthFree = 0;
846 for (i = 0; i < 76; ++i)
847 cat->hdr.bthResv[i] = 0;
848
849 map = ALLOC(char, HFS_MAP1SZ)((char *) malloc(((size_t) (sizeof(char) * (256)))));
850 if (map == 0)
851 {
852 if (result == 0)
853 {
854 ERROR(ENOMEM, 0)(hfs_error = (0), (*__errno()) = (12));
855 result = -1;
856 }
857 }
858 else
859 {
860 memset(map, 0, HFS_MAP1SZ256);
861 BMSET(map, 0)(((char *) (map))[(0) >> 3] |= (0x80 >> ((0) &
0x07)))
;
862 }
863
864 cat->map = map;
865 cat->mapsz = HFS_MAP1SZ256;
866 cat->flags = HFS_UPDATE_BTHDR0x01;
867 cat->compare = r_comparecatkeys;
868
869 if (result == 0 && bt_space(cat, 1) < 0)
870 result = -1;
871
872 --cat->hdr.bthFree;
873
874 /* create root folder */
875
876 if (result == 0 && v_newfolder(&vol, HFS_CNID_ROOTPAR1, vname) < 0)
877 result = -1;
878
879 vol.mdb.drNxtCNID = 16;
880
881 /* finish up */
882
883 if (result == 0)
884 {
885 block b;
886
887 /* write boot blocks */
888
889 memset(&b, 0, sizeof(b));
890 b_writelb(&vol, 0, &b);
891 b_writelb(&vol, 1, &b);
892
893 /* flush other disk state */
894
895 vol.flags |= HFS_UPDATE_MDB0x10 | HFS_UPDATE_ALTMDB0x20 | HFS_UPDATE_VBM0x40;
896
897 if (v_flush(&vol, 1) < 0)
898 result = -1;
899 }
900#ifndef APPLE_HYB1
901 if (close(vol.fd) < 0 && result == 0)
902 {
903 ERROR(errno, "error closing device")(hfs_error = ("error closing device"), (*__errno()) = ((*__errno
())))
;
904 result = -1;
905 }
906#endif /* APPLE_HYB */
907 FREE(vol.ext.map)((vol.ext.map) ? (void) free((void *) vol.ext.map) : (void) 0
)
;
908 FREE(vol.cat.map)((vol.cat.map) ? (void) free((void *) vol.cat.map) : (void) 0
)
;
909
910 return result;
911}
912
913/* High-Level Directory Routines =========================================== */
914
915/*
916 * NAME: hfs->chdir()
917 * DESCRIPTION: change current HFS directory
918 */
919int hfs_chdir(hfsvol *vol, char *path)
920{
921 CatDataRec data;
922
923 if (v_getvol(&vol) < 0 ||
924 v_resolve(&vol, path, &data, 0, 0, 0) <= 0)
925 return -1;
926
927 if (data.cdrType != cdrDirRec)
928 {
929 ERROR(ENOTDIR, 0)(hfs_error = (0), (*__errno()) = (20));
930 return -1;
931 }
932
933 vol->cwd = data.u.dir.dirDirID;
934
935 return 0;
936}
937
938/*
939 * NAME: hfs->getcwd()
940 * DESCRIPTION: return the current working directory ID
941 */
942long hfs_getcwd(hfsvol *vol)
943{
944 if (v_getvol(&vol) < 0)
945 return 0;
946
947 return vol->cwd;
948}
949
950/*
951 * NAME: hfs->setcwd()
952 * DESCRIPTION: set the current working directory ID
953 */
954int hfs_setcwd(hfsvol *vol, long id)
955{
956 if (v_getvol(&vol) < 0)
957 return -1;
958
959 if (id == vol->cwd)
960 return 0;
961
962 /* make sure the directory exists */
963
964 if (v_getdthread(vol, id, 0, 0)v_getthread(vol, id, 0, 0, cdrThdRec) <= 0)
965 return -1;
966
967 vol->cwd = id;
968
969 return 0;
970}
971
972/*
973 * NAME: hfs->dirinfo()
974 * DESCRIPTION: given a directory ID, return its (name and) parent ID
975 */
976int hfs_dirinfo(hfsvol *vol, long *id, char *name)
977{
978 CatDataRec thread;
979
980 if (v_getvol(&vol) < 0 ||
981 v_getdthread(vol, *id, &thread, 0)v_getthread(vol, *id, &thread, 0, cdrThdRec) <= 0)
982 return -1;
983
984 *id = thread.u.dthd.thdParID;
985
986 if (name)
987 strcpy(name, thread.u.dthd.thdCName);
988
989 return 0;
990}
991
992/*
993 * NAME: hfs->opendir()
994 * DESCRIPTION: prepare to read the contents of a directory
995 */
996hfsdir *hfs_opendir(hfsvol *vol, char *path)
997{
998 hfsdir *dir;
999 CatKeyRec key;
1000 CatDataRec data;
1001 unsigned char pkey[HFS_CATKEYLENsizeof(CatKeyRec)];
1002
1003 if (v_getvol(&vol) < 0)
1004 return 0;
1005
1006 dir = ALLOC(hfsdir, 1)((hfsdir *) malloc(((size_t) (sizeof(hfsdir) * (1)))));
1007 if (dir == 0)
1008 {
1009 ERROR(ENOMEM, 0)(hfs_error = (0), (*__errno()) = (12));
1010 return 0;
1011 }
1012
1013 dir->vol = vol;
1014
1015 if (*path == 0)
1016 {
1017 /* meta-directory containing root dirs from all mounted volumes */
1018
1019 dir->dirid = 0;
1020 dir->vptr = hfs_mounts;
1021 }
1022 else
1023 {
1024 if (v_resolve(&vol, path, &data, 0, 0, 0) <= 0)
1025 {
1026 FREE(dir)((dir) ? (void) free((void *) dir) : (void) 0);
1027 return 0;
1028 }
1029
1030 if (data.cdrType != cdrDirRec)
1031 {
1032 FREE(dir)((dir) ? (void) free((void *) dir) : (void) 0);
1033 ERROR(ENOTDIR, 0)(hfs_error = (0), (*__errno()) = (20));
1034 return 0;
1035 }
1036
1037 dir->dirid = data.u.dir.dirDirID;
1038 dir->vptr = 0;
1039
1040 r_makecatkey(&key, dir->dirid, "");
1041 r_packcatkey(&key, pkey, 0);
1042
1043 if (bt_search(&vol->cat, pkey, &dir->n) <= 0)
1044 {
1045 FREE(dir)((dir) ? (void) free((void *) dir) : (void) 0);
1046 return 0;
1047 }
1048 }
1049
1050 dir->prev = 0;
1051 dir->next = vol->dirs;
1052
1053 if (vol->dirs)
1054 vol->dirs->prev = dir;
1055
1056 vol->dirs = dir;
1057
1058 return dir;
1059}
1060
1061/*
1062 * NAME: hfs->readdir()
1063 * DESCRIPTION: return the next entry in the directory
1064 */
1065int hfs_readdir(hfsdir *dir, hfsdirent *ent)
1066{
1067 CatKeyRec key;
1068 CatDataRec data;
1069 unsigned char *ptr;
1070
1071 if (dir->dirid == 0)
1072 {
1073 hfsvol *vol;
1074 char cname[HFS_MAX_FLEN31 + 1];
1075
1076 for (vol = hfs_mounts; vol; vol = vol->next)
1077 {
1078 if (vol == dir->vptr)
1079 break;
1080 }
1081
1082 if (vol == 0)
1083 {
1084 ERROR(ENOENT, "no more entries")(hfs_error = ("no more entries"), (*__errno()) = (2));
1085 return -1;
1086 }
1087
1088 if (v_getdthread(vol, HFS_CNID_ROOTDIR, &data, 0)v_getthread(vol, 2, &data, 0, cdrThdRec) <= 0 ||
1089 v_catsearch(vol, HFS_CNID_ROOTPAR1, data.u.dthd.thdCName,
1090 &data, cname, 0) < 0)
1091 return -1;
1092
1093 r_unpackdirent(HFS_CNID_ROOTPAR1, cname, &data, ent);
1094
1095 dir->vptr = vol->next;
1096
1097 return 0;
1098 }
1099
1100 if (dir->n.rnum == -1)
1101 {
1102 ERROR(ENOENT, "no more entries")(hfs_error = ("no more entries"), (*__errno()) = (2));
1103 return -1;
1104 }
1105
1106 while (1)
1107 {
1108 ++dir->n.rnum;
1109
1110 while (dir->n.rnum >= dir->n.nd.ndNRecs)
1111 {
1112 dir->n.nnum = dir->n.nd.ndFLink;
1113 if (dir->n.nnum == 0)
1114 {
1115 dir->n.rnum = -1;
1116 ERROR(ENOENT, "no more entries")(hfs_error = ("no more entries"), (*__errno()) = (2));
1117 return -1;
1118 }
1119
1120 if (bt_getnode(&dir->n) < 0)
1121 {
1122 dir->n.rnum = -1;
1123 return -1;
1124 }
1125
1126 dir->n.rnum = 0;
1127 }
1128
1129 ptr = HFS_NODEREC(dir->n, dir->n.rnum)((dir->n).data + (dir->n).roff[dir->n.rnum]);
1130
1131 r_unpackcatkey(ptr, &key);
1132
1133 if (key.ckrParID != dir->dirid)
1134 {
1135 dir->n.rnum = -1;
1136 ERROR(ENOENT, "no more entries")(hfs_error = ("no more entries"), (*__errno()) = (2));
1137 return -1;
1138 }
1139
1140 r_unpackcatdata(HFS_RECDATA(ptr)((ptr) + ((1 + (*(unsigned char *) (ptr)) + 1) & ~1)), &data);
1141
1142 switch (data.cdrType)
1143 {
1144 case cdrDirRec:
1145 case cdrFilRec:
1146 r_unpackdirent(key.ckrParID, key.ckrCName, &data, ent);
1147 return 0;
1148
1149 case cdrThdRec:
1150 case cdrFThdRec:
1151 break;
1152
1153 default:
1154 dir->n.rnum = -1;
1155
1156 ERROR(EIO, "unexpected directory entry found")(hfs_error = ("unexpected directory entry found"), (*__errno(
)) = (5))
;
1157 return -1;
1158 }
1159 }
1160}
1161
1162/*
1163 * NAME: hfs->closedir()
1164 * DESCRIPTION: stop reading a directory
1165 */
1166int hfs_closedir(hfsdir *dir)
1167{
1168 hfsvol *vol = dir->vol;
1169
1170 if (dir->prev)
8
Assuming field 'prev' is null
9
Taking false branch
1171 dir->prev->next = dir->next;
1172 if (dir->next)
10
Assuming field 'next' is null
11
Taking false branch
1173 dir->next->prev = dir->prev;
1174 if (dir == vol->dirs)
12
Assuming 'dir' is not equal to field 'dirs'
13
Taking false branch
1175 vol->dirs = dir->next;
1176
1177 FREE(dir)((dir) ? (void) free((void *) dir) : (void) 0);
14
'?' condition is true
15
Memory is released
1178
1179 return 0;
1180}
1181
1182/* High-Level File Routines ================================================ */
1183
1184/*
1185 * NAME: hfs->open()
1186 * DESCRIPTION: prepare a file for I/O
1187 */
1188hfsfile *hfs_open(hfsvol *vol, char *path)
1189{
1190 hfsfile *file;
1191
1192 if (v_getvol(&vol) < 0)
1193 return 0;
1194
1195 file = ALLOC(hfsfile, 1)((hfsfile *) malloc(((size_t) (sizeof(hfsfile) * (1)))));
1196 if (file == 0)
1197 {
1198 ERROR(ENOMEM, 0)(hfs_error = (0), (*__errno()) = (12));
1199 return 0;
1200 }
1201
1202 if (v_resolve(&vol, path, &file->cat, &file->parid, file->name, 0) <= 0)
1203 {
1204 FREE(file)((file) ? (void) free((void *) file) : (void) 0);
1205 return 0;
1206 }
1207
1208 if (file->cat.cdrType != cdrFilRec)
1209 {
1210 FREE(file)((file) ? (void) free((void *) file) : (void) 0);
1211 ERROR(EISDIR, 0)(hfs_error = (0), (*__errno()) = (21));
1212 return 0;
1213 }
1214
1215 file->vol = vol;
1216 file->clump = file->cat.u.fil.filClpSize;
1217 file->flags = 0;
1218
1219 f_selectfork(file, 0);
1220
1221 file->prev = 0;
1222 file->next = vol->files;
1223
1224 if (vol->files)
1225 vol->files->prev = file;
1226
1227 vol->files = file;
1228
1229 return file;
1230}
1231
1232/*
1233 * NAME: hfs->setfork()
1234 * DESCRIPTION: select file fork for I/O operations
1235 */
1236int hfs_setfork(hfsfile *file, int fork)
1237{
1238 int result = 0;
1239
1240 if (! (file->vol->flags & HFS_READONLY0x01) &&
1241 f_trunc(file) < 0)
1242 result = -1;
1243
1244 f_selectfork(file, fork);
1245
1246 return result;
1247}
1248
1249/*
1250 * NAME: hfs->getfork()
1251 * DESCRIPTION: return the current fork for I/O operations
1252 */
1253int hfs_getfork(hfsfile *file)
1254{
1255 return file->fork != fkData;
1256}
1257
1258/*
1259 * NAME: hfs->read()
1260 * DESCRIPTION: read from an open file
1261 */
1262long hfs_read(hfsfile *file, void *buf, unsigned long len)
1263{
1264 unsigned long *lglen, count;
1265 unsigned char *ptr = buf;
1266
1267 f_getptrs(file, &lglen, 0, 0);
1268
1269 if (file->pos + len > *lglen)
1270 len = *lglen - file->pos;
1271
1272 count = len;
1273 while (count)
1274 {
1275 block b;
1276 unsigned long bnum, offs, chunk;
1277
1278 bnum = file->pos / HFS_BLOCKSZ512;
1279 offs = file->pos % HFS_BLOCKSZ512;
1280
1281 chunk = HFS_BLOCKSZ512 - offs;
1282 if (chunk > count)
1283 chunk = count;
1284
1285 if (f_getblock(file, bnum, &b)f_doblock(file, bnum, &b, b_readab) < 0)
1286 return -1;
1287
1288 memcpy(ptr, b + offs, chunk);
1289 ptr += chunk;
1290
1291 file->pos += chunk;
1292 count -= chunk;
1293 }
1294
1295 return len;
1296}
1297
1298/*
1299 * NAME: hfs->write()
1300 * DESCRIPTION: write to an open file
1301 */
1302long hfs_write(hfsfile *file, void *buf, unsigned long len)
1303{
1304 unsigned long *lglen, *pylen, count;
1305 unsigned char *ptr = buf;
1306
1307 if (file->vol->flags & HFS_READONLY0x01)
1308 {
1309 ERROR(EROFS, 0)(hfs_error = (0), (*__errno()) = (30));
1310 return -1;
1311 }
1312
1313 f_getptrs(file, &lglen, &pylen, 0);
1314
1315 count = len;
1316
1317 /* set flag to update (at least) the modification time */
1318
1319 if (count)
1320 {
1321 file->cat.u.fil.filMdDat = d_tomtime(time(0));
1322 file->flags |= HFS_UPDATE_CATREC0x01;
1323 }
1324
1325 while (count)
1326 {
1327 block b;
1328 unsigned long bnum, offs, chunk;
1329
1330 bnum = file->pos / HFS_BLOCKSZ512;
1331 offs = file->pos % HFS_BLOCKSZ512;
1332
1333 chunk = HFS_BLOCKSZ512 - offs;
1334 if (chunk > count)
1335 chunk = count;
1336
1337 if (file->pos + chunk > *pylen)
1338 {
1339 if (bt_space(&file->vol->ext, 1) < 0 ||
1340 f_alloc(file) < 0)
1341 return -1;
1342 }
1343#ifndef APPLE_HYB1
1344 /* Ignore this part as we are always writing new files to an empty disk
1345 i.e. offs will always be 0 */
1346
1347 if (offs > 0 || chunk < HFS_BLOCKSZ512)
1348 {
1349 if (f_getblock(file, bnum, &b)f_doblock(file, bnum, &b, b_readab) < 0)
1350 return -1;
1351 }
1352#endif /* APPLE_HYB */
1353 memcpy(b + offs, ptr, chunk);
1354 ptr += chunk;
1355
1356 if (f_putblock(file, bnum, &b)f_doblock(file, bnum, &b, b_writeab) < 0)
1357 return -1;
1358
1359 file->pos += chunk;
1360 count -= chunk;
1361
1362 if (file->pos > *lglen)
1363 *lglen = file->pos;
1364 }
1365
1366 return len;
1367}
1368
1369/*
1370 * NAME: hfs->truncate()
1371 * DESCRIPTION: truncate an open file
1372 */
1373int hfs_truncate(hfsfile *file, unsigned long len)
1374{
1375 unsigned long *lglen;
1376
1377 f_getptrs(file, &lglen, 0, 0);
1378
1379 if (*lglen > len)
1380 {
1381 if (file->vol->flags & HFS_READONLY0x01)
1382 {
1383 ERROR(EROFS, 0)(hfs_error = (0), (*__errno()) = (30));
1384 return -1;
1385 }
1386
1387 *lglen = len;
1388
1389 file->cat.u.fil.filMdDat = d_tomtime(time(0));
1390 file->flags |= HFS_UPDATE_CATREC0x01;
1391
1392 if (file->pos > len)
1393 file->pos = len;
1394 }
1395
1396 return 0;
1397}
1398
1399/*
1400 * NAME: hfs->lseek()
1401 * DESCRIPTION: change file seek pointer
1402 */
1403long hfs_lseek(hfsfile *file, long offset, int from)
1404{
1405 unsigned long *lglen;
1406 long newpos;
1407
1408 f_getptrs(file, &lglen, 0, 0);
1409
1410 switch (from)
1411 {
1412 case SEEK_SET0:
1413 newpos = offset;
1414 break;
1415
1416 case SEEK_CUR1:
1417 newpos = file->pos + offset;
1418 break;
1419
1420 case SEEK_END2:
1421 newpos = *lglen + offset;
1422 break;
1423
1424 default:
1425 ERROR(EINVAL, 0)(hfs_error = (0), (*__errno()) = (22));
1426 return -1;
1427 }
1428
1429 if (newpos < 0)
1430 newpos = 0;
1431 else if (newpos > *lglen)
1432 newpos = *lglen;
1433
1434 file->pos = newpos;
1435
1436 return newpos;
1437}
1438
1439/*
1440 * NAME: hfs->close()
1441 * DESCRIPTION: close a file
1442 */
1443#ifdef APPLE_HYB1
1444/* extra args are used to set the start of the forks in the ISO volume */
1445int hfs_close(hfsfile *file, long dext, long rext)
1446{
1447 int offset;
1448#else
1449int hfs_close(hfsfile *file)
1450{
1451#endif /* APPLE_HYB */
1452 hfsvol *vol = file->vol;
1453 int result = 0;
1454
1455 if (f_trunc(file) < 0 ||
1456 f_flush(file) < 0)
1457 result = -1;
1458
1459#ifdef APPLE_HYB1
1460 /* "start" of file is relative to the first available block */
1461 offset = vol->hce->hfs_hdr_size + vol->hce->hfs_map_size;
1462 /* update the "real" starting extent and re-flush the file */
1463 if (dext)
1464 file->cat.u.fil.filExtRec[0].xdrStABN = (dext - offset)/vol->lpa;
1465
1466 if (rext)
1467 file->cat.u.fil.filRExtRec[0].xdrStABN = (rext - offset)/vol->lpa;
1468
1469 if (dext || rext)
1470 file->flags |= HFS_UPDATE_CATREC0x01;
1471
1472 if (f_flush(file) < 0)
1473 result = -1;
1474#endif /*APPLE_HYB */
1475
1476 if (file->prev)
1477 file->prev->next = file->next;
1478 if (file->next)
1479 file->next->prev = file->prev;
1480 if (file == vol->files)
1481 vol->files = file->next;
1482
1483 FREE(file)((file) ? (void) free((void *) file) : (void) 0);
1484
1485 return result;
1486}
1487
1488/* High-Level Catalog Routines ============================================= */
1489
1490/*
1491 * NAME: hfs->stat()
1492 * DESCRIPTION: return catalog information for an arbitrary path
1493 */
1494int hfs_stat(hfsvol *vol, char *path, hfsdirent *ent)
1495{
1496 CatDataRec data;
1497 long parid;
1498 char name[HFS_MAX_FLEN31 + 1];
1499
1500 if (v_getvol(&vol) < 0 ||
1501 v_resolve(&vol, path, &data, &parid, name, 0) <= 0)
1502 return -1;
1503
1504 r_unpackdirent(parid, name, &data, ent);
1505
1506 return 0;
1507}
1508
1509/*
1510 * NAME: hfs->fstat()
1511 * DESCRIPTION: return catalog information for an open file
1512 */
1513int hfs_fstat(hfsfile *file, hfsdirent *ent)
1514{
1515 r_unpackdirent(file->parid, file->name, &file->cat, ent);
1516
1517 return 0;
1518}
1519
1520/*
1521 * NAME: hfs->setattr()
1522 * DESCRIPTION: change a file's attributes
1523 */
1524int hfs_setattr(hfsvol *vol, char *path, hfsdirent *ent)
1525{
1526 CatDataRec data;
1527 node n;
1528
1529 if (v_getvol(&vol) < 0 ||
1530 v_resolve(&vol, path, &data, 0, 0, &n) <= 0)
1531 return -1;
1532
1533 if (vol->flags & HFS_READONLY0x01)
1534 {
1535 ERROR(EROFS, 0)(hfs_error = (0), (*__errno()) = (30));
1536 return -1;
1537 }
1538
1539 r_packdirent(&data, ent);
1540
1541 if (v_putcatrec(&data, &n) < 0)
1542 return -1;
1543
1544 return 0;
1545}
1546
1547/*
1548 * NAME: hfs->fsetattr()
1549 * DESCRIPTION: change an open file's attributes
1550 */
1551int hfs_fsetattr(hfsfile *file, hfsdirent *ent)
1552{
1553 if (file->vol->flags & HFS_READONLY0x01)
1554 {
1555 ERROR(EROFS, 0)(hfs_error = (0), (*__errno()) = (30));
1556 return -1;
1557 }
1558
1559 r_packdirent(&file->cat, ent);
1560
1561 file->flags |= HFS_UPDATE_CATREC0x01;
1562
1563 return 0;
1564}
1565
1566/*
1567 * NAME: hfs->mkdir()
1568 * DESCRIPTION: create a new directory
1569 */
1570int hfs_mkdir(hfsvol *vol, char *path)
1571{
1572 CatDataRec data;
1573 long parid;
1574 char name[HFS_MAX_FLEN31 + 1];
1575 int found;
1576
1577 if (v_getvol(&vol) < 0)
1578 return -1;
1579
1580 found = v_resolve(&vol, path, &data, &parid, name, 0);
1581 if (found < 0 || parid == 0)
1582 return -1;
1583 else if (found)
1584 {
1585 ERROR(EEXIST, 0)(hfs_error = (0), (*__errno()) = (17));
1586 return -1;
1587 }
1588
1589 if (parid == HFS_CNID_ROOTPAR1)
1590 {
1591 ERROR(EINVAL, 0)(hfs_error = (0), (*__errno()) = (22));
1592 return -1;
1593 }
1594
1595 if (vol->flags & HFS_READONLY0x01)
1596 {
1597 ERROR(EROFS, 0)(hfs_error = (0), (*__errno()) = (30));
1598 return -1;
1599 }
1600
1601 if (v_newfolder(vol, parid, name) < 0)
1602 return -1;
1603
1604 return 0;
1605}
1606
1607/*
1608 * NAME: hfs->rmdir()
1609 * DESCRIPTION: delete an empty directory
1610 */
1611int hfs_rmdir(hfsvol *vol, char *path)
1612{
1613 CatKeyRec key;
1614 CatDataRec data;
1615 long parid;
1616 char name[HFS_MAX_FLEN31 + 1];
1617 unsigned char pkey[HFS_CATKEYLENsizeof(CatKeyRec)];
1618
1619 if (v_getvol(&vol) < 0 ||
1620 v_resolve(&vol, path, &data, &parid, name, 0) <= 0)
1621 return -1;
1622
1623 if (data.cdrType != cdrDirRec)
1624 {
1625 ERROR(ENOTDIR, 0)(hfs_error = (0), (*__errno()) = (20));
1626 return -1;
1627 }
1628
1629 if (data.u.dir.dirVal != 0)
1630 {
1631 ERROR(ENOTEMPTY, 0)(hfs_error = (0), (*__errno()) = (66));
1632 return -1;
1633 }
1634
1635 if (parid == HFS_CNID_ROOTPAR1)
1636 {
1637 ERROR(EINVAL, 0)(hfs_error = (0), (*__errno()) = (22));
1638 return -1;
1639 }
1640
1641 if (vol->flags & HFS_READONLY0x01)
1642 {
1643 ERROR(EROFS, 0)(hfs_error = (0), (*__errno()) = (30));
1644 return -1;
1645 }
1646
1647 /* delete directory record */
1648
1649 r_makecatkey(&key, parid, name);
1650 r_packcatkey(&key, pkey, 0);
1651
1652 if (bt_delete(&vol->cat, pkey) < 0)
1653 return -1;
1654
1655 /* delete thread record */
1656
1657 r_makecatkey(&key, data.u.dir.dirDirID, "");
1658 r_packcatkey(&key, pkey, 0);
1659
1660 if (bt_delete(&vol->cat, pkey) < 0 ||
1661 v_adjvalence(vol, parid, 1, -1) < 0)
1662 return -1;
1663
1664 return 0;
1665}
1666
1667/*
1668 * NAME: hfs->create()
1669 * DESCRIPTION: create a new file
1670 */
1671int hfs_create(hfsvol *vol, char *path, char *type, char *creator)
1672{
1673 CatKeyRec key;
1674 CatDataRec data;
1675 long id, parid;
1676 char name[HFS_MAX_FLEN31 + 1];
1677 unsigned char record[HFS_CATRECMAXLEN(sizeof(CatKeyRec) + sizeof(CatDataRec))];
1678 int found, i, reclen;
1679
1680 if (v_getvol(&vol) < 0)
1681 return -1;
1682
1683 found = v_resolve(&vol, path, &data, &parid, name, 0);
1684 if (found < 0 || parid == 0)
1685 return -1;
1686 else if (found)
1687 {
1688 ERROR(EEXIST, 0)(hfs_error = (0), (*__errno()) = (17));
1689 return -1;
1690 }
1691
1692 if (parid == HFS_CNID_ROOTPAR1)
1693 {
1694 ERROR(EINVAL, 0)(hfs_error = (0), (*__errno()) = (22));
1695 return -1;
1696 }
1697
1698 if (vol->flags & HFS_READONLY0x01)
1699 {
1700 ERROR(EROFS, 0)(hfs_error = (0), (*__errno()) = (30));
1701 return -1;
1702 }
1703
1704 /* create file `name' in parent `parid' */
1705
1706 if (bt_space(&vol->cat, 1) < 0)
1707 return -1;
1708
1709 id = vol->mdb.drNxtCNID++;
1710 vol->flags |= HFS_UPDATE_MDB0x10;
1711
1712 /* create file record */
1713
1714 data.cdrType = cdrFilRec;
1715 data.cdrResrv2 = 0;
1716
1717 data.u.fil.filFlags = 0;
1718 data.u.fil.filTyp = 0;
1719
1720 memset(&data.u.fil.filUsrWds, 0, sizeof(data.u.fil.filUsrWds));
1721
1722 data.u.fil.filUsrWds.fdType = d_getl((unsigned char *) type);
1723 data.u.fil.filUsrWds.fdCreator = d_getl((unsigned char *) creator);
1724
1725 data.u.fil.filFlNum = id;
1726 data.u.fil.filStBlk = 0;
1727 data.u.fil.filLgLen = 0;
1728 data.u.fil.filPyLen = 0;
1729 data.u.fil.filRStBlk = 0;
1730 data.u.fil.filRLgLen = 0;
1731 data.u.fil.filRPyLen = 0;
1732 data.u.fil.filCrDat = d_tomtime(time(0));
1733 data.u.fil.filMdDat = data.u.fil.filCrDat;
1734 data.u.fil.filBkDat = 0;
1735
1736 memset(&data.u.fil.filFndrInfo, 0, sizeof(data.u.fil.filFndrInfo));
1737
1738 data.u.fil.filClpSize = 0;
1739
1740 for (i = 0; i < 3; ++i)
1741 {
1742 data.u.fil.filExtRec[i].xdrStABN = 0;
1743 data.u.fil.filExtRec[i].xdrNumABlks = 0;
1744
1745 data.u.fil.filRExtRec[i].xdrStABN = 0;
1746 data.u.fil.filRExtRec[i].xdrNumABlks = 0;
1747 }
1748
1749 data.u.fil.filResrv = 0;
1750
1751 r_makecatkey(&key, parid, name);
1752 r_packcatkey(&key, record, &reclen);
1753 r_packcatdata(&data, HFS_RECDATA(record)((record) + ((1 + (*(unsigned char *) (record)) + 1) & ~1
))
, &reclen);
1754
1755 if (bt_insert(&vol->cat, record, reclen) < 0 ||
1756 v_adjvalence(vol, parid, 0, 1) < 0)
1757 return -1;
1758
1759 return 0;
1760}
1761
1762/*
1763 * NAME: hfs->delete()
1764 * DESCRIPTION: remove both forks of a file
1765 */
1766int hfs_delete(hfsvol *vol, char *path)
1767{
1768 hfsfile file;
1769 CatKeyRec key;
1770 unsigned char pkey[HFS_CATKEYLENsizeof(CatKeyRec)];
1771 int found;
1772
1773 if (v_getvol(&vol) < 0 ||
1774 v_resolve(&vol, path, &file.cat, &file.parid, file.name, 0) <= 0)
1775 return -1;
1776
1777 if (file.cat.cdrType != cdrFilRec)
1778 {
1779 ERROR(EISDIR, 0)(hfs_error = (0), (*__errno()) = (21));
1780 return -1;
1781 }
1782
1783 if (file.parid == HFS_CNID_ROOTPAR1)
1784 {
1785 ERROR(EINVAL, 0)(hfs_error = (0), (*__errno()) = (22));
1786 return -1;
1787 }
1788
1789 if (vol->flags & HFS_READONLY0x01)
1790 {
1791 ERROR(EROFS, 0)(hfs_error = (0), (*__errno()) = (30));
1792 return -1;
1793 }
1794
1795 /* free disk blocks */
1796
1797 file.vol = vol;
1798 file.flags = 0;
1799
1800 file.cat.u.fil.filLgLen = 0;
1801 file.cat.u.fil.filRLgLen = 0;
1802
1803 f_selectfork(&file, 0);
1804 if (f_trunc(&file) < 0)
1805 return -1;
1806
1807 f_selectfork(&file, 1);
1808 if (f_trunc(&file) < 0)
1809 return -1;
1810
1811 /* delete file record */
1812
1813 r_makecatkey(&key, file.parid, file.name);
1814 r_packcatkey(&key, pkey, 0);
1815
1816 if (bt_delete(&vol->cat, pkey) < 0 ||
1817 v_adjvalence(vol, file.parid, 0, -1) < 0)
1818 return -1;
1819
1820 /* delete file thread, if any */
1821
1822 found = v_getfthread(vol, file.cat.u.fil.filFlNum, 0, 0)v_getthread(vol, file.cat.u.fil.filFlNum, 0, 0, cdrFThdRec);
1823 if (found < 0)
1824 return -1;
1825
1826 if (found)
1827 {
1828 r_makecatkey(&key, file.cat.u.fil.filFlNum, "");
1829 r_packcatkey(&key, pkey, 0);
1830
1831 if (bt_delete(&vol->cat, pkey) < 0)
1832 return -1;
1833 }
1834
1835 return 0;
1836}
1837
1838/*
1839 * NAME: hfs->rename()
1840 * DESCRIPTION: change the name of and/or move a file or directory
1841 */
1842int hfs_rename(hfsvol *vol, char *srcpath, char *dstpath)
1843{
1844 hfsvol *srcvol;
1845 CatDataRec src, dst;
1846 long srcid, dstid;
1847 CatKeyRec key;
1848 char srcname[HFS_MAX_FLEN31 + 1], dstname[HFS_MAX_FLEN31 + 1];
1849 unsigned char record[HFS_CATRECMAXLEN(sizeof(CatKeyRec) + sizeof(CatDataRec))];
1850 int found, isdir, moving, reclen;
1851 node n;
1852
1853 if (v_getvol(&vol) < 0 ||
1854 v_resolve(&vol, srcpath, &src, &srcid, srcname, 0) <= 0)
1855 return -1;
1856
1857 isdir = (src.cdrType == cdrDirRec);
1858 srcvol = vol;
1859
1860 found = v_resolve(&vol, dstpath, &dst, &dstid, dstname, 0);
1861 if (found < 0)
1862 return -1;
1863
1864 if (vol != srcvol)
1865 {
1866 ERROR(EINVAL, "can't move across volumes")(hfs_error = ("can't move across volumes"), (*__errno()) = (22
))
;
1867 return -1;
1868 }
1869
1870 if (dstid == 0)
1871 {
1872 ERROR(ENOENT, "bad destination path")(hfs_error = ("bad destination path"), (*__errno()) = (2));
1873 return -1;
1874 }
1875
1876 if (found &&
1877 dst.cdrType == cdrDirRec &&
1878 dst.u.dir.dirDirID != src.u.dir.dirDirID)
1879 {
1880 dstid = dst.u.dir.dirDirID;
1881 strcpy(dstname, srcname);
1882
1883 found = v_catsearch(vol, dstid, dstname, 0, 0, 0);
1884 if (found < 0)
1885 return -1;
1886 }
1887
1888 moving = (srcid != dstid);
1889
1890 if (found)
1891 {
1892 char *ptr;
1893
1894 ptr = strrchr(dstpath, ':');
1895 if (ptr == 0)
1896 ptr = dstpath;
1897 else
1898 ++ptr;
1899
1900 if (*ptr)
1901 strcpy(dstname, ptr);
1902
1903 if (! moving && strcmp(srcname, dstname) == 0)
1904 return 0; /* source and destination are the same */
1905
1906 if (moving || d_relstring(srcname, dstname))
1907 {
1908 ERROR(EEXIST, "can't use destination name")(hfs_error = ("can't use destination name"), (*__errno()) = (
17))
;
1909 return -1;
1910 }
1911 }
1912
1913 /* can't move anything into the root directory's parent */
1914
1915 if (moving && dstid == HFS_CNID_ROOTPAR1)
1916 {
1917 ERROR(EINVAL, "can't move above root directory")(hfs_error = ("can't move above root directory"), (*__errno()
) = (22))
;
1918 return -1;
1919 }
1920
1921 if (moving && isdir)
1922 {
1923 long id;
1924
1925 /* can't move root directory anywhere */
1926
1927 if (src.u.dir.dirDirID == HFS_CNID_ROOTDIR2)
1928 {
1929 ERROR(EINVAL, "can't move root directory")(hfs_error = ("can't move root directory"), (*__errno()) = (22
))
;
1930 return -1;
1931 }
1932
1933 /* make sure we aren't trying to move a directory inside itself */
1934
1935 for (id = dstid; id != HFS_CNID_ROOTDIR2; id = dst.u.dthd.thdParID)
1936 {
1937 if (id == src.u.dir.dirDirID)
1938 {
1939 ERROR(EINVAL, "can't move directory inside itself")(hfs_error = ("can't move directory inside itself"), (*__errno
()) = (22))
;
1940 return -1;
1941 }
1942
1943 if (v_getdthread(vol, id, &dst, 0)v_getthread(vol, id, &dst, 0, cdrThdRec) <= 0)
1944 return -1;
1945 }
1946 }
1947
1948 if (vol->flags & HFS_READONLY0x01)
1949 {
1950 ERROR(EROFS, 0)(hfs_error = (0), (*__errno()) = (30));
1951 return -1;
1952 }
1953
1954 /* change volume name */
1955
1956 if (dstid == HFS_CNID_ROOTPAR1)
1957 {
1958 if (strlen(dstname) > HFS_MAX_VLEN27)
1959 {
1960 ERROR(ENAMETOOLONG, 0)(hfs_error = (0), (*__errno()) = (63));
1961 return -1;
1962 }
1963
1964 strcpy(vol->mdb.drVN, dstname);
1965 vol->flags |= HFS_UPDATE_MDB0x10;
1966 }
1967
1968 /* remove source record */
1969
1970 r_makecatkey(&key, srcid, srcname);
1971 r_packcatkey(&key, record, 0);
1972
1973 if (bt_delete(&vol->cat, record) < 0)
1974 return -1;
1975
1976 /* insert destination record */
1977
1978 r_makecatkey(&key, dstid, dstname);
1979 r_packcatkey(&key, record, &reclen);
1980 r_packcatdata(&src, HFS_RECDATA(record)((record) + ((1 + (*(unsigned char *) (record)) + 1) & ~1
))
, &reclen);
1981
1982 if (bt_insert(&vol->cat, record, reclen) < 0)
1983 return -1;
1984
1985 /* update thread record */
1986
1987 if (isdir)
1988 {
1989 if (v_getdthread(vol, src.u.dir.dirDirID, &dst, &n)v_getthread(vol, src.u.dir.dirDirID, &dst, &n, cdrThdRec
)
<= 0)
1990 return -1;
1991
1992 dst.u.dthd.thdParID = dstid;
1993 strcpy(dst.u.dthd.thdCName, dstname);
1994
1995 if (v_putcatrec(&dst, &n) < 0)
1996 return -1;
1997 }
1998 else
1999 {
2000 found = v_getfthread(vol, src.u.fil.filFlNum, &dst, &n)v_getthread(vol, src.u.fil.filFlNum, &dst, &n, cdrFThdRec
)
;
2001 if (found < 0)
2002 return -1;
2003
2004 if (found)
2005 {
2006 dst.u.fthd.fthdParID = dstid;
2007 strcpy(dst.u.fthd.fthdCName, dstname);
2008
2009 if (v_putcatrec(&dst, &n) < 0)
2010 return -1;
2011 }
2012 }
2013
2014 /* update directory valences */
2015
2016 if (moving)
2017 {
2018 if (v_adjvalence(vol, srcid, isdir, -1) < 0 ||
2019 v_adjvalence(vol, dstid, isdir, 1) < 0)
2020 return -1;
2021 }
2022
2023 return 0;
2024}
2025#ifdef APPLE_HYB1
2026/*
2027 * NAME: hfs->hfs_get_drAllocPtr()
2028 * DESCRIPTION: get the current start of next allocation search
2029 */
2030unsigned short
2031hfs_get_drAllocPtr(hfsfile *file)
2032{
2033 return(file->vol->mdb.drAllocPtr);
2034}
2035
2036/*
2037 * NAME: hfs->hfs_set_drAllocPtr()
2038 * DESCRIPTION: set the current start of next allocation search
2039 */
2040int
2041hfs_set_drAllocPtr(hfsfile *file, unsigned short drAllocPtr, int size)
2042{
2043 hfsvol *vol = file->vol;
2044 int result = 0;
2045
2046 /* truncate the current fork */
2047 if (f_trunc(file) < 0 ||
2048 f_flush(file) < 0)
2049 result = -1;
2050
2051 /* convert the fork size into allocation blocks */
2052 size = (size + vol->mdb.drAlBlkSiz - 1)/vol->mdb.drAlBlkSiz;
2053
2054 /* set the start of next allocation search to be after this fork */
2055 vol->mdb.drAllocPtr = drAllocPtr + size;
2056
2057 vol->flags |= HFS_UPDATE_MDB0x10;
2058
2059 return result;
2060}
2061
2062/*
2063 * NAME: hfs->vsetbless()
2064 * DESCRIPTION: set blessed folder
2065 *
2066 * adapted from vsetattr() from v3.2.6
2067 */
2068void
2069hfs_vsetbless(hfsvol *vol, unsigned long cnid)
2070{
2071 vol->mdb.drFndrInfo[0] = cnid;
2072
2073 vol->flags |= HFS_UPDATE_MDB0x10;
2074}
2075#endif /* APPLE_HYB */