]> git.saurik.com Git - hfs.git/blob - fsck_hfs/dfalib/SDevice.c
hfs-226.1.1.tar.gz
[hfs.git] / fsck_hfs / dfalib / SDevice.c
1 /*
2 * Copyright (c) 1999-2000, 2002, 2005, 2007-2008 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23 #include "SRuntime.h"
24 #include "../fsck_hfs.h"
25
26 #if BSD
27
28 #include <unistd.h>
29 #include <errno.h>
30 #include <sys/ioctl.h>
31
32 #include <IOKit/storage/IOMediaBSDClient.h>
33
34 #else
35
36 #include <Files.h>
37 #include <Device.h>
38 #include <Disks.h>
39
40 #endif
41
42
43 OSErr GetDeviceSize(int driveRefNum, UInt64 *numBlocks, UInt32 *blockSize)
44 {
45 #if BSD
46 UInt64 devBlockCount = 0;
47 int devBlockSize = 0;
48
49 if (ioctl(driveRefNum, DKIOCGETBLOCKCOUNT, &devBlockCount) < 0) {
50 plog("ioctl(DKIOCGETBLOCKCOUNT) for fd %d: %s\n", driveRefNum, strerror(errno));
51 return (-1);
52 }
53
54 if (ioctl(driveRefNum, DKIOCGETBLOCKSIZE, &devBlockSize) < 0) {
55 plog("ioctl(DKIOCGETBLOCKSIZE) for fd %d: %s\n", driveRefNum, strerror(errno));
56 return (-1);
57 }
58
59 if (devBlockSize != 512) {
60 *numBlocks = (devBlockCount * (UInt64)devBlockSize) / 512;
61 *blockSize = 512;
62 } else {
63 *numBlocks = devBlockCount;
64 *blockSize = devBlockSize;
65 }
66 return (0);
67 #else
68 /* Various Mac OS device constants */
69 enum
70 {
71 /* return format list status code */
72 kFmtLstCode = 6,
73
74 /* reference number of .SONY driver */
75 kSonyRefNum = 0xfffb,
76
77 /* values returned by DriveStatus in DrvSts.twoSideFmt */
78 kSingleSided = 0,
79 kDoubleSided = -1,
80 kSingleSidedSize = 800, /* 400K */
81 kDoubleSidedSize = 1600, /* 800K */
82
83 /* values in DrvQEl.qType */
84 kWordDrvSiz = 0,
85 kLongDrvSiz = 1,
86
87 /* more than enough formatListRecords */
88 kMaxFormatListRecs = 16
89 };
90
91 ParamBlockRec pb;
92 FormatListRec formatListRecords[kMaxFormatListRecs];
93 DrvSts status;
94 short formatListRecIndex;
95 OSErr result;
96 unsigned long blocks = 0;
97
98
99 /* Attempt to get the drive's format list. */
100 /* (see the Technical Note "What Your Sony Drives For You") */
101
102 pb.cntrlParam.ioVRefNum = driveQElementPtr->dQDrive;
103 pb.cntrlParam.ioCRefNum = driveQElementPtr->dQRefNum;
104 pb.cntrlParam.csCode = kFmtLstCode;
105 pb.cntrlParam.csParam[0] = kMaxFormatListRecs;
106 *(long *)&pb.cntrlParam.csParam[1] = (long)&formatListRecords[0];
107
108 result = PBStatusSync(&pb);
109
110 if ( result == noErr )
111 {
112 /* The drive supports ReturnFormatList status call. */
113
114 /* Get the current disk's size. */
115 for( formatListRecIndex = 0;
116 formatListRecIndex < pb.cntrlParam.csParam[0];
117 ++formatListRecIndex )
118 {
119 if ( (formatListRecords[formatListRecIndex].formatFlags &
120 diCIFmtFlagsCurrentMask) != 0 )
121 {
122 blocks = formatListRecords[formatListRecIndex].volSize;
123 }
124 }
125 if ( blocks == 0 )
126 {
127 /* This should never happen */
128 result = paramErr;
129 }
130 }
131 else if ( driveQElementPtr->dQRefNum == (short)kSonyRefNum )
132 {
133 /* The drive is a non-SuperDrive floppy which only supports 400K and 800K disks */
134
135 result = DriveStatus(driveQElementPtr->dQDrive, &status);
136 if ( result == noErr )
137 {
138 switch ( status.twoSideFmt )
139 {
140 case kSingleSided:
141 blocks = kSingleSidedSize;
142 break;
143
144 case kDoubleSided:
145 blocks = kDoubleSidedSize;
146 break;
147
148 default: // This should never happen
149 result = paramErr;
150 break;
151 }
152 }
153 }
154 else
155 {
156 /* The drive is not a floppy and it doesn't support ReturnFormatList */
157 /* so use the dQDrvSz field(s) */
158
159 result = noErr; /* reset result */
160
161 switch ( driveQElementPtr->qType )
162 {
163 case kWordDrvSiz:
164 blocks = driveQElementPtr->dQDrvSz;
165 break;
166
167 case kLongDrvSiz:
168 blocks = ((unsigned long)driveQElementPtr->dQDrvSz2 << 16) +
169 driveQElementPtr->dQDrvSz;
170 break;
171
172 default: // This should never happen
173 result = paramErr;
174 break;
175 }
176 }
177
178 *numBlocks = blocks;
179 *blockSize = 512;
180
181 return( result );
182 #endif
183 }
184
185
186 OSErr DeviceRead(int device, int drive, void* buffer, SInt64 offset, UInt32 reqBytes, UInt32 *actBytes)
187 {
188 #if BSD
189 off_t seek_off;
190 ssize_t nbytes;
191
192 *actBytes = 0;
193
194 seek_off = lseek(device, offset, SEEK_SET);
195 if (seek_off == -1) {
196 plog("# DeviceRead: lseek(%qd) failed with %d\n", offset, errno);
197 return (errno);
198 }
199
200 nbytes = read(device, buffer, reqBytes);
201 if (nbytes == -1)
202 return (errno);
203 if (nbytes == 0) {
204 plog("CANNOT READ: BLK %ld\n", (long)offset/512);
205 return (5);
206 }
207
208 *actBytes = nbytes;
209 return (0);
210
211 #else
212 OSErr err;
213 XIOParam pb;
214
215 pb.ioVRefNum = drive;
216 pb.ioRefNum = device;
217 pb.ioPosMode = fsFromStart;
218 pb.ioReqCount = reqBytes;
219 pb.ioBuffer = buffer;
220
221 if ( (offset & 0xFFFFFFFF00000000) != 0 )
222 {
223 *(SInt64*)&pb.ioWPosOffset = offset;
224 pb.ioPosMode |= (1 << kWidePosOffsetBit);
225 }
226 else
227 {
228 ((IOParam*)&pb)->ioPosOffset = offset;
229 }
230
231 err = PBReadSync( (ParamBlockRec *)&pb );
232
233 return (err);
234 #endif
235 }
236
237
238 OSErr DeviceWrite(int device, int drive, void* buffer, SInt64 offset, UInt32 reqBytes, UInt32 *actBytes)
239 {
240 #if BSD
241 off_t seek_off;
242 ssize_t nbytes;
243
244 *actBytes = 0;
245
246 seek_off = lseek(device, offset, SEEK_SET);
247 if (seek_off == -1) {
248 plog("# DeviceRead: lseek(%qd) failed with %d\n", offset, errno);
249 return (errno);
250 }
251
252 nbytes = write(device, buffer, reqBytes);
253 if (nbytes == -1) {
254 return (errno);
255 }
256 if (nbytes == 0) {
257 plog("CANNOT WRITE: BLK %ld\n", (long)offset/512);
258 return (5);
259 }
260
261 *actBytes = nbytes;
262 return (0);
263 #else
264 OSErr err;
265 XIOParam pb;
266
267 pb.ioVRefNum = drive;
268 pb.ioRefNum = device;
269 pb.ioPosMode = fsFromStart;
270 pb.ioReqCount = reqBytes;
271 pb.ioBuffer = buffer;
272
273 if ( (offset & 0xFFFFFFFF00000000) != 0 )
274 {
275 *(SInt64*)&pb.ioWPosOffset = offset;
276 pb.ioPosMode |= (1 << kWidePosOffsetBit);
277 }
278 else
279 {
280 ((IOParam*)&pb)->ioPosOffset = offset;
281 }
282
283 err = PBWriteSync( (ParamBlockRec *)&pb );
284
285 return (err);
286 #endif
287 }