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 */ 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 */ 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 */ 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 */ 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