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 # include <string.h>
21 # include <sys/types.h>
22 # include <unistd.h>
23 # include <errno.h>
24 # include <time.h>
25
26 # include "internal.h"
27 # include "data.h"
28 # include "block.h"
29 # include "low.h"
30
31 #ifdef DEBUG
32 #include <stdio.h>
33 #endif /* DEBUG */
34
35 /*
36 * NAME: block->readlb()
37 * DESCRIPTION: read a logical block from a volume
38 */
b_readlb(hfsvol * vol,unsigned long num,block * bp)39 int b_readlb(hfsvol *vol, unsigned long num, block *bp)
40 {
41 #ifdef APPLE_HYB
42 block *b;
43 hce_mem *hce;
44
45 #ifdef DEBUG
46 fprintf(stderr,"b_readlb: start block = %d\n", vol->vstart + num);
47 #endif /* DEBUG */
48
49 hce = vol->hce;
50
51 /* Check to see if requested block is in the HFS header or catalog/exents
52 files. If it is, read info from memory copy. If not, then something
53 has gone horribly wrong ... */
54
55 if (num < hce->hfs_hdr_size)
56 b = (block *)hce->hfs_hdr + num;
57 else if (num < hce->hfs_hdr_size + hce->hfs_ce_size)
58 b = (block *)hce->hfs_ce + num - hce->hfs_hdr_size;
59 else
60 {
61 ERROR(EIO, "should not happen!");
62 return -1;
63 }
64
65 memcpy(bp, b, HFS_BLOCKSZ);
66
67 #else
68 int bytes;
69
70 if (lseek(vol->fd, (vol->vstart + num) * HFS_BLOCKSZ, SEEK_SET) < 0)
71 {
72 ERROR(errno, "error seeking device");
73 return -1;
74 }
75
76 bytes = read(vol->fd, bp, HFS_BLOCKSZ);
77 if (bytes < 0)
78 {
79 ERROR(errno, "error reading from device");
80 return -1;
81 }
82 else if (bytes == 0)
83 {
84 ERROR(EIO, "read EOF on volume");
85 return -1;
86 }
87 else if (bytes != HFS_BLOCKSZ)
88 {
89 ERROR(EIO, "read incomplete block");
90 return -1;
91 }
92 #endif /* APPLE_HYB */
93 return 0;
94 }
95
96 /*
97 * NAME: block->writelb()
98 * DESCRIPTION: write a logical block to a volume
99 */
b_writelb(hfsvol * vol,unsigned long num,block * bp)100 int b_writelb(hfsvol *vol, unsigned long num, block *bp)
101 {
102 #ifdef APPLE_HYB
103 block *b;
104 hce_mem *hce;
105
106 #ifdef DEBUG
107 fprintf(stderr,"b_writelb: start block = %d\n", vol->vstart + num);
108 #endif /* DEBUG */
109
110 hce = vol->hce;
111
112 /* Check to see if requested block is in the HFS header or catalog/exents
113 files. If it is, write info to memory copy. If not, then it's a block
114 for an ordinary file - and as we are writing the files later, then just
115 ignore and return OK */
116 if (num < hce->hfs_hdr_size)
117 b = (block *)hce->hfs_hdr + num;
118 else if (num < hce->hfs_hdr_size + hce->hfs_ce_size)
119 b = (block *)hce->hfs_ce + num - hce->hfs_hdr_size;
120 else
121 {
122 #ifdef DEBUG
123 fprintf(stderr,"b_writelb: ignoring\n");
124 #endif /* DEBUG */
125 return 0;
126 }
127
128 memcpy(b, bp, HFS_BLOCKSZ);
129
130 #else
131 int bytes;
132
133 if (lseek(vol->fd, (vol->vstart + num) * HFS_BLOCKSZ, SEEK_SET) < 0)
134 {
135 ERROR(errno, "error seeking device");
136 return -1;
137 }
138
139 bytes = write(vol->fd, bp, HFS_BLOCKSZ);
140
141 if (bytes < 0)
142 {
143 ERROR(errno, "error writing to device");
144 return -1;
145 }
146 else if (bytes != HFS_BLOCKSZ)
147 {
148 ERROR(EIO, "wrote incomplete block");
149 return -1;
150 }
151 #endif /* APPLE_HYB */
152 return 0;
153 }
154
155 /*
156 * NAME: block->readab()
157 * DESCRIPTION: read a block from an allocation block from a volume
158 */
b_readab(hfsvol * vol,unsigned int anum,unsigned int index,block * bp)159 int b_readab(hfsvol *vol,
160 unsigned int anum, unsigned int index, block *bp)
161 {
162 /* verify the allocation block exists and is marked as in-use */
163
164 if (anum >= vol->mdb.drNmAlBlks)
165 {
166 ERROR(EIO, "read nonexistent block");
167 return -1;
168 }
169 else if (vol->vbm && ! BMTST(vol->vbm, anum))
170 {
171 ERROR(EIO, "read unallocated block");
172 return -1;
173 }
174
175 return b_readlb(vol, vol->mdb.drAlBlSt + anum * vol->lpa + index, bp);
176 }
177
178 /*
179 * NAME: b->writeab()
180 * DESCRIPTION: write a block to an allocation block to a volume
181 */
b_writeab(hfsvol * vol,unsigned int anum,unsigned int index,block * bp)182 int b_writeab(hfsvol *vol,
183 unsigned int anum, unsigned int index, block *bp)
184 {
185 /* verify the allocation block exists and is marked as in-use */
186
187 if (anum >= vol->mdb.drNmAlBlks)
188 {
189 ERROR(EIO, "write nonexistent block");
190 return -1;
191 }
192 else if (vol->vbm && ! BMTST(vol->vbm, anum))
193 {
194 ERROR(EIO, "write unallocated block");
195 return -1;
196 }
197
198 vol->mdb.drAtrb &= ~HFS_ATRB_UMOUNTED;
199 vol->mdb.drLsMod = d_tomtime(time(0));
200 ++vol->mdb.drWrCnt;
201
202 vol->flags |= HFS_UPDATE_MDB;
203
204 return b_writelb(vol, vol->mdb.drAlBlSt + anum * vol->lpa + index, bp);
205 }
206