Mercurial > hg > Members > kono > os9 > sbc09
comparison src/vdisk.c @ 57:2088fd998865
sbc09 directry clean up
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 23 Jul 2018 16:07:12 +0900 |
parents | vdisk.c@4fa2bdb0c457 |
children | 7c6dc25c2b05 |
comparison
equal
deleted
inserted
replaced
56:4fa2bdb0c457 | 57:2088fd998865 |
---|---|
1 /******************************************************************** | |
2 * Virtual RBF - Random Block File Manager | |
3 * | |
4 * Shinji KONO (kono@ie.u-ryukyu.ac.jp) 2018/7/17 | |
5 * GPL v1 license | |
6 */ | |
7 | |
8 #define engine extern | |
9 #include "v09.h" | |
10 #include <stdio.h> | |
11 #include <stdlib.h> | |
12 #include <unistd.h> | |
13 #include <sys/stat.h> | |
14 #include <sys/select.h> | |
15 #include <dirent.h> | |
16 #include <string.h> | |
17 #include <time.h> | |
18 #include <arpa/inet.h> | |
19 | |
20 static int vdiskdebug = 0; // bit 1 trace, bit 2 filename | |
21 | |
22 | |
23 Byte pmmu[8]; // process dat mmu | |
24 | |
25 extern char *prog ; // for disass | |
26 #ifdef USE_MMU | |
27 extern Byte * mem0(Byte *iphymem, Word adr, Byte *immu) ; | |
28 // smem physical address using system mmu | |
29 // pmem physical address using caller's mmu | |
30 #define smem(a) mem0(phymem,a,&mem[0x20+IOPAGE]) | |
31 #define pmem(a) mem0(phymem,a,pmmu) | |
32 #else | |
33 #define smem(a) (&mem[a]) | |
34 #define pmem(a) (&mem[a]) | |
35 #endif | |
36 | |
37 #define MAXPDV 256 | |
38 | |
39 | |
40 typedef struct pathDesc { | |
41 char *name; | |
42 FILE *fp; | |
43 int mode; | |
44 int inode ; // lower 24 bit of unix inode, os9 lsn | |
45 int num ; | |
46 int sz ; // used only for directory | |
47 char drv ; | |
48 char use ; | |
49 char dir; | |
50 char *fd ; | |
51 char *dirfp; | |
52 } PathDesc, *PathDescPtr; | |
53 | |
54 static void | |
55 vdisklog(Word u,PathDesc *pd, Word pdptr, int curdir,FILE *fp) ; | |
56 | |
57 #define MAXVDRV 4 | |
58 | |
59 static char *drvRoot[] = { ".",".",".","."}; | |
60 static PathDesc pdv[MAXPDV]; | |
61 | |
62 /* | |
63 * us 0 system | |
64 * 1 caller | |
65 */ | |
66 static inline Word | |
67 getword(Byte *adr) { | |
68 Word *padr = (Word*)adr; | |
69 return ntohs(*padr); | |
70 } | |
71 | |
72 static inline void | |
73 setword(Byte *adr,Word value) { | |
74 Word *padr = (Word*)adr; | |
75 *padr = htons(value); | |
76 } | |
77 | |
78 static int | |
79 setVdisk(int drv,char *name) { | |
80 if (drv<0 || drv>=MAXVDRV) return -1; | |
81 drvRoot[drv] = name; | |
82 return 0; | |
83 } | |
84 | |
85 static void | |
86 closepd(PathDesc *pd) { | |
87 if(pd->fp) fclose(pd->fp) ; | |
88 pd->dir = 0; | |
89 pd->use = 0; | |
90 pd->fp = 0; | |
91 pd->mode = 0; | |
92 free(pd->dirfp); pd->dirfp = 0; | |
93 free(pd->name); pd->name = 0; | |
94 } | |
95 | |
96 /* | |
97 * keep track current directory ( most recently 256 entry ) | |
98 * too easy approach | |
99 */ | |
100 char *cdt[512]; | |
101 static int cdtptr = 0; | |
102 | |
103 Byte | |
104 setcd(char *name) { | |
105 int len; | |
106 for(int i=0;i<512;i++) { | |
107 if (cdt[i] && strcmp(name,cdt[i])==0) return i; | |
108 } | |
109 cdtptr &= 0x1ff; | |
110 if (cdt[cdtptr]) free(cdt[cdtptr]); | |
111 cdt[cdtptr] = (char*)malloc(len=strlen(name)+1); | |
112 strcpy(cdt[cdtptr],name); | |
113 return cdtptr++; | |
114 } | |
115 | |
116 #define MAXPAHTLEN 256 | |
117 | |
118 static void | |
119 putOs9str(char *s,int max) { | |
120 if (s==0) { | |
121 printf("(null)"); | |
122 return; | |
123 } | |
124 while(*s && (*s&0x7f)>=' ' && ((*s&0x80)==0) && --max !=0) { | |
125 putchar(*s); s++; | |
126 } | |
127 if (*s&0x80) putchar(*s&0x7f); | |
128 } | |
129 | |
130 static void | |
131 err(int error) { | |
132 printf("err %d\n",error); | |
133 } | |
134 | |
135 static char * | |
136 addCurdir(char *name, PathDesc *pd, int curdir) { | |
137 int ns =0 ; | |
138 char *n = name; | |
139 if(vdiskdebug&0x2) { printf("addcur \""); putOs9str(name,0); printf("\" cur \""); putOs9str( cdt[curdir],0); printf("\"\n"); } | |
140 if (name[0]=='/') { | |
141 name++; while(*name !='/' && *name!=0) name ++ ; // skip /d0 | |
142 while(name[ns]!=0) ns++; | |
143 } else if (!cdt[curdir] ) return 0; // no current directory | |
144 else ns = strlen(name); | |
145 int ps = ns; | |
146 char *base ; | |
147 if (name[0]=='/') { | |
148 base = drvRoot[pd->drv]; ps += strlen(drvRoot[pd->drv])+1; name++; | |
149 } else if (name[0]==0) { | |
150 base = drvRoot[pd->drv]; | |
151 char *path = (char*)malloc(strlen(base)+1); // we'll free this, malloc it. | |
152 int i = 0; | |
153 for(;base[i];i++) path[i] = base[i]; | |
154 path[i]=0; | |
155 return path; | |
156 } else { | |
157 base = cdt[curdir]; ps += strlen(cdt[curdir])+2; | |
158 } | |
159 char *path = (char*)malloc(ps); | |
160 int i = 0; | |
161 for(;base[i];i++) path[i] = base[i]; | |
162 path[i++] = '/'; | |
163 for(int j=0;i<ps;j++,i++) path[i] = name[j]; | |
164 path[i] = 0; | |
165 if (i>ps) | |
166 printf("overrun i=%d ps=%d\n",i,ps); // err(__LINE__); | |
167 return path; | |
168 } | |
169 | |
170 static char * | |
171 checkFileName(char *path, PathDesc *pd, int curdir) { | |
172 char *p = path; | |
173 char *name = path; | |
174 int maxlen = MAXPAHTLEN; | |
175 if(vdiskdebug&2) { printf("checkf \""); putOs9str(name,0); printf("\"\n"); } | |
176 while(*p!=0 && (*p&0x80)==0 && (*p&0x7f)>' ' && maxlen-->0) p++; | |
177 if (maxlen==MAXPAHTLEN) return 0; | |
178 if (*p) { // 8th bit termination or non ascii termination | |
179 int eighth = ((*p&0x80)!=0); | |
180 name = (char *)malloc(p-path+1+eighth); | |
181 int i; | |
182 for(i=0;i<p-path;i++) name[i] = path[i]; | |
183 if (eighth) { name[i] = path[i]&0x7f; p++ ; i++; } | |
184 name[i] = 0; | |
185 } | |
186 char *name1 = addCurdir(name,pd,curdir); | |
187 if (name1!=name && name1!=path) free(name); | |
188 if (name1==0) return 0; | |
189 pd->name = name1; | |
190 if(vdiskdebug&2) { | |
191 printf(" remain = \""); | |
192 char *p1 = p; int max=31; | |
193 while(*p1 && (*p1&0x80)==0 && max-->0) { if (*p1<0x20) printf("(0x%02x)",*p1); else putchar(*p1); p1++; } | |
194 if (*p1) { if ((*p1&0x7f)<0x20) printf("(0x%02x)",*p1); else putchar(*p1&0x7f); } | |
195 printf("\" checkname result \""); putOs9str(pd->name,0); printf("\"\n"); | |
196 } | |
197 return p; | |
198 } | |
199 | |
200 static void | |
201 os9setmode(Byte *os9mode,int mode) { | |
202 char m = 0; | |
203 if (mode&S_IFDIR) m|=0x80; | |
204 if (mode&S_IRUSR) m|=0x01; | |
205 if (mode&S_IWUSR) m|=0x02; | |
206 if (mode&S_IXUSR) m|=0x04; | |
207 if (mode&S_IROTH) m|=0x08; | |
208 if (mode&S_IWOTH) m|=0x10; | |
209 if (mode&S_IXOTH) m|=0x20; | |
210 m|=0x60; // always sharable | |
211 *os9mode = m; | |
212 } | |
213 | |
214 static char * | |
215 os9toUnixAttr(Byte attr) { | |
216 if ((attr&0x1) && (attr&0x2)) return "r+"; | |
217 if (!(attr&0x1) && (attr&0x2)) return "w"; | |
218 if ((attr&0x1) && !(attr&0x2)) return "r"; | |
219 return "r"; | |
220 } | |
221 | |
222 /* | |
223 * os9 file descriptor | |
224 * * File Descriptor Format | |
225 * | |
226 * The file descriptor is a sector that is present for every file | |
227 * on an RBF device. It contains attributes, modification dates, | |
228 * and segment information on a file. | |
229 * | |
230 * ORG 0 | |
231 *FD.ATT RMB 1 Attributes | |
232 *FD.OWN RMB 2 Owner | |
233 *FD.DAT RMB 5 Date last modified | |
234 *FD.LNK RMB 1 Link count | |
235 *FD.SIZ RMB 4 File size | |
236 *FD.Creat RMB 3 File creation date (YY/MM/DD) | |
237 *FD.SEG EQU . Beginning of segment list | |
238 * Segment List Entry Format | |
239 ORG 0 | |
240 * FDSL.A RMB 3 Segment beginning physical sector number | |
241 * FDSL.B RMB 2 Segment size | |
242 * FDSL.S EQU . Segment list entry size | |
243 * FD.LS1 EQU FD.SEG+((256-FD.SEG)/FDSL.S-1)*FDSL.S | |
244 * FD.LS2 EQU (256/FDSL.S-1)*FDSL.S | |
245 * MINSEC SET 16 | |
246 */ | |
247 | |
248 #define FD_ATT 0 | |
249 #define FD_OWN 1 | |
250 #define FD_DAT 3 | |
251 #define FD_LNK 8 | |
252 #define FD_SIZ 9 | |
253 #define FD_Creat 13 | |
254 #define FD_SEG 16 | |
255 | |
256 | |
257 /* | |
258 * os9 directory structure | |
259 * | |
260 * ORG 0 | |
261 *DIR.NM RMB 29 File name | |
262 *DIR.FD RMB 3 File descriptor physical sector number | |
263 *DIR.SZ EQU . Directory record size | |
264 */ | |
265 #define DIR_SZ 32 | |
266 #define DIR_NM 29 | |
267 | |
268 | |
269 /* read direcotry entry */ | |
270 static int | |
271 os9opendir(PathDesc *pd) { | |
272 DIR *dir; | |
273 struct dirent *dp; | |
274 if (pd->dirfp) return 0; // already opened | |
275 dir = opendir(pd->name); | |
276 if (dir==0) return -1; | |
277 int dircount = 0; | |
278 while ((dp = readdir(dir)) != NULL) dircount++; // pass 1 to determine the size | |
279 if (dircount==0) return 0; // should contains . and .. at least | |
280 pd->sz = dircount*DIR_SZ; | |
281 pd->dirfp = (char *)malloc(dircount*DIR_SZ); | |
282 rewinddir(dir); | |
283 int i = 0; | |
284 while ((dp = readdir(dir)) != NULL && dircount-->=0) { | |
285 int j = 0; | |
286 for(j = 0; j < DIR_NM ; j++) { | |
287 if (j< dp->d_namlen) { | |
288 pd->dirfp[i+j] = dp->d_name[j]&0x7f; | |
289 if (j== dp->d_namlen-1) | |
290 pd->dirfp[i+j] |= 0x80; // os9 EOL | |
291 } else | |
292 pd->dirfp[i+j] = 0; | |
293 } | |
294 pd->dirfp[i+j] = (dp->d_ino&0xff0000)>>16; | |
295 pd->dirfp[i+j+1] = (dp->d_ino&0xff00)>>8; | |
296 pd->dirfp[i+j+2] = dp->d_ino&0xff; | |
297 i += DIR_SZ; | |
298 if (i>pd->sz) | |
299 return 0; | |
300 } | |
301 pd->fp = fmemopen(pd->dirfp,pd->sz,"r"); | |
302 return 0; | |
303 } | |
304 | |
305 static void | |
306 os9setdate(Byte *d,struct timespec * unixtime) { | |
307 // yymmddhhss | |
308 struct tm r; | |
309 localtime_r(&unixtime->tv_sec,&r); | |
310 d[0] = r.tm_year-2048; | |
311 d[1] = r.tm_mon + 1; | |
312 d[2] = r.tm_mday; | |
313 d[3] = r.tm_hour; | |
314 d[4] = r.tm_min; | |
315 d[5] = r.tm_sec; | |
316 } | |
317 | |
318 /* read file descriptor of Path Desc | |
319 * create file descriptor sector if necessary | |
320 * if buf!=0, copy it | |
321 */ | |
322 static int | |
323 filedescriptor(Byte *buf, int len, Byte *name,int curdir) { | |
324 int err = 0x255; | |
325 PathDesc pd; | |
326 if (len<13) return -1; | |
327 checkFileName((char*)name,&pd,curdir); | |
328 struct stat st; | |
329 if (stat(pd.name,&st)!=0) goto err1; | |
330 os9setmode(buf+FD_ATT,st.st_mode); | |
331 buf[FD_OWN]=(st.st_uid&0xff00)>>8; | |
332 buf[FD_OWN+1]=st.st_uid&0xff; | |
333 os9setdate(buf+ FD_DAT,&st.st_mtimespec); | |
334 buf[FD_LNK]=st.st_nlink&0xff; | |
335 buf[FD_SIZ+0]=(st.st_size&0xff000000)>>24; | |
336 buf[FD_SIZ+1]=(st.st_size&0xff0000)>>16; | |
337 buf[FD_SIZ+2]=(st.st_size&0xff00)>>8; | |
338 buf[FD_SIZ+3]=st.st_size&0xff; | |
339 os9setdate(buf+FD_Creat,&st.st_ctimespec); | |
340 err = 0; | |
341 err1: | |
342 free(pd.name); | |
343 return err; | |
344 } | |
345 | |
346 /* read direcotry entry for any file in the directory | |
347 * we only returns a file descriptor only in the current opened directory | |
348 * | |
349 * inode==0 should return disk id section | |
350 * inode==bitmap should return disk sector map for os9 free command | |
351 */ | |
352 static int | |
353 fdinfo(Byte *buf,int len, int inode, PathDesc *pd,int curdir) { | |
354 int i; | |
355 for(i=0;i<MAXPDV;i++) { | |
356 PathDesc *pd = pdv+i; | |
357 if (!pd->use || !pd->dir) continue; | |
358 // find inode in directory | |
359 Byte *dir = (Byte*)pd->dirfp; | |
360 Byte *end = (Byte*)pd->dirfp + pd->sz; | |
361 while( dir < end ) { | |
362 Byte *p = (dir + DIR_NM); | |
363 int dinode = (p[0]<<16)+(p[1]<<8)+p[2]; | |
364 if (inode == dinode) { | |
365 return filedescriptor(buf,len,dir,curdir); | |
366 } | |
367 dir += 0x20; | |
368 } | |
369 } | |
370 return 255; | |
371 } | |
372 | |
373 void | |
374 getDAT() { | |
375 Word ps = getword(smem(0x50)); // process structure | |
376 Byte *dat = smem(ps+0x40); // process dat (dynamic address translation) | |
377 for(int i=0; i<8; i++) { | |
378 pmmu[i] = dat[i*2+1]; | |
379 } | |
380 } | |
381 | |
382 /* | |
383 * each command should have preallocated os9 path descriptor on Y | |
384 * | |
385 * name or buffer, can be in a user map, check that drive number ( mem[0x41+IOPAGE] 0 sys 1 user ) | |
386 * current directory path number mem[0x42+IOPAGE] | |
387 * yreg has pd number | |
388 */ | |
389 void | |
390 do_vdisk(Byte cmd) { | |
391 int err; | |
392 int curdir = mem[0x44+IOPAGE]; // garbage until set | |
393 Byte attr ; | |
394 Word u = getword(&mem[0x45+IOPAGE]); // caller's stack in system segment | |
395 Byte *frame = smem(u); | |
396 xreg = getword(frame+4); | |
397 yreg = getword(frame+6); | |
398 *areg = *smem(u+1); | |
399 *breg = *smem(u+2); | |
400 Byte mode = 0; | |
401 Byte *os9pd = smem(getword(&mem[0x47+IOPAGE])); | |
402 PathDesc *pd = pdv+*os9pd; | |
403 | |
404 getDAT(); | |
405 pd->num = *os9pd; | |
406 pd->drv = mem[0x41+IOPAGE]; | |
407 char *path,*next,*buf; | |
408 if (vdiskdebug&1) vdisklog(u,pd,getword(&mem[0x47+IOPAGE]),curdir,stdout); | |
409 | |
410 switch(cmd) { | |
411 /* | |
412 * I$Create Entry Point | |
413 * | |
414 * Entry: A = access mode desired | |
415 * B = file attributes | |
416 * X = address of the pathlist | |
417 * | |
418 * Exit: A = pathnum | |
419 * X = last byte of pathlist address | |
420 * | |
421 * Error: CC Carry set | |
422 * B = errcode | |
423 */ | |
424 case 0xd1: | |
425 mode = *areg; | |
426 attr = *breg; | |
427 path = (char *)pmem(xreg); | |
428 next = pd->name = checkFileName(path,pd,curdir); | |
429 pd->dir = 0; | |
430 pd->fp = fopen(pd->name, os9toUnixAttr(attr)); | |
431 if (next!=0 && pd->fp ) { | |
432 xreg += ( next - path ); | |
433 pd->use = 1; | |
434 } else { | |
435 *breg = 0xff; | |
436 free(pd->name); | |
437 pd->use = 0; | |
438 } | |
439 break; | |
440 | |
441 /* | |
442 * I$Open Entry Point | |
443 * | |
444 * Entry: A = access mode desired | |
445 * X = address of the pathlist | |
446 * | |
447 * Exit: A = pathnum | |
448 * X = last byte of pathlist address | |
449 * | |
450 * Error: CC Carry set | |
451 * B = errcode | |
452 */ | |
453 case 0xd2: | |
454 *breg = 0xff; | |
455 mode = *areg; | |
456 attr = *breg; | |
457 pd->fp = 0; | |
458 path = (char*)pmem(xreg); | |
459 next = checkFileName(path,pd,curdir); | |
460 *breg = 0xff; | |
461 if (next!=0) { | |
462 struct stat buf; | |
463 if (stat(pd->name,&buf)!=0) break; | |
464 if ((buf.st_mode & S_IFMT) == S_IFDIR) { | |
465 pd->dir = 1; | |
466 os9opendir(pd); | |
467 } else { | |
468 pd->dir = 0; | |
469 pd->fp = fopen( pd->name,os9toUnixAttr(mode)); | |
470 } | |
471 pd->use = 1; | |
472 } | |
473 if (next!=0 && pd->fp !=0) { | |
474 *breg = 0; | |
475 *areg = pd->num; | |
476 *smem(u+1) = *areg ; | |
477 xreg += ( next - path ); | |
478 pd->use = 1; | |
479 } else { | |
480 pd->use = 0; | |
481 } | |
482 break; | |
483 | |
484 /* | |
485 * I$MakDir Entry Point | |
486 * | |
487 * Entry: X = address of the pathlist | |
488 * B = directory attributes | |
489 * | |
490 * Exit: X = last byte of pathlist address | |
491 * | |
492 * Error: CC Carry set | |
493 * B = errcode | |
494 */ | |
495 | |
496 case 0xd3: | |
497 *breg = 0xff; | |
498 path = (char*)pmem(xreg); | |
499 next = checkFileName(path,pd,curdir); | |
500 if (next!=0 && mkdir(pd->name,0)!= 0 ) { | |
501 xreg += ( next - path ); | |
502 *breg = 0; | |
503 } | |
504 closepd(pd); | |
505 break; | |
506 | |
507 /* | |
508 * I$ChgDir Entry Point | |
509 * | |
510 * data dir P$DIO 3-5 contains open dir Path number | |
511 * exec dir P$DIO 9-11 contains open dir Path number | |
512 * | |
513 * Entry: | |
514 * | |
515 * *areg = access mode | |
516 * 0 = Use any special device capabilities | |
517 * 1 = Read only | |
518 * 2 = Write only | |
519 * 3 = Update (read and write) | |
520 * Entry: X = address of the pathlist | |
521 * | |
522 * Exit: X = last byte of pathlist address | |
523 * A = open directory Path Number | |
524 * | |
525 * Error: CC Carry set | |
526 * B = errcode | |
527 * | |
528 * | |
529 * we keep track a cwd and a cxd for a process using 8bit id | |
530 */ | |
531 case 0xd4: | |
532 path = (char*)pmem(xreg); | |
533 next = checkFileName(path,pd,curdir); | |
534 if (next!=0) { | |
535 struct stat buf; | |
536 if (stat(pd->name,&buf)!=0) break; | |
537 if ((buf.st_mode & S_IFMT) != S_IFDIR) break; | |
538 xreg += ( next - path ); | |
539 *areg = setcd(pd->name); | |
540 *smem(u+1) = *areg ; | |
541 pd->use = 1; | |
542 pd->dir = 1; | |
543 *breg = 0; | |
544 break; | |
545 } | |
546 *breg = 0xff; | |
547 break; | |
548 | |
549 /* | |
550 * I$Delete Entry Point | |
551 * | |
552 * Entry: | |
553 * | |
554 * Exit: | |
555 * | |
556 * Error: CC Carry set | |
557 * B = errcode | |
558 */ | |
559 case 0xd5: { | |
560 *breg = 0xff; | |
561 if (pd==0) break; | |
562 struct stat st; | |
563 path = (char*)pmem(xreg); | |
564 next = checkFileName(path,pd,curdir); | |
565 pd->use = 0; | |
566 if (next!=0 && stat(pd->name,&st)!=0) break; | |
567 if (next!=0 && ((st.st_mode&S_IFDIR)?rmdir(pd->name):unlink(pd->name)) == 0) { | |
568 xreg += ( next - path ); | |
569 *breg = 0; | |
570 } | |
571 } | |
572 break; | |
573 | |
574 /* | |
575 * I$Seek Entry Point | |
576 * | |
577 * Entry Conditions | |
578 * A path number | |
579 * X MS 16 bits of the desired file position | |
580 * U LS 16 bits of the desired file position | |
581 * | |
582 * Exit: | |
583 * | |
584 * Error: CC Carry set | |
585 * B = errcode | |
586 */ | |
587 case 0xd6: { | |
588 *breg = 0xff; | |
589 ureg = (*smem(u+8)<<8)+*smem(u+9); | |
590 off_t seek = (xreg<<16)+ureg; | |
591 *breg = fseek(pd->fp,(off_t)seek,SEEK_SET); | |
592 break; | |
593 } | |
594 /* | |
595 * I$ReadLn Entry Point | |
596 * | |
597 * Entry: | |
598 * Entry Conditions in correct mmu map | |
599 * A path number | |
600 * X address at which to store data | |
601 * Y maximum number of bytes to read | |
602 * | |
603 * Exit: | |
604 * | |
605 * Y number of bytes read | |
606 * | |
607 * Error: CC Carry set | |
608 * B = errcode | |
609 * | |
610 * | |
611 */ | |
612 case 0xd7: | |
613 *breg = 0xff; | |
614 buf = (char*)pmem(xreg); | |
615 char *b; | |
616 if ((b=fgets(buf,yreg,pd->fp))) { | |
617 if (b==0) { | |
618 *breg = 0xd3; | |
619 break; | |
620 } | |
621 int i; | |
622 for(i=0;i<yreg && buf[i];i++); | |
623 if (i>0 && buf[i-1]=='\n') { | |
624 buf[i-1] = '\r'; | |
625 yreg = i; | |
626 } | |
627 // set y | |
628 setword(smem(u+6),yreg); | |
629 *breg = 0; | |
630 } | |
631 break; | |
632 | |
633 /* | |
634 * I$Read Entry Point | |
635 * | |
636 * Entry: | |
637 * | |
638 * Exit: | |
639 * | |
640 * Error: CC Carry set | |
641 * B = errcode | |
642 */ | |
643 case 0xd8: | |
644 *breg = 0xff; | |
645 buf = (char*)pmem(xreg); | |
646 int i = fread(buf,1,yreg,pd->fp); | |
647 // set y | |
648 setword(smem(u+6),i); | |
649 *breg = (i==0?0xd3:0) ; | |
650 break; | |
651 | |
652 /* | |
653 * I$WritLn Entry Point | |
654 * | |
655 * Entry: | |
656 * A path number | |
657 * X address of the data to write | |
658 * Y maximum number of bytes to read | |
659 | |
660 * | |
661 * Exit: | |
662 * Y number of bytes written | |
663 * | |
664 * Error: CC Carry set | |
665 * B = errcode | |
666 */ | |
667 case 0xd9: { | |
668 *breg = 0xff; | |
669 if (pd->dir) break; | |
670 int len = yreg; | |
671 int i = 0; | |
672 Byte *buf = pmem(xreg); | |
673 while(len>0 && *buf !='\r') { | |
674 fputc(buf[i++],pd->fp); | |
675 len--; | |
676 } | |
677 if (buf[i]=='\r') { | |
678 fputc('\n',pd->fp); | |
679 i++; | |
680 } | |
681 *breg = 0; | |
682 // set y | |
683 setword(smem(u+6),i); | |
684 break; | |
685 } | |
686 | |
687 /* | |
688 * I$Write Entry Point | |
689 * | |
690 * Entry: | |
691 * | |
692 * Exit: | |
693 * | |
694 * Error: CC Carry set | |
695 * B = errcode | |
696 */ | |
697 case 0xda : | |
698 *breg = 0xff; | |
699 if (!pd->dir) { | |
700 Byte *buf = pmem(xreg); | |
701 int len = yreg; | |
702 int err = fwrite(buf,1,len,pd->fp); | |
703 *breg = err?0:0xff; | |
704 // set y | |
705 setword(smem(u+6),err); | |
706 } | |
707 break; | |
708 | |
709 /* I$Close Entry Point | |
710 * | |
711 * Entry: A = path number | |
712 * | |
713 * Exit: | |
714 * | |
715 * Error: CC Carry set | |
716 * B = errcode | |
717 * | |
718 */ | |
719 case 0xdb: | |
720 *breg = 0xff; | |
721 if (pd==0) break; | |
722 closepd(pd); | |
723 *breg = 0; | |
724 break; | |
725 | |
726 /* | |
727 * I$GetStat Entry Point | |
728 * | |
729 * Entry: | |
730 * | |
731 * Exit: | |
732 * | |
733 * Error: CC Carry set | |
734 * B = errcode | |
735 */ | |
736 case 0xdc: { | |
737 struct stat st; | |
738 off_t pos; | |
739 switch (*breg) { | |
740 case 01: // SS.Ready | |
741 *breg = 0xff; | |
742 if (pd==0) break; | |
743 fstat(fileno(pd->fp),&st); | |
744 if ((pos = ftell(pd->fp))) { | |
745 xreg = st.st_size - pos; | |
746 *breg = 0; | |
747 } | |
748 break; | |
749 case 02: // SS.SIZ | |
750 *breg = 0xff; | |
751 if (pd==0) break; | |
752 fstat(fileno(pd->fp),&st); | |
753 xreg = st.st_size ; | |
754 *breg = 0; | |
755 break; | |
756 case 05: // SS.Pos | |
757 *breg = 0xff; | |
758 if (pd==0) break; | |
759 xreg = ftell(pd->fp); | |
760 *breg = 0; | |
761 break; | |
762 case 15: // SS.FD | |
763 /* SS.FD ($0F) - Returns a file descriptor | |
764 * Entry: R$A=Path # | |
765 * R$B=SS.FD ($0F) | |
766 * R$X=Pointer to a 256 byte buffer | |
767 * R$Y=# bytes of FD required | |
768 */ | |
769 *breg = 0xff; | |
770 if (pd==0) break; | |
771 *breg = filedescriptor(pmem(xreg), yreg,(Byte*)pd->name,curdir) ; | |
772 break; | |
773 case 0x20: // Pos.FDInf mandatry for dir command | |
774 /* SS.FDInf ($20) - Directly reads a file descriptor from anywhere | |
775 * on drive. | |
776 * Entry: R$A=Path # | |
777 * R$B=SS.FDInf ($20) | |
778 * R$X=Pointer to a 256 byte buffer | |
779 * R$Y= MSB - Length of read | |
780 * LSB - MSB of logical sector # | |
781 * R$U= LSW of logical sector # | |
782 */ | |
783 *breg = 0xff; | |
784 if (pd==0) break; | |
785 ureg = getword(smem(u+8)); | |
786 *breg = fdinfo(pmem(xreg),(yreg&0xff),((yreg&0xff00)>>8)*0x10000+ureg,pd,curdir); | |
787 break; | |
788 default: | |
789 *breg = 0xff; | |
790 } | |
791 break; | |
792 } | |
793 | |
794 /* | |
795 * I$SetStat Entry Point | |
796 * | |
797 * Entry: | |
798 * | |
799 * Exit: | |
800 * | |
801 * | |
802 * Error: CC Carry set | |
803 * B = errcode | |
804 */ | |
805 case 0xdd: | |
806 switch (*breg) { | |
807 case 0: // SS.Opt | |
808 case 02: // SS.SIZ | |
809 case 15: // SS.FD | |
810 case 0x11: // SS.Lock | |
811 case 0x10: // SS.Ticks | |
812 case 0x20: // SS.RsBit | |
813 case 0x1c: // SS.Attr | |
814 default: | |
815 *breg = 0xff; | |
816 } | |
817 break; | |
818 } | |
819 if (vdiskdebug && *breg) printf(" vdisk call error %x\n",*breg); | |
820 // return value | |
821 mem[0x40+IOPAGE] = *breg; | |
822 *smem(u+2) = *breg ; | |
823 setword(smem(u+4),xreg); | |
824 } | |
825 | |
826 static void | |
827 vdisklog(Word u,PathDesc *pd, Word pdptr, int curdir, FILE *fp) { | |
828 char *cd = cdt[curdir]?cdt[curdir]:"(null)"; | |
829 fprintf(fp,"pd %d 0x%x cd[%d]=%s ",pd->num, pdptr, curdir,cd); | |
830 Byte *frame = smem(u); | |
831 sreg = u; | |
832 ccreg = frame[0]; | |
833 *areg = frame[1]; | |
834 *breg = frame[2]; | |
835 xreg = getword(frame+4); | |
836 yreg = getword(frame+6); | |
837 ureg = getword(frame+8); | |
838 pcreg = getword(frame+10)-3; | |
839 prog = (char*)(pmem(pcreg) - pcreg); | |
840 do_trace(fp); | |
841 } | |
842 | |
843 | |
844 /* end */ |