Mercurial > hg > Members > kono > os9 > sbc09
comparison vdisk.c @ 44:b26c23331d02
add more function on vdisk
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Thu, 19 Jul 2018 11:31:17 +0900 |
parents | 7a83a6a1685a |
children | 07c84761da6f |
comparison
equal
deleted
inserted
replaced
43:7a83a6a1685a | 44:b26c23331d02 |
---|---|
3 * | 3 * |
4 * Shinji KONO (kono@ie.u-ryukyu.ac.jp) 2018/7/17 | 4 * Shinji KONO (kono@ie.u-ryukyu.ac.jp) 2018/7/17 |
5 * GPL v1 license | 5 * GPL v1 license |
6 */ | 6 */ |
7 | 7 |
8 #define engine extern | |
9 #include "v09.h" | |
8 #include <stdio.h> | 10 #include <stdio.h> |
9 #include <stdlib.h> | 11 #include <stdlib.h> |
10 #include <unistd.h> | 12 #include <unistd.h> |
11 #include <sys/stat.h> | 13 #include <sys/stat.h> |
12 #include <sys/select.h> | 14 #include <sys/select.h> |
13 | 15 #include <dirent.h> |
14 | 16 #include <string.h> |
15 /**************************** | 17 |
16 * | 18 |
17 * Main entry point for RBF | 19 #ifdef USE_MMU |
18 * | 20 extern char *prog ; // for disass |
19 lbra Open | 21 extern Byte * mem0(Byte *iphymem, Word adr, Byte *immu) ; |
20 lbra MakDir | 22 #define pmem(a) mem0(phymem,a,mmu) |
21 lbra ChgDir | 23 #define umem(a) (mem[0x41+IOPAGE]?mem0(phymem,a,&mem[0x21+IOPAGE]):mem0(phymem,a,&mem[0x20+IOPAGE])) |
22 lbra Delete | 24 #else |
23 lbra Seek | 25 #define pmem(a) (&mem[a]) |
24 lbra Read | 26 #define umem(a) (&mem[a]) |
25 lbra Write | 27 #endif |
26 lbra ReadLn | 28 |
27 lbra WriteLn | 29 #define MAXPDV 256 |
28 lbra GetStat | 30 |
29 lbra SetStat | 31 typedef struct pathDesc { |
30 lbra Close | 32 char *name; |
31 */ | 33 FILE *fp; |
32 | 34 int mode; |
33 | 35 int inode ; // lower 24 bit of unix inode, os9 lsn |
34 /* | 36 int num ; |
35 * I$Create Entry Point | 37 char use ; |
36 * | 38 char dir; |
37 * Entry: A = access mode desired | 39 char *fd ; |
38 * B = file attributes | 40 char *dirfp; |
39 * X = address of the pathlist | 41 } PathDesc, *PathDescPtr; |
40 * | 42 |
41 * Exit: A = pathnum | 43 |
42 * X = last byte of pathlist address | 44 PathDesc pdv[MAXPDV]; |
43 * | 45 |
44 * Error: CC Carry set | 46 PathDesc *findPD() { |
45 * B = errcode | 47 for(int i=0;i<MAXPDV;i++) { |
46 */ | 48 if (!pdv[i].use) { |
49 pdv[i].use = 1; | |
50 pdv[i].num = i; | |
51 pd[i].mode = 0; | |
52 pd[i].fp = 0; | |
53 pd[i].dirfp = 0; | |
54 pd[i].name = 0; | |
55 pd[i].fd = 0; | |
56 return &pdv[i]; | |
57 } | |
58 } | |
59 return 0; | |
60 } | |
61 | |
62 void closepd(PathDesc *pd) { | |
63 int err = fclose(pd->fp) ; | |
64 pd->use = 0; | |
65 pd->fp = 0; | |
66 pd->mode = 0; | |
67 free(pd->dirfp); pd->dirfp = 0; | |
68 free(pd->name); pd->name = 0; | |
69 free(pd->fd); pd->fd = 0; | |
70 } | |
47 | 71 |
48 #define MAXPAHTLEN 256 | 72 #define MAXPAHTLEN 256 |
49 | 73 |
50 char * checkFileName(char *path, PathDesc *pd) { | 74 char *addCurdir(char *name, PathDesc *curdir) { |
75 int ns = strlen(name); | |
76 int ps = ns; | |
77 int ds=0 ; | |
78 if (curdir==0 && name[0]!='/') return 0; // no current directory | |
79 if (name[0]!='/') ps += (ds=strlen(curdir->name))+1; | |
80 char *path = (char*)malloc(ps+1); | |
81 int i = 0; | |
82 if (ds) { | |
83 for(;i<ds;i++) path[i] = curdir->name[i]; | |
84 path[i++] = '/'; | |
85 } | |
86 for(int j=0;j<ns;j++,i++) path[i] = name[j]; | |
87 path[i++] = 0; | |
88 return path; | |
89 } | |
90 | |
91 char * checkFileName(char *path, PathDesc *pd, PathDesc *curdir) { | |
51 char *p = path; | 92 char *p = path; |
93 char *name = path; | |
52 int maxlen = MAXPAHTLEN; | 94 int maxlen = MAXPAHTLEN; |
53 pd->lastChar = p; | |
54 while(*p!=0 && (*p&80)==0 && maxlen-->0) p++; | 95 while(*p!=0 && (*p&80)==0 && maxlen-->0) p++; |
55 if (maxlen==MAXPAHTLEN) return 0; | 96 if (maxlen==MAXPAHTLEN) return 0; |
56 pd->lastChar = p; | |
57 if (*p!=0) { | 97 if (*p!=0) { |
58 p = (char *)malloc(len+1); | 98 name = (char *)malloc(p-path+1); |
59 strncpy(path,p, MAXPAHTLEN-maxlen); | 99 strncpy(path,p, MAXPAHTLEN-maxlen); |
60 } | 100 } |
101 char *name1 = addCurdir(name,curdir); | |
102 if (name1!=name && name1!=path) free(name); | |
103 pd->name = name1; | |
61 return p; | 104 return p; |
62 } | 105 } |
63 | 106 |
64 int os9toUnixAttr(Byte attr) { | 107 void os9setmode(char &os9mode,int mode) { |
65 return "r+"; | 108 char m = 0; |
66 } | 109 if (mode&S_IFDIR) m|=0x80; |
67 | 110 if (mode&S_IRUSR) m|=0x01; |
68 int vrbf_create(byte mode,Byte attr,char *path,PathDesc *pd) { | 111 if (mode&S_IWUSR) m|=0x02; |
69 char *p = pd->unixName = checkFileName(path,pd); | 112 if (mode&S_IXUSR) m|=0x04; |
70 if (p==0) return -1; | 113 if (mode&S_IROTH) m|=0x08; |
71 p->dir = 0; | 114 if (mode&S_IWOTH) m|=0x10; |
72 p->fp = fopen(p->unixName,"w+"); // os9toUnixAttr(attr)); | 115 if (mode&S_IXOTH) m|=0x20; |
73 if (fd) return 0; | 116 m|=0x60; // always sharable |
74 return -1; | 117 *os9mode = m; |
75 } | 118 } |
76 | 119 |
120 char * os9toUnixAttr(Byte attr) { | |
121 if ((attr&0x1) && (attr&0x2)) return "r+"; | |
122 if (!(attr&0x1) && (attr&0x2)) return "w"; | |
123 if ((attr&0x1) && !(attr&0x2)) return "r"; | |
124 return "r"; | |
125 } | |
77 | 126 |
78 /* | 127 /* |
79 * I$Open Entry Point | 128 * os9 file descriptor |
80 * | 129 * * File Descriptor Format |
81 * Entry: A = access mode desired | 130 * |
82 * X = address of the pathlist | 131 * The file descriptor is a sector that is present for every file |
83 * | 132 * on an RBF device. It contains attributes, modification dates, |
84 * Exit: A = pathnum | 133 * and segment information on a file. |
85 * X = last byte of pathlist address | 134 * |
86 * | 135 * ORG 0 |
87 * Error: CC Carry set | 136 *FD.ATT RMB 1 Attributes |
88 * B = errcode | 137 *FD.OWN RMB 2 Owner |
89 */ | 138 *FD.DAT RMB 5 Date last modified |
90 | 139 *FD.LNK RMB 1 Link count |
91 int vrbf_open(byte mode,char *path, PathDesc *pd) { | 140 *FD.SIZ RMB 4 File size |
92 char *p = pd->unixName = checkFileName(path,pd); | 141 *FD.Creat RMB 3 File creation date (YY/MM/DD) |
93 if (p==0) return -1; | 142 *FD.SEG EQU . Beginning of segment list |
94 struct stat buf; | 143 * Segment List Entry Format |
95 if (stat(p,&buf)!=0) return -1; | 144 ORG 0 |
96 if ((buf.st_mode & S_IFMT) == S_IFDIR) { | 145 * FDSL.A RMB 3 Segment beginning physical sector number |
97 pd->dir = 1; | 146 * FDSL.B RMB 2 Segment size |
98 return 0; | 147 * FDSL.S EQU . Segment list entry size |
148 * FD.LS1 EQU FD.SEG+((256-FD.SEG)/FDSL.S-1)*FDSL.S | |
149 * FD.LS2 EQU (256/FDSL.S-1)*FDSL.S | |
150 * MINSEC SET 16 | |
151 */ | |
152 | |
153 /* | |
154 * os9 directory structure | |
155 * | |
156 * ORG 0 | |
157 *DIR.NM RMB 29 File name | |
158 *DIR.FD RMB 3 File descriptor physical sector number | |
159 *DIR.SZ EQU . Directory record size | |
160 */ | |
161 | |
162 | |
163 /* read direcotry entry */ | |
164 int os9opendir(PathDesc pd) { | |
165 DIR *dir; | |
166 struct dirent *dp; | |
167 dir = opendir(pd->name); | |
168 pd->name=fname; | |
169 int dircount = 0; | |
170 while ((dp = readdir(dirp)) != NULL) dircout++; // pass 1 to determine the size | |
171 if (dircount==0) return 0; // should contains . and .. at least | |
172 pd->sz = dircount*DIR_SZ | |
173 pd->dirfp = (char *)malloc(dircount*DIR_SZ); | |
174 rewinddir(dir); | |
175 int i = 0; | |
176 while ((dp = readdir(dirp)) != NULL) { | |
177 i += DIR_SZ; | |
178 if (i>pd->SZ) return 0; | |
179 int j = 0; | |
180 for(j = 0; j < DIR_NM ; j++) { | |
181 if (j< dp->d_namlen) | |
182 pd->dirfp[j] = dp->d_name[j]; | |
183 else | |
184 pd->dirfp[j] = 0; | |
185 } | |
186 pd->dirfp[j] = (d_ino&0xff0000)>>16; | |
187 pd->dirfp[j+1] = (d_ino&0xff00)>>8; | |
188 pd->dirfp[j+2] = d_ino&0xff; | |
99 } | 189 } |
100 pd->dir = 0; | 190 pd->fp = fmemopen(pd->dirfp,pd->sz,"r"); |
101 pd->fp = fopen(p->unixName,"r"); // os9toUnixAttr(attr)); | 191 return 0; |
102 if (fp) return 0; | 192 } |
103 return -1; | 193 |
104 } | 194 |
105 | 195 /* read file descriptor of Path Desc |
196 * create file descriptor sector if necessary | |
197 * if buf!=0, copy it | |
198 */ | |
199 int filedescriptor(Byte *buf, int len, PathDesc *pd) { | |
200 struct stat st; | |
201 if (pd->fd) return 1; | |
202 pd->fd = (char *)malloc(256); | |
203 stat((pd->name,&st); | |
204 os9setmode(pd->fd,st.st_mode); | |
205 pd->fd+FD_OWN=(st.st_uid&0xff00)>>8; | |
206 pd->fd+FD_OWN+1=st.st_uid&0xff; | |
207 os9setdate(pd->fd,st.st_mtimespec); | |
208 pd->fd+FD_LNK+0=(st.st_uid&0xff000000)>>24; | |
209 pd->fd+FD_LNK+1=(st.st_uid&0xff0000)>>16; | |
210 pd->fd+FD_LNK+2=(st.st_uid&0xff00)>>8; | |
211 pd->fd+FD_LNK+3=st.st_nlink&0xff; | |
212 os9setdate(pd->fd,st.st_ctimespec); | |
213 // dummy segment list | |
214 for(int i=0x10 ; i < 256; i++) pd->fd[i] = 0; | |
215 return 0; | |
216 } | |
217 | |
218 /* read direcotry entry for any file in the directory | |
219 * we only returns a file descriptor only in the current opened directory | |
220 * | |
221 * inode==0 should return disk id section | |
222 * inode==bitmap should return disk sector map for os9 free command | |
223 */ | |
224 int fdinfo(Byte *buf,int len, int inode) { | |
225 int i; | |
226 for(i=0;i<MAXPDV;i++) { | |
227 PathDesc *pd = pdv+i; | |
228 if (!pd->use || !pd->dir) continue; | |
229 // find inode in directory | |
230 char *dir = (char *)pd->dirfp; | |
231 while( dir < dir + pd->sz ) { | |
232 Byte *p = (Byte *)(dir + DIR_NM); | |
233 int dinode = (p[0]<<16)+(p[1]<<8)+p[2]; | |
234 if (inode == dir) { | |
235 filedescriptor(buf,len,pd); | |
236 return 1; | |
237 } | |
238 } | |
239 } | |
240 return 0; | |
241 } | |
106 | 242 |
107 /* | 243 /* |
108 * I$MakDir Entry Point | 244 * each command should have preallocated os9 path descriptor on Y |
109 * | 245 * |
110 * Entry: X = address of the pathlist | 246 * name or buffer, can be in a user map, pmem check that drive number ( mem[0x41+IOPAGE] 0 sys 1 user ) |
111 * | 247 * current directory path number mem[0x42+IOPAGE] |
112 * Exit: X = last byte of pathlist address | 248 */ |
113 * | 249 void do_vdisk(Byte cmd) { |
114 * Error: CC Carry set | 250 int err; |
115 * B = errcode | 251 PathDesc *pd = pdv + *areg; |
116 */ | 252 PathDesc *curdir = pdv+mem[0x42+IOPAGE]; |
117 | 253 Byte mode,attr ; |
118 int vrbf_mkdir(char **path,PathDesc *pd) { | 254 char *path,*next,*buf; |
119 char *p = checkFileName(path,pd); | 255 |
120 if (p==0) return -1; | 256 switch(cmd) { |
121 return mkdir(p,0); | 257 /* |
122 } | 258 * I$Create Entry Point |
123 | 259 * |
124 /* | 260 * Entry: A = access mode desired |
125 * I$ChgDir Entry Point | 261 * B = file attributes |
126 * | 262 * X = address of the pathlist |
127 * Entry: | 263 * |
128 * | 264 * Exit: A = pathnum |
129 * Exit: | 265 * X = last byte of pathlist address |
130 * | 266 * |
131 * Error: CC Carry set | 267 * Error: CC Carry set |
132 * B = errcode | 268 * B = errcode |
133 */ | 269 */ |
134 | 270 case 0xd1: |
135 char * vrbf_chdir(char *path) { | 271 pd = findPD(); |
136 cahr *p = checkFileName(path); | 272 if (pd==0) { *breg = 0xff; break; } |
137 if (p==0) return -1; | 273 mode = *areg; |
138 struct stat buf; | 274 attr = *breg; |
139 if (stat(p,&buf)!=0) return -1; | 275 path = (char *)pmem(xreg); |
140 if ((buf.st_mode & S_IFMT) == S_IFDIR) { | 276 next = pd->name = checkFileName(path,pd,curdir); |
141 chdir(p); | 277 pd->dir = 0; |
142 return p; | 278 pd->fp = fopen(pd->name, os9toUnixAttr(attr)); |
143 } | 279 if (next!=0 && pd->fp ) { |
144 return -1; | 280 xreg += ( next - path ); |
145 } | 281 pd->use = 1; |
146 | 282 } else { |
147 | 283 *breg = 0xff; |
148 /* | 284 free(pd->name); |
149 * I$Delete Entry Point | 285 } |
150 * | 286 break; |
151 * Entry: | 287 |
152 * | 288 /* |
153 * Exit: | 289 * I$Open Entry Point |
154 * | 290 * |
155 * Error: CC Carry set | 291 * Entry: A = access mode desired |
156 * B = errcode | 292 * X = address of the pathlist |
157 */ | 293 * |
158 | 294 * Exit: A = pathnum |
159 int vrbf_delete(char *path) { | 295 * X = last byte of pathlist address |
160 cahr *p = checkFileName(path); | 296 * |
161 if (p==0) return -1; | 297 * Error: CC Carry set |
162 return rmdir(p); | 298 * B = errcode |
163 } | 299 */ |
164 | 300 case 0xd2: |
165 | 301 pd = findPD(); |
166 /* | 302 *breg = 0xff; |
167 * I$Seek Entry Point | 303 if (pd==0) break; |
168 * | 304 mode = *areg; |
169 * Entry: | 305 attr = *breg; |
170 * | 306 pd->fp = 0; |
171 * Exit: | 307 path = (char*)pmem(xreg); |
172 * | 308 next = pd->name = checkFileName(path,pd,curdir); |
173 * Error: CC Carry set | 309 if (next!=0) { |
174 * B = errcode | 310 struct stat buf; |
175 */ | 311 if (stat(pd->name,&buf)!=0) break; |
176 | 312 if ((buf.st_mode & S_IFMT) == S_IFDIR) { |
177 int vrbf_seek(PathDesc *p, int seek) { | 313 pd->dir = 1; |
178 return fseek(p->fp,(off_t)seek,SEEK_SET); | 314 os9opendir(pd); |
179 } | 315 } else { |
180 | 316 char *fname; |
181 | 317 pd->dir = 0; |
182 * | 318 if (curdir==0 && name[0]!='/') return 0; // no current directory |
183 * I$ReadLn Entry Point | 319 pd->fp = fopen( fname=findfile(pd->name,curdir),"r+"); |
184 * | 320 free(fname); |
185 * Entry: | 321 } |
186 * | 322 } |
187 * Exit: | 323 if (next!=0 && pd->fp !=0) { |
188 * | 324 *areg = pd->num; |
189 * Error: CC Carry set | 325 xreg += ( next - path ); |
190 * B = errcode | 326 } |
191 * | 327 break; |
192 * | 328 |
193 int vrbf_readln(PathDesc *p, byte *buf, int len) { | 329 /* |
194 if (p->dir) return -1; | 330 * I$MakDir Entry Point |
195 if (fgets(buf,len,p->fp)) { | 331 * |
196 int i; | 332 * Entry: X = address of the pathlist |
197 for(i=0;i<len && buf[i];i++); | 333 * B = directory attributes |
198 if (i>0 && buf[i-1]=='\n') { | 334 * |
199 buf[i-1] = '\r'; | 335 * Exit: X = last byte of pathlist address |
200 return i; | 336 * |
201 } | 337 * Error: CC Carry set |
202 } | 338 * B = errcode |
203 return -1; | 339 */ |
204 } | 340 |
205 | 341 case 0xd3: |
206 /* | 342 pd = findPD(); |
207 * I$Read Entry Point | 343 *breg = 0xff; |
208 * | 344 if (pd==0) break; |
209 * Entry: | 345 path = (char*)pmem(xreg); |
210 * | 346 next = checkFileName(path,pd,curdir); |
211 * Exit: | 347 if (next!=0 && mkdir(pd->name,0)!= 0 ) { |
212 * | 348 xreg += ( next - path ); |
213 * Error: CC Carry set | 349 *breg = 0; |
214 * B = errcode | 350 } |
215 */ | 351 closepd(pd); |
216 | 352 break; |
217 int vrbf_read(PathDesc *p, byte *buf, int len) { | 353 |
218 if (p->dir) return dirread(p,buf,len); | 354 /* |
219 return fread(buf,len,1,p->fp); | 355 * I$ChgDir Entry Point |
220 } | 356 * |
221 | 357 * data dir P$DIO 3-5 contains open dir Path number |
222 /* | 358 * exec dir P$DIO 9-11 contains open dir Path number |
223 * I$WritLn Entry Point | 359 * |
224 * | 360 * Entry: |
225 * Entry: | 361 * |
226 * | 362 * *areg = access mode |
227 * Exit: | 363 * 0 = Use any special device capabilities |
228 * | 364 * 1 = Read only |
229 * Error: CC Carry set | 365 * 2 = Write only |
230 * B = errcode | 366 * 3 = Update (read and write) |
231 */ | 367 * Entry: X = address of the pathlist |
232 | 368 * |
233 int vrbf_writeln(PathDesc *p, byte *buf, int len) { | 369 * Exit: X = last byte of pathlist address |
234 if (p->dir) return -1; | 370 * A = open directory Path Number |
235 int = 0; | 371 * |
236 while(len>0 && *buf !='\r) { | 372 * Error: CC Carry set |
237 fputc(buf[i++],p->fp); | 373 * B = errcode |
238 len--; | 374 */ |
375 case 0xd4: | |
376 pd = findPD(); | |
377 if (pd==0) { *breg = 0xff; break; } | |
378 path = (char*)pmem(xreg); | |
379 next = checkFileName(path,pd,curdir); | |
380 if (next!=0 && os9opendir(pd)) { | |
381 if (curdir!=pd) closepd(curdir); | |
382 if (pd->name != path) { | |
383 free(path); | |
384 } | |
385 xreg += ( next - path ); | |
386 *areg = pd->num; | |
387 *breg = 0; | |
388 break; | |
389 } | |
390 *breg = 0xff; | |
391 break; | |
392 | |
393 /* | |
394 * I$Delete Entry Point | |
395 * | |
396 * Entry: | |
397 * | |
398 * Exit: | |
399 * | |
400 * Error: CC Carry set | |
401 * B = errcode | |
402 */ | |
403 case 0xd5: { | |
404 *breg = 0xff; | |
405 if (pd==0) break; | |
406 struct stat st; | |
407 path = (char*)pmem(xreg); | |
408 next = checkFileName(path,pd,curdir); | |
409 if (next!=0 && stat(pd->name,&st)!=0) break; | |
410 if (next!=0 && ((st->st_mode&S_IFDIR)?rmdir(pd->name):unlink(pd->name)) == 0) { | |
411 xreg += ( next - path ); | |
412 *breg = 0; | |
413 } | |
414 } | |
415 break; | |
416 | |
417 /* | |
418 * I$Seek Entry Point | |
419 * | |
420 * Entry Conditions | |
421 * A path number | |
422 * X MS 16 bits of the desired file position | |
423 * Y LS 16 bits of the desired file position | |
424 * | |
425 * Exit: | |
426 * | |
427 * Error: CC Carry set | |
428 * B = errcode | |
429 */ | |
430 case 0xd6: { | |
431 *breg = 0xff; | |
432 if (pd==0) break; | |
433 off_t seek = (xreg<<16)+yreg; | |
434 *breg = fseek(pd->fp,(off_t)seek,SEEK_SET); | |
435 break; | |
436 } | |
437 /* | |
438 * I$ReadLn Entry Point | |
439 * | |
440 * Entry: | |
441 * Entry Conditions in correct mmu map | |
442 * A path number | |
443 * X address at which to store data | |
444 * Y maximum number of bytes to read | |
445 * | |
446 * Exit: | |
447 * | |
448 * Y number of bytes read | |
449 * | |
450 * Error: CC Carry set | |
451 * B = errcode | |
452 * | |
453 * | |
454 */ | |
455 case 0xd7: | |
456 *breg = 0xff; | |
457 if (pd==0) break; | |
458 if (pd->dir) break; | |
459 buf = (char*)pmem(xreg); | |
460 if (fgets(buf,yreg,pd->fp)) { | |
461 int len = yreg; | |
462 int i; | |
463 for(i=0;i<len && buf[i];i++); | |
464 if (i>0 && buf[i-1]=='\n') { | |
465 buf[i-1] = '\r'; | |
466 yreg = i; | |
467 } | |
468 *breg = 0; | |
469 } | |
470 break; | |
471 | |
472 /* | |
473 * I$Read Entry Point | |
474 * | |
475 * Entry: | |
476 * | |
477 * Exit: | |
478 * | |
479 * Error: CC Carry set | |
480 * B = errcode | |
481 */ | |
482 case 0xd8: | |
483 *breg = 0xff; | |
484 if (pd==0) break; | |
485 buf = (char*)pmem(xreg); | |
486 err = fread(buf,yreg,1,pd->fp); | |
487 *breg = err==0?0xff:0 ; | |
488 yreg = err ; | |
489 break; | |
490 | |
491 /* | |
492 * I$WritLn Entry Point | |
493 * | |
494 * Entry: | |
495 * A path number | |
496 * X address of the data to write | |
497 * Y maximum number of bytes to read | |
498 | |
499 * | |
500 * Exit: | |
501 * Y number of bytes written | |
502 * | |
503 * Error: CC Carry set | |
504 * B = errcode | |
505 */ | |
506 case 0xd9: | |
507 *breg = 0xff; | |
508 if (pd==0) break; | |
509 if (pd->dir) break; | |
510 int len = yreg; | |
511 int i = 0; | |
512 Byte *buf = pmem(xreg); | |
513 while(len>0 && *buf !='\r') { | |
514 fputc(buf[i++],pd->fp); | |
515 len--; | |
516 } | |
517 if (buf[i]=='\r') { | |
518 fputc('\n',pd->fp); | |
519 i++; | |
520 } | |
521 *breg = 0; | |
522 yreg = i; | |
523 break; | |
524 | |
525 /* | |
526 * I$Write Entry Point | |
527 * | |
528 * Entry: | |
529 * | |
530 * Exit: | |
531 * | |
532 * Error: CC Carry set | |
533 * B = errcode | |
534 */ | |
535 case 0xda : | |
536 *breg = 0xff; | |
537 if (!pd->dir) { | |
538 Byte *buf = pmem(xreg); | |
539 int len = yreg; | |
540 int err = fwrite(buf,len,1,pd->fp); | |
541 *breg = err?0xff:0; | |
542 yreg = err; | |
543 } | |
544 break; | |
545 | |
546 /* I$Close Entry Point | |
547 * | |
548 * Entry: A = path number | |
549 * | |
550 * Exit: | |
551 * | |
552 * Error: CC Carry set | |
553 * B = errcode | |
554 * | |
555 */ | |
556 case 0xdb: | |
557 *breg = 0xff; | |
558 if (pd==0) break; | |
559 closepd(pd); | |
560 *breg = 0; | |
561 break; | |
562 | |
563 /* | |
564 * I$GetStat Entry Point | |
565 * | |
566 * Entry: | |
567 * | |
568 * Exit: | |
569 * | |
570 * Error: CC Carry set | |
571 * B = errcode | |
572 */ | |
573 case 0xdc: { | |
574 struct stat st; | |
575 off_t pos; | |
576 switch (*breg) { | |
577 case 01: // SS.Ready | |
578 *breg = 0xff; | |
579 if (pd==0) break; | |
580 fstat(fileno(pd->fp),&st); | |
581 if ((pos = ftell(pd->fp))) { | |
582 xreg = st.st_size - pos; | |
583 *breg = 0; | |
584 } | |
585 break; | |
586 case 02: // SS.SIZ | |
587 *breg = 0xff; | |
588 if (pd==0) break; | |
589 fstat(fileno(pd->fp),&st); | |
590 xreg = st.st_size ; | |
591 *breg = 0; | |
592 break; | |
593 case 05: // SS.Pos | |
594 *breg = 0xff; | |
595 if (pd==0) break; | |
596 xreg = ftell(pd->fp); | |
597 *breg = 0; | |
598 break; | |
599 case 15: // SS.FD | |
600 /* SS.FD ($0F) - Returns a file descriptor | |
601 * Entry: R$A=Path # | |
602 * R$B=SS.FD ($0F) | |
603 * R$X=Pointer to a 256 byte buffer | |
604 * R$Y=# bytes of FD required | |
605 * this should be handled in vrbf | |
606 */ | |
607 *breg = 0xff; | |
608 if (pd==0) break; | |
609 *breg = filedescriptor(pmem(xreg), yreg,pd) ; | |
610 break; | |
611 case 0x20: // Pos.FDInf mandatry for dir command | |
612 /* SS.FDInf ($20) - Directly reads a file descriptor from anywhere | |
613 * on drive. | |
614 * Entry: R$A=Path # | |
615 * R$B=SS.FDInf ($20) | |
616 * R$X=Pointer to a 256 byte buffer | |
617 * R$Y= MSB - Length of read | |
618 * LSB - MSB of logical sector # | |
619 * R$U= LSW of logical sector # | |
620 */ | |
621 *breg = 0xff; | |
622 if (pd==0) break; | |
623 *breg = fdinfo(pmem(xreg),yreg,xreg*0x10000+ureg,pd); | |
624 break; | |
625 default: | |
626 *breg = 0xff; | |
627 } | |
628 break; | |
629 } | |
630 | |
631 /* | |
632 * I$SetStat Entry Point | |
633 * | |
634 * Entry: | |
635 * | |
636 * Exit: | |
637 * | |
638 * | |
639 * Error: CC Carry set | |
640 * B = errcode | |
641 */ | |
642 case 0xdd: | |
643 switch (*breg) { | |
644 case 0: // SS.Opt | |
645 case 02: // SS.SIZ | |
646 case 15: // SS.FD | |
647 case 0x11: // SS.Lock | |
648 case 0x10: // SS.Ticks | |
649 case 0x20: // SS.RsBit | |
650 case 0x1c: // SS.Attr | |
651 default: | |
652 *breg = 0xff; | |
653 } | |
654 break; | |
239 } | 655 } |
240 if (buf[i]=='\r') { | 656 } |
241 fputc('\n',p->fp); | 657 |
242 i++; | 658 |
243 } | |
244 return i; | |
245 } | |
246 | |
247 /* | |
248 * I$Write Entry Point | |
249 * | |
250 * Entry: | |
251 * | |
252 * Exit: | |
253 * | |
254 * Error: CC Carry set | |
255 * B = errcode | |
256 */ | |
257 | |
258 int vrbf_write(PathDesc *p, byte *buf, int len) { | |
259 if (p->dir) return -1; | |
260 return fwrite(buf,len,1,p->fp); | |
261 } | |
262 | |
263 /* I$Close Entry Point | |
264 * | |
265 * Entry: A = path number | |
266 * | |
267 * Exit: | |
268 * | |
269 * Error: CC Carry set | |
270 * B = errcode | |
271 * | |
272 */ | |
273 | |
274 int vrbf_close(PathDesc *p, byte *buf) { | |
275 return fclose(p->fp); | |
276 } | |
277 | |
278 /* | |
279 * I$GetStat Entry Point | |
280 * | |
281 * Entry: | |
282 * | |
283 * Exit: | |
284 * | |
285 * Error: CC Carry set | |
286 * B = errcode | |
287 */ | |
288 | |
289 int vrbf_getstat(int code,OPathDesc *p, O9Stat *s) { | |
290 struct stat st; | |
291 | |
292 switch (code) { | |
293 case 01: // SS.Ready | |
294 fstat(fileno(p->fp),&st); | |
295 if (pos = ftell(fp)) { | |
296 return st.size - pos; | |
297 } | |
298 break; | |
299 case 02: // SS.SIZ | |
300 fstat(fileno(p->fp),&st); | |
301 return st.size ; | |
302 break; | |
303 case 05: // SS.Pos | |
304 return ftell(s->fp); | |
305 break; | |
306 case 15: // SS.FD | |
307 break; | |
308 case 0x20: // Pos.FDInf | |
309 break; | |
310 default: return -1; | |
311 } | |
312 return -1; | |
313 } | |
314 | |
315 /* | |
316 * I$SetStat Entry Point | |
317 * | |
318 * Entry: | |
319 * | |
320 * Exit: | |
321 * | |
322 * Error: CC Carry set | |
323 * B = errcode | |
324 */ | |
325 | |
326 int vrbf_getstat(int code,OPathDesc *p, O9Stat *s) { | |
327 switch (code) { | |
328 case 0: // SS.Opt | |
329 break; | |
330 case 02: // SS.SIZ | |
331 break; | |
332 case 15: // SS.FD | |
333 break; | |
334 case 0x11: // SS.Lock | |
335 break; | |
336 case 0x10: // SS.Ticks | |
337 break; | |
338 case 0x20: // SS.RsBit | |
339 break; | |
340 case 0x1c: // SS.Attr | |
341 break; | |
342 default: return -1; | |
343 } | |
344 } | |
345 | |
346 |