1 /*
2 * This file has been modified for the cdrkit suite.
3 *
4 * The behaviour and appearence of the program code below can differ to a major
5 * extent from the version distributed by the original author(s).
6 *
7 * For details, see Changelog file distributed with the cdrkit package. If you
8 * received this file from another source then ask the distributing person for
9 * a log of modifications.
10 *
11 */
12
13 /* @(#)block.c 1.3 01/11/01 joerg */
14 /*
15 * hfsutils - tools for reading and writing Macintosh HFS volumes
16 * Copyright (C) 1996, 1997 Robert Leslie
17 *
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation; either version 2 of the License, or
21 * (at your option) any later version.
22 *
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
27 *
28 * You should have received a copy of the GNU General Public License
29 * along with this program; if not, write to the Free Software
30 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
31 */
32
33 #include <mconfig.h>
34 #include <strdefs.h>
35 #include <unixstd.h>
36 #include <errno.h>
37
38 #include "internal.h"
39 #include "data.h"
40 #include "block.h"
41 #include "low.h"
42
43 #ifdef DEBUG
44 #include <stdio.h>
45 #endif /* DEBUG */
46
47 /*
48 * NAME: block->readlb()
49 * DESCRIPTION: read a logical block from a volume
50 */
b_readlb(hfsvol * vol,unsigned long num,block * bp)51 int b_readlb(hfsvol *vol, unsigned long num, block *bp)
52 {
53 #ifndef APPLE_HYB
54 int bytes;
55 #endif
56 #ifdef APPLE_HYB
57 block *b;
58 hce_mem *hce;
59
60 #ifdef DEBUG
61 fprintf(stderr,"b_readlb: start block = %d\n", vol->vstart + num);
62 #endif /* DEBUG */
63
64 hce = vol->hce;
65
66 /* Check to see if requested block is in the HFS header or catalog/exents
67 files. If it is, read info from memory copy. If not, then something
68 has gone horribly wrong ... */
69
70 if (num < hce->hfs_hdr_size)
71 b = (block *)hce->hfs_hdr + num;
72 else if (num < hce->hfs_hdr_size + hce->hfs_ce_size)
73 b = (block *)hce->hfs_ce + num - hce->hfs_hdr_size;
74 else
75 {
76 ERROR(EIO, "should not happen!");
77 return -1;
78 }
79
80 memcpy(bp, b, HFS_BLOCKSZ);
81
82 #else
83
84 if (lseek(vol->fd, (vol->vstart + num) * HFS_BLOCKSZ, SEEK_SET) < 0)
85 {
86 ERROR(errno, "error seeking device");
87 return -1;
88 }
89
90 bytes = read(vol->fd, bp, HFS_BLOCKSZ);
91 if (bytes < 0)
92 {
93 ERROR(errno, "error reading from device");
94 return -1;
95 }
96 else if (bytes == 0)
97 {
98 ERROR(EIO, "read EOF on volume");
99 return -1;
100 }
101 else if (bytes != HFS_BLOCKSZ)
102 {
103 ERROR(EIO, "read incomplete block");
104 return -1;
105 }
106 #endif /* APPLE_HYB */
107 return 0;
108 }
109
110 /*
111 * NAME: block->writelb()
112 * DESCRIPTION: write a logical block to a volume
113 */
b_writelb(hfsvol * vol,unsigned long num,block * bp)114 int b_writelb(hfsvol *vol, unsigned long num, block *bp)
115 {
116 #ifndef APPLE_HYB
117 int bytes;
118 #endif
119 #ifdef APPLE_HYB
120 block *b;
121 hce_mem *hce;
122
123 #ifdef DEBUG
124 fprintf(stderr,"b_writelb: start block = %d\n", vol->vstart + num);
125 #endif /* DEBUG */
126
127 hce = vol->hce;
128
129 /* Check to see if requested block is in the HFS header or catalog/exents
130 files. If it is, write info to memory copy. If not, then it's a block
131 for an ordinary file - and as we are writing the files later, then just
132 ignore and return OK */
133 if (num < hce->hfs_hdr_size)
134 b = (block *)hce->hfs_hdr + num;
135 else if (num < hce->hfs_hdr_size + hce->hfs_ce_size)
136 b = (block *)hce->hfs_ce + num - hce->hfs_hdr_size;
137 else
138 {
139 #ifdef DEBUG
140 fprintf(stderr,"b_writelb: ignoring\n");
141 #endif /* DEBUG */
142 return 0;
143 }
144
145 memcpy(b, bp, HFS_BLOCKSZ);
146
147 #else
148
149 if (lseek(vol->fd, (vol->vstart + num) * HFS_BLOCKSZ, SEEK_SET) < 0)
150 {
151 ERROR(errno, "error seeking device");
152 return -1;
153 }
154
155 bytes = write(vol->fd, bp, HFS_BLOCKSZ);
156
157 if (bytes < 0)
158 {
159 ERROR(errno, "error writing to device");
160 return -1;
161 }
162 else if (bytes != HFS_BLOCKSZ)
163 {
164 ERROR(EIO, "wrote incomplete block");
165 return -1;
166 }
167 #endif /* APPLE_HYB */
168 return 0;
169 }
170
171 /*
172 * NAME: block->readab()
173 * DESCRIPTION: read a block from an allocation block from a volume
174 */
b_readab(hfsvol * vol,unsigned int anum,unsigned int idx,block * bp)175 int b_readab(hfsvol *vol, unsigned int anum, unsigned int idx, block *bp)
176 {
177 /* verify the allocation block exists and is marked as in-use */
178
179 if (anum >= vol->mdb.drNmAlBlks)
180 {
181 ERROR(EIO, "read nonexistent block");
182 return -1;
183 }
184 else if (vol->vbm && ! BMTST(vol->vbm, anum))
185 {
186 ERROR(EIO, "read unallocated block");
187 return -1;
188 }
189
190 return b_readlb(vol, vol->mdb.drAlBlSt + anum * vol->lpa + idx, bp);
191 }
192
193 /*
194 * NAME: b->writeab()
195 * DESCRIPTION: write a block to an allocation block to a volume
196 */
b_writeab(hfsvol * vol,unsigned int anum,unsigned int idx,block * bp)197 int b_writeab(hfsvol *vol, unsigned int anum, unsigned int idx, block *bp)
198 {
199 /* verify the allocation block exists and is marked as in-use */
200
201 if (anum >= vol->mdb.drNmAlBlks)
202 {
203 ERROR(EIO, "write nonexistent block");
204 return -1;
205 }
206 else if (vol->vbm && ! BMTST(vol->vbm, anum))
207 {
208 ERROR(EIO, "write unallocated block");
209 return -1;
210 }
211
212 vol->mdb.drAtrb &= ~HFS_ATRB_UMOUNTED;
213 vol->mdb.drLsMod = d_tomtime(time(0));
214 ++vol->mdb.drWrCnt;
215
216 vol->flags |= HFS_UPDATE_MDB;
217
218 return b_writelb(vol, vol->mdb.drAlBlSt + anum * vol->lpa + idx, bp);
219 }
220