|
|
1.1 root 1: /*
2: * UAE - The Un*x Amiga Emulator
3: *
4: * pos-disk.c: Creates pseudo dev: handler. Copy tracks to rawfile
5: * (used in zfile.c).
6: *
7: * Copyright 1997, Samuel Devulder.
8: */
9:
10: /****************************************************************************/
11:
12: #include "sysconfig.h"
13: #include "sysdeps.h"
14:
15: #include <ctype.h>
16: #include <signal.h>
17:
18: #include "config.h"
19: #include "options.h"
20: #include "memory.h"
21: #include "custom.h"
22: #include "keyboard.h"
23: #include "keybuf.h"
24: #include "disk.h"
25: #include "debug.h"
26: #include "gui.h"
27:
28: /****************************************************************************/
29:
30: struct pOS_Locale;
31: struct pOS_Library;
32: struct pOS_ExecBase;
33: struct pOS_DosBase;
34: struct pOS_Method;
35: struct pOS_Resource;
36: struct pOS_RawDoFmtData;
37: struct pOS_AsciiDoFmtData;
38: struct pOS_AsciiFmtData;
39: struct pOS_ClassGrp;
40: struct pOS_DosDevPathInfo;
41: struct pOS_ShellScript;
42: struct pOS_SegmentInfo;
43: struct IClass;
44: struct Isrvstr;
45: struct TagItem;
46: struct MemHeader;
47: struct SemaphoreMessage;
48: struct StackSwapStruct;
49: struct Interrupt;
50: struct StandardPacket;
51: struct InfoData;
52: struct WBStartup;
53:
54: #define _SIZE_T /* to avoid interference with <sys/types.h> */
55: #include <pExec/Types.h>
56: #include <pExec/MsgPort.h>
57: #include <pExec/Device.h>
58: #include <pDOS/Lock.h>
59: #include <pDOS/Files.h>
60: #include <pDOS/DosSig.h>
61: #include <pDOS/DosErrors.h>
62: #include <pDevice/Trackdisk.h>
63:
64: #include <pInline/pExec2.h>
65: #include <pInline/pDos2.h>
66:
67: extern struct pOS_ExecBase *gb_ExecBase;
68: extern struct pOS_ExecLibFunction *gb_ExecLib;
69: extern struct pOS_DosBase *gb_DosBase;
70:
71: /****************************************************************************/
72:
73: char *amiga_dev_path = "DEV:";
74: char *ixemul_dev_path = "/dev/";
75:
76: int readdevice(char *name, char *dst);
77: void initpseudodevices(void);
78: void closepseudodevices(void);
79: char *to_unix_path(char *s);
80: char *from_unix_path(char *s);
81: void split_dir_file(char *src, char **dir, char **file);
82:
83: /****************************************************************************/
84:
85: static char *pseudo_dev_path = "T:DEV";
86:
87: static char pseudo_dev_created = 0;
88: static char pseudo_dev_assigned = 0;
89: static char dfx_done[4];
90:
91: static int device_exists(char *device_name, int device_unit);
92:
93: /****************************************************************************/
94: /* support routines to handle unix filename convention
95: */
96: char *to_unix_path(char *s)
97: {
98: char *t,*r,*u;
99: int l;
100:
101: for(u=s,l=0;*u;++u,++l) if(*u=='/' || *u==':') l+=2;
102:
103: r = t = malloc(1+l);
104: if(!r) return NULL;
105:
106: for(u=s;*u && *u!=':';++u);
107: if(*u) {
108: *t++='/';
109: while(*s!=':') *t++=*s++;
110: *t++='/';++s;
111: }
112: while(*s=='/') {*t++='.';*t++='.';*t++=*s++;}
113: while(*s) {
114: if(s[0]=='/' && s[1]=='/') {*t++=*s++;*t++='.';*t++='.';*t++=*s++;}
115: else *t++=*s++;
116: }
117: *t='\0';
118: return r;
119: }
120:
121: /****************************************************************************/
122:
123: char *from_unix_path(char *s)
124: {
125: char *t,*r;
126:
127: r = t = malloc(strlen(s)+1);
128: if(!r) return NULL;
129:
130: if(*s=='/') {
131: ++s;
132: while(*s && *s!='/') *t++=*s++;
133: if(*s=='/') {*t++=':';++s;}
134: }
135:
136: while(*s) {
137: if(s[0]=='.' && s[1]=='.') s+=2;
138: else *t++=*s++;
139: }
140:
141: *t='\0';
142:
143: return r;
144: }
145:
146: /****************************************************************************/
147:
148: void split_dir_file(char *src, char **dir, char **file)
149: { /* note: src is freed() */
150: char *s=src;
151:
152: while(*s) ++s;
153: while(s>src && (*s!=':' && *s!='/')) --s;
154: if(*s==':' || *s=='/') {
155: *file = my_strdup(s+1);
156: s[1] = '\0';
157: *dir = my_strdup(src);
158: free(src);
159: } else {
160: *file = src;
161: *dir = my_strdup("");
162: }
163: }
164:
165: /****************************************************************************/
166: /*
167: * Creates peudo DEV:DFx files.
168: */
169: void initpseudodevices(void)
170: {
171: struct pOS_FileLock *lock;
172: int i;
173:
174: /* check for T: and TMP: */
175: lock = pOS_LockObject(NULL, "T:", FILELKACC_Shared|FILELKACC_NoReq);
176: if(!lock) {
177: pOS_CreateDosAssign("T",NULL,"RAM:",DDTYP_Assign);
178: } else pOS_UnlockObject(lock);
179:
180: lock = pOS_LockObject(NULL, "TMP:", FILELKACC_Shared|FILELKACC_NoReq);
181: if(!lock) {
182: pOS_CreateDosAssign("TMP",NULL,"RAM:",DDTYP_Assign);
183: } else pOS_UnlockObject(lock);
184:
185: pseudo_dev_created = 0;
186: pseudo_dev_assigned = 0;
187: for(i=0;i<4;++i) dfx_done[i]=0;
188:
189: /* check if dev: already exists */
190: lock = pOS_LockObject(NULL, amiga_dev_path,
191: FILELKACC_Shared|FILELKACC_NoReq);
192: if(!lock) {
193: char name[80];
194: lock = pOS_LockObject(NULL, pseudo_dev_path,
195: FILELKACC_Shared|FILELKACC_NoReq);
196: if(!lock) {
197: /* create it */
198: lock = pOS_CreateDirectory(NULL, pseudo_dev_path);
199: if(!lock) goto fail;
200: pOS_UnlockObject(lock);
201: lock = pOS_LockObject(NULL, pseudo_dev_path,
202: FILELKACC_Shared|FILELKACC_NoReq);
203: pseudo_dev_created = 1;
204: }
205: strcpy(name,amiga_dev_path);
206: if(*name && name[strlen(name)-1]==':') name[strlen(name)-1]='\0';
207: if(!pOS_CreateDosAssign(name,lock,NULL, DDTYP_Assign)) {
208: pOS_UnlockObject(lock);
209: goto fail;
210: }
211: /* the lock is the assign now */
212: pseudo_dev_assigned = 1;
213: } else pOS_UnlockObject(lock);
214:
215: /* Create the dev:DFi entry */
216: for(i=0;i<4;++i) if(device_exists("pTrackdisk.device",i)) {
217: struct pOS_FileHandle *fd;
218: char name[80];
219:
220: sprintf(name,"%sDF%d",amiga_dev_path,i);
221: fd = pOS_OpenFile(NULL,name,FILEHDMOD_Write);
222: if(fd) {pOS_CloseFile(fd);dfx_done[i]=1;}
223: }
224:
225: return;
226: fail:
227: fprintf(stderr,"Failed to create pseudo DEV: entry!\n");
228: }
229:
230: /****************************************************************************/
231: /*
232: * Cleanup pseudo DEV:DFx
233: */
234: void closepseudodevices(void)
235: {
236: int i;
237: for(i=0;i<4;++i) if(dfx_done[i]) {
238: char name[80];
239: sprintf(name,"%sDF%d",amiga_dev_path,i);
240: pOS_DeleteObjectName(NULL, name);
241: dfx_done[i] = 0;
242: }
243:
244: if(pseudo_dev_assigned) {
245: char name[80];
246: strcpy(name,amiga_dev_path);
247: if(*name && name[strlen(name)-1]==':') name[strlen(name)-1]='\0';
248: pOS_DeleteDosAssign(name,NULL,0);
249: pseudo_dev_assigned = 0;
250: }
251:
252: if(pseudo_dev_created) {
253: pOS_DeleteObjectName(NULL, pseudo_dev_path);
254: pseudo_dev_created = 0;
255: }
256: }
257:
258: /****************************************************************************/
259: /*
260: * checks if a device exists
261: */
262: static int device_exists(char *device_name, int device_unit)
263: {
264: struct pOS_MsgPort port;
265: struct pOS_TrackdiskIO *IO;
266: int ret = 0;
267:
268: if(pOS_ConstructMsgPort(&port)) {
269: IO=(void *)pOS_CreateIORequest(&port, sizeof(struct pOS_TrackdiskIO));
270: if(IO) {
271: if(!pOS_OpenDevice(device_name, device_unit,
272: (struct pOS_IORequest*)IO, 0, 0)) {
273: pOS_CloseDevice((struct pOS_IORequest*)IO);
274: ret = 1;
275: }
276: pOS_DeleteIORequest((struct pOS_IORequest*)IO);
277: }
278: pOS_DestructMsgPort(&port);
279: }
280: return ret;
281: }
282:
283: /****************************************************************************/
284: /*
285: * extract the device and unit form a filename.
286: */
287: static void extract_dev_unit(char *name, char **dev_name, int *dev_unit)
288: {
289: struct pOS_DosMountDevice *dev = NULL;
290: char *s;
291:
292: if((s = malloc(strlen(name)+2))) {
293: sprintf(s,"%s:",name);
294: dev = pOS_GetDosMountName(s);
295: free(s);
296: }
297: if(dev && dev->dmd_Type == DMDTYP_BOD) {
298: *dev_name = strdup(dev->dmd_U.dmd_BOD.dmbod_DevName);
299: *dev_unit = dev->dmd_U.dmd_BOD.dmbod_UnitNum;
300: } else if((s = strrchr(name,'/'))) {
301: /* pTrackdisk[.device]/0 */
302: *dev_unit = atoi(s+1);
303: *dev_name = malloc(1 + s-name);
304: if(*dev_name) {
305: strncpy(*dev_name, name, 1 + s-name);
306: (*dev_name)[s-name]='\0';
307: }
308: } else {
309: /* ?? STRANGEDISK0: ?? */
310: *dev_unit = 0;
311: *dev_name = strdup(name);
312: }
313: if(*dev_name) {
314: char *s;
315: if(!(s = strrchr(*dev_name,'.'))) {
316: /* .device is missing: add it */
317: s = malloc(8+strlen(*dev_name));
318: if(s) {
319: sprintf(s,"%s.device",*dev_name);
320: free(*dev_name);
321: *dev_name = s;
322: }
323: }
324: }
325: }
326:
327: /****************************************************************************/
328:
329: static int dev_inhibit(char *name, int on)
330: {
331: struct pOS_DosDevice *dev;
332: if((dev = pOS_GetDosDevice(NULL, name))) {
333: pOS_InhibitDosDevice(dev,on?TRUE:FALSE);
334: return 1;
335: }
336: return 0;
337: }
338:
339: /****************************************************************************/
340: /*
341: * copy a device to a FILE
342: */
343: static int raw_copy(char *dev_name, int dev_unit, FILE *dst)
344: {
345: struct pOS_MsgPort Port;
346: struct pOS_TrackdiskIO *IO;
347: int ret = 0;
348:
349: if(pOS_ConstructMsgPort(&Port)) {
350: if((IO=(void*)pOS_CreateIORequest(&Port,sizeof(struct pOS_TrackdiskIO)))) {
351: if(!pOS_OpenDevice(dev_name, dev_unit,(struct pOS_IORequest*)IO,0,0)) {
352: struct pOS_DriveGeometry Geom;
353: char *buf;
354:
355: memset(&Geom,0,sizeof(struct pOS_DriveGeometry));
356: IO->tdio_Command = TDCMD_GetGeometry;
357: IO->tdio_Data = &Geom;
358: IO->tdio_Length = sizeof(struct pOS_DriveGeometry);
359: pOS_DoIO((struct pOS_IORequest*)IO);
360: if(IO->tdio_Error!=0) {
361: Geom.dg_SectorSize = 512;
362: Geom.dg_TotalSectors = 880*2;
363: }
364:
365: if((buf=pOS_AllocMem(Geom.dg_SectorSize,Geom.dg_BufMemType))) {
366: ULONG sec;
367: ret = 1;
368:
369: for(sec = 0; sec<Geom.dg_TotalSectors; ++sec) {
370: if((sec % Geom.dg_CylSectors) == 0) {
371: printf("Reading sector %d/%d (%02d%%) of %s unit %d \r",
372: sec, Geom.dg_TotalSectors,
373: (100*sec)/Geom.dg_TotalSectors, dev_name, dev_unit);
374: fflush(stdout);
375: }
376:
377: IO->tdio_Command = CMD_READ;
378: IO->tdio_Data = buf;
379: IO->tdio_Length = Geom.dg_SectorSize;
380: IO->tdio_LOffset = Geom.dg_SectorSize*sec;
381: pOS_DoIO((struct pOS_IORequest*)IO);
382: if(IO->tdio_Error) printf("Err. on\n");
383: if(fwrite(buf,1,Geom.dg_SectorSize,dst)!=Geom.dg_SectorSize) {
384: ret = 0;
385: break;
386: }
387: }
388: IO->tdio_Command = TDCMD_Motor;
389: IO->tdio_Length = 0;
390: pOS_DoIO((struct pOS_IORequest*)IO);
391: printf(" \r");
392: fflush(stdout);
393:
394: pOS_FreeMem(buf,Geom.dg_SectorSize);
395: }
396: pOS_CloseDevice((struct pOS_IORequest*)IO);
397: } pOS_DeleteIORequest((struct pOS_IORequest*)IO);
398: } pOS_DestructMsgPort(&Port);
399: }
400: return ret;
401: }
402:
403: /****************************************************************************/
404: /*
405: * Copy one raw disk to a file.
406: */
407: int readdevice(char *name, char *dst)
408: {
409: FILE *f = NULL;
410: char *device_name;
411: int device_unit;
412: int retstatus = 0;
413: #ifdef HAVE_SIGACTION
414: struct sigaction oldsa;
415: int oldsa_valid;
416: #endif
417: int inhibited;
418:
419: #ifdef HAVE_SIGACTION
420: /* disable break */
421: oldsa_valid = (0==sigaction(SIGINT, NULL, &oldsa));
422: signal(SIGINT, SIG_IGN); /* <--- gcc complains about something */
423: /* in there but I don't know why. */
424: #endif
425: /* get device name & unit */
426: extract_dev_unit(name, &device_name, &device_unit);
427:
428: if(device_name) {
429: /* if no destination then just check if the device exists */
430: if(dst == NULL)
431: retstatus = device_exists(device_name, device_unit);
432: else {
433: inhibited = dev_inhibit(name,1);
434: /* open dest file */
435: if((f = fopen(dst,"wb"))) {
436: retstatus = raw_copy(device_name, device_unit, f);
437: fclose(f);
438: }
439: if(inhibited) dev_inhibit(name,0);
440: }
441: free(device_name);
442: }
443:
444: #ifdef HAVE_SIGACTION
445: /* enable break */
446: if(oldsa_valid) sigaction(SIGINT, &oldsa, NULL);
447: #endif
448: return retstatus;
449: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.