Build fix, see comment.
[AROS.git] / arch / all-unix / devs / hostdisk / hostdisk_host.c
blob7343000d910a75f0bb7adb21fb5d759c3f7a8c1c
1 #ifdef HOST_OS_ios
3 #ifdef __arm__
4 /*
5 * Under ARM iOS quadwords are long-aligned, however in AROS (according to AAPCS)
6 * they are quad-aligned. This macro turns on some tricks which bypass this problem
7 */
8 #define HOST_LONG_ALIGNED
9 #endif
10 #ifdef __i386__
12 * Under i386 we pick up MacOS' libSystem.dylib instead of Simulator's libSystem.dylib,
13 * so we have to use special versions of certain functions. We can't simply #define _DARWIN_NO_64_BIT_INODE
14 * because iOS SDK forbids this (in iOS inode_t is always 64-bit wide)
16 #define INODE64_SUFFIX "$INODE64"
17 #endif
19 /* Correspondingly, there's no struct stat64. Use struct stat instead. */
20 #define stat64 stat
21 #else
23 /*
24 * Use 32-bit inode_t on Darwin. Otherwise we are expected to use "stat$INODE64"
25 * instead of "stat" function which is available only on MacOS 10.6.
27 #define _DARWIN_NO_64_BIT_INODE
28 /* This enables struct stat64 definition */
29 #define _DARWIN_C_SOURCE /* For Darwin */
30 #define _LARGEFILE64_SOURCE /* For Linux */
31 #endif
33 #ifndef INODE64_SUFFIX
34 #define INODE64_SUFFIX
35 #endif
37 #include <aros/debug.h>
38 #include <aros/symbolsets.h>
39 #include <devices/trackdisk.h>
40 #include <exec/errors.h>
41 #include <proto/exec.h>
42 #include <proto/hostlib.h>
43 #include <proto/intuition.h>
44 #include <proto/kernel.h>
46 #ifdef HOST_LONG_ALIGNED
47 #pragma pack(4)
48 #endif
50 /* Prevents struct timeval redefinition */
51 #define timeval sys_timeval
54 * avoid conflicts between our __unused define and the ones that might come in
55 * via fcntl.h
57 #undef __unused
59 #include <errno.h>
60 #include <fcntl.h>
61 #include <unistd.h>
63 #pragma pack()
65 #include "hostdisk_host.h"
66 #include "hostdisk_device.h"
68 static ULONG error(int unixerr)
70 switch (unixerr)
72 case 0:
73 return 0;
75 case EBUSY:
76 return TDERR_DriveInUse;
78 case EPERM:
79 return TDERR_WriteProt;
81 default:
82 return TDERR_NotSpecified;
86 ULONG Host_Open(struct unit *Unit)
88 struct HostDiskBase *hdskBase = Unit->hdskBase;
89 struct stat64 st;
90 int err;
92 D(bug("hostdisk: Host_Open(%s)\n", Unit->filename));
94 HostLib_Lock();
96 Unit->file = hdskBase->iface->open(Unit->filename, O_RDWR, 0755, &err);
97 AROS_HOST_BARRIER
98 err = *hdskBase->errnoPtr;
100 if (err == EBUSY)
102 /* This allows to work on Darwin, at least in read-only mode */
103 D(bug("hostdisk: EBUSY, retrying with read-only access\n", Unit->filename, Unit->file, err));
105 Unit->file = hdskBase->iface->open(Unit->filename, O_RDONLY, 0755, &err);
106 AROS_HOST_BARRIER
107 err = *hdskBase->errnoPtr;
110 HostLib_Unlock();
112 if (Unit->file == -1)
114 D(bug("hostdisk: Error %d\n", err));
116 return error(err);
119 Unit->flags = 0;
121 HostLib_Lock();
122 err = hdskBase->iface->fstat64(Unit->file, &st);
123 HostLib_Unlock();
125 if (err != -1)
127 if (S_ISBLK(st.st_mode))
128 Unit->flags |= UNIT_DEVICE;
131 D(bug("hostdisk: Unit flags 0x%02X\n", Unit->flags));
132 return 0;
135 void Host_Close(struct unit *Unit)
137 struct HostDiskBase *hdskBase = Unit->hdskBase;
139 D(bug("hostdisk: Close device %s\n", Unit->n.ln_Name));
140 D(bug("hostdisk: HostLibBase 0x%p, close() 0x%p\n", HostLibBase, hdskBase->iface->close));
142 HostLib_Lock();
144 hdskBase->iface->close(Unit->file);
145 AROS_HOST_BARRIER
147 HostLib_Unlock();
150 LONG Host_Read(struct unit *Unit, APTR buf, ULONG size, ULONG *ioerr)
152 struct HostDiskBase *hdskBase = Unit->hdskBase;
153 int ret, err;
155 HostLib_Lock();
157 ret = hdskBase->iface->read(Unit->file, buf, size);
158 AROS_HOST_BARRIER
159 err = *hdskBase->errnoPtr;
161 HostLib_Unlock();
163 if (ret == -1)
164 *ioerr = error(err);
166 return ret;
169 LONG Host_Write(struct unit *Unit, APTR buf, ULONG size, ULONG *ioerr)
171 struct HostDiskBase *hdskBase = Unit->hdskBase;
172 int ret, err;
174 HostLib_Lock();
176 ret = hdskBase->iface->write(Unit->file, buf, size);
177 AROS_HOST_BARRIER
178 err = *hdskBase->errnoPtr;
180 HostLib_Unlock();
182 if (ret == -1)
183 *ioerr = error(err);
185 return ret;
188 ULONG Host_Seek(struct unit *Unit, ULONG pos)
190 return Host_Seek64(Unit, pos, 0);
193 ULONG Host_Seek64(struct unit *Unit, ULONG pos, ULONG pos_hi)
195 struct HostDiskBase *hdskBase = Unit->hdskBase;
196 int res;
199 * Host OS is usually not reentrant.
200 * All host OS calls should be protected by global lock (since hostlib.resource v3).
202 HostLib_Lock();
204 res = LSeek(Unit->file, pos, pos_hi, SEEK_SET);
205 AROS_HOST_BARRIER
207 HostLib_Unlock();
209 return (res == -1) ? TDERR_SeekError : 0;
212 ULONG Host_GetGeometry(struct unit *Unit, struct DriveGeometry *dg)
214 struct HostDiskBase *hdskBase = Unit->hdskBase;
215 int res, err;
216 struct stat64 st;
218 if (Unit->flags & UNIT_DEVICE)
220 /* This routine returns UNIX error code, for simplicity */
221 err = Host_DeviceGeometry(Unit, dg);
223 /* If this routine is not implemented, use fstat() (worst case) */
224 if (err != ENOSYS)
225 return error(err);
228 HostLib_Lock();
230 res = hdskBase->iface->fstat64(Unit->file, &st);
231 err = *hdskBase->errnoPtr;
233 HostLib_Unlock();
235 D(bug("hostdisk: Image file length: %ld\n", st.st_size));
236 if (res != -1)
238 dg->dg_TotalSectors = st.st_size / dg->dg_SectorSize;
239 dg->dg_Cylinders = dg->dg_TotalSectors; /* LBA, CylSectors == 1 */
241 return 0;
244 D(bug("hostdisk: Host_GetGeometry(): UNIX error %u\n", err));
245 return error(err);
248 extern const char Hostdisk_LibName[];
250 static const char *libcSymbols[] =
252 "open",
253 "close",
254 "read",
255 "write",
256 "ioctl",
257 "lseek",
258 #ifdef HOST_OS_linux
259 "__errno_location",
260 "__fxstat64",
261 #else
262 #ifdef HOST_OS_android
263 "__errno",
264 #else
265 "__error",
266 #endif
267 "fstat64" INODE64_SUFFIX,
268 #endif
269 NULL
272 static BOOL CheckArch(const char *Component, const char *MyArch, const char *SystemArch)
274 const char *arg[3] = {Component, MyArch, SystemArch};
276 D(bug("hostdisk: My architecture: %s, kernel architecture: %s\n", arg[1], arg[2]));
278 if (strcmp(arg[1], arg[2]))
280 struct IntuitionBase *IntuitionBase;
282 IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 36);
283 if (IntuitionBase)
285 struct EasyStruct es =
287 sizeof (struct EasyStruct),
289 "Incompatible architecture",
290 "Used version of %s is built for use\n"
291 "with %s architecture, but your\n"
292 "system architecture is %s.",
293 "Ok",
296 EasyRequestArgs(NULL, &es, NULL, (IPTR *)arg);
298 CloseLibrary(&IntuitionBase->LibNode);
300 return FALSE;
303 D(bug("hostdisk: Architecture check done\n"));
304 return TRUE;
307 static int Host_Init(struct HostDiskBase *hdskBase)
309 ULONG r;
310 STRPTR arch;
312 * This device is disk-based and it can travel from disk to disk.
313 * In order to prevent unexplained crashes we check that system architecture
314 * is the architecture we were built for.
316 APTR KernelBase = OpenResource("kernel.resource");
318 if (!KernelBase)
319 return FALSE;
321 arch = (STRPTR)KrnGetSystemAttr(KATTR_Architecture);
322 if (!arch)
323 return FALSE;
325 if (!CheckArch(Hostdisk_LibName, AROS_ARCHITECTURE, arch))
326 return FALSE;
328 hdskBase->KernelHandle = HostLib_Open(LIBC_NAME, NULL);
329 if (!hdskBase->KernelHandle)
330 return FALSE;
332 hdskBase->iface = (struct HostInterface *)HostLib_GetInterface(hdskBase->KernelHandle, libcSymbols, &r);
333 if ((!hdskBase->iface) || r)
334 return FALSE;
336 hdskBase->errnoPtr = hdskBase->iface->__error();
338 hdskBase->DiskDevice = DISK_DEVICE;
339 hdskBase->unitBase = DISK_BASE;
341 return TRUE;
344 ADD2INITLIB(Host_Init, 0);