Copyright clean-up (part 1):
[AROS.git] / arch / all-unix / devs / hostdisk / hostdisk_host.c
blob08b8fa2c70768d757c25fbf4d960e738997c3968
1 /*
2 Copyright © 1995-2014, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #ifdef HOST_OS_ios
8 #ifdef __arm__
9 /*
10 * Under ARM iOS quadwords are long-aligned, however in AROS (according to AAPCS)
11 * they are quad-aligned. This macro turns on some tricks which bypass this problem
13 #define HOST_LONG_ALIGNED
14 #endif
15 #ifdef __i386__
17 * Under i386 we pick up MacOS' libSystem.dylib instead of Simulator's libSystem.dylib,
18 * so we have to use special versions of certain functions. We can't simply #define _DARWIN_NO_64_BIT_INODE
19 * because iOS SDK forbids this (in iOS inode_t is always 64-bit wide)
21 #define INODE64_SUFFIX "$INODE64"
22 #endif
24 /* Correspondingly, there's no struct stat64. Use struct stat instead. */
25 #define stat64 stat
26 #else
28 /*
29 * Use 32-bit inode_t on Darwin. Otherwise we are expected to use "stat$INODE64"
30 * instead of "stat" function which is available only on MacOS 10.6.
32 #define _DARWIN_NO_64_BIT_INODE
33 /* This enables struct stat64 definition */
34 #define _DARWIN_C_SOURCE /* For Darwin */
35 #define _LARGEFILE64_SOURCE /* For Linux */
36 #endif
38 #ifndef INODE64_SUFFIX
39 #define INODE64_SUFFIX
40 #endif
42 /* Prevents struct timeval redefinition */
43 #define timeval sys_timeval
45 #include <errno.h>
46 #include <fcntl.h>
47 #include <unistd.h>
48 #include <string.h>
49 #include <sys/stat.h>
51 #ifdef __linux__
52 #define stat64 stat
53 #endif
55 #undef timeval
57 #include <aros/debug.h>
58 #include <aros/symbolsets.h>
59 #include <devices/trackdisk.h>
60 #include <exec/errors.h>
61 #include <proto/exec.h>
62 #include <proto/hostlib.h>
63 #include <proto/intuition.h>
64 #include <proto/kernel.h>
66 #ifdef HOST_LONG_ALIGNED
67 #pragma pack(4)
68 #endif
70 #pragma pack()
72 #include "hostdisk_host.h"
73 #include "hostdisk_device.h"
75 static ULONG error(int unixerr)
77 D(bug("hostdisk: UNIX error %d\n", unixerr));
79 switch (unixerr)
81 case 0:
82 return 0;
84 case EBUSY:
85 return TDERR_DriveInUse;
87 case EPERM:
88 return TDERR_WriteProt;
90 default:
91 return TDERR_NotSpecified;
95 ULONG Host_Open(struct unit *Unit)
97 struct HostDiskBase *hdskBase = Unit->hdskBase;
98 int err;
100 D(bug("hostdisk: Host_Open(%s)\n", Unit->filename));
101 Unit->flags = 0;
103 HostLib_Lock();
105 Unit->file = hdskBase->iface->open(Unit->filename, O_RDWR, 0755, &err);
106 AROS_HOST_BARRIER
107 err = *hdskBase->errnoPtr;
109 if (err == EBUSY || err == EROFS)
111 /* This allows to work on Darwin, at least in read-only mode */
112 D(bug("hostdisk: EBUSY, retrying with read-only access\n", Unit->filename, Unit->file, err));
113 Unit->flags = UNIT_READONLY;
115 Unit->file = hdskBase->iface->open(Unit->filename, O_RDONLY, 0755);
116 AROS_HOST_BARRIER
117 err = *hdskBase->errnoPtr;
120 HostLib_Unlock();
122 if (Unit->file == -1)
124 D(bug("hostdisk: Error %d\n", err));
126 return error(err);
129 return 0;
132 void Host_Close(struct unit *Unit)
134 struct HostDiskBase *hdskBase = Unit->hdskBase;
136 D(bug("hostdisk: Close device %s\n", Unit->n.ln_Name));
137 D(bug("hostdisk: HostLibBase 0x%p, close() 0x%p\n", HostLibBase, hdskBase->iface->close));
139 HostLib_Lock();
141 hdskBase->iface->close(Unit->file);
142 AROS_HOST_BARRIER
144 HostLib_Unlock();
147 LONG Host_Read(struct unit *Unit, APTR buf, ULONG size, ULONG *ioerr)
149 struct HostDiskBase *hdskBase = Unit->hdskBase;
150 int ret, err;
152 D(bug("hostdisk: Read %u bytes\n", size));
154 HostLib_Lock();
156 ret = hdskBase->iface->read(Unit->file, buf, size);
157 AROS_HOST_BARRIER
158 err = *hdskBase->errnoPtr;
160 HostLib_Unlock();
162 if (ret == -1)
163 *ioerr = error(err);
165 return ret;
168 LONG Host_Write(struct unit *Unit, APTR buf, ULONG size, ULONG *ioerr)
170 struct HostDiskBase *hdskBase = Unit->hdskBase;
171 int ret, err;
173 D(bug("hostdisk: Write %u bytes\n", size));
175 HostLib_Lock();
177 ret = hdskBase->iface->write(Unit->file, buf, size);
178 AROS_HOST_BARRIER
179 err = *hdskBase->errnoPtr;
181 HostLib_Unlock();
183 if (ret == -1)
184 *ioerr = error(err);
186 return ret;
189 ULONG Host_Seek(struct unit *Unit, ULONG pos)
191 return Host_Seek64(Unit, pos, 0);
194 ULONG Host_Seek64(struct unit *Unit, ULONG pos, ULONG pos_hi)
196 struct HostDiskBase *hdskBase = Unit->hdskBase;
197 int res;
199 D(bug("hostdisk: Seek to block 0x%08X%08X (%llu)\n", pos_hi, pos, (((UQUAD)pos_hi) << 32) + pos));
202 * Host OS is usually not reentrant.
203 * All host OS calls should be protected by global lock (since hostlib.resource v3).
205 HostLib_Lock();
207 res = LSeek(Unit->file, pos, pos_hi, SEEK_SET);
208 AROS_HOST_BARRIER
210 HostLib_Unlock();
212 return (res == -1) ? TDERR_SeekError : 0;
215 static ULONG InternalGetGeometry(int file, struct DriveGeometry *dg, struct HostDiskBase *hdskBase)
217 int res, err;
218 struct stat64 st;
220 HostLib_Lock();
222 res = hdskBase->iface->fstat64(file, &st);
223 err = *hdskBase->errnoPtr;
225 HostLib_Unlock();
227 if (res != -1)
229 if (S_ISBLK(st.st_mode))
232 * For real block devices we can use IOCTL-based function. It will provide better info.
233 * This routine returns UNIX error code, for simplicity.
235 err = Host_DeviceGeometry(file, dg, hdskBase);
237 /* If this routine is not implemented, use fstat() (worst case) */
238 if (err != ENOSYS)
239 return error(err);
242 D(bug("hostdisk: Image file length: %ld\n", st.st_size));
244 dg->dg_TotalSectors = st.st_size / dg->dg_SectorSize;
245 dg->dg_Cylinders = dg->dg_TotalSectors; /* LBA, CylSectors == 1 */
247 return 0;
250 D(bug("hostdisk: InternalGetGeometry(): UNIX error %u\n", err));
251 return err;
254 ULONG Host_GetGeometry(struct unit *Unit, struct DriveGeometry *dg)
256 int err = InternalGetGeometry(Unit->file, dg, Unit->hdskBase);
258 return error(err);
261 int Host_ProbeGeometry(struct HostDiskBase *hdskBase, char *name, struct DriveGeometry *dg)
263 int file, res;
265 HostLib_Lock();
267 file = hdskBase->iface->open(name, O_RDONLY, 0755);
268 AROS_HOST_BARRIER
270 HostLib_Unlock();
272 if (file == -1)
273 return -1;
275 res = InternalGetGeometry(file, dg, hdskBase);
277 HostLib_Lock();
279 hdskBase->iface->close(file);
280 AROS_HOST_BARRIER
282 HostLib_Unlock();
284 return res;
287 extern const char Hostdisk_LibName[];
289 static const char *libcSymbols[] =
291 "open",
292 "close",
293 "read",
294 "write",
295 "ioctl",
296 "lseek",
297 #ifdef HOST_OS_linux
298 "__errno_location",
299 "__fxstat64",
300 "__xstat64",
301 #else
302 #ifdef HOST_OS_android
303 "__errno",
304 #else
305 "__error",
306 #endif
307 "fstat64" INODE64_SUFFIX,
308 "stat64" INODE64_SUFFIX,
309 #endif
310 NULL
313 static BOOL CheckArch(const char *Component, const char *MyArch, const char *SystemArch)
315 const char *arg[3] = {Component, MyArch, SystemArch};
317 D(bug("hostdisk: My architecture: %s, kernel architecture: %s\n", arg[1], arg[2]));
319 if (strcmp(arg[1], arg[2]))
321 struct IntuitionBase *IntuitionBase;
323 IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 36);
324 if (IntuitionBase)
326 struct EasyStruct es =
328 sizeof (struct EasyStruct),
330 "Incompatible architecture",
331 "Used version of %s is built for use\n"
332 "with %s architecture, but your\n"
333 "system architecture is %s.",
334 "Ok",
337 EasyRequestArgs(NULL, &es, NULL, (IPTR *)arg);
339 CloseLibrary(&IntuitionBase->LibNode);
341 return FALSE;
344 D(bug("hostdisk: Architecture check done\n"));
345 return TRUE;
348 static int Host_Init(struct HostDiskBase *hdskBase)
350 ULONG r;
351 STRPTR arch;
353 * This device is disk-based and it can travel from disk to disk.
354 * In order to prevent unexplained crashes we check that system architecture
355 * is the architecture we were built for.
357 APTR KernelBase = OpenResource("kernel.resource");
359 if (!KernelBase)
360 return FALSE;
362 arch = (STRPTR)KrnGetSystemAttr(KATTR_Architecture);
363 if (!arch)
364 return FALSE;
366 if (!CheckArch(Hostdisk_LibName, AROS_ARCHITECTURE, arch))
367 return FALSE;
369 hdskBase->KernelHandle = HostLib_Open(LIBC_NAME, NULL);
370 if (!hdskBase->KernelHandle)
371 return FALSE;
373 hdskBase->iface = (struct HostInterface *)HostLib_GetInterface(hdskBase->KernelHandle, libcSymbols, &r);
374 if ((!hdskBase->iface) || r)
375 return FALSE;
377 hdskBase->errnoPtr = hdskBase->iface->__error();
379 hdskBase->DiskDevice = DISK_DEVICE;
380 hdskBase->unitBase = DISK_BASE;
382 return TRUE;
385 ADD2INITLIB(Host_Init, 0);