xref: /netbsd-src/external/gpl2/mkhybrid/dist/libhfs_iso/block.c (revision ddaa4e7dfcdb43ad63a53c6e313d42cd4abcc54b)
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