1 /*
2 * Copyright (C) 2001, 2002, 2003, 2004, 2005 K. M. Indlekofer
3 *
4 * M.Indlekofer@fz-juelich.de
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21 /* XXX make buffers and large structs static (if non-recursive) to prevent from stack overflow!?! */
22
23
24
25 #include "cmios9_err.h"
26 #include "cmios9_io.h"
27 #include "cmios9.h"
28
29
30
31 /* general */
32 struct lsn0_s lsn0[PARTITION_NR];
33 struct part_s part[PARTITION_NR];
34 u_int partnr; /* number of used partitions */
35
36 /* current partition */
37 struct part_s *curpart;
38 u_int curowner; /* who we are */
39
40
41
42 /* OS9 */
43 /* current directory */
44 u_int curdirsec;
45
46 /* general */
47 int dirlevel; /* 0: root, level index to dirlist=dirlevel-1 */
48 char dirlist[DIRLEVELNR][FILENAMELEN];
49
50 /* general */
51 /* device aliases */
52 struct devalias_s devalias[]={
53 "k0","k000",
54 "k1","k001",
55 "k2","k002",
56 "k3","k003",
57 "k4","k004",
58 "k5","k005",
59 "k6","k006",
60 "k7","k007",
61 "c0","c000",
62 "c1","c001",
63 "c2","c002",
64 "c3","c003",
65 "c4","c004",
66 "c5","c005",
67 "c6","c006",
68 "c7","c007",
69 "d0","k000",
70 "d1","k001",
71 "d2","k002",
72 "d3","k003",
73 "f0","k000",
74 "f1","k001",
75 "f2","k002",
76 "f3","k003",
77 "cmif","c000",
78 "tape","sc10",
79 "xtape","sc50",
80 "w0","sc30",
81 "w1","sc40",
82 "w2","sc50",
83 "w3","sc60",
84 "w4","sc70",
85 "u0","c000",
86 "u1","c200",
87 "u2","c300",
88 "u3","c400",
89 "u4","c500",
90 "u5","c600",
91 "u6","c700",
92 "q0","q000",
93 "q1","q001",
94 "q2","q002",
95 "q3","q003",
96 "q4","q004",
97 "q5","q005",
98 "q6","q006",
99 "q7","q007",
100 NULL,NULL /* end */
101 };
102
103
104
105 /* general */
106 void
translatename(char * name,char * buf)107 translatename(char *name,char *buf)
108 {
109 int i;
110 u_char u;
111
112 if ((name==NULL)||(buf==NULL)){
113 return;
114 }
115
116 for (i=0;i<FILENAMELEN;i++){
117 u=name[i];
118 if (u==0){
119 buf[i]='\0';
120 break; /* end of string */
121 }
122 if (u&0x80){
123 buf[i]=u&0x7f;
124 buf[i+1]='\0';
125 break; /* end of string */
126 }
127 buf[i]=u;
128 }
129 if (i==FILENAMELEN){
130 buf[i]='\0';
131 }
132 }
133
134 /* general */
135 void
translatebackname(char * name,char * buf,u_int size)136 translatebackname(char *name,char *buf,u_int size)
137 {
138 u_int i;
139 u_char u;
140
141 if ((name==NULL)||(buf==NULL)){
142 return;
143 }
144
145 for (i=0;i<size;i++){
146 u=name[i];
147 if (u==0){ /* end of string */
148 if (i==0){
149 break;
150 }else{
151 buf[i-1]|=0x80;
152 break;
153 }
154 }
155 buf[i]=u;
156 }
157 if (i==size){
158 buf[i-1]|=0x80;
159 }
160 for (;i<size;i++){
161 buf[i]=0;
162 }
163 }
164
165 /* general */
166 void
printname(char * name)167 printname(char *name)
168 {
169 static char buf[FILENAMELEN+1]; /* XXX take OS9 lenght */
170
171 if (name==NULL){
172 return;
173 }
174
175 translatename(name,buf);
176 printf("%s",buf);
177 }
178
179 /* general */
180 void
printnstr(char * str,int maxn)181 printnstr(char *str,int maxn)
182 {
183 int i;
184 char c;
185
186 if (str==NULL){
187 return;
188 }
189
190 for (i=0;i<maxn;i++){
191 c=str[i];
192 if (!isprint(c)){
193 c=' ';
194 }
195 putchar(c);
196 }
197 }
198
199 /* QDOS */
200 void
qdos_makefname(char * in,char * out)201 qdos_makefname(char *in,char *out)
202 {
203 char *dotp;
204 int i;
205
206 if ((in==NULL)||(out==NULL)){
207 return;
208 }
209
210 /* Note: dir_sx[2] directly follows dir_nm[8] in struct qdos_dir_s!!! */
211 sprintf(out," "); /* XXX empty name */
212 for (i=0;i<8;i++){
213 if (in[i]=='\0'){
214 break; /* done */
215 }
216 if (in[i]==' '){
217 break; /* done */
218 }
219 if (in[i]=='.'){
220 break; /* done */
221 }
222 if (!isalnum(in[i])){
223 break; /* done */
224 }
225 out[i]=toupper(in[i]);
226 }
227 dotp=strchr(in,'.');
228 if (dotp!=NULL){
229 for (i=8;i<10;i++){
230 if (dotp[i-7]=='\0'){
231 break; /* done */
232 }
233 if (dotp[i-7]==' '){
234 break; /* done */
235 }
236 if (!isalnum(dotp[i-7])){
237 break; /* done */
238 }
239 out[i]=toupper(dotp[i-7]);
240 }
241 }
242 }
243
244
245
246 /* OS9/MDR-DOS */
247 int
lsn0label(char * name)248 lsn0label(char *name)
249 {
250
251 if (curpart->type!=PARTTYPE_OS9MDR){
252 return -1;
253 }
254
255 if (name==NULL){
256 return -1;
257 }
258 if (strlen(name)>FILENAMELEN){ /* XXX good for OS9 and MDR-DOS LSN0! */
259 err_print("lsn0label: name too long\n");
260 return -1;
261 }
262
263 if (curpart->mdr){
264 /* MDR-DOS */
265
266 /* null-terminated */
267 bcopy(name,MDR_LSN0_P(curpart->lsn0)->mdr_name,strlen(name)+1);
268 }else{
269 /* OS9 */
270
271 /* Bit-7-terminated */
272 translatebackname(name,(curpart->lsn0)->dd_name,strlen(name));
273 }
274
275 /* save new LSN0 */
276 if (WRITEBLOCK_CURPART(0,curpart->lsn0,1)<0){
277 err_print("lsn0label: cannot write LSN0\n");
278 /* XXX can't undo previous actions */
279 return -1;
280 }
281
282 return 0;
283 }
284
285 /* QDOS */
286 int
qdos_didlabel(char * id,char * vnrn,char * date,char * user)287 qdos_didlabel(char *id,char *vnrn,char *date,char *user)
288 {
289 struct qdos_did_s *qp;
290 int i,imax;
291
292 if (curpart->type!=PARTTYPE_QDOS){
293 return -1;
294 }
295
296 if ((id==NULL)&&(vnrn==NULL)&&(date==NULL)&&(user==NULL)){
297 return -1;
298 }
299
300 qp=QDOS_LSN0_P(curpart->lsn0);
301
302 if (id!=NULL){
303 /* ID */
304 imax=strlen(id);
305 if (imax>8)
306 imax=8;
307 for (i=0;i<imax;i++){
308 qp->did_id[i]=toupper(id[i]);
309 }
310 for (;i<8;i++){
311 qp->did_id[i]=' ';
312 }
313 }
314
315 if (vnrn!=NULL){
316 /* vnrn */
317 imax=strlen(vnrn);
318 if (imax>4)
319 imax=4;
320 /* Note: did_vn[2],did_rn[2] are contiguous! */
321 for (i=0;i<imax;i++){
322 qp->did_vn[i]=toupper(vnrn[i]);
323 }
324 for (;i<4;i++){
325 qp->did_vn[i]=' ';
326 }
327 }
328
329 if (date!=NULL){
330 /* date */
331 imax=strlen(date);
332 if (imax>6)
333 imax=6;
334 for (i=0;i<imax;i++){
335 qp->did_dt[i]=toupper(date[i]);
336 }
337 for (;i<6;i++){
338 qp->did_dt[i]=' ';
339 }
340 }
341
342 if (user!=NULL){
343 /* user */
344 imax=strlen(user);
345 if (imax>20)
346 imax=20;
347 for (i=0;i<imax;i++){
348 qp->did_nm[i]=toupper(user[i]);
349 }
350 for (;i<20;i++){
351 qp->did_nm[i]=' ';
352 }
353 }
354
355 /* save new DID */
356 if (WRITEBLOCK_CURPART(0,curpart->lsn0,1)<0){
357 err_print("qdos_didlabel: cannot write DID\n");
358 /* XXX can't undo previous actions */
359 return -1;
360 }
361
362 return 0;
363 }
364
365
366
367 /* OS9 */
368 void
setdate(struct filedes_s * fd,int cre)369 setdate(struct filedes_s *fd,int cre)
370 {
371 time_t tt;
372 struct tm *tmp;
373
374 if (fd==NULL)
375 return;
376
377 tt=time(NULL);
378 tmp=localtime(&tt);
379 if (tmp==NULL)
380 return;
381
382 if (cre){
383 fd->fd_creat[0]=tmp->tm_year;
384 fd->fd_creat[1]=tmp->tm_mon+1;
385 fd->fd_creat[2]=tmp->tm_mday;
386 }
387 fd->fd_dat[0]=tmp->tm_year;
388 fd->fd_dat[1]=tmp->tm_mon+1;
389 fd->fd_dat[2]=tmp->tm_mday;
390 fd->fd_dat[3]=tmp->tm_hour;
391 fd->fd_dat[4]=tmp->tm_min;
392 }
393
394 /* OS9 */
395 void
lsn0setdate(struct lsn0_s * pp)396 lsn0setdate(struct lsn0_s *pp)
397 {
398 time_t tt;
399 struct tm *tmp;
400
401 if (pp==NULL)
402 return;
403
404 tt=time(NULL);
405 tmp=localtime(&tt);
406 if (tmp==NULL)
407 return;
408
409 pp->dd_date[0]=tmp->tm_year;
410 pp->dd_date[1]=tmp->tm_mon+1;
411 pp->dd_date[2]=tmp->tm_mday;
412 pp->dd_date[3]=tmp->tm_hour;
413 pp->dd_date[4]=tmp->tm_min;
414 }
415
416 /* MDR-DOS */
417 void
mdr_setdate(struct mdr_dirent_s * fd,int cre)418 mdr_setdate(struct mdr_dirent_s *fd,int cre)
419 {
420 time_t tt;
421 struct tm *tmp;
422
423 if (fd==NULL)
424 return;
425
426 tt=time(NULL);
427 tmp=localtime(&tt);
428 if (tmp==NULL)
429 return;
430
431 if (cre){
432 fd->back[0]=tmp->tm_year;
433 fd->back[1]=tmp->tm_mon+1;
434 fd->back[2]=tmp->tm_mday;
435 fd->back[3]=tmp->tm_hour;
436 fd->back[4]=tmp->tm_min;
437 fd->back[5]=tmp->tm_sec;
438 }
439 fd->modif[0]=tmp->tm_year;
440 fd->modif[1]=tmp->tm_mon+1;
441 fd->modif[2]=tmp->tm_mday;
442 fd->modif[3]=tmp->tm_hour;
443 fd->modif[4]=tmp->tm_min;
444 fd->modif[5]=tmp->tm_sec;
445 }
446
447
448
449 /* OS9 */
450 int
setseg(struct seg_s * seglist,u_int start,u_int size)451 setseg(struct seg_s *seglist,u_int start,u_int size)
452 {
453
454 if (seglist==NULL){
455 return -1;
456 }
457 /* XXX check size overflow */
458
459 seglist->addr[0]=start>>16;
460 seglist->addr[1]=start>>8;
461 seglist->addr[2]=start;
462 seglist->size[0]=size>>8;
463 seglist->size[1]=size;
464
465 return 0;
466 }
467
468 /* OS9 */
469 int
getseg(struct seg_s * seglist,u_int * startp,u_int * sizep)470 getseg(struct seg_s *seglist,u_int *startp,u_int *sizep)
471 {
472
473 if (seglist==NULL){
474 return -1;
475 }
476
477 if (startp!=NULL){
478 *startp=(seglist->addr[0]<<16)
479 +(seglist->addr[1]<<8)
480 +seglist->addr[2];
481 }
482 if (sizep!=NULL){
483 *sizep=(seglist->size[0]<<8)
484 +seglist->size[1];
485 }
486
487 return 0;
488 }
489
490 /* OS9 */
491 u_int
countseg(struct seg_s * seglist,u_int segnr,u_int * contblp)492 countseg(struct seg_s *seglist,u_int segnr,u_int *contblp)
493 {
494 u_int i;
495 u_int count,ccount;
496 int ccountend;
497 u_int addr,size;
498 u_int oldaddr,oldsize;
499
500 if (seglist==NULL){
501 return 0;
502 }
503
504 count=0;
505 ccount=0;
506 ccountend=0;
507 for (i=0;i<segnr;i++){
508 getseg(seglist+i,&addr,&size);
509 if (size==0){
510 /* end */
511 break;
512 }
513 count+=size;
514 if (!ccountend){
515 if ((i==0)||(addr==oldaddr+oldsize)){
516 /* contiguous clusters */
517 ccount+=size;
518 oldaddr=addr;
519 oldsize=size;
520 }else{
521 ccountend=1; /* end of cont.clusters */
522 }
523 }
524 }
525 if (contblp!=NULL){
526 *contblp=ccount; /* number of contiguous blocks */
527 }
528 return count; /* number of blocks */
529 }
530
531 /* MDR-DOS */
532 u_int
mdr_countclu(struct mdr_dirent_s * direntp,u_int clunr,u_int * contclp)533 mdr_countclu(struct mdr_dirent_s *direntp,u_int clunr,u_int *contclp)
534 {
535 u_int i;
536 u_int clu;
537 u_int oldclu;
538 u_int ccount;
539 int ccountend;
540
541 if (direntp==NULL){
542 return 0;
543 }
544
545 ccount=0;
546 ccountend=0;
547 for (i=0;i<clunr;i++){
548 /* physical cluster */
549 clu=(direntp->clist[i][0]<<8)+(direntp->clist[i][1]);
550 if (clu==0){
551 break; /* end of clist */
552 }
553 if (!ccountend){
554 if ((i==0)||(clu==oldclu+1)){
555 /* contiguous clusters */
556 ccount++;
557 oldclu=clu;
558 }else{
559 ccountend=1; /* end of cont.clusters */
560 }
561 }
562 }
563
564 if (contclp!=NULL){
565 *contclp=ccount; /* number of contiguous clusters */
566 }
567 return i; /* number of clusters */
568 }
569
570 /* QDOS */
571 int
qdos_setseg(struct qdos_rib_s * ribp,u_int seg,u_int start,u_int size)572 qdos_setseg(struct qdos_rib_s *ribp,u_int seg,u_int start,u_int size)
573 {
574 u_int r;
575
576 if (ribp==NULL){
577 return -1;
578 }
579 if (seg>=QDOS_RIB_SDWNR){
580 return -1;
581 }
582 /* XXX check size overflow */
583
584 if (size==0){
585 /* mark end */
586 /* Note: SEGTOTSIZ is in QDOS_BLOCKSIZE! */
587 r=QDOS_RIB_SDWEND|start; /* special: mark end, save SEGTOTSIZ(in start)!!! */
588 }else{
589 r=(QDOS_RIB_SDWOFF&start)
590 |(QDOS_RIB_SDWSIZ&((size-1)<<10)); /* -1 !!! */
591 }
592 ribp->rib_sdw[seg][0]=(r>>8)&0xff;
593 ribp->rib_sdw[seg][1]=r&0xff;
594
595 return 0;
596 }
597
598 /* QDOS */
599 int
qdos_getseg(struct qdos_rib_s * ribp,u_int seg,u_int * startp,u_int * sizep)600 qdos_getseg(struct qdos_rib_s *ribp,u_int seg,u_int *startp,u_int *sizep)
601 {
602 u_int r;
603
604 if (ribp==NULL){
605 return -1;
606 }
607 if (seg>=QDOS_RIB_SDWNR){
608 if (sizep!=NULL){
609 *sizep=0; /* end */
610 }
611 return -1;
612 }
613
614 r=(ribp->rib_sdw[seg][0]<<8)+ribp->rib_sdw[seg][1];
615 if (r&QDOS_RIB_SDWEND){
616 /* end of list */
617 if (startp!=NULL){
618 /* Note: totsiz is in QDOS_BLOCKSIZE! */
619 *startp=(QDOS_RIB_SDWTOTSIZ&r)+1; /* special: get SEGTOTSIZ+1(in *startp)!!! */
620 }
621 if (sizep!=NULL){
622 *sizep=0; /* end */
623 }
624 }else{
625 if (startp!=NULL){
626 *startp=r&QDOS_RIB_SDWOFF;
627 }
628 if (sizep!=NULL){
629 *sizep=((r&QDOS_RIB_SDWSIZ)>>10)+1; /* +1 !!! */
630 }
631 }
632
633 return 0;
634 }
635
636 /* QDOS */
637 u_int
qdos_countseg(struct qdos_rib_s * ribp,u_int segnr,u_int * contclp)638 qdos_countseg(struct qdos_rib_s *ribp,u_int segnr,u_int *contclp)
639 {
640 u_int i;
641 u_int count,ccount;
642 int ccountend;
643 u_int addr,size;
644 u_int oldaddr,oldsize;
645
646 if (ribp==NULL){
647 return 0;
648 }
649
650 count=0;
651 ccount=0;
652 ccountend=0;
653 for (i=0;i<segnr;i++){
654 qdos_getseg(ribp,i,&addr,&size);
655 if (size==0){
656 /* end */
657 if (contclp!=NULL){
658 *contclp=ccount; /* number of contiguous clusters */
659 }
660 return count; /* number of clusters */
661 }
662 count+=size;
663 if (!ccountend){
664 if ((i==0)||(addr==oldaddr+oldsize)){
665 /* contiguous clusters */
666 ccount+=size;
667 oldaddr=addr;
668 oldsize=size;
669 }else{
670 ccountend=1; /* end of cont.clusters */
671 }
672 }
673 }
674 /* corrupt RIB, no end flag found */
675 if (contclp!=NULL){
676 *contclp=0; /* nothing */
677 }
678 return 0; /* nothing */
679 }
680
681 /* QDOS */
682 u_int
qdos_fsize(struct qdos_rib_s * ribp)683 qdos_fsize(struct qdos_rib_s *ribp)
684 {
685 int i;
686 u_int r;
687 u_int totsiz;
688
689 if (ribp==NULL){
690 return 0;
691 }
692
693 /* find end segment */
694 for (i=0;i<QDOS_RIB_SDWNR;i++){
695 r=(ribp->rib_sdw[i][0]<<8)+ribp->rib_sdw[i][1];
696 if (r&QDOS_RIB_SDWEND){
697 /* end of list */
698 /* Note: SEGTOTSIZ is in QDOS_BLOCKSIZE! */
699 totsiz=curpart->blksiz*((QDOS_RIB_SDWTOTSIZ&r)+1); /* +1 !!! */
700 /* correct for unused bytes in last block: */
701 totsiz-=curpart->blksiz;
702 if (ribp->rib_lb==0){
703 /* 0 means full block */
704 totsiz+=curpart->blksiz;
705 }else if (ribp->rib_lb>curpart->blksiz){
706 /* XXX corrupt RIB, take full block */
707 totsiz+=curpart->blksiz;
708 }else{
709 /* MDOS requires rib_lb%8==0 */
710 totsiz+=ribp->rib_lb; /* bytes in last block */
711 }
712 return totsiz; /* in bytes */
713 }
714 }
715 return 0; /* corrupt RIB, no end flag found */
716 }
717
718 /* QDOS */
719 int
qdos_setfsize(struct qdos_rib_s * ribp,u_int fsize)720 qdos_setfsize(struct qdos_rib_s *ribp,u_int fsize)
721 {
722 int i;
723 u_int r;
724 u_int totsiz;
725 u_int lb;
726
727 if (ribp==NULL){
728 return -1;
729 }
730 /* XXX check for totsiz overflow */
731
732 /* find end segment */
733 for (i=0;i<QDOS_RIB_SDWNR;i++){
734 r=(ribp->rib_sdw[i][0]<<8)+ribp->rib_sdw[i][1];
735 if (r&QDOS_RIB_SDWEND){
736 /* end of list */
737 /* Note: SEGTOTSIZ is in QDOS_BLOCKSIZE! */
738 /* XXX 32-Bit overflow protection not necessary for QDOS */
739 totsiz=(fsize+curpart->blksiz-1)/curpart->blksiz; /* round up! */
740 if (totsiz<1){
741 totsiz=1;
742 }
743 totsiz--; /* -1 !!! */
744 ribp->rib_sdw[i][0]=((totsiz|QDOS_RIB_SDWEND)>>8)&0xff; /* end mark */
745 ribp->rib_sdw[i][1]=totsiz&0xff;
746 lb=fsize-totsiz*curpart->blksiz; /* bytes in last block */
747 /* MDOS requires rib_lb%8==0 */
748 lb=8*((lb+7)/8); /* round up */
749 if (lb>=curpart->blksiz){ /* XXX > should never happen */
750 #if 1
751 ribp->rib_lb=curpart->blksiz;
752 #else
753 /* 0 means full block */
754 ribp->rib_lb=0;
755 #endif
756 }else{
757 ribp->rib_lb=lb;
758 }
759 return 0;
760 }
761 }
762 return -1; /* corrupt RIB, no end flag found */
763 }
764
765
766
767 /* OS9 */
768 int
bitmaptranslate(u_int sec,u_int * bmapbitp,u_int * bmapbytep,u_int * bmapblkp)769 bitmaptranslate(u_int sec,u_int *bmapbitp,u_int *bmapbytep,u_int *bmapblkp)
770 {
771
772 if (curpart->type!=PARTTYPE_OS9MDR){
773 return -1;
774 }
775 if (curpart->mdr){
776 return -1;
777 }
778
779 if ((bmapbitp==NULL)||(bmapbytep==NULL)||(bmapblkp==NULL)){
780 return -1;
781 }
782
783 /* calculate block,byte,bit for current block sec */
784 *bmapbitp=sec/(curpart->clustersize);
785 *bmapbytep=*bmapbitp/8;
786 if (*bmapbytep>=(curpart->bitmapsize)){
787 err_print("bitmaptranslate: out of bitmap\n");
788 return -1;
789 }
790 *bmapblkp=curpart->bitmapstart+*bmapbytep/curpart->blksiz;
791 *bmapbitp%=8;
792 /* used Bit: lower Bit corresponds higher block! */
793 *bmapbitp=7-*bmapbitp;
794 *bmapbytep%=curpart->blksiz;
795
796 return 0;
797 }
798
799 /* MDR-DOS */
800 int
mdr_bitmaptranslate(u_int sec,u_int * bmapbitp,u_int * bmapbytep,u_int * bmapblkp)801 mdr_bitmaptranslate(u_int sec,u_int *bmapbitp,u_int *bmapbytep,u_int *bmapblkp)
802 {
803
804 if (curpart->type!=PARTTYPE_OS9MDR){
805 return -1;
806 }
807 if (!curpart->mdr){
808 return -1;
809 }
810
811 if ((bmapbitp==NULL)||(bmapbytep==NULL)||(bmapblkp==NULL)){
812 return -1;
813 }
814
815 /* calculate block,byte,bit for current block sec */
816 *bmapbitp=sec/(curpart->mdr_clustersize);
817 *bmapbytep=*bmapbitp/8;
818 if (*bmapbytep>=MDR_BMAPSIZE*curpart->blksiz){
819 err_print("mdr_bitmaptranslate: out of bitmap\n");
820 return -1;
821 }
822 *bmapblkp=MDR_BMAPSTART+*bmapbytep/curpart->blksiz;
823 *bmapbitp%=8;
824 /* used Bit: lower Bit corresponds higher block! */
825 *bmapbitp=7-*bmapbitp;
826 *bmapbytep%=curpart->blksiz;
827
828 return 0;
829 }
830
831 /* QDOS */
832 int
qdos_bitmaptranslate(u_int sec,u_int * bmapbitp,u_int * bmapbytep)833 qdos_bitmaptranslate(u_int sec,u_int *bmapbitp,u_int *bmapbytep)
834 {
835
836 if ((bmapbitp==NULL)||(bmapbytep==NULL)){
837 return -1;
838 }
839
840 /* calculate block,byte,bit for current block sec */
841 *bmapbitp=sec/QDOS_CSIZE;
842 *bmapbytep=*bmapbitp/8;
843 if (*bmapbytep>=curpart->blksiz){ /* 1 block! */
844 err_print("qdos_bitmaptranslate: out of bitmap\n");
845 return -1;
846 }
847 *bmapbitp%=8;
848 /* used Bit: lower Bit corresponds higher block! */
849 *bmapbitp=7-*bmapbitp;
850 *bmapbytep%=curpart->blksiz;
851
852 return 0;
853 }
854
855 /* OS9 */
856 int
markbitmap2(u_int startblk,u_int size,int markused,int check)857 markbitmap2(u_int startblk,u_int size,int markused,int check)
858 {
859 u_int blk,bmapblk,bmapbyte,bmapbit;
860 static char bmapbuf[OS9MAX_BLOCKSIZE];
861 int bmapbufblk;
862 int bmapbufchanged;
863 u_char used,newused;
864
865 if (curpart->type!=PARTTYPE_OS9MDR){
866 return -1;
867 }
868 if (curpart->mdr){
869 return -1;
870 }
871 if (size==0){
872 return 0;
873 }
874 if (check){
875 if (startblk+size>curpart->totsize){
876 err_print("markbitmap2: startblk+size out of partition\n");
877 return -1;
878 }
879 if ((!markused)&&(startblk<curpart->bitmapstart
880 +(curpart->bitmapsize+curpart->blksiz-1)/curpart->blksiz)){
881 err_print("markbitmap2: must not mark unused in system area\n");
882 return -1;
883 }
884 }
885
886 bmapbufblk=-1; /* invalid bitmap block */
887 bmapbufchanged=0; /* nothing changed yet */
888
889 /* scan blocks */
890 /* not necessarily cluster-oriented!!! -> must scan all blocks here! */
891 for (blk=startblk;blk<startblk+size;blk++){
892 /* calculate block,byte,bit for current block sec */
893 if (bitmaptranslate(blk,&bmapbit,&bmapbyte,&bmapblk)<0){
894 err_print("markbitmap2: invalid block\n");
895 return -1;
896 }
897
898 /* need to load new bitmap block? */
899 if (((int)bmapblk)!=bmapbufblk){
900 /* write old bitmap block if necessary */
901 if ((bmapbufblk>=0)&&bmapbufchanged){
902 /* write block */
903 if (WRITEBLOCK_CURPART(bmapbufblk,bmapbuf,1)<0){
904 err_print("markbitmap2: cannot write bitmap block\n");
905 return -1;
906 }
907 }
908 /* read block */
909 if (READBLOCK_CURPART(bmapblk,bmapbuf,1)<0){
910 err_print("markbitmap2: cannot read bitmap block\n");
911 return -1;
912 }
913 bmapbufblk=bmapblk;
914 bmapbufchanged=0; /* nothing changed yet */
915 }
916
917 /* check if used */
918 used=1&(bmapbuf[bmapbyte]>>bmapbit);
919 newused=1<<bmapbit; /* Bit to modify */
920
921 /* mark used? */
922 if ((!used)&&markused){
923 bmapbuf[bmapbyte]|=newused; /* set Bit */
924 bmapbufchanged=1;
925 }
926 /* mark unused? */
927 if (used&&(!markused)){
928 bmapbuf[bmapbyte]&=~newused; /* clear Bit */
929 bmapbufchanged=1;
930 }
931 }
932
933 /* write bitmap block if necessary */
934 if ((bmapbufblk>=0)&&(bmapbufchanged)){
935 /* write block */
936 if (WRITEBLOCK_CURPART(bmapbufblk,bmapbuf,1)<0){
937 err_print("markbitmap2: cannot write bitmap block\n");
938 return -1;
939 }
940 }
941
942 return 0;
943 }
944
945 /* OS9 */
946 int
markbitmap(struct seg_s * seglist,u_int segnr,int markused)947 markbitmap(struct seg_s *seglist,u_int segnr,int markused)
948 {
949 u_int startblk,size;
950 u_int seg;
951
952 if (curpart->type!=PARTTYPE_OS9MDR){
953 return -1;
954 }
955 if (curpart->mdr){
956 return -1;
957 }
958
959 if (seglist==NULL){
960 return -1;
961 }
962
963 for (seg=0;seg<segnr;seg++){
964 /* get segment */
965 getseg(seglist+seg,&startblk,&size);
966 if (size==0){
967 /* end */
968 break; /* done */
969 }
970
971 /* mark bitmap */
972 if (markbitmap2(startblk,size,markused,1)<0){ /* 1: check */
973 return -1;
974 }
975 }
976
977 return 0;
978 }
979
980 /* MDR-DOS */
981 int
mdr_markbitmap2(u_int startblk,u_int size,int markused,int check)982 mdr_markbitmap2(u_int startblk,u_int size,int markused,int check)
983 {
984 u_int blk,bmapblk,bmapbyte,bmapbit;
985 char bmapbuf[MDR_BLOCKSIZE];
986 int bmapbufblk;
987 int bmapbufchanged;
988 u_char used,newused;
989
990 if (curpart->type!=PARTTYPE_OS9MDR){
991 return -1;
992 }
993 if (!curpart->mdr){
994 return -1;
995 }
996 if (size==0){
997 return 0;
998 }
999 if (check){
1000 if (startblk+size>curpart->totsize){
1001 err_print("mdr_markbitmap2: startblk+size out of partition\n");
1002 return -1;
1003 }
1004 if ((!markused)&&(startblk<MDR_DIRSTART+curpart->mdr_dfilenr*MDR_DIRENTRYSIZE)){
1005 err_print("mdr_markbitmap2: must not mark unused in system area\n");
1006 return -1;
1007 }
1008 }
1009
1010 bmapbufblk=-1; /* invalid bitmap block */
1011 bmapbufchanged=0; /* nothing changed yet */
1012
1013 /* scan blocks */
1014 /* XXX actually, first block of each cluster should be OK if cluster-oriented startblk,size! */
1015 for (blk=startblk;blk<startblk+size;blk++){
1016 /* calculate block,byte,bit for current block sec */
1017 if (mdr_bitmaptranslate(blk,&bmapbit,&bmapbyte,&bmapblk)<0){
1018 err_print("mdr_markbitmap2: invalid block\n");
1019 return -1;
1020 }
1021
1022 /* need to load new bitmap block? */
1023 if (((int)bmapblk)!=bmapbufblk){
1024 /* write old bitmap block if necessary */
1025 if ((bmapbufblk>=0)&&bmapbufchanged){
1026 /* write block */
1027 if (WRITEBLOCK_CURPART(bmapbufblk,bmapbuf,1)<0){
1028 err_print("mdr_markbitmap2: cannot write bitmap block\n");
1029 return -1;
1030 }
1031 }
1032 /* read block */
1033 if (READBLOCK_CURPART(bmapblk,bmapbuf,1)<0){
1034 err_print("mdr_markbitmap2: cannot read bitmap block\n");
1035 return -1;
1036 }
1037 bmapbufblk=bmapblk;
1038 bmapbufchanged=0; /* nothing changed yet */
1039 }
1040
1041 /* check if used */
1042 used=1&(bmapbuf[bmapbyte]>>bmapbit);
1043 newused=1<<bmapbit; /* Bit to modify */
1044
1045 /* mark used? */
1046 if ((!used)&&markused){
1047 bmapbuf[bmapbyte]|=newused; /* set Bit */
1048 bmapbufchanged=1;
1049 }
1050 /* mark unused? */
1051 if (used&&(!markused)){
1052 bmapbuf[bmapbyte]&=~newused; /* clear Bit */
1053 bmapbufchanged=1;
1054 }
1055 }
1056
1057 /* write bitmap block if necessary */
1058 if ((bmapbufblk>=0)&&(bmapbufchanged)){
1059 /* write block */
1060 if (WRITEBLOCK_CURPART(bmapbufblk,bmapbuf,1)<0){
1061 err_print("mdr_markbitmap2: cannot write bitmap block\n");
1062 return -1;
1063 }
1064 }
1065
1066 return 0;
1067 }
1068
1069 /* MDR-DOS */
1070 int
mdr_markbitmap(struct mdr_dirent_s * direntp,u_int fclunr,int markused)1071 mdr_markbitmap(struct mdr_dirent_s *direntp,u_int fclunr,int markused)
1072 {
1073 u_int startblk,size;
1074 u_int clu;
1075
1076 if (curpart->type!=PARTTYPE_OS9MDR){
1077 return -1;
1078 }
1079 if (!curpart->mdr){
1080 return -1;
1081 }
1082
1083 if (direntp==NULL){
1084 return -1;
1085 }
1086
1087 size=curpart->mdr_clustersize; /* fixed */
1088
1089 for (clu=0;clu<fclunr;clu++){
1090 /* get cluster start block */
1091 /* XXX might overflow!?! */
1092 startblk=curpart->mdr_clustersize
1093 *((direntp->clist[clu][0]<<8)+(direntp->clist[clu][1]));
1094 #ifdef DEBUG
1095 printf("mdr_markbitmap: clu: %04x startblk: %06x mark: %i\n",clu,startblk,markused);
1096 #endif
1097 /* stop at first cluster in dirent which is 0!!! */
1098 if (startblk==0){
1099 /* XXX check if direntp->size is consistent */
1100 /* with number of clusters counted so far */
1101 break; /* file end: OK */
1102 }
1103
1104 /* mark bitmap */
1105 if (mdr_markbitmap2(startblk,size,markused,1)<0){ /* 1: check */
1106 return -1;
1107 }
1108 }
1109
1110 return 0;
1111 }
1112
1113 /* QDOS */
1114 int
qdos_markbitmap2(u_int startblk,u_int size,int markused,int check,int lcat)1115 qdos_markbitmap2(u_int startblk,u_int size,int markused,int check,int lcat)
1116 {
1117 u_char catbuf[QDOS_BLOCKSIZE];
1118 u_char lcatbuf[QDOS_BLOCKSIZE];
1119 u_int blk;
1120 u_int bmapbit,bmapbyte;
1121 int catbufchanged,lcatbufchanged;
1122 u_char used,newused;
1123
1124 if (curpart->type!=PARTTYPE_QDOS){
1125 return -1;
1126 }
1127 if (size==0){
1128 return 0;
1129 }
1130 if (check){
1131 if (startblk+size>curpart->totsize){
1132 err_print("qdos_markbitmap2: startblk+size out of partition\n");
1133 return -1;
1134 }
1135 if ((!markused)&&(startblk<QDOS_FSYSSTART)){
1136 err_print("qdos_markbitmap2: must not mark unused in system area\n");
1137 return -1;
1138 }
1139 }
1140
1141 /* read existing CAT (1 block!) */
1142 if (READBLOCK_CURPART(QDOS_CATSTART,catbuf,1)<0){
1143 err_print("qdos_markbitmap2: cannot read CAT\n");
1144 return -1;
1145 }
1146 if (lcat){
1147 /* read existing LCAT (1 block!) */
1148 if (READBLOCK_CURPART(QDOS_LCATSTART,lcatbuf,1)<0){
1149 err_print("qdos_markbitmap2: cannot read LCAT\n");
1150 return -1;
1151 }
1152 }
1153
1154 catbufchanged=0; /* nothing modified yet */
1155 lcatbufchanged=0; /* nothing modified yet */
1156 for (blk=startblk;blk<startblk+size;blk++){
1157 /* calculate block,byte,bit for current block sec */
1158 if (qdos_bitmaptranslate(blk,&bmapbit,&bmapbyte)<0){
1159 err_print("qdos_markbitmap: invalid block\n");
1160 return -1;
1161 }
1162
1163 /* CAT */
1164 /* check if used */
1165 used=1&(catbuf[bmapbyte]>>bmapbit);
1166 newused=1<<bmapbit; /* Bit to modify */
1167 /* mark used? */
1168 if ((!used)&&markused){
1169 catbuf[bmapbyte]|=newused; /* set Bit */
1170 catbufchanged=1;
1171 }
1172 /* mark unused? */
1173 if (used&&(!markused)){
1174 catbuf[bmapbyte]&=~newused; /* clear Bit */
1175 catbufchanged=1;
1176 }
1177
1178 if (lcat){
1179 /* LCAT */
1180 /* check if used */
1181 used=1&(lcatbuf[bmapbyte]>>bmapbit);
1182 newused=1<<bmapbit; /* Bit to modify */
1183 /* mark used? */
1184 if ((!used)&&markused){
1185 lcatbuf[bmapbyte]|=newused; /* set Bit */
1186 lcatbufchanged=1;
1187 }
1188 /* mark unused? */
1189 if (used&&(!markused)){
1190 lcatbuf[bmapbyte]&=~newused; /* clear Bit */
1191 lcatbufchanged=1;
1192 }
1193 }
1194 }
1195
1196 if (catbufchanged){
1197 /* write new CAT (1 block!) */
1198 if (WRITEBLOCK_CURPART(QDOS_CATSTART,catbuf,1)<0){
1199 err_print("qdos_markbitmap2: cannot write CAT\n");
1200 return -1;
1201 }
1202 }
1203 if (lcat&&lcatbufchanged){
1204 /* write new LCAT (1 block!) */
1205 if (WRITEBLOCK_CURPART(QDOS_LCATSTART,lcatbuf,1)<0){
1206 err_print("qdos_markbitmap2: cannot write LCAT\n");
1207 return -1;
1208 }
1209 }
1210
1211 return 0;
1212 }
1213
1214 /* QDOS */
1215 int
qdos_markbitmap(struct qdos_rib_s * ribp,u_int segnr,int markused)1216 qdos_markbitmap(struct qdos_rib_s *ribp,u_int segnr,int markused)
1217 {
1218 u_int startblk,size;
1219 u_int seg;
1220
1221 if (curpart->type!=PARTTYPE_QDOS){
1222 return -1;
1223 }
1224
1225 if (ribp==NULL){
1226 return -1;
1227 }
1228
1229 for (seg=0;seg<segnr;seg++){
1230 /* get segment */
1231 qdos_getseg(ribp,seg,&startblk,&size);
1232 if (size==0){
1233 /* end */
1234 break; /* done */
1235 }
1236 startblk*=QDOS_CSIZE;
1237 size*=QDOS_CSIZE;
1238
1239 /* mark bitmap */
1240 if (qdos_markbitmap2(startblk,size,markused,1,0)<0){ /* 1: check, 0: not LCAT */
1241 return -1;
1242 }
1243 }
1244
1245 return 0;
1246 }
1247
1248
1249
1250 /* OS9 */
1251 int
initbitmap(void)1252 initbitmap(void)
1253 {
1254 static u_char bmapbuf[OS9MAX_BLOCKSIZE];
1255 int i;
1256 int start,size;
1257 int newrootdirsec;
1258
1259 if (curpart->type!=PARTTYPE_OS9MDR){
1260 return -1;
1261 }
1262 if (curpart->mdr){
1263 return -1;
1264 }
1265 if (curpart->clustersize==0){
1266 return -1;
1267 }
1268
1269 /* XXX curpart->filesyssize, curpart->clustersize, curpart->bitmapsize must be set! */
1270
1271 /* mark everything used */
1272 for (i=0;i<OS9MAX_BLOCKSIZE;i++){
1273 bmapbuf[i]=0xff; /* 8 Bits used */
1274 }
1275 /* number of blocks for bitmap */
1276 /* Note: curpart->bitmapsize is in bytes! */
1277 /* round up to blocks, in blocks now! */
1278 size=(curpart->bitmapsize+curpart->blksiz-1)/curpart->blksiz;
1279 /* write bitmap */
1280 #ifdef DEBUG
1281 printf("initbitmap: size: %06x\n",size);
1282 #endif
1283 for (i=0;i<size;i++){
1284 if (WRITEBLOCK_CURPART(curpart->bitmapstart+i,bmapbuf,1)<0){ /* 1: one block */
1285 err_print("initbitmap: cannot write bitmap\n");
1286 return -1;
1287 }
1288 }
1289
1290 /* used for all clusters up to bitmap (inclusive) */
1291 start=curpart->bitmapstart+size;
1292 /* now, start is new rootdirsec */
1293 /* Note: start might not be cluster-aligned now! doesn�t matter... */
1294 newrootdirsec=start;
1295 #ifdef DEBUG
1296 printf("initbitmap: newrootdirsec: %06x\n",newrootdirsec);
1297 #endif
1298
1299 /* max. number of blocks in one segment */
1300 /* setup fake seg_s for rest of filesystem */
1301 size=(int)curpart->filesyssize-start;
1302 if (size<2){ /* at least 2 for minimal root directory (filedes_s and 2x dirent_s) */
1303 err_print("initbitmap: filesyssize too small\n");
1304 return -1;
1305 }
1306 /* round down to cluster size */
1307 size=curpart->clustersize*(size/curpart->clustersize);
1308 #ifdef DEBUG
1309 printf("initbitmap: start: %06x size: %06x\n",start,size);
1310 #endif
1311
1312 /* mark unused in bitmap */
1313 if (markbitmap2(start,size,0,0)<0){ /* 0: unused!, 0: no check */
1314 return -1;
1315 }
1316
1317 /* XXX must set curpart->rootdirsec and create root directory by hand now! */
1318 /* XXX must update and write LSN0 */
1319
1320 return newrootdirsec;
1321 }
1322
1323 /* MDR-DOS */
1324 int
mdr_initbitmap(void)1325 mdr_initbitmap(void)
1326 {
1327 u_char bmapbuf[MDR_BMAPSIZE*MDR_BLOCKSIZE];
1328 int i;
1329 int cstart,csize;
1330
1331 if (curpart->type!=PARTTYPE_OS9MDR){
1332 return -1;
1333 }
1334 if (!curpart->mdr){
1335 return -1;
1336 }
1337
1338 /* XXX curpart->mdr_clustersize, curpart->mdr_clusternr, curpart->mdr_dfilenr must be set! */
1339
1340 /* mark everything used */
1341 for (i=0;i<MDR_BMAPSIZE*MDR_BLOCKSIZE;i++){
1342 bmapbuf[i]=0xff; /* 8 Bits used */
1343 }
1344 /* write bitmap */
1345 if (WRITEBLOCK_CURPART(MDR_BMAPSTART,bmapbuf,MDR_BMAPSIZE)<0){
1346 err_print("mdr_initbitmap: cannot write bitmap\n");
1347 return -1;
1348 }
1349
1350 /* used for all clusters up to directory (inclusive) */
1351 cstart=MDR_DIRSTART+curpart->mdr_dfilenr*MDR_DIRENTRYSIZE; /* in blocks!!! */
1352 /* round up to cluster size */
1353 cstart=(cstart+curpart->mdr_clustersize-1)/curpart->mdr_clustersize; /* in clusters */
1354
1355 /* rest of partition */
1356 csize=curpart->mdr_clusternr-cstart;
1357 if (csize<=0){ /* ==0: no filesystem space left! */
1358 err_print("mdr_initbitmap: totsize too small\n");
1359 return -1;
1360 }
1361 #ifdef DEBUG
1362 printf("mdr_initbitmap: cstart: %06x csize: %06x\n",cstart,csize);
1363 #endif
1364
1365 /* mark unused in bitmap */
1366 if (mdr_markbitmap2(cstart*curpart->mdr_clustersize,
1367 csize*curpart->mdr_clustersize,
1368 0,0)<0){ /* 0: unused!, 0: no check */
1369 return -1;
1370 }
1371
1372 /* XXX must create directory by hand now! */
1373 /* XXX must update and write LSN0 */
1374
1375 return 0;
1376 }
1377
1378 /* QDOS */
1379 int
qdos_initbitmap(int single,int newlcat)1380 qdos_initbitmap(int single,int newlcat)
1381 {
1382 u_char bmapbuf[QDOS_BLOCKSIZE];
1383 int i;
1384
1385 if (curpart->type!=PARTTYPE_QDOS){
1386 return -1;
1387 }
1388
1389 if (newlcat){
1390 /* mark everything free (1 block!) */
1391 bzero(bmapbuf,QDOS_BLOCKSIZE);
1392 }else{
1393 /* read existing LCAT (1 block!) */
1394 if (READBLOCK_CURPART(QDOS_LCATSTART,bmapbuf,1)<0){
1395 err_print("qdos_initbitmap: cannot read LCAT\n");
1396 return -1;
1397 }
1398 }
1399
1400 /* mark used up to directory: */
1401 /* starts at block 3, 0x15 blocks */
1402 /* => first 6 clusters: */
1403 bmapbuf[0x00]|=0xfc; /* XXX */
1404
1405 if (!single){
1406 /* double-sided floppy: */
1407 /* 4004 blocks == 512512 bytes == QDOS_PSIZE!!! */
1408 /* => last 23 clusters of 1024 in bitmap non-usable: */
1409 bmapbuf[0x7d]|=0x7f; /* XXX */
1410 bmapbuf[0x7e]|=0xff; /* XXX */
1411 bmapbuf[0x7f]|=0xff; /* XXX */
1412 }else{
1413 /* single-sided floppy: */
1414 /* 2002 blocks == 256256 bytes */
1415 /* => last 524 clusters of 1024 in bitmap non-usable: */
1416 /* 4 clusters: */
1417 bmapbuf[496/8]|=0x0f; /* XXX */
1418 /* 520 clusters: */
1419 for (i=504/8;i<1024/8;i++){
1420 bmapbuf[i]|=0xff; /* XXX */
1421 }
1422 }
1423
1424 /* write CAT (1 block!) */
1425 if (WRITEBLOCK_CURPART(QDOS_CATSTART,bmapbuf,1)<0){
1426 err_print("qdos_initbitmap: cannot write CAT\n");
1427 return -1;
1428 }
1429 if (newlcat){
1430 /* write new LCAT (1 block!) */
1431 if (WRITEBLOCK_CURPART(QDOS_LCATSTART,bmapbuf,1)<0){
1432 err_print("qdos_initbitmap: cannot write LCAT\n");
1433 return -1;
1434 }
1435 }
1436
1437 return 0;
1438 }
1439
1440
1441
1442 /* OS9 */
1443 u_int
fixblksiz(u_int blksiz)1444 fixblksiz(u_int blksiz)
1445 {
1446 u_int b;
1447
1448 if (blksiz>=OS9MAX_BLOCKSIZE){
1449 return OS9MAX_BLOCKSIZE;
1450 }
1451
1452 /* form 2^N and >= OS9L2_BLOCKSIZE */
1453 for (b=OS9MAX_BLOCKSIZE;b>=(OS9L2_BLOCKSIZE<<1);b>>=1){
1454 if (b&blksiz){
1455 break; /* found leading 1 */
1456 }
1457 }
1458
1459 return b;
1460 }
1461
1462 /* OS9 */
1463 int
newfs(u_int blksiz,u_int totsize,u_int clustersize,u_int filesyssize,int floppyflag)1464 newfs(u_int blksiz,u_int totsize,u_int clustersize,u_int filesyssize,int floppyflag)
1465 {
1466 int newrootsec,blknr;
1467 static struct filedes_s newrootfdes;
1468 static u_char newrootdent[OS9MAX_BLOCKSIZE]; /* enough space for 2x dirent (".." and ".") */
1469 struct dirent_s *newrootdentp;
1470 struct seg_s fakeseg;
1471 u_int bitmapsize;
1472
1473 if (curpart->type!=PARTTYPE_OS9MDR){
1474 return -1;
1475 }
1476 if (curpart->mdr){
1477 return -1;
1478 }
1479 if (totsize==0){
1480 return -1;
1481 }
1482 if (clustersize==0){
1483 return -1;
1484 }
1485 if (filesyssize==0){
1486 return -1;
1487 }
1488 filesyssize=clustersize*(filesyssize/clustersize); /* round down to clustersize!!! */
1489 if (filesyssize>totsize){
1490 err_print("newfs: totsize<filesyssize\n");
1491 return -1;
1492 }
1493 /* XXX check if new clustersize valid */
1494 /* XXX check if new totsize compatible with curpart->psize */
1495
1496 /* set curpart->... elements */
1497 if (blksiz==0){
1498 curpart->blksiz=OS9L2_BLOCKSIZE; /* XXX default */
1499 }else{
1500 /* fix if necessary */
1501 blksiz=fixblksiz(blksiz);
1502 curpart->blksiz=blksiz;
1503 }
1504 curpart->totsize=totsize; /* in blocks */
1505 curpart->clustersize=clustersize; /* in blocks */
1506 curpart->filesyssize=filesyssize; /* in blocks */
1507 /* Note: filesyssize already cluster-aligned, see above!!! */
1508 curpart->bitmapstart=OS9L2_BMAPSTART; /* XXX default */
1509 bitmapsize=(filesyssize+clustersize-1)/clustersize; /* one Bit per cluster, round up */
1510 bitmapsize=(bitmapsize+7)/8; /* in bytes, round up */
1511 if (bitmapsize==0){
1512 err_print("newfs: bitmapsize==0 (perhaps clustersize too large)\n");
1513 return -1;
1514 }
1515 if (bitmapsize>=0xffff){ /* XXX 16Bit max. value */
1516 err_print("newfs: bitmapsize too large (perhaps clustersize too small)\n");
1517 return -1;
1518 }
1519 curpart->bitmapsize=bitmapsize; /* in bytes */
1520
1521 /* initialize bitmap */
1522 /* curpart->filesyssize, curpart->clustersize, curpart->bitmapsize must be set! */
1523 if ((newrootsec=initbitmap())<0){
1524 err_print("newfs: cannot initialize bitmap\n");
1525 return -1;
1526 }
1527 /* Note: newrootsec might not be cluster-aligned now! doesn�t matter... */
1528
1529 /* set LSN0 elements */
1530 bzero(curpart->lsn0,sizeof(struct lsn0_s)); /* reset all! */
1531 curpart->lsn0->dd_tot[2]=totsize;
1532 curpart->lsn0->dd_tot[1]=totsize>>8;
1533 curpart->lsn0->dd_tot[0]=totsize>>16;
1534 curpart->lsn0->dd_map[1]=bitmapsize; /* dd_map!=0 for OS9 partition! */
1535 curpart->lsn0->dd_map[0]=bitmapsize>>8;
1536 curpart->lsn0->dd_bit[1]=clustersize;
1537 curpart->lsn0->dd_bit[0]=clustersize>>8;
1538 curpart->lsn0->dd_dir[2]=newrootsec;
1539 curpart->lsn0->dd_dir[1]=newrootsec>>8;
1540 curpart->lsn0->dd_dir[0]=newrootsec>>16;
1541 curpart->lsn0->dd_own[1]=0; /* XXX */
1542 curpart->lsn0->dd_own[0]=0; /* XXX */
1543 curpart->lsn0->dd_att=0xff; /* XXX */
1544 lsn0setdate(curpart->lsn0);
1545 if (floppyflag){
1546 curpart->lsn0->dd_fmt=0x03; /* double sided, double density (not track0,side0) */
1547 /* Note: track0,side0 set via firmware to 01: double sided, single density */
1548 curpart->lsn0->dd_spt[0]=0x00;
1549 curpart->lsn0->dd_spt[1]=0x1c; /* 28 sectors/track (not track0,side0) */
1550 /* Note: track0,side0 set via firmware to 0x10: 16 sectors/track */
1551 }
1552 /*curpart->lsn0->dd_maplsn=0;*/ /* XXX default */
1553 curpart->lsn0->dd_lsnsize[1]=blksiz;
1554 curpart->lsn0->dd_lsnsize[0]=blksiz>>8;
1555 /* XXX other elements */
1556 /* save new LSN0 */
1557 if (WRITEBLOCK_CURPART(0,curpart->lsn0,1)<0){
1558 err_print("newfs: cannot write LSN0\n");
1559 /* XXX can't undo previous actions */
1560 return -1;
1561 }
1562
1563 /* create and initialize minimal root directory */
1564 /* enough space guaranteeded by initbitmap: 2 blocks */
1565 /* mark used */
1566 blknr=2; /* one for file descriptor + one for directory data, see below */
1567 /* In order not to waste blocks for root directory (if newrootsec not cluster-aligned): */
1568 blknr+=newrootsec; /* last block+1 */
1569 blknr=clustersize*((blknr+clustersize-1)/clustersize); /* round up to clustersize */
1570 blknr-=newrootsec; /* blocks we can mark used */
1571 #ifdef DEBUG
1572 printf("newfs: newrootsec: %06x, blknr: %06x\n",newrootsec,blknr);
1573 #endif
1574 setseg(&fakeseg,newrootsec,blknr);
1575 if (markbitmap(&fakeseg,1,1)<0){ /* 1: one seg_s, 1: mark used */
1576 err_print("newfs: cannot mark root directory\n");
1577 /* XXX can't undo previous actions */
1578 return -1;
1579 }
1580
1581 /* setup root file descriptor */
1582 bzero(&newrootfdes,sizeof(struct filedes_s)); /* clear */
1583 /* set attributes */
1584 newrootfdes.fd_att=ATT_R|ATT_W|ATT_E|ATT_D; /* owner only, directory */
1585 /* set creation and modified date */
1586 setdate(&newrootfdes,1); /* 1: create */
1587 /* set link count */
1588 newrootfdes.fd_link=0; /* XXX must be 0? */
1589 /* set size */
1590 newrootfdes.fd_fsize[0]=0;
1591 newrootfdes.fd_fsize[1]=0;
1592 newrootfdes.fd_fsize[2]=0;
1593 newrootfdes.fd_fsize[3]=2*sizeof(struct dirent_s); /* ".." and "." */
1594 setseg(&newrootfdes.fd_seg[0],newrootsec+1,blknr-1); /* data directly behind descriptor! */
1595 /* save */
1596 if (WRITEBLOCK_CURPART(newrootsec,&newrootfdes,1)<0){
1597 err_print("newfs: cannot write root directory descriptor\n");
1598 /* XXX can't undo previous actions */
1599 return -1;
1600 }
1601
1602 /* setup root 2x dirent_s for ".." and "." */
1603 newrootdentp=(struct dirent_s *)newrootdent;
1604 bzero(newrootdent,OS9MAX_BLOCKSIZE); /* clear */
1605 /* ".." pointing back to us */
1606 newrootdentp[0].dir_addr[2]=newrootsec;
1607 newrootdentp[0].dir_addr[1]=newrootsec>>8;
1608 newrootdentp[0].dir_addr[0]=newrootsec>>16;
1609 translatebackname("..",newrootdentp[0].dir_name,FILENAMELEN);
1610 /* "." pointing back to us */
1611 newrootdentp[1].dir_addr[2]=newrootsec;
1612 newrootdentp[1].dir_addr[1]=newrootsec>>8;
1613 newrootdentp[1].dir_addr[0]=newrootsec>>16;
1614 translatebackname(".",newrootdentp[1].dir_name,FILENAMELEN);
1615 /* save */
1616 if (WRITEBLOCK_CURPART(newrootsec+1,newrootdent,1)<0){ /* +1: directly behind descriptor! */
1617 err_print("newfs: cannot write root directory\n");
1618 /* XXX can't undo previous actions */
1619 return -1;
1620 }
1621
1622 return 0;
1623 /* Note: must restart program after modification of LSN0!!! */
1624 }
1625
1626 /* MDR-DOS */
1627 int
mdr_newfs(u_int totsize,u_int clustersize,u_int dfilenr)1628 mdr_newfs(u_int totsize,u_int clustersize,u_int dfilenr)
1629 {
1630 u_int i;
1631 struct mdr_dirent_s zerodirent; /* should be MDR_DIRENTRYSIZE blocks */
1632 u_int clusternr;
1633
1634 if (curpart->type!=PARTTYPE_OS9MDR){
1635 return -1;
1636 }
1637 if (!curpart->mdr){
1638 return -1;
1639 }
1640 if (totsize==0){
1641 return -1;
1642 }
1643 /* adjust clustersize to granularity of MDR_CLUSTERSIZE blocks */
1644 clustersize=MDR_CLUSTERSIZE*((clustersize+MDR_CLUSTERSIZE-1)/MDR_CLUSTERSIZE);
1645 if (clustersize==0){
1646 return -1;
1647 }
1648 if (dfilenr==0){
1649 return -1;
1650 }
1651 /* XXX check if new clustersize valid */
1652 /* XXX check if dfilenr valid */
1653 /* XXX check if new totsize compatible with curpart->psize */
1654
1655 /* set curpart->... elements */
1656 curpart->blksiz=MDR_BLOCKSIZE;
1657 curpart->totsize=totsize; /* in blocks */
1658 curpart->mdr_clustersize=clustersize; /* in blocks */
1659 curpart->mdr_dfilenr=dfilenr;
1660 /* use whole partition for MDR-DOS filesystem: set clusternr to max. */
1661 clusternr=totsize/clustersize; /* rounded down to fit in totsize!!! */
1662 if (clusternr==0){
1663 err_print("mdr_newfs: clusternr==0 (perhaps clustersize too large)\n");
1664 return -1;
1665 }
1666 curpart->mdr_clusternr=clusternr;
1667
1668 /* initialize bitmap */
1669 /* curpart->mdr_clustersize, curpart->mdr_clusternr, curpart->mdr_dfilenr must be set! */
1670 if (mdr_initbitmap()<0){
1671 err_print("mdr_newfs: cannot initialize bitmap\n");
1672 return -1;
1673 }
1674
1675 /* initialize directory */
1676 bzero(&zerodirent,MDR_DIRENTRYSIZE*MDR_BLOCKSIZE); /* erase entry */
1677 for (i=0;i<curpart->mdr_dfilenr;i++){
1678 if (WRITEBLOCK_CURPART(MDR_DIRSTART+i*MDR_DIRENTRYSIZE,&zerodirent,MDR_DIRENTRYSIZE)<0){
1679 err_print("mdr_newfs: cannot write directory entry\n");
1680 /* XXX can't undo previous actions */
1681 return -1;
1682 }
1683 }
1684
1685 /* set LSN0 elements */
1686 bzero(curpart->lsn0,sizeof(struct lsn0_s)); /* reset all! */
1687 MDR_LSN0_P(curpart->lsn0)->mdr_tot[2]=totsize;
1688 MDR_LSN0_P(curpart->lsn0)->mdr_tot[1]=totsize>>8;
1689 MDR_LSN0_P(curpart->lsn0)->mdr_tot[0]=totsize>>16;
1690 MDR_LSN0_P(curpart->lsn0)->mdr_clsz=clustersize/MDR_CLUSTERSIZE; /* !!! */
1691 MDR_LSN0_P(curpart->lsn0)->mdr_clnr[1]=clusternr;
1692 MDR_LSN0_P(curpart->lsn0)->mdr_clnr[0]=clusternr>>8;
1693 MDR_LSN0_P(curpart->lsn0)->mdr_dfnr[1]=dfilenr;
1694 MDR_LSN0_P(curpart->lsn0)->mdr_dfnr[0]=dfilenr>>8;
1695 MDR_LSN0_P(curpart->lsn0)->mdr_fnr[1]=0; /* reset! */
1696 MDR_LSN0_P(curpart->lsn0)->mdr_fnr[0]=0;
1697 MDR_LSN0_P(curpart->lsn0)->zero1[1]=0; /* mdr_zero1==0 for MDR-DOS partition! */
1698 MDR_LSN0_P(curpart->lsn0)->zero1[0]=0;
1699 /* XXX other elements */
1700 /* save new LSN0 */
1701 if (WRITEBLOCK_CURPART(0,curpart->lsn0,1)<0){
1702 err_print("mdr_newfs: cannot write LSN0\n");
1703 /* XXX can't undo previous actions */
1704 return -1;
1705 }
1706
1707 return 0;
1708 /* Note: must restart program after modification of LSN0!!! */
1709 }
1710
1711 /* QDOS */
1712 int
qdos_newfs(int single,int newlcat)1713 qdos_newfs(int single,int newlcat)
1714 {
1715 u_char dirbuf[QDOS_DIRSIZE*QDOS_BLOCKSIZE];
1716 int i;
1717
1718 if (curpart->type!=PARTTYPE_QDOS){
1719 return -1;
1720 }
1721
1722 /* set curpart->... elements */
1723 curpart->blksiz=QDOS_BLOCKSIZE;
1724 curpart->totsize=QDOS_PSIZE; /* in QDOS blocks */
1725
1726 /* initialize bitmap */
1727 if (qdos_initbitmap(single,newlcat)<0){
1728 err_print("qdos_newfs: cannot initialize bitmap\n");
1729 return -1;
1730 }
1731
1732 /* initialize directory */
1733 bzero(dirbuf,QDOS_DIRSIZE*QDOS_BLOCKSIZE); /* erase entry */
1734 for (i=0;i<QDOS_DIRENTRYNR;i++){
1735 ((struct qdos_dir_s *)dirbuf)[i].dir_nm[0]=QDOS_DIR_VACANT;
1736 }
1737 if (WRITEBLOCK_CURPART(QDOS_DIRSTART,dirbuf,QDOS_DIRSIZE)<0){
1738 err_print("qdos_newfs: cannot write directory\n");
1739 /* XXX can't undo previous actions */
1740 return -1;
1741 }
1742
1743 /* set LSN0 elements */
1744 bzero(curpart->lsn0,QDOS_BLOCKSIZE); /* reset all! */
1745 /* did_id,did_vn,did_rn,did_dt,did_nm: */
1746 bcopy("QDOS 0000010101QDOS ",
1747 (char *)curpart->lsn0,38); /* XXX */
1748 /* XXX other elements */
1749 /* save new LSN0 */
1750 if (WRITEBLOCK_CURPART(0,curpart->lsn0,1)<0){
1751 err_print("qdos_newfs: cannot write LSN0\n");
1752 /* XXX can't undo previous actions */
1753 return -1;
1754 }
1755
1756 return 0;
1757 /* Note: must restart program after modification of LSN0!!! */
1758 }
1759
1760
1761
1762 /* OS9 */
1763 int
findfree(u_int seekstart,u_int minsize,u_int * segstartp,u_int * segsizep,u_int * lsegstartp,u_int * lsegsizep,u_int * segnrp,struct seg_s * skiplist,u_int skipnr,int fullscan)1764 findfree(u_int seekstart,u_int minsize,
1765 u_int *segstartp,u_int *segsizep,
1766 u_int *lsegstartp,u_int *lsegsizep,u_int *segnrp,
1767 struct seg_s *skiplist,u_int skipnr,int fullscan)
1768 {
1769 u_int sec,bmapblk,bmapbyte,bmapbit;
1770 static char bmapbuf[OS9MAX_BLOCKSIZE];
1771 int bmapbufblk;
1772 int used;
1773 u_int totfree;
1774 u_int segfree;
1775 int segstart;
1776 int lsegstart;
1777 u_int lsegfree;
1778 int cursegstart;
1779 u_int cursegfree;
1780 u_int segnr;
1781
1782 if (curpart->type!=PARTTYPE_OS9MDR){
1783 return -1;
1784 }
1785 if (curpart->mdr){
1786 return -1;
1787 }
1788
1789 if (seekstart>=curpart->totsize){
1790 return -1;
1791 }
1792 /* we must be careful to construct segments aligned to clusters */
1793 /* because algorithm below assumes this (not markbitmap)! */
1794 /* round down */
1795 seekstart=(seekstart/(curpart->clustersize))*(curpart->clustersize);
1796 /* round up to cluster size */
1797 minsize=((minsize+curpart->clustersize-1)
1798 /(curpart->clustersize))*(curpart->clustersize);
1799
1800 bmapbufblk=-1; /* invalid bitmap block */
1801
1802 /* scan bitmap */
1803 totfree=0; /* nothing found yet */
1804 segfree=0; /* nothing found yet */
1805 segstart=-1; /* invalid block */
1806 lsegfree=0; /* nothing found yet */
1807 lsegstart=-1; /* invalid block */
1808 cursegfree=0; /* nothing found yet */
1809 cursegstart=-1; /* invalid block */
1810 segnr=0; /* nothing found yet */
1811 for (sec=seekstart;sec<=curpart->filesyssize;sec++){
1812 if (sec<(curpart->filesyssize)){
1813 /* calculate block,byte,bit for current block sec */
1814 if (bitmaptranslate(sec,&bmapbit,&bmapbyte,&bmapblk)<0){
1815 err_print("findfree: invalid block\n");
1816 return -1;
1817 }
1818
1819 /* need to load bitmap block? */
1820 if (((int)bmapblk)!=bmapbufblk){
1821 /* read block */
1822 if (READBLOCK_CURPART(bmapblk,bmapbuf,1)<0){
1823 err_print("findfree: cannot read bitmap block\n");
1824 return -1;
1825 }
1826 bmapbufblk=bmapblk;
1827 }
1828
1829 /* check if used */
1830 used=1&(bmapbuf[bmapbyte]>>bmapbit);
1831
1832 /* check skiplist */
1833 if ((skiplist!=NULL)&&(!used)){
1834 u_int i;
1835 u_int start,size;
1836
1837 /* see if block is in skiplist */
1838 for (i=0;i<skipnr;i++){
1839 getseg(skiplist+i,&start,&size);
1840 if (size==0){
1841 /* end */
1842 break; /* done */
1843 }
1844 /* within segment? */
1845 if ((start<=sec)&&(sec<start+size)){
1846 used=1;
1847 break; /* used, done */
1848 }
1849 }
1850 }
1851 }
1852
1853 /* check if used or scan complete */
1854 if (used||(sec==curpart->filesyssize)){
1855 /* used block or end => end of segment */
1856 /* is there a segment? */
1857 if (cursegstart>=0){
1858 /* largest segment stuff */
1859 /* is this segment larger? */
1860 if (cursegfree>lsegfree){
1861 lsegfree=cursegfree;
1862 lsegstart=cursegstart;
1863 }
1864
1865 /* first large enough segment stuff */
1866 /* still looking for large enough segment? */
1867 if (segstart<0){
1868 /* check if current segment is large enough */
1869 if (cursegfree>=minsize){
1870 segfree=cursegfree;
1871 segstart=cursegstart;
1872 }
1873 }
1874
1875 /* reset current segment */
1876 cursegfree=0; /* nothing found yet */
1877 cursegstart=-1; /* invalid block */
1878 }
1879 }else{
1880 /* free block */
1881 totfree++;
1882
1883 /* current segment stuff */
1884 cursegfree++;
1885 /* first block of current segment? */
1886 if (cursegstart<0){
1887 cursegstart=sec;
1888 segnr++; /* one more segment */
1889 }
1890
1891 /* no full scan needed? */
1892 if (!fullscan){
1893 /* check if current (partial) segment is large enough */
1894 if (cursegfree>=minsize){
1895 segfree=cursegfree;
1896 /* we stop searching, so: round up to cluster size */
1897 segfree=((segfree+curpart->clustersize-1)
1898 /(curpart->clustersize))*(curpart->clustersize);
1899 segstart=cursegstart;
1900 /* largest segment stuff */
1901 /* is this segment larger? */
1902 if (cursegfree>lsegfree){
1903 lsegfree=cursegfree;
1904 lsegstart=cursegstart;
1905 }
1906 /* note that totfree,lsegfree are not complete, only what we found so far */
1907 break; /* done */
1908 }
1909 }
1910 }
1911 }
1912 /* since bitmapstranslate gives cluster alignment and the start blocks */
1913 /* in our search are also cluster aligned => xxxfree and xxxstart also! */
1914 /* -> doesn�t waste blocks */
1915
1916 if (segstartp!=NULL){
1917 *segstartp=segstart;
1918 }
1919 if (segsizep!=NULL){
1920 *segsizep=segfree;
1921 }
1922 if (lsegstartp!=NULL){
1923 *lsegstartp=lsegstart;
1924 }
1925 if (lsegsizep!=NULL){
1926 *lsegsizep=lsegfree;
1927 }
1928 if (segnrp!=NULL){
1929 *segnrp=segnr;
1930 }
1931
1932 return totfree;
1933 }
1934
1935 /* MDR-DOS */
1936 int
mdr_findfree(u_int seekstart,u_int minsize,u_int * segstartp,u_int * segsizep,u_int * lsegstartp,u_int * lsegsizep,u_int * segnrp,struct mdr_dirent_s * skipdirentp,u_int skipnr,int fullscan)1937 mdr_findfree(u_int seekstart,u_int minsize,
1938 u_int *segstartp,u_int *segsizep,
1939 u_int *lsegstartp,u_int *lsegsizep,u_int *segnrp,
1940 struct mdr_dirent_s *skipdirentp,u_int skipnr,int fullscan)
1941 {
1942 u_int sec,bmapblk,bmapbyte,bmapbit;
1943 char bmapbuf[MDR_BLOCKSIZE];
1944 int bmapbufblk;
1945 int used;
1946 u_int totfree;
1947 u_int segfree;
1948 int segstart;
1949 int lsegstart;
1950 u_int lsegfree;
1951 int cursegstart;
1952 u_int cursegfree;
1953 u_int segnr;
1954
1955 if (curpart->type!=PARTTYPE_OS9MDR){
1956 return -1;
1957 }
1958 if (!curpart->mdr){
1959 return -1;
1960 }
1961
1962 if (seekstart>=curpart->totsize){
1963 return -1;
1964 }
1965 /* we must be careful to construct segments aligned to clusters */
1966 /* because algorithm below assumes this (not mdr_markbitmap)! */
1967 /* round down */
1968 seekstart=(seekstart/(curpart->mdr_clustersize))*(curpart->mdr_clustersize);
1969 /* round up to cluster size */
1970 minsize=((minsize+curpart->mdr_clustersize-1)
1971 /(curpart->mdr_clustersize))*(curpart->mdr_clustersize);
1972
1973 bmapbufblk=-1; /* invalid bitmap block */
1974
1975 /* scan bitmap */
1976 totfree=0; /* nothing found yet */
1977 segfree=0; /* nothing found yet */
1978 segstart=-1; /* invalid block */
1979 lsegfree=0; /* nothing found yet */
1980 lsegstart=-1; /* invalid block */
1981 cursegfree=0; /* nothing found yet */
1982 cursegstart=-1; /* invalid block */
1983 segnr=0; /* nothing found yet */
1984 for (sec=seekstart;sec<=curpart->mdr_filesyssize;sec++){
1985 if (sec<(curpart->mdr_filesyssize)){
1986 /* calculate block,byte,bit for current block sec */
1987 if (mdr_bitmaptranslate(sec,&bmapbit,&bmapbyte,&bmapblk)<0){
1988 err_print("mdr_findfree: invalid block\n");
1989 return -1;
1990 }
1991
1992 /* need to load bitmap block? */
1993 if (((int)bmapblk)!=bmapbufblk){
1994 /* read block */
1995 if (READBLOCK_CURPART(bmapblk,bmapbuf,1)<0){
1996 err_print("mdr_findfree: cannot read bitmap block\n");
1997 return -1;
1998 }
1999 bmapbufblk=bmapblk;
2000 }
2001
2002 /* check if used */
2003 used=1&(bmapbuf[bmapbyte]>>bmapbit);
2004
2005 /* check skipdirentp */
2006 if ((skipdirentp!=NULL)&&(!used)){
2007 u_int i;
2008 u_int skipclu;
2009
2010 /* see if block is in skipdirentp */
2011 for (i=0;i<skipnr;i++){
2012 skipclu=(skipdirentp->clist[i][0]<<8)+skipdirentp->clist[i][1];
2013 if (skipclu==0){
2014 /* end */
2015 break; /* done */
2016 }
2017 if (skipclu==sec/curpart->mdr_clustersize){
2018 used=1;
2019 break; /* used, done */
2020 }
2021 }
2022 }
2023 }
2024
2025 /* check if used or scan complete */
2026 if (used||(sec==curpart->mdr_filesyssize)){
2027 /* used block or end => end of segment */
2028 /* is there a segment? */
2029 if (cursegstart>=0){
2030 /* largest segment stuff */
2031 /* is this segment larger? */
2032 if (cursegfree>lsegfree){
2033 lsegfree=cursegfree;
2034 lsegstart=cursegstart;
2035 }
2036
2037 /* first large enough segment stuff */
2038 /* still looking for large enough segment? */
2039 if (segstart<0){
2040 /* check if current segment is large enough */
2041 if (cursegfree>=minsize){
2042 segfree=cursegfree;
2043 segstart=cursegstart;
2044 }
2045 }
2046
2047 /* reset current segment */
2048 cursegfree=0; /* nothing found yet */
2049 cursegstart=-1; /* invalid block */
2050 }
2051 }else{
2052 /* free block */
2053 totfree++;
2054
2055 /* current segment stuff */
2056 cursegfree++;
2057 /* first block of current segment? */
2058 if (cursegstart<0){
2059 cursegstart=sec;
2060 segnr++; /* one more segment */
2061 }
2062
2063 /* no full scan needed? */
2064 if (!fullscan){
2065 /* check if current (partial) segment is large enough */
2066 if (cursegfree>=minsize){
2067 segfree=cursegfree;
2068 /* we stop searching, so: round up to cluster size */
2069 segfree=((segfree+curpart->mdr_clustersize-1)
2070 /(curpart->mdr_clustersize))*(curpart->mdr_clustersize);
2071 segstart=cursegstart;
2072 /* largest segment stuff */
2073 /* is this segment larger? */
2074 if (cursegfree>lsegfree){
2075 lsegfree=cursegfree;
2076 lsegstart=cursegstart;
2077 }
2078 /* note that totfree,lsegfree are not complete, only what we found so far */
2079 break; /* done */
2080 }
2081 }
2082 }
2083 }
2084 /* since bitmapstranslate gives cluster alignment and the start blocks */
2085 /* in our search are also cluster aligned => xxxfree and xxxstart also! */
2086 /* -> doesn�t waste blocks */
2087
2088 if (segstartp!=NULL){
2089 *segstartp=segstart;
2090 }
2091 if (segsizep!=NULL){
2092 *segsizep=segfree;
2093 }
2094 if (lsegstartp!=NULL){
2095 *lsegstartp=lsegstart;
2096 }
2097 if (lsegsizep!=NULL){
2098 *lsegsizep=lsegfree;
2099 }
2100 if (segnrp!=NULL){
2101 *segnrp=segnr;
2102 }
2103
2104 return totfree;
2105 }
2106
2107 /* QDOS */
2108 int
qdos_findfree(u_int seekstart,u_int minsize,u_int * segstartp,u_int * segsizep,u_int * lsegstartp,u_int * lsegsizep,u_int * segnrp,struct qdos_rib_s * skipribp,u_int skipnr,int fullscan)2109 qdos_findfree(u_int seekstart,u_int minsize,
2110 u_int *segstartp,u_int *segsizep,
2111 u_int *lsegstartp,u_int *lsegsizep,u_int *segnrp,
2112 struct qdos_rib_s *skipribp,u_int skipnr,int fullscan)
2113 {
2114 u_int sec,bmapbyte,bmapbit;
2115 char bmapbuf[QDOS_BLOCKSIZE];
2116 int used;
2117 u_int totfree;
2118 u_int segfree;
2119 int segstart;
2120 int lsegstart;
2121 u_int lsegfree;
2122 int cursegstart;
2123 u_int cursegfree;
2124 u_int segnr;
2125
2126 if (curpart->type!=PARTTYPE_QDOS){
2127 return -1;
2128 }
2129
2130 if (seekstart>=curpart->totsize){
2131 return -1;
2132 }
2133 /* we must be careful to construct segments aligned to clusters */
2134 /* because algorithm below assumes this (not qdos_markbitmap)! */
2135 /* round down */
2136 seekstart=(seekstart/QDOS_CSIZE)*QDOS_CSIZE;
2137 /* round up to cluster size */
2138 minsize=((minsize+QDOS_CSIZE-1)/QDOS_CSIZE)*QDOS_CSIZE;
2139
2140 /* read CAT block */
2141 if (READBLOCK_CURPART(QDOS_CATSTART,bmapbuf,1)<0){
2142 err_print("qdos_findfree: cannot read bitmap block\n");
2143 return -1;
2144 }
2145
2146 /* scan bitmap */
2147 totfree=0; /* nothing found yet */
2148 segfree=0; /* nothing found yet */
2149 segstart=-1; /* invalid block */
2150 lsegfree=0; /* nothing found yet */
2151 lsegstart=-1; /* invalid block */
2152 cursegfree=0; /* nothing found yet */
2153 cursegstart=-1; /* invalid block */
2154 segnr=0; /* nothing found yet */
2155 for (sec=seekstart;sec<=curpart->totsize;sec++){ /* totsize!!! */
2156 if (sec<curpart->totsize){ /* totsize!!! */
2157 /* calculate block,byte,bit for current block sec */
2158 if (qdos_bitmaptranslate(sec,&bmapbit,&bmapbyte)<0){
2159 err_print("qdos_findfree: invalid block\n");
2160 return -1;
2161 }
2162
2163 /* check if used */
2164 used=1&(bmapbuf[bmapbyte]>>bmapbit);
2165
2166 /* check skipribp */
2167 if ((skipribp!=NULL)&&(!used)){
2168 u_int i;
2169 u_int start,size;
2170
2171 /* see if block is in skiplist */
2172 for (i=0;i<skipnr;i++){
2173 qdos_getseg(skipribp,i,&start,&size);
2174 if (size==0){
2175 /* end */
2176 break; /* done */
2177 }
2178 start*=QDOS_CSIZE;
2179 size*=QDOS_CSIZE;
2180 /* within segment? */
2181 if ((start<=sec)&&(sec<start+size)){
2182 used=1;
2183 break; /* used, done */
2184 }
2185 }
2186 }
2187 }
2188
2189 /* check if used or scan complete */
2190 if (used||(sec==curpart->totsize)){ /* totsize!!! */
2191 /* used block or end => end of segment */
2192 /* is there a segment? */
2193 if (cursegstart>=0){
2194 /* largest segment stuff */
2195 /* is this segment larger? */
2196 if (cursegfree>lsegfree){
2197 lsegfree=cursegfree;
2198 lsegstart=cursegstart;
2199 }
2200
2201 /* first large enough segment stuff */
2202 /* still looking for large enough segment? */
2203 if (segstart<0){
2204 /* check if current segment is large enough */
2205 if (cursegfree>=minsize){
2206 segfree=cursegfree;
2207 segstart=cursegstart;
2208 }
2209 }
2210
2211 /* reset current segment */
2212 cursegfree=0; /* nothing found yet */
2213 cursegstart=-1; /* invalid block */
2214 }
2215 }else{
2216 /* free block */
2217 totfree++;
2218
2219 /* current segment stuff */
2220 cursegfree++;
2221 /* first block of current segment? */
2222 if (cursegstart<0){
2223 cursegstart=sec;
2224 segnr++; /* one more segment */
2225 }
2226
2227 /* no full scan needed? */
2228 if (!fullscan){
2229 /* check if current (partial) segment is large enough */
2230 if (cursegfree>=minsize){
2231 segfree=cursegfree;
2232 /* we stop searching, so: round up to cluster size */
2233 segfree=((segfree+QDOS_CSIZE-1)/QDOS_CSIZE)*QDOS_CSIZE;
2234 segstart=cursegstart;
2235 /* largest segment stuff */
2236 /* is this segment larger? */
2237 if (cursegfree>lsegfree){
2238 lsegfree=cursegfree;
2239 lsegstart=cursegstart;
2240 }
2241 /* note that totfree,lsegfree are not complete, only what we found so far */
2242 break; /* done */
2243 }
2244 }
2245 }
2246 }
2247 /* since qdos_bitmapstranslate gives cluster alignment and the start blocks */
2248 /* in our search are also cluster aligned => xxxfree and xxxstart also! */
2249 /* -> doesn�t waste blocks */
2250
2251 if (segstartp!=NULL){
2252 *segstartp=segstart;
2253 }
2254 if (segsizep!=NULL){
2255 *segsizep=segfree;
2256 }
2257 if (lsegstartp!=NULL){
2258 *lsegstartp=lsegstart;
2259 }
2260 if (lsegsizep!=NULL){
2261 *lsegsizep=lsegfree;
2262 }
2263 if (segnrp!=NULL){
2264 *segnrp=segnr;
2265 }
2266
2267 return totfree;
2268 }
2269
2270 /* OS9 */
2271 int
findfreelist(struct seg_s * seglist,u_int segnr,u_int startblk,u_int blknr)2272 findfreelist(struct seg_s *seglist,u_int segnr,
2273 u_int startblk,u_int blknr)
2274 {
2275 u_int segstart;
2276 u_int segsize;
2277 u_int lsegstart;
2278 u_int lsegsize;
2279 int totfree;
2280 u_int seg;
2281
2282 if (curpart->type!=PARTTYPE_OS9MDR){
2283 return -1;
2284 }
2285 if (curpart->mdr){
2286 return -1;
2287 }
2288
2289 if (seglist==NULL){
2290 return -1;
2291 }
2292 if (segnr==0){
2293 return -1;
2294 }
2295 if (blknr==0){
2296 return 0;
2297 }
2298 if (startblk+blknr>curpart->totsize){
2299 startblk=0; /* XXX */
2300 }
2301
2302 /* we must be careful to construct segments aligned to clusters (see findfree) */
2303 /* round down */
2304 startblk=(startblk/(curpart->clustersize))*(curpart->clustersize);
2305 /* round up to cluster size */
2306 blknr=((blknr+curpart->clustersize-1)
2307 /(curpart->clustersize))*(curpart->clustersize);
2308
2309 /* scan segments */
2310 /* first try with given startblk */
2311 for (seg=0;seg<segnr;seg++){
2312 findfreelist_again:
2313 /* see if we find remaining blknr as one segment */
2314 /* use seglist as skiplist with seg segments in it */
2315 /* use remaining blknr as minsize */
2316 totfree=findfree(startblk,blknr,
2317 &segstart,&segsize,
2318 &lsegstart,&lsegsize,NULL,
2319 seglist,seg,0); /* no full scan */
2320 if (totfree<0){
2321 err_print("findfreelist: findfree\n");
2322 return -1;
2323 }
2324
2325 #ifdef DEBUG
2326 printf("findfreelist:\ntotfree: %06x\n",totfree);
2327 printf("seg: %02x\nstartblk: %06x blknr: %06x\n",
2328 seg,startblk,blknr);
2329 printf("segstart: %06x segsize: %06x\n",
2330 segstart,segsize);
2331 printf("lsegstart: %06x lsegsize: %06x\n\n",
2332 lsegstart,lsegsize);
2333 #endif
2334
2335 if (totfree<(int)blknr){
2336 if (startblk>0){ /* search above was not for whole partition? */
2337 /* one more try with startblk=0 */
2338 startblk=0; /* searches whole partition */
2339 goto findfreelist_again;
2340 }else{
2341 err_print("findfreelist: not enough blocks\n");
2342 return -1;
2343 }
2344 }
2345
2346 /* truncate segment sizes: */
2347 if (segsize>SEG_S_SIZEMAX){
2348 segsize=SEG_S_SIZEMAX;
2349 }
2350 if (lsegsize>SEG_S_SIZEMAX){
2351 lsegsize=SEG_S_SIZEMAX;
2352 }
2353
2354 startblk=0; /* in the following searches: whole partition */
2355
2356 /* is there one segment large enough? */
2357 if (segsize>=blknr){
2358 /* set segment */
2359 setseg(seglist+seg,segstart,blknr);
2360
2361 /* fill rest of seglist */
2362 {
2363 u_int i;
2364
2365 for (i=seg+1;i<segnr;i++){
2366 setseg(seglist+i,0,0);
2367 }
2368 }
2369
2370 return seg+1; /* return number of segments */
2371 }
2372 /* if we arrive here: lsegsize<blknr and we are not done yet */
2373
2374 /* should use largest segment available to avoid seglist overrun */
2375 /* assume that findfree returned cluster aligned lsegstart and lsegsize */
2376 /* set segment */
2377 setseg(seglist+seg,lsegstart,lsegsize);
2378
2379 /* remaining blocks */
2380 blknr-=lsegsize;
2381 }
2382 /* if we arrive here: not enough segments in seglist */
2383
2384 err_print("findfreelist: seglist too short\n");
2385 return -1;
2386 }
2387
2388 /* MDR-DOS */
2389 int
mdr_findfreelist(struct mdr_dirent_s * direntp,u_int startfclu,u_int fclunr,u_int startblk,u_int blknr)2390 mdr_findfreelist(struct mdr_dirent_s *direntp,u_int startfclu,u_int fclunr,
2391 u_int startblk,u_int blknr)
2392 {
2393 u_int segstart;
2394 u_int segsize;
2395 u_int lsegstart;
2396 u_int lsegsize;
2397 int totfree;
2398 u_int fclu,clu,c;
2399
2400 if (curpart->type!=PARTTYPE_OS9MDR){
2401 return -1;
2402 }
2403 if (!curpart->mdr){
2404 return -1;
2405 }
2406
2407 if (direntp==NULL){
2408 return -1;
2409 }
2410 if (fclunr>MDR_FILECLNR){
2411 return -1;
2412 }
2413 if (startfclu+fclunr>MDR_FILECLNR){
2414 return -1;
2415 }
2416 if (blknr==0){
2417 return 0;
2418 }
2419 if (startblk+blknr>curpart->totsize){
2420 startblk=0; /* XXX */
2421 }
2422 if (curpart->mdr_clustersize==0){
2423 return -1;
2424 }
2425
2426 /* we must be careful to construct segments aligned to clusters (see mdr_findfree) */
2427 /* round down */
2428 startblk=(startblk/(curpart->mdr_clustersize))*(curpart->mdr_clustersize);
2429 /* round up to cluster size */
2430 blknr=((blknr+curpart->mdr_clustersize-1)
2431 /(curpart->mdr_clustersize))*(curpart->mdr_clustersize);
2432 if (fclunr*curpart->mdr_clustersize<blknr){
2433 err_print("mdr_findfreelist: fclunr too small for blknr\n");
2434 return -1;
2435 }
2436
2437 /* scan clusters */
2438 /* first try with given startblk */
2439 for (fclu=startfclu;fclu<startfclu+fclunr;){
2440 mdr_findfreelist_again:
2441 /* see if we find remaining blknr as one segment (i.e. contiguous block here) */
2442 /* use direntp as skipdirentp with fclu clusters in it */
2443 /* use remaining blknr as minsize */
2444 /* Note: use clist 0...flcu for skiplist (and not startfclu...fclu): OK */
2445 totfree=mdr_findfree(startblk,blknr,
2446 &segstart,&segsize,
2447 &lsegstart,&lsegsize,NULL,
2448 direntp,fclu,0); /* no full scan */
2449 if (totfree<0){
2450 err_print("mdr_findfreelist: mdr_findfree\n");
2451 return -1;
2452 }
2453
2454 #ifdef DEBUG
2455 printf("mdr_findfreelist:\ntotfree: %06x\n",totfree);
2456 printf("startfclu: %06x\nstartblk: %06x blknr: %06x\n",
2457 startfclu,startblk,blknr);
2458 printf("segstart: %06x segsize: %06x\n",
2459 segstart,segsize);
2460 printf("lsegstart: %06x lsegsize: %06x\n\n",
2461 lsegstart,lsegsize);
2462 #endif
2463
2464 if (totfree<(int)blknr){
2465 if (startblk>0){ /* search above was not for whole partition? */
2466 /* one more try with startblk=0 */
2467 startblk=0; /* searches whole partition */
2468 goto mdr_findfreelist_again;
2469 }else{
2470 err_print("mdr_findfreelist: not enough blocks\n");
2471 return -1;
2472 }
2473 }
2474
2475 startblk=0; /* in the following searches: whole partition */
2476
2477 /* is there one segment large enough? */
2478 if (segsize>=blknr){
2479 /* set segment */
2480 for (c=0,clu=segstart/curpart->mdr_clustersize;
2481 c<blknr/curpart->mdr_clustersize;c++,clu++,fclu++){
2482 direntp->clist[fclu][0]=clu>>8;
2483 direntp->clist[fclu][1]=clu&0xff;
2484 }
2485 /* Note: fclu++ above => now fclu==last used fclu+1 !!! */
2486
2487 /* fill rest of direntp */
2488 for (c=fclu;c<startfclu+fclunr;c++){
2489 direntp->clist[c][0]=0;
2490 direntp->clist[c][1]=0;
2491 }
2492
2493 return fclu-startfclu; /* return number of clusters */
2494 }
2495 /* if we arrive here: lsegsize<blknr and we are not done yet */
2496
2497 /* should use largest segment available */
2498 /* assume that mdr_findfree returned cluster aligned lsegstart and lsegsize */
2499 /* set segment */
2500 for (c=0,clu=lsegstart/curpart->mdr_clustersize;
2501 c<lsegsize/curpart->mdr_clustersize;c++,clu++,fclu++){
2502 direntp->clist[fclu][0]=clu>>8;
2503 direntp->clist[fclu][1]=clu&0xff;
2504 }
2505
2506 /* remaining blocks */
2507 blknr-=lsegsize;
2508 }
2509 /* XXX should never arrive here, see check for fclunr large enough for blknr above!!! */
2510
2511 err_print("mdr_findfreelist: internal error!!!\n");
2512 return -1;
2513 }
2514
2515 /* QDOS */
2516 int
qdos_findfreelist(struct qdos_rib_s * ribp,u_int startseg,u_int segnr,u_int startblk,u_int blknr)2517 qdos_findfreelist(struct qdos_rib_s *ribp,u_int startseg,u_int segnr,
2518 u_int startblk,u_int blknr)
2519 {
2520 u_int segstart;
2521 u_int segsize;
2522 u_int lsegstart;
2523 u_int lsegsize;
2524 int totfree;
2525 u_int seg;
2526
2527 if (curpart->type!=PARTTYPE_QDOS){
2528 return -1;
2529 }
2530
2531 if (ribp==NULL){
2532 return -1;
2533 }
2534 /* must have at least one segment to terminate RIB!!! */
2535 if (segnr<1){
2536 return -1;
2537 }
2538 if (segnr>QDOS_RIB_SDWNR){
2539 return -1;
2540 }
2541 if (startseg+segnr>QDOS_RIB_SDWNR){
2542 return -1;
2543 }
2544 if (blknr==0){
2545 return 0;
2546 }
2547 if (startblk+blknr>curpart->totsize){
2548 startblk=0; /* XXX */
2549 }
2550
2551 /* we must be careful to construct segments aligned to clusters (see findfree) */
2552 /* round down */
2553 startblk=(startblk/QDOS_CSIZE)*QDOS_CSIZE;
2554 /* round up to cluster size */
2555 blknr=((blknr+QDOS_CSIZE-1)/QDOS_CSIZE)*QDOS_CSIZE;
2556
2557 /* scan segments */
2558 /* first try with given startblk */
2559 /* one segment to terminate RIB!!! => segnr-1: */
2560 for (seg=startseg;seg<startseg+segnr-1;seg++){
2561 qdos_findfreelist_again:
2562 /* see if we find remaining blknr as one segment */
2563 /* use qibp as skipribp with seg segments in it */
2564 /* use remaining blknr as minsize */
2565 totfree=qdos_findfree(startblk,blknr,
2566 &segstart,&segsize,
2567 &lsegstart,&lsegsize,NULL,
2568 ribp,seg,0); /* no full scan */
2569 if (totfree<0){
2570 err_print("qdos_findfreelist: qdos_findfree\n");
2571 return -1;
2572 }
2573
2574 #ifdef DEBUG
2575 printf("qdos_findfreelist:\ntotfree: %06x\n",totfree);
2576 printf("seg: %02x\nstartblk: %06x blknr: %06x\n",
2577 seg,startblk,blknr);
2578 printf("segstart: %06x segsize: %06x\n",
2579 segstart,segsize);
2580 printf("lsegstart: %06x lsegsize: %06x\n\n",
2581 lsegstart,lsegsize);
2582 #endif
2583
2584 if (totfree<(int)blknr){
2585 if (startblk>0){ /* search above was not for whole partition? */
2586 /* one more try with startblk=0 */
2587 startblk=0; /* searches whole partition */
2588 goto qdos_findfreelist_again;
2589 }else{
2590 err_print("qdos_findfreelist: not enough blocks\n");
2591 return -1;
2592 }
2593 }
2594
2595 /* truncate segment sizes: */
2596 if (segsize>QDOS_RIB_SDWSIZMAX*QDOS_CSIZE){
2597 segsize=QDOS_RIB_SDWSIZMAX*QDOS_CSIZE;
2598 }
2599 if (lsegsize>QDOS_RIB_SDWSIZMAX*QDOS_CSIZE){
2600 lsegsize=QDOS_RIB_SDWSIZMAX*QDOS_CSIZE;
2601 }
2602
2603 startblk=0; /* in the following searches: whole partition */
2604
2605 /* is there one segment large enough? */
2606 if (segsize>=blknr){
2607 /* set segment */
2608 qdos_setseg(ribp,seg,segstart/QDOS_CSIZE,blknr/QDOS_CSIZE);
2609
2610 /* terminate RIB */
2611 /* Note: segnr-1 above => seg+1<startseg+segnr!!! */
2612 qdos_setseg(ribp,seg+1,0,0); /* mark end */
2613
2614 return seg+1; /* return number of segments */
2615 }
2616 /* if we arrive here: lsegsize<blknr and we are not done yet */
2617
2618 /* should use largest segment available to avoid seglist overrun */
2619 /* assume that findfree returned cluster aligned lsegstart and lsegsize */
2620 /* set segment */
2621 qdos_setseg(ribp,seg,lsegstart/QDOS_CSIZE,lsegsize/QDOS_CSIZE);
2622
2623 /* remaining blocks */
2624 blknr-=lsegsize;
2625 }
2626 /* if we arrive here: not enough segments in ribp */
2627
2628 err_print("qdos_findfreelist: ribp too short\n");
2629 return -1;
2630 }
2631
2632 /* OS9 */
2633 int
appendfreelist(struct seg_s * seglist,u_int segnr,u_int blknr)2634 appendfreelist(struct seg_s *seglist,u_int segnr,u_int blknr)
2635 {
2636 u_int startblk,size;
2637 u_int startblk2,size2;
2638 int i;
2639 int seg;
2640 struct seg_s *segstart;
2641 u_int seekstart,seeknr;
2642
2643 if (curpart->type!=PARTTYPE_OS9MDR){
2644 return -1;
2645 }
2646 if (curpart->mdr){
2647 return -1;
2648 }
2649
2650 if (seglist==NULL){
2651 return -1;
2652 }
2653 if (blknr==0){
2654 return 0; /* number of appended segments */
2655 }
2656 /* at least two segments */
2657 if (segnr<2){
2658 return -1;
2659 }
2660
2661 /* get seglist[0] */
2662 getseg(seglist,&startblk,&size);
2663 if (size==0){
2664 /* segment[0] is empty */
2665 segstart=seglist;
2666 seekstart=0;
2667 seeknr=segnr;
2668 }else{
2669 /* seglist[0] is non-empty */
2670 segstart=seglist+1;
2671 seekstart=startblk+size; /* directly behind end of seglist[0] */
2672 seeknr=segnr-1;
2673 }
2674
2675 /* append blknr new segments, starting at segstart */
2676 /* use seekstart as a hint for findfreelist to get contiguous blocks (if possible) */
2677 seg=findfreelist(segstart,seeknr,seekstart,blknr);
2678 if (seg<=0){
2679 err_print("appendfreelist: cannot find free blocks\n");
2680 return -1;
2681 }
2682
2683 if (segstart==seglist+1){ /* seglist[0] was non-empty? */
2684 /* get segment 1 */
2685 getseg(seglist+1,&startblk2,&size2);
2686 /* check if segment 1 is adjacent to segment 0 */
2687 if (startblk2==startblk+size){
2688 if (size+size2<=SEG_S_SIZEMAX){ /* fits into one segment? */
2689 /* merge segment 0 and 1 into 0 */
2690 setseg(seglist,startblk,size+size2);
2691 /* shift remaining segments */
2692 for (i=1;i<((int)segnr)-1;i++){
2693 getseg(seglist+i+1,&startblk,&size);
2694 setseg(seglist+i,startblk,size);
2695 }
2696 /* clear last segment */
2697 setseg(seglist+segnr-1,0,0);
2698 seg--; /* Note: might become 0 now which is OK! */
2699 }
2700 }
2701 }
2702
2703 return seg; /* return number of appended segments */
2704 }
2705
2706 /* MDR-DOS */
2707 int
mdr_appendfreelist(struct mdr_dirent_s * direntp,u_int startfclu,u_int fclunr,u_int blknr)2708 mdr_appendfreelist(struct mdr_dirent_s *direntp,u_int startfclu,u_int fclunr,u_int blknr)
2709 {
2710 int ret;
2711 u_int startblk;
2712 u_int fclu1;
2713 u_int seekstart,seeknr;
2714
2715 if (curpart->type!=PARTTYPE_OS9MDR){
2716 return -1;
2717 }
2718 if (!curpart->mdr){
2719 return -1;
2720 }
2721
2722 if (direntp==NULL){
2723 return -1;
2724 }
2725 if (blknr==0){
2726 return 0; /* number of appended clusters */
2727 }
2728 /* at least 2 clusters */
2729 if (fclunr<2){
2730 return -1;
2731 }
2732 if (startfclu+fclunr>MDR_FILECLNR){
2733 return -1;
2734 }
2735
2736 /* get clist[startfclu] */
2737 startblk=curpart->mdr_clustersize
2738 *((direntp->clist[startfclu][0]<<8)+(direntp->clist[startfclu][1]));
2739 if (startblk==0){
2740 /* clist[startfclu] is empty */
2741 fclu1=startfclu;
2742 seekstart=0;
2743 seeknr=fclunr;
2744 }else{
2745 /* clist[startfclu] is non-empty */
2746 fclu1=startfclu+1;
2747 seekstart=startblk+curpart->mdr_clustersize; /* directly behind end of clist[0] */
2748 seeknr=fclunr-1;
2749 }
2750
2751 /* append blknr new clusters, starting at index flcu1 */
2752 /* use seekstart as a hint for mdr_findfreelist to get contiguous blocks (if possible) */
2753 ret=mdr_findfreelist(direntp,fclu1,seeknr,seekstart,blknr);
2754 if (ret<=0){
2755 err_print("mdr_appendfreelist: cannot find free blocks\n");
2756 return -1;
2757 }
2758
2759 return ret; /* return number of appended clusters */
2760 }
2761
2762 /* QDOS */
2763 int
qdos_appendfreelist(struct qdos_rib_s * ribp,u_int startseg,u_int segnr,u_int blknr)2764 qdos_appendfreelist(struct qdos_rib_s *ribp,u_int startseg,u_int segnr,u_int blknr)
2765 {
2766 u_int startblk,size;
2767 u_int startblk2,size2;
2768 int i;
2769 int seg;
2770 u_int seg1;
2771 u_int seekstart,seeknr;
2772
2773 if (curpart->type!=PARTTYPE_QDOS){
2774 return -1;
2775 }
2776
2777 if (ribp==NULL){
2778 return -1;
2779 }
2780 if (blknr==0){
2781 return 0; /* number of appended segments */
2782 }
2783 /* at least three segments */
2784 /* must have at least one segment to terminate RIB!!! */
2785 if (segnr<3){
2786 return -1;
2787 }
2788 if (startseg+segnr>QDOS_RIB_SDWNR){
2789 return -1;
2790 }
2791
2792 /* get ribp->rib_sdw[startseg] */
2793 qdos_getseg(ribp,startseg,&startblk,&size);
2794 if (size==0){
2795 /* segment[startseg] is end */
2796 seg1=startseg;
2797 seekstart=0;
2798 seeknr=segnr;
2799 }else{
2800 /* seglist[startseg] is non-end */
2801 startblk*=QDOS_CSIZE;
2802 size*=QDOS_CSIZE;
2803 seg1=startseg+1;
2804 seekstart=startblk+size; /* directly behind end of ribp->rib_sdw[startseg] */
2805 seeknr=segnr-1;
2806 }
2807
2808 /* append blknr new segments, starting at seg1 */
2809 /* use seekstart as a hint for qdos_findfreelist to get contiguous blocks (if possible) */
2810 seg=qdos_findfreelist(ribp,seg1,seeknr,seekstart,blknr);
2811 if (seg<=0){
2812 err_print("qdos_appendfreelist: cannot find free blocks\n");
2813 return -1;
2814 }
2815
2816 if (seg1==startseg+1){ /* ribp->rib_sdw[startseg] was non-end? */
2817 /* get segment startseg+1 */
2818 qdos_getseg(ribp,startseg+1,&startblk2,&size2);
2819 startblk2*=QDOS_CSIZE;
2820 size2*=QDOS_CSIZE;
2821 /* check if segment startseg+1 is adjacent to segment startseg */
2822 if (startblk2==startblk+size){
2823 if (size+size2<=QDOS_RIB_SDWSIZMAX*QDOS_CSIZE){ /* fits into one segment? */
2824 /* merge segment startseg and startseg+1 into startseg */
2825 qdos_setseg(ribp,startseg,startblk/QDOS_CSIZE,(size+size2)/QDOS_CSIZE);
2826 /* shift remaining segments */
2827 for (i=startseg+1;i<((int)(startseg+segnr))-1;i++){
2828 qdos_getseg(ribp,i+1,&startblk,&size);
2829 qdos_setseg(ribp,i,startblk,size);
2830 }
2831 /* terminate last segment */
2832 /* XXX actually not necessary (qdos_findfreelist already did for previous segment) */
2833 qdos_setseg(ribp,startseg+segnr-1,0,0); /* mark end */
2834 seg--; /* Note: might become 0 now which is OK! */
2835 }
2836 }
2837 }
2838
2839 return seg; /* return number of appended segments */
2840 }
2841
2842
2843
2844 /* QDOS */
2845 void
qdos_printatt0(u_char att)2846 qdos_printatt0(u_char att)
2847 {
2848 u_char fmt;
2849
2850 if (att&QDOS_ATT_WRT){
2851 putchar('w');
2852 }else{
2853 putchar('-');
2854 }
2855 if (att&QDOS_ATT_DEL){
2856 putchar('d');
2857 }else{
2858 putchar('-');
2859 }
2860 if (att&QDOS_ATT_SYS){
2861 putchar('s');
2862 }else{
2863 putchar('-');
2864 }
2865 if (att&QDOS_ATT_CON){
2866 putchar('c');
2867 }else{
2868 putchar('-');
2869 }
2870 if (att&QDOS_ATT_NCS){
2871 putchar('n');
2872 }else{
2873 putchar('-');
2874 }
2875 putchar(' ');
2876
2877 fmt=att&QDOS_ATT_FMM;
2878 switch (fmt){
2879 case QDOS_ATT_FMU:
2880 printf("UserDef");
2881 break;
2882 case QDOS_ATT_FMD:
2883 printf("DefRec ");
2884 break;
2885 case QDOS_ATT_FML:
2886 printf("BinLoad");
2887 break;
2888 case QDOS_ATT_FMB:
2889 printf("BinRec ");
2890 break;
2891 case QDOS_ATT_FMA:
2892 printf("ARec ");
2893 break;
2894 case QDOS_ATT_FMC:
2895 printf("ABinRec");
2896 break;
2897 default:
2898 printf("???????");
2899 break;
2900 }
2901 }
2902
2903 /* OS9 */
2904 void
printatt(u_char att)2905 printatt(u_char att)
2906 {
2907
2908 if (att&ATT_D){
2909 putchar('D');
2910 }else{
2911 putchar('-');
2912 }
2913 if (att&ATT_S){
2914 putchar('S');
2915 }else{
2916 putchar('-');
2917 }
2918 if (att&ATT_PE){
2919 putchar('E');
2920 }else{
2921 putchar('-');
2922 }
2923 if (att&ATT_PW){
2924 putchar('W');
2925 }else{
2926 putchar('-');
2927 }
2928 if (att&ATT_PR){
2929 putchar('R');
2930 }else{
2931 putchar('-');
2932 }
2933 if (att&ATT_E){
2934 putchar('e');
2935 }else{
2936 putchar('-');
2937 }
2938 if (att&ATT_W){
2939 putchar('w');
2940 }else{
2941 putchar('-');
2942 }
2943 if (att&ATT_R){
2944 putchar('r');
2945 }else{
2946 putchar('-');
2947 }
2948 }
2949
2950 /* OS9 */
2951 int
setattr(struct filedes_s * fdes,char * str)2952 setattr(struct filedes_s *fdes,char *str)
2953 {
2954 u_int i;
2955 int set;
2956 u_char att[2];
2957
2958 if (fdes==NULL){
2959 return -1;
2960 }
2961 if (str==NULL){
2962 return -1;
2963 }
2964
2965 /* scan string */
2966 set=-1; /* nothing */
2967 att[0]=0;
2968 att[1]=0;
2969 for (i=0;i<strlen(str);i++){
2970 if (str[i]=='+'){
2971 set=1; /* set */
2972 }else if (str[i]=='-'){
2973 set=0; /* clear */
2974 }else{
2975 if (set<0){
2976 err_print("setattr: must specify + or - first\n");
2977 return -1;
2978 }
2979 if (str[i]=='D'){
2980 #if 0
2981 att[set]|=ATT_D;
2982 #else
2983 err_print("setattr: not allowed to change directory status\n");
2984 return -1;
2985 #endif
2986 }else if (str[i]=='S'){
2987 att[set]|=ATT_S;
2988 }else if (str[i]=='E'){
2989 att[set]|=ATT_PE;
2990 }else if (str[i]=='W'){
2991 att[set]|=ATT_PW;
2992 }else if (str[i]=='R'){
2993 att[set]|=ATT_PR;
2994 }else if (str[i]=='e'){
2995 att[set]|=ATT_E;
2996 }else if (str[i]=='w'){
2997 att[set]|=ATT_W;
2998 }else if (str[i]=='r'){
2999 att[set]|=ATT_R;
3000 }else{
3001 char b[128];
3002 sprintf(b,"setattr: invalid character '%c'\n",str[i]);
3003 err_print(b);
3004 return -1;
3005 }
3006 }
3007 }
3008
3009 /* modify fdes */
3010 fdes->fd_att|=att[1]; /* set */
3011 fdes->fd_att&=~att[0]; /* clear */
3012
3013 /* XXX don�t forget to save fdes */
3014 return 0;
3015 }
3016
3017 /* set/clear ATT_CON flag in directory entry if file is contiguous */
3018 int
qdos_setattr(struct qdos_rib_s * ribp,u_int fnr,void * indirp,char * attstr)3019 qdos_setattr(struct qdos_rib_s *ribp,u_int fnr,void *indirp,char *attstr)
3020 {
3021 u_int alloc,contig;
3022 u_char dirbuf[QDOS_DIRSIZE*QDOS_BLOCKSIZE];
3023 struct qdos_dir_s *qdp;
3024
3025 if (ribp==0){
3026 return -1;
3027 }
3028 if (curpart->type!=PARTTYPE_QDOS){
3029 return -1;
3030 }
3031 if (fnr>=QDOS_DIRENTRYNR){
3032 return -1;
3033 }
3034
3035 if (indirp==NULL){
3036 /* read directory */
3037 if (READBLOCK_CURPART(QDOS_DIRSTART,(void *)dirbuf,QDOS_DIRSIZE)<0){
3038 err_print("qdos_setattr: cannot read directory\n");
3039 return -1;
3040 }
3041 qdp=(struct qdos_dir_s *)dirbuf;
3042 }else{
3043 /* directory already read */
3044 qdp=(struct qdos_dir_s *)indirp;
3045 }
3046
3047 /* set/clear ATT_CON extra!!! */
3048 alloc=qdos_countseg(ribp,QDOS_RIB_SDWNR,&contig);
3049 if ((alloc!=0)&&(alloc==contig)){
3050 qdp[fnr].dir_at[0]|=QDOS_ATT_CON; /* set flag */
3051 }else{
3052 qdp[fnr].dir_at[0]&=~QDOS_ATT_CON; /* clear flag */
3053 }
3054
3055 if (attstr!=NULL){
3056 /* first check for format strings */
3057 if (strcasecmp(attstr,"userdef")==0){
3058 qdp[fnr].dir_at[0]=(qdp[fnr].dir_at[0]&QDOS_ATT_FLM)|QDOS_ATT_FMU;
3059 }else if (strcasecmp(attstr,"defrec")==0){
3060 qdp[fnr].dir_at[0]=(qdp[fnr].dir_at[0]&QDOS_ATT_FLM)|QDOS_ATT_FMD;
3061 }else if (strcasecmp(attstr,"binload")==0){
3062 qdp[fnr].dir_at[0]=(qdp[fnr].dir_at[0]&QDOS_ATT_FLM)|QDOS_ATT_FML;
3063 }else if (strcasecmp(attstr,"binrec")==0){
3064 qdp[fnr].dir_at[0]=(qdp[fnr].dir_at[0]&QDOS_ATT_FLM)|QDOS_ATT_FMB;
3065 }else if (strcasecmp(attstr,"arec")==0){
3066 qdp[fnr].dir_at[0]=(qdp[fnr].dir_at[0]&QDOS_ATT_FLM)|QDOS_ATT_FMA;
3067 }else if (strcasecmp(attstr,"abinrec")==0){
3068 qdp[fnr].dir_at[0]=(qdp[fnr].dir_at[0]&QDOS_ATT_FLM)|QDOS_ATT_FMC;
3069 }else{
3070 u_int i;
3071 int set;
3072 u_char att[2];
3073
3074 /* scan string */
3075 set=-1; /* nothing */
3076 att[0]=0;
3077 att[1]=0;
3078 for (i=0;i<strlen(attstr);i++){
3079 if (attstr[i]=='+'){
3080 set=1; /* set */
3081 }else if (attstr[i]=='-'){
3082 set=0; /* clear */
3083 }else{
3084 if (set<0){
3085 err_print("qdos_setattr: must specify + or - first\n");
3086 return -1;
3087 }
3088 if (attstr[i]=='w'){
3089 att[set]|=QDOS_ATT_WRT;
3090 }else if (attstr[i]=='d'){
3091 att[set]|=QDOS_ATT_DEL;
3092 }else if (attstr[i]=='s'){
3093 att[set]|=QDOS_ATT_SYS;
3094 }else if (attstr[i]=='n'){
3095 att[set]|=QDOS_ATT_NCS;
3096 }else{
3097 char b[128];
3098 sprintf(b,"qdos_setattr: invalid character '%c'\n",attstr[i]);
3099 err_print(b);
3100 return -1;
3101 }
3102 }
3103 }
3104
3105 /* modify dir_at[0] */
3106 qdp[fnr].dir_at[0]|=att[1]; /* set */
3107 qdp[fnr].dir_at[0]&=~att[0]; /* clear */
3108 }
3109 }
3110
3111 /* write updated directory */
3112 if (WRITEBLOCK_CURPART(QDOS_DIRSTART,(void *)qdp,QDOS_DIRSIZE)<0){ /* qdp!!! */
3113 err_print("qdos_setattr: cannot write directory\n");
3114 return -1;
3115 }
3116
3117 return 0;
3118 }
3119
3120
3121
3122 /* OS9 */
3123 u_int
printfiledes(struct part_s * pp,struct filedes_s * fdes,int verbose)3124 printfiledes(struct part_s *pp,struct filedes_s *fdes,int verbose)
3125 {
3126 u_int fsize,asize,corrupt;
3127 int i;
3128 u_int contbl;
3129
3130 if (fdes==NULL){
3131 return 0;
3132 }
3133 if (pp==NULL){
3134 return -1;
3135 }
3136
3137 fsize=(fdes->fd_fsize[0]<<24)
3138 +(fdes->fd_fsize[1]<<16)
3139 +(fdes->fd_fsize[2]<<8)
3140 +fdes->fd_fsize[3]; /* size according to directory entry */
3141 asize=countseg(&(fdes->fd_seg[0]),FILEDES_SEGNR,&contbl); /* allocated */
3142
3143 /* check if corrupt */
3144 if (pp->type!=PARTTYPE_OS9MDR){
3145 return -1;
3146 }
3147 if (pp->mdr)
3148 return -1;
3149 corrupt=(fsize>asize*pp->blksiz)||(asize>pp->filesyssize);
3150
3151 if (verbose){
3152 printf("fd_att: %02x (",fdes->fd_att);
3153 printatt(fdes->fd_att);
3154 printf(")\nfd_own: %02x%02x\n",fdes->fd_own[0],fdes->fd_own[1]);
3155 printf("fd_dat: %02i-%02i-%02i %02i:%02i\n",
3156 fdes->fd_dat[0]%100,fdes->fd_dat[1]%100,fdes->fd_dat[2]%100,
3157 fdes->fd_dat[3]%100,fdes->fd_dat[4]%100);
3158 printf("fd_link: %02x\n",fdes->fd_link);
3159 printf("fd_fsize: %08x (%u bytes)\n",fsize,fsize);
3160 printf(" alloc: %08x (%u bytes)\n",asize*pp->blksiz,asize*pp->blksiz);
3161 printf(" contig: %08x (%u bytes)\n",contbl*pp->blksiz,contbl*pp->blksiz);
3162 printf("fd_creat: %02i-%02i-%02i\n",
3163 fdes->fd_creat[0]%100,fdes->fd_creat[1]%100,fdes->fd_creat[2]%100);
3164 for (i=0;i<FILEDES_SEGNR;i++){ /* max. FILEDES_SEGNR entries */
3165 if ((fdes->fd_seg[i].size[0]==0)&&(fdes->fd_seg[i].size[1]==0)){
3166 break; /* end of list */
3167 }
3168 printf("fd_seg[%02x]: addr: %02x%02x%02x size: %02x%02x\n",
3169 i,
3170 fdes->fd_seg[i].addr[0],
3171 fdes->fd_seg[i].addr[1],
3172 fdes->fd_seg[i].addr[2],
3173 fdes->fd_seg[i].size[0],fdes->fd_seg[i].size[1]);
3174 }
3175 if (corrupt){
3176 printf("*** corrupt file size/allocation size ***\n");
3177 }
3178 printf("\n");
3179 }else{
3180 printf("%02x%02x ",fdes->fd_own[0],fdes->fd_own[1]);
3181 printatt(fdes->fd_att);
3182 printf(" %02i-%02i-%02i",
3183 fdes->fd_creat[0]%100,fdes->fd_creat[1]%100,fdes->fd_creat[2]%100);
3184 printf(" %02i-%02i-%02i %02i:%02i",
3185 fdes->fd_dat[0]%100,fdes->fd_dat[1]%100,fdes->fd_dat[2]%100,
3186 fdes->fd_dat[3]%100,fdes->fd_dat[4]%100);
3187 printf(" %02x",fdes->fd_link);
3188 printf(" %08x",fsize);
3189 }
3190
3191 if (corrupt)
3192 return -7; /* corrupt */
3193 return fsize;
3194 }
3195
3196 /* MDR-DOS */
3197 void
mdr_printdirent(struct mdr_dirent_s * direntp)3198 mdr_printdirent(struct mdr_dirent_s *direntp)
3199 {
3200 u_int i,iold,istart;
3201 u_int pblk,pblkold,pblkstart;
3202 u_int fsize;
3203 u_int cnr,contcl;
3204
3205 if (direntp==NULL){
3206 return;
3207 }
3208
3209 /* check if entry not used */
3210 if (direntp->name[0]==0){
3211 printf("*** unused directory entry ***\n");
3212 return;
3213 }
3214 printf("name: %s\n",direntp->name); /* XXX no length check */
3215 printf("type: %c%c%c%c\n",
3216 direntp->type[0],direntp->type[1],direntp->type[2],direntp->type[3]);
3217 fsize=(direntp->size[0]<<24)
3218 +(direntp->size[1]<<16)
3219 +(direntp->size[2]<<8)
3220 +direntp->size[3];
3221 printf("size: %08x (%u bytes)\n",fsize,fsize);
3222 cnr=mdr_countclu(direntp,MDR_FILECLNR,&contcl);
3223 printf("alloc: %08x (%u bytes)\n",
3224 cnr*curpart->mdr_clustersize*curpart->blksiz,
3225 cnr*curpart->mdr_clustersize*curpart->blksiz);
3226 printf("conti: %08x (%u bytes)\n",
3227 contcl*curpart->mdr_clustersize*curpart->blksiz,
3228 contcl*curpart->mdr_clustersize*curpart->blksiz);
3229 printf("back: %02i-%02i-%02i %02i:%02i:%02i\n",
3230 direntp->back[0]%100,direntp->back[1]%100,direntp->back[2]%100,
3231 direntp->back[3]%100,direntp->back[4]%100,direntp->back[5]%100);
3232 printf("modif: %02i-%02i-%02i %02i:%02i:%02i\n",
3233 direntp->modif[0]%100,direntp->modif[1]%100,direntp->modif[2]%100,
3234 direntp->modif[3]%100,direntp->modif[4]%100,direntp->modif[5]%100);
3235 /* scan clusters */
3236 pblkstart=0; /* invalid pblkstart */
3237 for (i=0;i<MDR_FILECLNR;i++){
3238 pblk=(direntp->clist[i][0]<<8)+direntp->clist[i][1];
3239 if (pblk==0){
3240 /* end if clist */
3241 /* check if segment present */
3242 if (pblkstart!=0){ /* valid pblkstart? */
3243 if (iold>istart){
3244 printf("clist[%04x-%04x] -> %04x-%04x\n",
3245 istart,iold,pblkstart,pblkold);
3246 }else{
3247 printf("clist[%04x] -> %04x\n",
3248 istart,pblkstart);
3249 }
3250 }
3251 break;
3252 }
3253 /* Note: pblk!=0 now!!! */
3254 if (pblkstart==0){ /* invalid pblkstart? */
3255 /* new segment start */
3256 pblkstart=pblk;
3257 istart=i;
3258 }else if (pblk!=pblkold+1){
3259 /* pblk is not contiguous => end of current segment */
3260 if (iold>istart){
3261 printf("clist[%04x-%04x] -> %04x-%04x\n",
3262 istart,iold,pblkstart,pblkold);
3263 }else{
3264 printf("clist[%04x] -> %04x\n",
3265 istart,pblkstart);
3266 }
3267 /* new segment start */
3268 pblkstart=pblk;
3269 istart=i;
3270 }
3271 /* save current block */
3272 pblkold=pblk;
3273 iold=i;
3274 }
3275 printf("\n");
3276 }
3277
3278 /* QDOS */
3279 void
qdos_printfdes(struct qdos_dir_s * dirp,struct qdos_rib_s * ribp)3280 qdos_printfdes(struct qdos_dir_s *dirp,struct qdos_rib_s *ribp)
3281 {
3282 u_int i;
3283 u_int off,size;
3284 u_int fsize,cnr,contcl;
3285
3286 if (dirp!=NULL){
3287 /* check if entry not used */
3288 if (dirp->dir_nm[0]==0){
3289 printf("*** unused directory entry ***\n");
3290 return;
3291 }
3292 printf("dir_nm: ");
3293 printnstr(dirp->dir_nm,8);
3294 printf(".");
3295 printnstr(dirp->dir_sx,2);
3296 printf("\ndir_rb: %02x%02x\n",dirp->dir_rb[0],dirp->dir_rb[1]);
3297 printf("dir_at: %02x%02x (",dirp->dir_at[0],dirp->dir_at[1]);
3298 qdos_printatt0(dirp->dir_at[0]);
3299 printf(")\n");
3300 }
3301 if (ribp!=NULL){
3302 printf("rib_lb: %02x%\n",ribp->rib_lb);
3303 printf("rib_sl: %02x%02x\n",ribp->rib_sl[0],ribp->rib_sl[1]);
3304 printf("rib_la: %02x%02x\n",ribp->rib_la[0],ribp->rib_la[1]);
3305 printf("rib_sa: %02x%02x\n",ribp->rib_sa[0],ribp->rib_sa[1]);
3306 /* scan segments */
3307 for (i=0;i<QDOS_RIB_SDWNR;i++){
3308 qdos_getseg(ribp,i,&off,&size);
3309 if (size==0){
3310 /* end of list */
3311 printf("seg[%02x]: END TOTSIZ:%04x\n",i,off);
3312 break;
3313 }else{
3314 printf("seg[%02x]: SIZ:%02x OFF:%04x\n",i,size,off);
3315 }
3316 }
3317 fsize=qdos_fsize(ribp);
3318 printf("fsize: %06x (%u bytes)\n",fsize,fsize);
3319 cnr=qdos_countseg(ribp,QDOS_RIB_SDWNR,&contcl);
3320 printf("alloc: %06x (%u bytes)\n",
3321 cnr*QDOS_CSIZE*curpart->blksiz,
3322 cnr*QDOS_CSIZE*curpart->blksiz);
3323 /* Note: first block of file allocation is used for RIB!!! */
3324 printf("contig: %06x (%u bytes)\n",
3325 contcl*QDOS_CSIZE*curpart->blksiz-curpart->blksiz,
3326 contcl*QDOS_CSIZE*curpart->blksiz-curpart->blksiz);
3327 printf("\n");
3328 }
3329 }
3330
3331
3332
3333 /* general */
3334 /* Note: blocks in filesystem blksiz!!! */
3335 /* Note: we allow lseek within allocated data-area of file!!! */
3336 int
filelseek(union genfdes_u * fp,u_int lblk,u_int * contblksp)3337 filelseek(union genfdes_u *fp,u_int lblk,u_int *contblksp)
3338 {
3339
3340 if (fp==NULL){
3341 return -1;
3342 }
3343
3344 if (curpart->type==PARTTYPE_QDOS){
3345 /* QDOS */
3346 int i;
3347 u_int blknr;
3348 u_int addr,size;
3349 struct qdos_rib_s *ribp;
3350
3351 ribp=&fp->qdos.rib;
3352
3353 lblk++; /* first block of file allocation is used for RIB!!! */
3354
3355 blknr=0; /* block counter */
3356 for (i=0;i<QDOS_RIB_SDWNR;i++){
3357 qdos_getseg(ribp,i,&addr,&size);
3358 if (size==0){
3359 /* end of list but lblk not reached */
3360 return -1;
3361 }
3362 size*=QDOS_CSIZE;
3363 addr*=QDOS_CSIZE;
3364
3365 if (blknr+size>lblk){
3366 /* lblk is within this segment */
3367 break; /* found */
3368 }
3369 blknr+=size;
3370 }
3371 if (i>=QDOS_RIB_SDWNR){
3372 /* end of list but lblk not reached */
3373 return -1; /* beyond end of file! */
3374 }
3375 if (contblksp!=NULL){
3376 u_int oldaddr,oldsize,addr2,size2,cblknr;
3377
3378 /* number of following contiguous blocks in this segment */
3379 cblknr=blknr+size-lblk;
3380 /* scan following segments if also contiguous */
3381 oldaddr=addr;
3382 oldsize=size;
3383 i++; /* must start scan with next segment! */
3384 for (;i<QDOS_RIB_SDWNR;i++){
3385 qdos_getseg(ribp,i,&addr2,&size2);
3386 if (size2==0){
3387 /* end of list */
3388 break;
3389 }
3390 size2*=QDOS_CSIZE;
3391 addr2*=QDOS_CSIZE;
3392 if (addr2!=oldaddr+oldsize){
3393 /* not contiguous to previous segment */
3394 break;
3395 }
3396 cblknr+=size2; /* contiguous */
3397 oldaddr=addr2;
3398 oldsize=size2;
3399 }
3400 *contblksp=cblknr;
3401 }
3402 return addr+lblk-blknr; /* physical start block */
3403 }else if (curpart->type!=PARTTYPE_OS9MDR){
3404 err_print("filelseek: invalid partition type\n");
3405 return -1;
3406 }
3407 /* now OS9 or MDR-DOS */
3408
3409 if (!curpart->mdr){
3410 /* OS9 */
3411 int i;
3412 u_int blknr;
3413 u_int addr,size;
3414 struct filedes_s *fdes;
3415
3416 fdes=&fp->os9;
3417
3418 blknr=0; /* block counter */
3419 for (i=0;i<FILEDES_SEGNR;i++){ /* max. FILEDES_SEGNR entries */
3420 getseg(&fdes->fd_seg[i],&addr,&size);
3421 if (size==0){
3422 /* end of list but lblk not reached */
3423 return -1;
3424 }
3425 if (blknr+size>lblk){
3426 /* lblk is within this segment */
3427 break; /* found */
3428 }
3429 blknr+=size;
3430 }
3431 if (i>=FILEDES_SEGNR){
3432 /* end of list but lblk not reached */
3433 return -1; /* beyond end of file! */
3434 }
3435 if (contblksp!=NULL){
3436 u_int oldaddr,oldsize,addr2,size2,cblknr;
3437
3438 /* number of following contiguous blocks in this segment */
3439 cblknr=blknr+size-lblk;
3440 /* scan following segments if also contiguous */
3441 oldaddr=addr;
3442 oldsize=size;
3443 for (;i<FILEDES_SEGNR;i++){
3444 getseg(&fdes->fd_seg[i],&addr2,&size2);
3445 if (size2==0){
3446 /* end of list */
3447 break;
3448 }
3449 if (addr2!=oldaddr+oldsize){
3450 /* not contiguous to previous segment */
3451 break;
3452 }
3453 cblknr+=size2; /* contiguous */
3454 oldaddr=addr2;
3455 oldsize=size2;
3456 }
3457 *contblksp=cblknr;
3458 }
3459 return addr+lblk-blknr; /* physical start block */
3460 }else{
3461 /* MDR-DOS */
3462 u_int c;
3463 u_int fclu;
3464 u_int clu;
3465 u_int blknr;
3466 struct mdr_dirent_s *direntp;
3467
3468 direntp=(struct mdr_dirent_s *)fp;
3469
3470 /* index for logical block lblk in direntp->clist */
3471 fclu=lblk/curpart->mdr_clustersize;
3472 if (fclu>=MDR_FILECLNR){
3473 return -1; /* beyond end of file! */
3474 }
3475 /* important: must check number of used&&valid cluster entries in clist!!! */
3476 for (c=0;c<MDR_FILECLNR;c++){
3477 clu=(direntp->clist[c][0]<<8)+(direntp->clist[c][1]);
3478 if (clu==0){
3479 break; /* end of clist */
3480 }
3481 }
3482 if (fclu>=c){
3483 return -1; /* beyond end of file! */
3484 }
3485
3486 /* physical cluster */
3487 clu=(direntp->clist[fclu][0]<<8)+(direntp->clist[fclu][1]);
3488 /* Note: now, clu!=0 and valid after check above! */
3489 /* physical block */
3490 blknr=curpart->mdr_clustersize*clu
3491 +lblk%curpart->mdr_clustersize;
3492 if (contblksp!=NULL){
3493 u_int i,newclu,oldclu,size;
3494
3495 /* number of remaining blocks following lblk in cluster fclu: */
3496 size=curpart->mdr_clustersize-(lblk%curpart->mdr_clustersize);
3497 /* scan starting at cluster fclu+1: */
3498 oldclu=clu; /* physical cluster for fclu */
3499 for (i=fclu+1;i<MDR_FILECLNR;i++){
3500 /* physical cluster for i */
3501 newclu=(direntp->clist[i][0]<<8)+(direntp->clist[i][1]);
3502 if ((newclu==0)||(newclu!=oldclu+1)){
3503 break; /* end of contiguous physical blocks */
3504 }
3505 size+=curpart->mdr_clustersize;
3506 oldclu++;
3507 }
3508 /* number of following contiguous blocks */
3509 *contblksp=size;
3510 }
3511
3512 return blknr; /* physical start block */
3513 }
3514 }
3515
3516 /* general */
3517 /* Note: blocks in filesystem blksiz!!! */
3518 int
fileread(union genfdes_u * fp,void * buf,u_int lblkstart,u_int lblknr)3519 fileread(union genfdes_u *fp,void *buf,u_int lblkstart,u_int lblknr)
3520 {
3521 u_int i;
3522 int blk;
3523 u_int contblks;
3524
3525 if ((fp==NULL)||(buf==NULL)){
3526 return -1;
3527 }
3528
3529 /* Note: filelseek below will return error for blocks that are beyond file allocation! */
3530 #ifdef FILEDEBUG
3531 printf("fileread: lblkstart=%06x lblknr=%06x\n",
3532 lblkstart,lblknr);
3533 #endif
3534
3535 contblks=0;
3536 for (i=0;i<lblknr;i+=contblks){
3537 /* seek logical block */
3538 blk=filelseek(fp,lblkstart+i,&contblks);
3539 if (contblks==0){
3540 /* should not happen! */
3541 err_print("fileread: internal error: contblks==0\n");
3542 return -1;
3543 }
3544 #ifdef FILEDEBUG
3545 printf("fileread: lblk=%06x -> blk=%06x contblks=%06x\n",
3546 lblkstart+i,blk,contblks);
3547 #endif
3548 if ((blk<0)||(contblks==0)){
3549 return i; /* number of blocks read */
3550 }
3551 /* truncate if necessary */
3552 if ((lblknr-i)<contblks){
3553 contblks=lblknr-i;
3554 #ifdef FILEDEBUG
3555 printf("fileread: truncated: contblks=%06x\n",contblks);
3556 #endif
3557 }
3558 /* read blocks */
3559 if (READBLOCK_CURPART(blk,((char *)buf)+i*curpart->blksiz,contblks)<0){
3560 return i; /* number of blocks read */
3561 }
3562 }
3563
3564 return lblknr; /* number of blocks read */
3565 }
3566
3567 /* general */
3568 /* Note: blocks in filesystem blksiz!!! */
3569 int
filewrite(union genfdes_u * fp,void * buf,u_int lblkstart,u_int lblknr)3570 filewrite(union genfdes_u *fp,void *buf,u_int lblkstart,u_int lblknr)
3571 {
3572 u_int i;
3573 int blk;
3574 u_int contblks;
3575
3576 if ((fp==NULL)||(buf==NULL)){
3577 return -1;
3578 }
3579
3580 /* Note: filelseek below will return error for blocks that are beyond file allocation! */
3581 #ifdef FILEDEBUG
3582 printf("filewrite: lblkstart=%06x lblknr=%06x\n",
3583 lblkstart,lblknr);
3584 #endif
3585
3586 contblks=0;
3587 for (i=0;i<lblknr;i+=contblks){
3588 /* seek logical block */
3589 blk=filelseek(fp,lblkstart+i,&contblks);
3590 #ifdef FILEDEBUG
3591 printf("filewrite: lblk=%06x -> blk=%06x contblks=%06x\n",
3592 lblkstart+i,blk,contblks);
3593 #endif
3594 if ((blk<0)||(contblks==0)){
3595 return i; /* number of blocks written */
3596 }
3597 /* truncate if necessary */
3598 if ((lblknr-i)<contblks){
3599 contblks=lblknr-i;
3600 #ifdef FILEDEBUG
3601 printf("filewrite: truncated: contblks=%06x\n",contblks);
3602 #endif
3603 }
3604 /* write blocks */
3605 if (WRITEBLOCK_CURPART(blk,((char *)buf)+i*curpart->blksiz,contblks)<0){
3606 return i; /* number of blocks written */
3607 }
3608 }
3609
3610 return lblknr; /* number of blocks written */
3611 }
3612
3613
3614
3615 /* OS9 */
3616 int
filedel(u_int fdessec)3617 filedel(u_int fdessec)
3618 {
3619 static struct filedes_s fdes;
3620 struct seg_s fdesseg;
3621 static u_int bstart;
3622
3623 if (curpart->type!=PARTTYPE_OS9MDR){
3624 return -1;
3625 }
3626 if (curpart->mdr){
3627 return -1;
3628 }
3629
3630 /* read file descriptor */
3631 if (READBLOCK_CURPART(fdessec,&fdes,1)<0){
3632 err_print("filedel: cannot read file descriptor\n");
3633 return -1;
3634 }
3635
3636 #ifdef DEBUG
3637 printf("filedel:\n");
3638 printfiledes(curpart,&fdes,1);
3639 #endif
3640
3641 /* warn if bootfile */
3642 getseg(&fdes.fd_seg[0],&bstart,NULL);
3643 if ((curpart->bootsize!=0)&&(bstart==curpart->bootsec)){
3644 err_print("filedel: warning: was bootfile\n");
3645 /* XXX it�s too late if deldirent already called!!! */
3646 }
3647 /* warn if partition table file */
3648 if ((curpart->pnr!=0)&&(bstart==curpart->ptabsec)){
3649 err_print("filedel: warning: was partfile\n");
3650 /* XXX it�s too late if deldirent already called!!! */
3651 }
3652
3653 /* check if link count <=1 (0 also OK) */
3654 if (fdes.fd_link<=1){
3655
3656 /* delete data segments */
3657 if (markbitmap(&(fdes.fd_seg[0]),FILEDES_SEGNR,0)<0){
3658 err_print("filedel: cannot delete segments\n");
3659 return -1;
3660 }
3661
3662 /* delete file descriptor as well! */
3663 /* set file descriptor block */
3664 /* delete whole cluster */
3665 setseg(&fdesseg,fdessec,curpart->clustersize);
3666 /* delete file descriptor block */
3667 if (markbitmap(&fdesseg,1,0)<0){
3668 err_print("filedel: cannot delete file descriptor\n");
3669 return -1;
3670 }
3671 }else{
3672 /* linked elsewhere, must decrement link count only! */
3673
3674 fdes.fd_link--; /* unlink */
3675 /* write updated file descriptor */
3676 if (WRITEBLOCK_CURPART(fdessec,&fdes,1)<0){
3677 err_print("filedel: cannot write updated file descriptor\n");
3678 return -1;
3679 }
3680 }
3681
3682 /* don't forget to delete directory entry */
3683
3684 return 0;
3685 }
3686
3687 /* MDR-DOS */
3688 int
mdr_filedel(struct mdr_dirent_s * direntp)3689 mdr_filedel(struct mdr_dirent_s *direntp)
3690 {
3691
3692 if (curpart->type!=PARTTYPE_OS9MDR){
3693 return -1;
3694 }
3695 if (!curpart->mdr){
3696 return -1;
3697 }
3698
3699 #ifdef DEBUG
3700 printf("mdr_filedel\n");
3701 #endif
3702
3703 /* delete clusters */
3704 if (mdr_markbitmap(direntp,MDR_FILECLNR,0)<0){
3705 err_print("mdr_filedel: cannot delete clusters\n");
3706 return -1;
3707 }
3708
3709 return 0;
3710
3711 /* don't forget to delete directory entry */
3712 }
3713
3714 /* QDOS */
3715 int
qdos_filedel(struct qdos_rib_s * qrib)3716 qdos_filedel(struct qdos_rib_s *qrib)
3717 {
3718
3719 if (curpart->type!=PARTTYPE_QDOS){
3720 return -1;
3721 }
3722
3723 #ifdef DEBUG
3724 printf("qdos_filedel\n");
3725 #endif
3726
3727 /* delete segments */
3728 /* Note: first block of file allocation is used for RIB!!! */
3729 if (qdos_markbitmap(qrib,QDOS_RIB_SDWNR,0)<0){
3730 err_print("qdos_filedel: cannot delete segments\n");
3731 return -1;
3732 }
3733
3734 return 0;
3735
3736 /* don't forget to delete directory entry */
3737 }
3738
3739
3740
3741 /* OS9 */
3742 int
filecreat(struct filedes_s * fdes,u_int blknr,int extend)3743 filecreat(struct filedes_s *fdes,u_int blknr,int extend)
3744 {
3745 u_int fdesblk;
3746 u_int s;
3747
3748 if (curpart->type!=PARTTYPE_OS9MDR){
3749 return -1;
3750 }
3751 if (curpart->mdr){
3752 return -1;
3753 }
3754
3755 if (fdes==NULL){
3756 return -1;
3757 }
3758
3759 /* at least one block */
3760 if (blknr==0)
3761 blknr=1;
3762
3763 fdesblk=0;
3764
3765 /* new file? */
3766 if (!extend){
3767 /* create segment list */
3768 /* allocate one extra block for file descriptor (see below)!!! */
3769 /* Note: to allocate the file descriptor this way is not mandatory but convenient! */
3770 if (findfreelist(&(fdes->fd_seg[0]),FILEDES_SEGNR,0,blknr+1)<0){
3771 err_print("filecreat: cannot create segment list\n");
3772 return -1;
3773 }
3774 }else{
3775 int i;
3776 u_int size;
3777
3778 /* extend segment list */
3779 /* find end of segment list in file descriptor */
3780 for (i=0;i<FILEDES_SEGNR;i++){
3781 getseg(&(fdes->fd_seg[i]),NULL,&size);
3782 if (size==0){
3783 /* found free segment */
3784 break;
3785 }
3786 }
3787 if (i>=FILEDES_SEGNR){
3788 /* no free segment */
3789 err_print("filecreat: no free segment for extension\n");
3790 return -1;
3791 }
3792 /* now i is first free index */
3793 if (i==0){
3794 /* first segment is free => create segment list */
3795 if (findfreelist(&(fdes->fd_seg[0]),FILEDES_SEGNR,0,blknr)<0){
3796 err_print("filecreat: cannot create segment list\n");
3797 return -1;
3798 }
3799 }else{
3800 /* append blocks */
3801 if (appendfreelist(&(fdes->fd_seg[i-1]),FILEDES_SEGNR-i+1,blknr)<0){
3802 err_print("filecreat: cannot extend segment list\n");
3803 return -1;
3804 }
3805 }
3806 }
3807
3808 #ifdef DEBUG
3809 printf("filecreat: blknr: %06x\n",blknr);
3810 printfiledes(curpart,fdes,1);
3811 #endif
3812
3813 /* allocate segments */
3814 if (markbitmap(&(fdes->fd_seg[0]),FILEDES_SEGNR,1)<0){
3815 err_print("filecreat: cannot allocate segments\n");
3816 return -1;
3817 }
3818
3819 /* new file? */
3820 if (!extend){
3821 /* Note: we have allocated blknr+1 above! */
3822 /* get new file descriptor block: take first block in first segment */
3823 getseg(&(fdes->fd_seg[0]),&fdesblk,&s);
3824
3825 /* remove this block from file-data area */
3826 if (s==0){
3827 /* XXX should never happen!!! */
3828 err_print("filecreat: internal error: s==0\n");
3829 return -1;
3830 }
3831 s--;
3832 if (s==0){
3833 u_int i,startblk,size;
3834
3835 /* must shift remaining segments */
3836 for (i=1;i<FILEDES_SEGNR-1;i++){
3837 getseg(&fdes->fd_seg[i+1],&startblk,&size);
3838 setseg(&fdes->fd_seg[i],startblk,size);
3839 }
3840 /* clear last segment */
3841 setseg(&fdes->fd_seg[i],0,0);
3842 }else{
3843 setseg(&fdes->fd_seg[0],fdesblk+1,s); /* see s-- above! */
3844 }
3845 }
3846
3847 return fdesblk;
3848
3849 /* don't forget to set elements of file descriptor */
3850 /* don't forget to write file descriptor */
3851 /* don't forget to create directory entry! */
3852 }
3853
3854 /* MDR-DOS */
3855 int
mdr_filecreat(struct mdr_dirent_s * direntp,u_int blknr,int extend)3856 mdr_filecreat(struct mdr_dirent_s *direntp,u_int blknr,int extend)
3857 {
3858
3859 if (curpart->type!=PARTTYPE_OS9MDR){
3860 return -1;
3861 }
3862 if (!curpart->mdr){
3863 return -1;
3864 }
3865
3866 if (direntp==NULL){
3867 return -1;
3868 }
3869
3870 /* at least one block */
3871 if (blknr==0)
3872 blknr=1;
3873
3874 /* new file? */
3875 if (!extend){
3876 /* create new direntp->clist */
3877 if (mdr_findfreelist(direntp,0,MDR_FILECLNR,0,blknr)<0){
3878 err_print("mdr_filecreat: cannot allocate space\n");
3879 return -1;
3880 }
3881 }else{
3882 u_int fclu;
3883
3884 /* find end cluster index of file */
3885 for (fclu=0;fclu<MDR_FILECLNR;fclu++){
3886 if ((direntp->clist[fclu][0]==0)&&(direntp->clist[fclu][1]==0)){
3887 break; /* found end */
3888 }
3889 }
3890 /* no index free? */
3891 if (fclu==MDR_FILECLNR){
3892 err_print("mdr_filecreat: no cluster free in directory entry\n");
3893 return -1;
3894 }
3895 /* now fclu is first free index */
3896 if (fclu==0){
3897 /* first cluster is free => create cluster list */
3898 if (mdr_findfreelist(direntp,0,MDR_FILECLNR,0,blknr)<0){
3899 err_print("mdr_filecreat: cannot allocate space\n");
3900 return -1;
3901 }
3902 }else{
3903 /* append blocks */
3904 if (mdr_appendfreelist(direntp,fclu-1,MDR_FILECLNR-fclu+1,blknr)<0){
3905 err_print("mdr_filecreat: cannot append space\n");
3906 return -1;
3907 }
3908 }
3909 }
3910
3911 #ifdef DEBUG
3912 printf("mdr_filecreat: blknr: %06x\n",blknr);
3913 #endif
3914
3915 /* allocate in bitmp */
3916 if (mdr_markbitmap(direntp,MDR_FILECLNR,1)<0){
3917 err_print("mdr_filecreat: cannot allocate in bitmap\n");
3918 return -1;
3919 }
3920 return 0;
3921
3922 /* don't forget to set elements of direntp */
3923 /* don't forget to create directory entry! */
3924 }
3925
3926 /* QDOS */
3927 int
qdos_filecreat(struct qdos_rib_s * ribp,u_int blknr,int extend)3928 qdos_filecreat(struct qdos_rib_s *ribp,u_int blknr,int extend)
3929 {
3930
3931 if (curpart->type!=PARTTYPE_QDOS){
3932 return -1;
3933 }
3934
3935 /* at least one block for data */
3936 if (blknr==0)
3937 blknr=1;
3938
3939 /* new file? */
3940 if (!extend){
3941 /* create segment list */
3942 /* allocate one extra block for RIB!!! */
3943 /* Note: first block of file allocation is used for RIB!!! */
3944 if (qdos_findfreelist(ribp,0,QDOS_RIB_SDWNR,0,blknr+1)<0){
3945 err_print("qdos_filecreat: cannot create segment list\n");
3946 return -1;
3947 }
3948 }else{
3949 int i;
3950 u_int size;
3951
3952 /* extend segment list */
3953 /* find end of segment list in file descriptor */
3954 for (i=0;i<QDOS_RIB_SDWNR;i++){
3955 qdos_getseg(ribp,i,NULL,&size);
3956 if (size==0){
3957 /* found free segment */
3958 break;
3959 }
3960 }
3961 if (i>=QDOS_RIB_SDWNR){
3962 /* no free segment */
3963 err_print("qdos_filecreat: no free segment for extension\n");
3964 return -1;
3965 }
3966 /* now i is first free index */
3967 if (i==0){
3968 /* first segment is free => create segment list */
3969 /* allocate one extra block for RIB!!! */
3970 /* Note: first block of file allocation is used for RIB!!! */
3971 if (qdos_findfreelist(ribp,0,QDOS_RIB_SDWNR,0,blknr+1)<0){
3972 err_print("qdos_filecreat: cannot create segment list\n");
3973 return -1;
3974 }
3975 }else{
3976 /* append blocks */
3977 if (qdos_appendfreelist(ribp,i-1,QDOS_RIB_SDWNR-i+1,blknr)<0){
3978 err_print("qdos_filecreat: cannot extend segment list\n");
3979 return -1;
3980 }
3981 }
3982 }
3983
3984 #ifdef DEBUG
3985 printf("qdos_filecreat: blknr: %06x\n",blknr);
3986 #endif
3987
3988 /* allocate segments */
3989 if (qdos_markbitmap(ribp,QDOS_RIB_SDWNR,1)<0){
3990 err_print("qdos_filecreat: cannot allocate segments\n");
3991 return -1;
3992 }
3993
3994 return 0;
3995
3996 /* don't forget to set elements of RIB */
3997 /* don't forget to write RIB to first allocated block! */
3998 /* don't forget to create directory entry! */
3999 }
4000
4001
4002
4003 /* OS9 */
4004 int
getdir(u_int newdirsec,struct filedes_s * curdirdesp,u_int * curdirsizep)4005 getdir(u_int newdirsec,struct filedes_s *curdirdesp,u_int *curdirsizep)
4006 {
4007
4008 if (curpart->type!=PARTTYPE_OS9MDR){
4009 return -1;
4010 }
4011 if (curpart->mdr){
4012 return -1;
4013 }
4014 if (curdirdesp==NULL){
4015 return -1;
4016 }
4017 if (newdirsec==0){
4018 /* invalid sec for directory file descriptor */
4019 err_print("getdir: invalid directory\n");
4020 return -1;
4021 }
4022
4023 /* read directory file descriptor */
4024 if (READBLOCK_CURPART(newdirsec,curdirdesp,1)<0){
4025 err_print("getdir: READBLOCK_CURPART(newdirsec)\n");
4026 return -1;
4027 }
4028
4029 /* check if directory file */
4030 if ((curdirdesp->fd_att&ATT_D)==0){
4031 err_print("getdir: file is no directory\n");
4032 return -1;
4033 }
4034
4035 if (curdirsizep!=NULL){
4036 *curdirsizep=(curdirdesp->fd_fsize[0]<<24)
4037 +(curdirdesp->fd_fsize[1]<<16)
4038 +(curdirdesp->fd_fsize[2]<<8)
4039 +curdirdesp->fd_fsize[3];
4040 }
4041
4042 return 0;
4043 }
4044
4045
4046
4047 /* OS9 */
4048 /* returns sector of file descriptor */
4049 int
findfile(char * name,int countfree,u_int * freeentp)4050 findfile(char *name,int countfree,u_int *freeentp)
4051 {
4052 static struct filedes_s curdirdes;
4053 u_int curdirsize;
4054 struct dirent_s *curdirp;
4055 u_int blknr;
4056 u_int i;
4057 static char tmpname[FILENAMELEN+1];
4058 u_int startsec;
4059 int countonly,count;
4060
4061 if (curpart->type!=PARTTYPE_OS9MDR){
4062 return -1;
4063 }
4064 if (curpart->mdr)
4065 return -1;
4066
4067 if (name==NULL){
4068 countonly=1;
4069 count=0;
4070 }else{
4071 if((strlen(name)==0)||(strlen(name)>FILENAMELEN)){
4072 return -1;
4073 }
4074 countonly=0;
4075 }
4076
4077 if (getdir(curdirsec,&curdirdes,&curdirsize)<0){
4078 return -1;
4079 }
4080 /* in findfile we allow totally empty directories!!! */
4081 if (curdirsize==0){
4082 if (countonly){
4083 return 0;
4084 }
4085
4086 return -1; /* file not found */
4087 }
4088
4089 /* XXX read whole directory file */
4090
4091 /* read directory file */
4092 /* XXX 32-Bit overflow protection */
4093 blknr=(u_int)((((OFF_T)curdirsize)+((OFF_T)curpart->blksiz-1))
4094 /((OFF_T)curpart->blksiz));
4095
4096 /* allocate memory for directory file */
4097 curdirp=(struct dirent_s *)malloc(blknr*curpart->blksiz);
4098 if (curdirp==NULL){
4099 perror("findfile: malloc");
4100 return -1;
4101 }
4102
4103 /* read directory file */
4104 if (fileread((union genfdes_u *)&curdirdes,(void *)curdirp,0,blknr)!=(int)blknr){
4105 err_print("findfile: fileread(curdirdes)\n");
4106 free((void *)curdirp);
4107 return -1;
4108 }
4109
4110 /* scan directory entries */
4111 for (i=0;i<curdirsize/sizeof(struct dirent_s);i++){
4112 if (curdirp[i].dir_name[0]==0){
4113 /* free entry */
4114 if (countonly){
4115 /* count */
4116 if (countfree){
4117 /* count free entries */
4118 count++;
4119 if (freeentp!=NULL){
4120 *freeentp=i; /* last free entry index */
4121 }
4122 }
4123 }
4124 continue; /* skip entry */
4125 }
4126 /* entry found */
4127 translatename(curdirp[i].dir_name,tmpname);
4128 if (countonly){
4129 /* count */
4130 if (!countfree){
4131 /* count used entries */
4132 /* don't count . and .. */
4133 if ((strcmp(tmpname,".")!=0)&&(strcmp(tmpname,"..")!=0)){
4134 count++;
4135 }
4136 }
4137 }else{
4138 /* compare name */
4139 if (strcasecmp(name,tmpname)==0){
4140 /* name found */
4141 startsec=(curdirp[i].dir_addr[0]<<16)
4142 +(curdirp[i].dir_addr[1]<<8)
4143 +curdirp[i].dir_addr[2];
4144
4145 free((void *)curdirp);
4146 return startsec; /* return sector of file descriptor */
4147 }
4148 }
4149 }
4150
4151 free((void *)curdirp);
4152
4153 if (countonly){
4154 return count;
4155 }
4156
4157 return -1; /* file not found */
4158 }
4159
4160 /* MDR-DOS */
4161 /* returns file number+1 !!! */
4162 /* Note: 0 is used as symbolic value for root directory in findfile3!!! */
4163 int
mdr_findfile(char * name)4164 mdr_findfile(char *name)
4165 {
4166 static struct mdr_dirent_s dirent;
4167 u_int fnr;
4168
4169 if (curpart->type!=PARTTYPE_OS9MDR){
4170 return -1;
4171 }
4172 if (!curpart->mdr){
4173 return -1;
4174 }
4175 if (name==NULL){
4176 return -1;
4177 }
4178
4179 /* scan directory */
4180 /* up to mdr_filenr (and not mdr_dfilenr) */
4181 for (fnr=0;fnr<curpart->mdr_filenr;fnr++){
4182 /* read directory entry */
4183 if (READBLOCK_CURPART(MDR_DIRSTART+fnr*MDR_DIRENTRYSIZE,
4184 (void *)&dirent,MDR_DIRENTRYSIZE)<0){
4185 err_print("mdr_findfile: READBLOCK_CURPART\n");
4186 return -1;
4187 }
4188
4189 /* check if entry not used */
4190 if (dirent.name[0]==0)
4191 continue; /* next */
4192
4193 /* compare name */
4194 if (strcasecmp(name,dirent.name)==0){
4195 /* name found */
4196 return fnr+1;
4197 }
4198 }
4199
4200 return -1; /* file not found */
4201 }
4202
4203 /* QDOS */
4204 /* returns file number+1 !!! */
4205 /* Note: 0 is used as symbolic value for root directory in findfile3!!! */
4206 int
qdos_findfile(char * name)4207 qdos_findfile(char *name)
4208 {
4209 u_int fnr;
4210 u_char dirbuf[QDOS_DIRSIZE*QDOS_BLOCKSIZE];
4211 struct qdos_dir_s *qdp;
4212 int i;
4213 char qname[11],dname[11]; /* NNNNNNNNSS with terminating '\0' */
4214
4215 if (curpart->type!=PARTTYPE_QDOS){
4216 return -1;
4217 }
4218 if (name==NULL){
4219 return -1;
4220 }
4221
4222 /* read directory */
4223 if (READBLOCK_CURPART(QDOS_DIRSTART,(void *)dirbuf,QDOS_DIRSIZE)<0){
4224 err_print("qdos_findfile: READBLOCK_CURPART\n");
4225 return -1;
4226 }
4227 qdp=(struct qdos_dir_s *)dirbuf;
4228
4229 /* convert name into QDOS-conformant name */
4230 qdos_makefname(name,qname);
4231
4232 /* scan directory */
4233 for (fnr=0;fnr<QDOS_DIRENTRYNR;fnr++){
4234 /* check if entry not used */
4235 if (qdp[fnr].dir_nm[0]==QDOS_DIR_VACANT){
4236 /* vacant directory entry */
4237 continue; /* next */
4238 }
4239 if (qdp[fnr].dir_nm[0]==QDOS_DIR_DELETED){
4240 /* deleted directory entry */
4241 continue; /* next */
4242 }
4243
4244 /* get file name */
4245 /* Note: dir_sx[2] directly follows dir_nm[8] in struct qdos_dir_s!!! */
4246 for (i=0;i<10;i++){
4247 dname[i]=qdp[fnr].dir_nm[i];
4248 }
4249 dname[10]='\0'; /* terminate string */
4250
4251 /* compare name */
4252 if (strcasecmp(qname,dname)==0){
4253 /* name found */
4254 return fnr+1;
4255 }
4256 }
4257
4258 return -1; /* file not found */
4259 }
4260
4261
4262
4263 /* OS9 */
4264 int
deldirent(char * name,int dir)4265 deldirent(char *name,int dir)
4266 {
4267 static struct filedes_s curdirdes;
4268 u_int curdirsize;
4269 static struct filedes_s fdes;
4270 struct dirent_s *curdirp;
4271 static char tmpname[FILENAMELEN+1];
4272 u_int blknr;
4273 u_int i;
4274 u_int startsec;
4275 u_int dirblk;
4276
4277 if (curpart->type!=PARTTYPE_OS9MDR){
4278 return -1;
4279 }
4280 if (curpart->mdr){
4281 return -1;
4282 }
4283
4284 if ((name==NULL)||(strlen(name)==0)){
4285 return -1;
4286 }
4287
4288 /* check for "." and ".." */
4289 if ((strcmp(name,".")==0)||(strcmp(name,"..")==0)){
4290 err_print("deldirent: . or .. not allowed\n");
4291 return -1;
4292 }
4293
4294 if (getdir(curdirsec,&curdirdes,&curdirsize)<0){
4295 return -1;
4296 }
4297 /* XXX read whole directory file */
4298 if (curdirsize==0){
4299 err_print("deldirent: directoy empty\n");
4300 return -1;
4301 }
4302
4303 /* read directory file */
4304 /* XXX 32-Bit overflow protection */
4305 blknr=(u_int)((((OFF_T)curdirsize)+((OFF_T)curpart->blksiz-1))
4306 /((OFF_T)curpart->blksiz));
4307
4308 /* allocate memory for directory file */
4309 curdirp=(struct dirent_s *)malloc(blknr*curpart->blksiz);
4310 if (curdirp==NULL){
4311 perror("deldirent: malloc");
4312 return -1;
4313 }
4314
4315 /* read directory file */
4316 if (fileread((union genfdes_u *)&curdirdes,(void *)curdirp,0,blknr)!=(int)blknr){
4317 err_print("deldirent: fileread(curdirdes)\n");
4318 free((void *)curdirp);
4319 return -1;
4320 }
4321
4322 /* scan directory entries */
4323 for (i=0;i<curdirsize/sizeof(struct dirent_s);i++){
4324 if (curdirp[i].dir_name[0]==0){
4325 continue; /* skip entry */
4326 }
4327 translatename(curdirp[i].dir_name,tmpname);
4328 if (strcasecmp(name,tmpname)==0){
4329 /* name found */
4330 startsec=(curdirp[i].dir_addr[0]<<16)
4331 +(curdirp[i].dir_addr[1]<<8)
4332 +curdirp[i].dir_addr[2];
4333
4334 /* need to check file type? */
4335 if (dir>=0){
4336 /* read file descriptor */
4337 if (READBLOCK_CURPART(startsec,&fdes,1)<0){
4338 err_print("deldirent: cannot read file descriptor\n");
4339 free((void *)curdirp);
4340 return -1;
4341 }
4342 /* check if directory file? */
4343 if (dir){
4344 /* must be directory */
4345 /* check if directory file */
4346 if ((fdes.fd_att&ATT_D)==0){
4347 err_print("deldirent: file is no directory\n");
4348 free((void *)curdirp);
4349 return -1;
4350 }
4351 }else{
4352 /* must not be directory */
4353 /* check if directory file */
4354 if (fdes.fd_att&ATT_D){
4355 err_print("deldirent: file is directory\n");
4356 free((void *)curdirp);
4357 return -1;
4358 }
4359 }
4360 }
4361
4362 /* delete directory entry */
4363 curdirp[i].dir_name[0]=0;
4364
4365 /* write modified directory block */
4366 /* blocksize must be integer multiple of sizeof(struct dirent_s) */
4367 dirblk=(i*sizeof(struct dirent_s))/curpart->blksiz; /* block in file */
4368 if (filewrite((union genfdes_u *)&curdirdes,
4369 ((char *)(curdirp))+dirblk*curpart->blksiz,
4370 dirblk,1)!=1){
4371 err_print("deldirent: cannot write directory\n");
4372 free((void *)curdirp);
4373 return -1;
4374 }
4375
4376 /* update of directory size not necessary */
4377 /* XXX should search for unused blocks at the end and release them */
4378
4379 /* update modif time of current directory */
4380 setdate(&curdirdes,0); /* 0: not creat */
4381 /* write updated file descriptor */
4382 if (WRITEBLOCK_CURPART(curdirsec,&curdirdes,1)<0){
4383 err_print("deldirent: cannot write updated file descriptor\n");
4384 return -1;
4385 }
4386
4387 free((void *)curdirp);
4388 return startsec; /* file whose entry was deleted */
4389 }
4390 }
4391
4392 free((void *)curdirp);
4393
4394 err_print("deldirent: file not found\n");
4395 return -1;
4396 }
4397
4398 /* OS9 */
4399 int
creatdirent(char * name,u_int startsec)4400 creatdirent(char *name,u_int startsec)
4401 {
4402 static struct filedes_s curdirdes;
4403 u_int curdirsize;
4404 int entfree;
4405 u_int freeent;
4406 int space;
4407 static char buf[OS9MAX_BLOCKSIZE];
4408 u_int entblk,entoff;
4409 struct dirent_s *direntp;
4410
4411 if (curpart->type!=PARTTYPE_OS9MDR){
4412 return -1;
4413 }
4414 if (curpart->mdr){
4415 return -1;
4416 }
4417
4418 if ((name==NULL)||(strlen(name)==0)){
4419 return -1;
4420 }
4421 if (strlen(name)>FILENAMELEN){
4422 err_print("creatdirent: name too long\n");
4423 return -1;
4424 }
4425
4426 /* don't refuse . and .. so we can use creatdirent for them!!! */
4427
4428 /* check if file with this name already exists */
4429 if (findfile(name,0,NULL)>=0){
4430 err_print("creatdirent: name already used\n");
4431 return -1;
4432 }
4433
4434 /* check if startsec valid */
4435 if (startsec>=curpart->totsize){
4436 err_print("creatdirent: invalid startsec\n");
4437 return -1;
4438 }
4439
4440 /* see how many entries free in current directory */
4441 entfree=findfile(NULL,1,&freeent);
4442 if (entfree<0){
4443 err_print("creatdirent: findfile\n");
4444 return -1;
4445 }
4446
4447 if (getdir(curdirsec,&curdirdes,&curdirsize)<0){
4448 return -1;
4449 }
4450
4451 #ifdef DEBUG
4452 printf("creatdirent: entfree: %i freeent: %06x\n",entfree,freeent);
4453 printfiledes(curpart,&curdirdes,1);
4454 #endif
4455
4456 if (entfree>0){
4457 /* free entry found */
4458 #ifdef DEBUG
4459 printf("creatdirent: free entry found\n");
4460 #endif
4461
4462 /* read directory block with free entry */
4463 entblk=(freeent*sizeof(struct dirent_s))/curpart->blksiz;
4464 /* read entblk from current directory file */
4465 if (fileread((union genfdes_u *)&curdirdes,buf,entblk,1)!=1){
4466 err_print("creatdirent: fileread(curdirdes)\n");
4467 return -1;
4468 }
4469
4470 /* entry index offset in block */
4471 entoff=((freeent*sizeof(struct dirent_s))%curpart->blksiz)
4472 /sizeof(struct dirent_s);
4473 }else{
4474 /* no free entries found */
4475 #ifdef DEBUG
4476 printf("creatdirent: no free entry found\n");
4477 #endif
4478
4479 /* see if space in last segment is left in current directory */
4480 space=(int)countseg(&(curdirdes.fd_seg[0]),FILEDES_SEGNR,NULL)*curpart->blksiz
4481 -curdirsize;
4482 /* curdirsize should be integer multiple of sizeof(struct dirent_s) */
4483 if ((curdirsize%sizeof(struct dirent_s)!=0)||(space<0)){
4484 /* should not happen */
4485 err_print("creatdirent: directory size corrupt\n");
4486 return -1;
4487 }
4488
4489 if (space>0){
4490 /* free space */
4491 #ifdef DEBUG
4492 printf("creatdirent: free space: %06x\n",space);
4493 #endif
4494
4495 /* read directory block corresponding to curdirsize+1 */
4496 /* note: fileread doesn't check for block outside official file size! */
4497 /* as long as it is within the file's allocated space!!! */
4498 entblk=(curdirsize+1)/curpart->blksiz;
4499 /* read entblk from current directory file */
4500 if (fileread((union genfdes_u *)&curdirdes,buf,entblk,1)!=1){
4501 err_print("creatdirent: fileread(curdirdes)\n");
4502 return -1;
4503 }
4504
4505 /* entry index offset in block */
4506 entoff=(curdirsize%curpart->blksiz)/sizeof(struct dirent_s);
4507
4508 /* the following is probably not necessary */
4509 /* clear rest of block */
4510 /* note: 0 => directory entry free */
4511 bzero(buf+(curdirsize%curpart->blksiz),
4512 curpart->blksiz-(curdirsize%curpart->blksiz));
4513 }else{
4514 /* no free space */
4515 #ifdef DEBUG
4516 printf("creatdirent: no free space\n");
4517 #endif
4518
4519 /* extend directory file */
4520 /* XXX DIRBLKS blocks */
4521 if (filecreat(&curdirdes,DIRBLKS,1)<0){ /* 1:extend */
4522 err_print("creatdirent: cannot extend directory file\n");
4523 return -1;
4524 }
4525
4526 /* new entry is at beginning of block corresponding to curdirsize+1 */
4527 /* no need to load block from disk */
4528 entblk=(curdirsize+1)/curpart->blksiz;
4529
4530 /* entry index offset in block */
4531 entoff=0; /* first entry in new block */
4532
4533 /* the following is probably not necessary */
4534 /* clear block */
4535 bzero(buf,curpart->blksiz); /* note: 0 => directory entry free */
4536 }
4537
4538 /* update directory size */
4539 curdirsize+=sizeof(struct dirent_s);
4540
4541 /* modify curdirdes.fd_fsize and write to disk */
4542 curdirdes.fd_fsize[0]=curdirsize>>24;
4543 curdirdes.fd_fsize[1]=curdirsize>>16;
4544 curdirdes.fd_fsize[2]=curdirsize>>8;
4545 curdirdes.fd_fsize[3]=curdirsize;
4546 /* XXX update last modified date */
4547
4548 /* write file descriptor of current directory */
4549 if (WRITEBLOCK_CURPART(curdirsec,&curdirdes,1)<0){
4550 err_print("creatdirent: cannot write file descriptor\n");
4551 return -1;
4552 }
4553 }
4554 /* now buf contains block entblk with entry at entoff to be used */
4555 #ifdef DEBUG
4556 printf("creatdirent: entblk: %06x entoff: %02x\n",entblk,entoff);
4557 #endif
4558
4559 /* set new entry at entoff in buf */
4560 direntp=&(((struct dirent_s *)buf)[entoff]);
4561 /* set name */
4562 translatebackname(name,&(direntp->dir_name[0]),
4563 FILENAMELEN);
4564 /* set startsec */
4565 direntp->dir_addr[0]=startsec>>16;
4566 direntp->dir_addr[1]=startsec>>8;
4567 direntp->dir_addr[2]=startsec;
4568 /* write entblk to current directory file */
4569 if (filewrite((union genfdes_u *)&curdirdes,buf,entblk,1)!=1){
4570 err_print("creatdirent: filewrite(curdirdes)\n");
4571 return -1;
4572 }
4573
4574 /* update modif time of current directory */
4575 setdate(&curdirdes,0); /* 0: not creat */
4576 /* write updated file descriptor */
4577 if (WRITEBLOCK_CURPART(curdirsec,&curdirdes,1)<0){
4578 err_print("creatdirent: cannot write updated file descriptor\n");
4579 return -1;
4580 }
4581
4582 /* if name is "..", must increment link count of parent directory??? */
4583 /* XXX */
4584
4585 return 0;
4586 }
4587
4588
4589
4590 /* OS9 */
4591 int
changedir2(char * name)4592 changedir2(char *name)
4593 {
4594 int startsec;
4595 static struct filedes_s curdirdes;
4596
4597 if (curpart->type!=PARTTYPE_OS9MDR){
4598 return -1;
4599 }
4600 if (curpart->mdr)
4601 return -1;
4602
4603 if (name==NULL){
4604 return -1;
4605 }
4606 startsec=findfile(name,0,NULL);
4607 if (startsec<0){
4608 err_print("changedir2: directory not found\n");
4609 return -1;
4610 }
4611 /* check if valid directory: */
4612 if (getdir(startsec,&curdirdes,NULL)<0){
4613 err_print("changedir2: not a directory\n");
4614 return -1;
4615 }
4616 /* change directory: */
4617 curdirsec=startsec;
4618
4619 return 0;
4620 }
4621
4622
4623
4624 /* OS9 */
4625 int
delfile(char * name,int dir)4626 delfile(char *name,int dir)
4627 {
4628 int startsec;
4629 int ret;
4630 u_int savecurdirsec;
4631
4632 if (curpart->type!=PARTTYPE_OS9MDR){
4633 return -1;
4634 }
4635 if (curpart->mdr){
4636 return -1;
4637 }
4638
4639 if (name==NULL){
4640 return -1;
4641 }
4642
4643 /* check if name is directory and check if it is empty */
4644 /* otherwise all files within this directory are lost forever */
4645 /* (if not linked elsewhere), still consuming disk space!!! */
4646 /* see deldirent below!!! */
4647 if (dir>0){
4648 /* save state */
4649 savecurdirsec=curdirsec;
4650
4651 if (changedir2(name)<0){
4652 /* e.g. not a directory! */
4653 err_print("delfile: cannot test directory\n");
4654 return -1;
4655 }
4656 ret=findfile(NULL,0,NULL); /* count used entries (except . and ..) */
4657
4658 /* restore state */
4659 curdirsec=savecurdirsec;
4660
4661 if (ret<0){
4662 err_print("delfile: findfile failed\n");
4663 return -1;
4664 }
4665 if (ret>0){
4666 err_print("delfile: directory not empty\n");
4667 return -1;
4668 }
4669 /* now name is a directory and is empty */
4670
4671 /* now must decrement link count of parent directory ".."??? */
4672 /* XXX */
4673 }
4674
4675 /* delete directory entry */
4676 /* Note: deldirent will not proceed if name is directory but dir==0 (see above)!!! */
4677 startsec=deldirent(name,dir);
4678 if (startsec<0){
4679 err_print("delfile: deldirent failed\n");
4680 return -1;
4681 }
4682
4683 /* unlink or delete file descriptor + data segments */
4684 if (filedel(startsec)<0){
4685 err_print("delfile: filedel failed\n");
4686 return -1;
4687 }
4688
4689 return 0;
4690 }
4691
4692 /* MDR-DOS */
4693 int
mdr_updatefilenr(void)4694 mdr_updatefilenr(void)
4695 {
4696 struct mdr_dirent_s dirent;
4697 int i;
4698
4699 if (curpart->type!=PARTTYPE_OS9MDR){
4700 return -1;
4701 }
4702 if (!curpart->mdr){
4703 return -1;
4704 }
4705
4706 if (curpart->mdr_filenr>curpart->mdr_dfilenr){
4707 /* XXX should never happen! */
4708 err_print("mdr_updatefilenr: mdr_filenr corrupt\n");
4709 curpart->mdr_filenr=curpart->mdr_dfilenr;
4710 }
4711
4712 /* start with mdr_filenr-1 (if >=0) */
4713 for (i=((int)curpart->mdr_filenr)-1;i>=0;i--){
4714 /* read directory entry */
4715 if (READBLOCK_CURPART(MDR_DIRSTART+i*MDR_DIRENTRYSIZE,&dirent,MDR_DIRENTRYSIZE)<0){
4716 err_print("mdr_updatefilenr: cannot read directory\n");
4717 return -1;
4718 }
4719 /* slot unused? */
4720 if (dirent.name[0]=='\0'){
4721 curpart->mdr_filenr=(u_int)i;
4722 }else{
4723 /* first used slot in our scan downwards => end of empty slots */
4724 break;
4725 }
4726 }
4727
4728 /* set curpart->lsn0 */
4729 MDR_LSN0_P(curpart->lsn0)->mdr_fnr[0]=curpart->mdr_filenr>>8;
4730 MDR_LSN0_P(curpart->lsn0)->mdr_fnr[1]=curpart->mdr_filenr&0xff;
4731 /* write updated curpart->lsn0 */
4732 if (WRITEBLOCK_CURPART(0,curpart->lsn0,1)<0){
4733 err_print("mdr_updatefilenr: cannot write updated LSN0\n");
4734 return -1;
4735 }
4736
4737 return 0;
4738 }
4739
4740 /* MDR-DOS */
4741 int
mdr_delfile(char * name)4742 mdr_delfile(char *name)
4743 {
4744 struct mdr_dirent_s dirent;
4745 int fsec,fnr1;
4746
4747 if (curpart->type!=PARTTYPE_OS9MDR){
4748 return -1;
4749 }
4750 if (!curpart->mdr){
4751 return -1;
4752 }
4753
4754 if (name==NULL){
4755 return -1;
4756 }
4757
4758 /* find directory entry for file */
4759 if ((fnr1=mdr_findfile(name))<0){
4760 err_print("mdr_delfile: cannot find file\n");
4761 return -1;
4762 }
4763 fsec=MDR_DIRSTART+(fnr1-1)*MDR_DIRENTRYSIZE;
4764
4765 /* read directory entry */
4766 if (READBLOCK_CURPART(fsec,&dirent,MDR_DIRENTRYSIZE)<0){
4767 err_print("mdr_delfile: cannot read directory\n");
4768 return -1;
4769 }
4770 /* deallocate in bitmap */
4771 if (mdr_filedel(&dirent)<0){
4772 err_print("mdr_delfile: mdr_filedel\n");
4773 return -1;
4774 }
4775
4776 /* delete directory entry */
4777 dirent.name[0]='\0';
4778 /* write dirent */
4779 if (WRITEBLOCK_CURPART(fsec,&dirent,MDR_DIRENTRYSIZE)<0){
4780 err_print("mdr_delfile: cannot write directory entry\n");
4781 return -1;
4782 }
4783
4784 /* update mdr_filenr */
4785 /* Note: might have removed last file behind a gap */
4786 /* => must rescan for new mdr_filenr! */
4787 if (mdr_updatefilenr()<0){
4788 return -1;
4789 }
4790
4791 return 0;
4792 }
4793
4794 /* QDOS */
4795 int
qdos_delfile(char * name)4796 qdos_delfile(char *name)
4797 {
4798 u_char dirbuf[QDOS_DIRSIZE*QDOS_BLOCKSIZE];
4799 struct qdos_dir_s *qbufp;
4800 int fnr1;
4801 u_int ribsec;
4802 struct qdos_rib_s qrib;
4803
4804 if (curpart->type!=PARTTYPE_QDOS){
4805 return -1;
4806 }
4807
4808 /* find directory entry for file */
4809 if ((fnr1=qdos_findfile(name))<0){
4810 err_print("qdos_delfile: cannot find file\n");
4811 return -1;
4812 }
4813
4814 /* read directory */
4815 if (READBLOCK_CURPART(QDOS_DIRSTART,(void *)dirbuf,QDOS_DIRSIZE)<0){
4816 err_print("qdos_delfile: cannot read directory\n");
4817 return -1;
4818 }
4819 qbufp=(struct qdos_dir_s *)dirbuf;
4820
4821 /* read RIB */
4822 ribsec=(qbufp[fnr1-1].dir_rb[0]<<8)+qbufp[fnr1-1].dir_rb[1];
4823 if (ribsec!=0){
4824 if (READBLOCK_CURPART(ribsec,&qrib,1)<0){
4825 err_print("qdos_delfile: cannot read RIB\n");
4826 return -1;
4827 }
4828
4829 /* deallocate */
4830 if (qdos_filedel(&qrib)<0){
4831 err_print("qdos_delfile: qdos_filedel\n");
4832 return -1;
4833 }
4834 }else{
4835 err_print("qdos_delfile: warning: invalid RIB sector\n");
4836 }
4837
4838 /* mark directory entry deleted */
4839 qbufp[fnr1-1].dir_nm[0]=QDOS_DIR_DELETED;
4840 #if 1
4841 qbufp[fnr1-1].dir_nm[1]=QDOS_DIR_DELETED; /* XXX */
4842 #endif
4843
4844 /* write updated directory */
4845 if (WRITEBLOCK_CURPART(QDOS_DIRSTART,(void *)dirbuf,QDOS_DIRSIZE)<0){
4846 err_print("qdos_delfile: cannot write directory\n");
4847 return -1;
4848 }
4849
4850 return 0;
4851 }
4852
4853
4854
4855 /* OS9 */
4856 int
creatfile(char * name,u_int bytesize,int dir,struct filedes_s * tmplt)4857 creatfile(char *name,u_int bytesize,int dir,struct filedes_s *tmplt)
4858 {
4859 int startsec;
4860 static struct filedes_s fdes;
4861 u_int blknr;
4862
4863 if (curpart->type!=PARTTYPE_OS9MDR){
4864 return -1;
4865 }
4866 if (curpart->mdr){
4867 return -1;
4868 }
4869
4870 if ((name==NULL)||(strlen(name)==0)){
4871 return -1;
4872 }
4873 if (strlen(name)>FILENAMELEN){
4874 err_print("creatfile: name too long\n");
4875 return -1;
4876 }
4877
4878 /* check for "." and ".." */
4879 if ((strcmp(name,".")==0)||(strcmp(name,"..")==0)){
4880 err_print("creatfile: . or .. not allowed\n");
4881 return -1;
4882 }
4883
4884 /* check if file with this name already exists */
4885 if (findfile(name,0,NULL)>=0){
4886 err_print("creatfile: name already used\n");
4887 return -1;
4888 }
4889
4890 /* set new file descriptor */
4891 if (tmplt==NULL){
4892 bzero(&fdes,sizeof(struct filedes_s));
4893 fdes.fd_att|=ATT_R|ATT_W|ATT_E; /* XXX owner only */
4894 /* owner */
4895 fdes.fd_own[1]=curowner;
4896 fdes.fd_own[0]=curowner>>8;
4897 /* set creation and modified date */
4898 setdate(&fdes,1); /* 1: creat */
4899 }else{
4900 bcopy(tmplt,&fdes,sizeof(struct filedes_s));
4901 /* clear segment list */
4902 bzero(&(fdes.fd_seg[0]),FILEDES_SEGNR*sizeof(struct seg_s));
4903 #if 0
4904 /* update modif date */
4905 setdate(&fdes,0); /* 0: not creat */
4906 #endif
4907 }
4908 /* set attributes */
4909 if (dir){
4910 fdes.fd_att|=ATT_D;
4911 }else{
4912 fdes.fd_att&=~ATT_D;
4913 }
4914 /* set link count */
4915 fdes.fd_link=1;
4916 if (dir){
4917 bytesize=0; /* directory still empty */
4918 }
4919 /* set size */
4920 fdes.fd_fsize[0]=bytesize>>24;
4921 fdes.fd_fsize[1]=bytesize>>16;
4922 fdes.fd_fsize[2]=bytesize>>8;
4923 fdes.fd_fsize[3]=bytesize;
4924
4925 /* number of blocks */
4926 if (dir){
4927 /* XXX DIRBLKS granularity */
4928 blknr=DIRBLKS;
4929 }else{
4930 /* round up */
4931 /* XXX 32-Bit overflow protection */
4932 blknr=(u_int)((((OFF_T)bytesize)+((OFF_T)curpart->blksiz-1))
4933 /((OFF_T)curpart->blksiz));
4934 }
4935
4936 /* create file */
4937 startsec=filecreat(&fdes,blknr,0); /* 0:create */
4938 if (startsec<0){
4939 err_print("creatfile: filecreat\n");
4940 return -1;
4941 }
4942 /* write file descriptor */
4943 if (WRITEBLOCK_CURPART(startsec,&fdes,1)<0){
4944 err_print("creatfile: cannot write file descriptor\n");
4945 /* try to remove file again */
4946 filedel(startsec);
4947 return -1;
4948 }
4949
4950 /* create directory entry */
4951 if (creatdirent(name,startsec)<0){
4952 err_print("creatfile: creatdirent\n");
4953 /* try to remove file again */
4954 filedel(startsec);
4955 return -1;
4956 }
4957
4958 /* directory? */
4959 if (dir){
4960 u_int savecurdirsec;
4961
4962 /* create . and .. entries */
4963 /* save state */
4964 savecurdirsec=curdirsec;
4965 /* change to new directory */
4966 curdirsec=startsec;
4967 /* .. */
4968 if (creatdirent("..",savecurdirsec)<0){ /* that's the old current dir. */
4969 err_print("creatfile: cannot create ..\n");
4970 /* try to remove file */
4971 delfile(name,1); /* 1:dir */
4972 /* restore state */
4973 curdirsec=savecurdirsec;
4974 return -1;
4975 }
4976 /* . */
4977 if (creatdirent(".",startsec)<0){ /* that's us */
4978 err_print("creatfile: cannot create .\n");
4979 /* try to remove file */
4980 delfile(name,1); /* 1:dir */
4981 /* restore state */
4982 curdirsec=savecurdirsec;
4983 return -1;
4984 }
4985 /* restore state */
4986 curdirsec=savecurdirsec;
4987 }
4988
4989 return startsec; /* start sector of new file */
4990 }
4991
4992 /* MDR-DOS */
4993 int
mdr_creatfile(char * name,u_int bytesize,struct mdr_dirent_s * tmplt)4994 mdr_creatfile(char *name,u_int bytesize,struct mdr_dirent_s *tmplt)
4995 {
4996 u_int fnr;
4997 static struct mdr_dirent_s dirent;
4998 u_int blknr;
4999
5000 if (curpart->type!=PARTTYPE_OS9MDR){
5001 return -1;
5002 }
5003 if (!curpart->mdr){
5004 return -1;
5005 }
5006
5007 if ((name==NULL)||(strlen(name)==0)){
5008 return -1;
5009 }
5010 if (strlen(name)>FILENAMELEN){ /* good for MDR-DOS dirent */
5011 err_print("mdr_creatfile: name too long\n");
5012 return -1;
5013 }
5014
5015 #if 0
5016 /* XXX check for "." and ".." */
5017 if ((strcmp(name,".")==0)||(strcmp(name,"..")==0)){
5018 err_print("mdr_creatfile: . or .. not allowed\n");
5019 return -1;
5020 }
5021 #endif
5022
5023 /* check if file with this name already exists */
5024 if (mdr_findfile(name)>=0){
5025 err_print("mdr_creatfile: name already used\n");
5026 return -1;
5027 }
5028
5029 /* find empty directory entry */
5030 /* up to mdr_filenr (and not mdr_dfilenr) */
5031 for (fnr=0;fnr<curpart->mdr_filenr;fnr++){
5032 /* read directory entry */
5033 if (READBLOCK_CURPART(MDR_DIRSTART+MDR_DIRENTRYSIZE*fnr,&dirent,MDR_DIRENTRYSIZE)<0){
5034 err_print("mdr_creatfile: cannot read directory\n");
5035 return -1;
5036 }
5037 /* file slot free? */
5038 if (dirent.name[0]=='\0'){
5039 break; /* found free slot */
5040 }
5041 }
5042 /* Note: if no empty slot below mdr_filenr */
5043 /* => fnr==mdr_filenr, which is what we need in this case! */
5044 /* no free slot found? */
5045 if (fnr>=curpart->mdr_dfilenr){
5046 err_print("mdr_creatfile: no free directory slot\n");
5047 return -1;
5048 }
5049 #ifdef DEBUG
5050 printf("mdr_creatfile: mdr_filenr=%04x fnr=%04x\n",
5051 curpart->mdr_filenr,fnr);
5052 #endif
5053 /* set new directory entry */
5054 if (tmplt==NULL){
5055 bzero(&dirent,sizeof(struct mdr_dirent_s));
5056 /* set MDR-DOS type */
5057 bcopy(MDR_MDOSTYPE,&(dirent.type[0]),4);
5058 /* set creation and modified date */
5059 mdr_setdate(&dirent,1); /* 1: creat */
5060 }else{
5061 bcopy(tmplt,&dirent,sizeof(struct mdr_dirent_s));
5062 /* clear cluster list */
5063 bzero(&(dirent.clist[0]),MDR_FILECLNR*2);
5064 #if 0
5065 /* update modif date */
5066 mdr_setdate(&dirent,0); /* 0: not creat */
5067 #endif
5068 }
5069 /* set size */
5070 dirent.size[0]=bytesize>>24;
5071 dirent.size[1]=bytesize>>16;
5072 dirent.size[2]=bytesize>>8;
5073 dirent.size[3]=bytesize;
5074 /* set name without translation!!! */
5075 bcopy(name,&(dirent.name[0]),strlen(name)+1);
5076 /* XXX set other elements */
5077
5078 /* number of blocks */
5079 /* round up */
5080 /* XXX 32-Bit overflow protection */
5081 blknr=(u_int)((((OFF_T)bytesize)+((OFF_T)curpart->blksiz-1))
5082 /((OFF_T)curpart->blksiz));
5083
5084 /* create file */
5085 if (mdr_filecreat(&dirent,blknr,0)<0){ /* 0:create */
5086 err_print("mdr_creatfile: mdr_filecreat\n");
5087 return -1;
5088 }
5089 /* write dirent */
5090 if (WRITEBLOCK_CURPART(MDR_DIRSTART+MDR_DIRENTRYSIZE*fnr,&dirent,MDR_DIRENTRYSIZE)<0){
5091 err_print("mdr_creatfile: cannot write directory entry\n");
5092 /* try to remove file again */
5093 mdr_filedel(&dirent);
5094 return -1;
5095 }
5096
5097 /* update mdr_filenr */
5098 /* Note: fnr<mdr_dfilenr now (see check above!) */
5099 if (fnr>=curpart->mdr_filenr){
5100 curpart->mdr_filenr=fnr+1;
5101 /* => mdr_filenr<=mdr_dfilenr !!! */
5102 }
5103 /* always update, just in case mdr_filenr is too large somehow */
5104 if (mdr_updatefilenr()<0){
5105 return -1;
5106 }
5107
5108 return fnr; /* number of new file in directory */
5109 }
5110
5111 /* QDOS */
5112 int
qdos_creatfile(char * name,u_int bytesize,struct qdos_fdes_s * tmplt)5113 qdos_creatfile(char *name,u_int bytesize,struct qdos_fdes_s *tmplt)
5114 {
5115 u_char dirbuf[QDOS_DIRSIZE*QDOS_BLOCKSIZE];
5116 struct qdos_dir_s *qbufp;
5117 u_int fnr;
5118 struct qdos_rib_s qrib;
5119 struct qdos_dir_s qdir;
5120 u_int blknr;
5121 u_int ribsec,qsiz;
5122 char qname[11]; /* NNNNNNNNSS with terminating '\0' */
5123 u_int alloc,contig;
5124
5125 if (curpart->type!=PARTTYPE_QDOS){
5126 return -1;
5127 }
5128
5129 if ((name==NULL)||(strlen(name)==0)){
5130 return -1;
5131 }
5132
5133 #if 0
5134 /* XXX check for "." and ".." */
5135 if ((strcmp(name,".")==0)||(strcmp(name,"..")==0)){
5136 err_print("qdos_creatfile: . or .. not allowed\n");
5137 return -1;
5138 }
5139 #endif
5140
5141 /* check if file with this name already exists */
5142 if (qdos_findfile(name)>=0){
5143 err_print("qdos_creatfile: name already used\n");
5144 return -1;
5145 }
5146
5147 /* read directory */
5148 if (READBLOCK_CURPART(QDOS_DIRSTART,(void *)dirbuf,QDOS_DIRSIZE)<0){
5149 err_print("qdos_creatfile: cannot read directory\n");
5150 return -1;
5151 }
5152 qbufp=(struct qdos_dir_s *)dirbuf;
5153
5154 /* find empty directory entry */
5155 for (fnr=0;fnr<QDOS_DIRENTRYNR;fnr++){
5156 /* check if entry not used */
5157 if (qbufp[fnr].dir_nm[0]==QDOS_DIR_VACANT){
5158 /* first vacant directory entry */
5159 break; /* done */
5160 }
5161 if (qbufp[fnr].dir_nm[0]==QDOS_DIR_DELETED){
5162 /* first deleted directory entry */
5163 break; /* done */
5164 }
5165 }
5166 if (fnr>=QDOS_DIRENTRYNR){
5167 err_print("qdos_creatfile: no free directory slot\n");
5168 return -1;
5169 }
5170
5171 /* set new directory entry */
5172 if (tmplt==NULL){
5173 bzero(&qrib,sizeof(struct qdos_rib_s));
5174 bzero(&qdir,sizeof(struct qdos_dir_s));
5175 qdir.dir_at[0]=QDOS_ATT_FMU; /* user-defined */
5176 }else{
5177 bcopy(&tmplt->rib,&qrib,sizeof(struct qdos_rib_s));
5178 bcopy(&tmplt->dir,&qdir,sizeof(struct qdos_dir_s));
5179 }
5180 /* set name */
5181 qdos_makefname(name,qname); /* convert name into QDOS-conformant name */
5182 /* Note: dir_sx[2] directly follows dir_nm[8] in struct qdos_dir_s!!! */
5183 bcopy(qname,qdir.dir_nm,10);
5184
5185 /* number of blocks */
5186 /* round up */
5187 /* XXX 32-Bit overflow protection not necessary for QDOS */
5188 blknr=(bytesize+curpart->blksiz-1)/curpart->blksiz;
5189
5190 /* create file */
5191 if (qdos_filecreat(&qrib,blknr,0)<0){ /* 0:create */
5192 err_print("qdos_creatfile: qdos_filecreat\n");
5193 return -1;
5194 }
5195
5196 /* set file size in RIB */
5197 if (qdos_setfsize(&qrib,bytesize)<0){
5198 err_print("qdos_creatfile: corrupt RIB\n");
5199 /* try to remove file again */
5200 qdos_filedel(&qrib);
5201 return -1;
5202 }
5203
5204 /* write RIB */
5205 /* Note: first block of file allocation is used for RIB!!! */
5206 qdos_getseg(&qrib,0,&ribsec,&qsiz);
5207 if ((qsiz==0)||(ribsec==0)){
5208 /* empty or corrupt RIB!!! */
5209 err_print("qdos_creatfile: corrupt RIB\n");
5210 /* try to remove file again */
5211 qdos_filedel(&qrib);
5212 return -1;
5213 }
5214 ribsec*=QDOS_CSIZE;
5215 if (WRITEBLOCK_CURPART(ribsec,&qrib,1)<0){
5216 err_print("qdos_creatfile: cannot write RIB\n");
5217 /* try to remove file again */
5218 qdos_filedel(&qrib);
5219 return -1;
5220 }
5221
5222 /* set/clear ATT_CON flag in directory entry if file is contiguous: */
5223 alloc=qdos_countseg(&qrib,QDOS_RIB_SDWNR,&contig);
5224 if ((alloc!=0)&&(alloc==contig)){
5225 qdir.dir_at[0]|=QDOS_ATT_CON; /* set flag */
5226 }else{
5227 qdir.dir_at[0]&=~QDOS_ATT_CON; /* clear flag */
5228 }
5229 /* set RIB address in directory entry */
5230 qdir.dir_rb[0]=(ribsec>>8)&0xff;
5231 qdir.dir_rb[1]=ribsec&0xff;
5232
5233 /* save new directory entry */
5234 bcopy(&qdir,&qbufp[fnr],sizeof(struct qdos_dir_s));
5235
5236 /* write updated directory */
5237 if (WRITEBLOCK_CURPART(QDOS_DIRSTART,(void *)dirbuf,QDOS_DIRSIZE)<0){
5238 err_print("qdos_creatfile: cannot write directory\n");
5239 /* try to remove file again */
5240 qdos_filedel(&qrib);
5241 return -1;
5242 }
5243
5244 #ifdef DEBUG
5245 printf("qdos_creatfile:\n");
5246 qdos_printfdes(&qdir,&qrib);
5247 #endif
5248
5249 return fnr; /* number of new file in directory */
5250 }
5251
5252
5253
5254 /* OS9/MDR-DOS */
5255 int
readlsn0(u_int blocksize0)5256 readlsn0(u_int blocksize0)
5257 {
5258
5259 if (curpart->type!=PARTTYPE_OS9MDR){
5260 return -1;
5261 }
5262 if (curpart->psize==0){
5263 curpart->totsize=0; /* mark unusable */
5264 return -1;
5265 }
5266 if (blocksize0==0){
5267 blocksize0=OS9L2_BLOCKSIZE; /* default */
5268 }
5269
5270 /* Note: current curpart->startsec,psize are for blocksize0! */
5271 curpart->blksiz=blocksize0; /* premininary */
5272 curpart->totsize=1; /* for READBLOCK_CURPART below: at least LSN0 */
5273
5274 /* XXX for the case that READBLOCK_CURPART doesn't return an error */
5275 /* although lseek went beyond device/image file limits */
5276 /* (e.g., as the case for OSF1 with /sc00 image file!) */
5277 /* we set dd_tot in curpart->lsn0 to 0, to avoid that partition */
5278 bzero(curpart->lsn0,sizeof(struct lsn0_s)); /* esp. dd_tot=0 */
5279 if (READBLOCK_CURPART(0,curpart->lsn0,1)<0){
5280 /*err_print("readlsn0: READBLOCK_CURPART(curpart->lsn0)\n");*/ /* don't complain here */
5281 return -1; /* we must avoid this partition */
5282 }
5283
5284 /* OS9 bitmap size: needed as criterion for type! */
5285 curpart->bitmapsize=(curpart->lsn0->dd_map[0]<<8)+curpart->lsn0->dd_map[1];
5286
5287 /* size of partition dd_tot */
5288 curpart->totsize=(curpart->lsn0->dd_tot[0]<<16)
5289 +(curpart->lsn0->dd_tot[1]<<8)
5290 +curpart->lsn0->dd_tot[2];
5291
5292 /* partition type: */
5293 /* MDR-DOS partition: bitmapsize==0 but totsize>0 */
5294 if ((curpart->bitmapsize==0)&&(curpart->totsize>0)){
5295 curpart->mdr=1; /* MDR-DOS */
5296 curpart->blksiz=MDR_BLOCKSIZE;
5297 }else{
5298 u_int bb,bb1;
5299
5300 curpart->mdr=0; /* OS9 */
5301 bb=(curpart->lsn0->dd_lsnsize[0]<<8)
5302 +curpart->lsn0->dd_lsnsize[1];
5303 if (bb==0){
5304 bb1=OS9L2_BLOCKSIZE;
5305 }else{
5306 bb1=fixblksiz(bb);
5307 if (bb1!=bb){
5308 char b[128];
5309 sprintf(b,"warning: invalid lsnsize in partition %02x (%04x).\n set to reasonable size %04x.\n",
5310 partnr, /* XXX assumed to be current number during setup */
5311 bb,bb1);
5312 err_print(b);
5313 }
5314 }
5315 curpart->blksiz=bb1;
5316 }
5317
5318 /* convert to partition blocksize: */
5319 /* XXX 32-Bit overflow protection */
5320 curpart->startsec=(u_int)((((OFF_T)curpart->startsec)*((OFF_T)blocksize0))
5321 /((OFF_T)curpart->blksiz));
5322 curpart->psize=(u_int)((((OFF_T)curpart->psize)*((OFF_T)blocksize0))
5323 /((OFF_T)curpart->blksiz));
5324
5325 /* check partition size with partition table: */
5326 /* totsize <= size according to parttab entry! */
5327 /* Note: totsize will be used for partition limit checks during operation */
5328 /* this must be <= size according to parttab entry! */
5329 if (!curpart->master){ /* check psize only for non-master! */
5330 if (curpart->totsize>curpart->psize){
5331 char b[128];
5332 sprintf(b,"error: partition %02x too large.\n",partnr);
5333 err_print(b);
5334 return -1;
5335 }
5336 }else{
5337 /* master */
5338 curpart->psize=curpart->totsize; /* set equal to dd_tot for master! */
5339 }
5340
5341 /* partition type: */
5342 if (curpart->mdr){
5343 /* MDR-DOS */
5344
5345 curpart->mdr_clustersize=MDR_CLUSTERSIZE*MDR_LSN0_P(curpart->lsn0)->mdr_clsz;
5346 curpart->mdr_clusternr=(MDR_LSN0_P(curpart->lsn0)->mdr_clnr[0]<<8)
5347 +MDR_LSN0_P(curpart->lsn0)->mdr_clnr[1];
5348 curpart->mdr_filesyssize=curpart->mdr_clustersize*curpart->mdr_clusternr;
5349
5350 curpart->mdr_dfilenr=(MDR_LSN0_P(curpart->lsn0)->mdr_dfnr[0]<<8)
5351 +MDR_LSN0_P(curpart->lsn0)->mdr_dfnr[1];
5352 curpart->mdr_filenr=(MDR_LSN0_P(curpart->lsn0)->mdr_fnr[0]<<8)
5353 +MDR_LSN0_P(curpart->lsn0)->mdr_fnr[1];
5354
5355 /* basic filesystem checks: */
5356
5357 /* 1) mdr_filesyssize <= totsize */
5358 if (curpart->mdr_filesyssize>curpart->totsize){
5359 char b[128];
5360 sprintf(b,"error: filesystem in partition %02x too large (%08x).\n partition size (%08x).\n",
5361 partnr, /* XXX assumed to be current number during setup */
5362 curpart->mdr_filesyssize,curpart->totsize);
5363 err_print(b);
5364 if (!curpart->master){
5365 return -1;
5366 }
5367 }
5368 /* 2) mdr_filesyssize >= MDR_DIRSTART+mdr_dfilenr*MDR_DIRENTRYSIZE */
5369 if (curpart->mdr_filesyssize
5370 <(MDR_DIRSTART+curpart->mdr_dfilenr*MDR_DIRENTRYSIZE)){
5371 char b[128];
5372 sprintf(b,"error: filesystem in partition %02x too small (%08x).\n needed at least %08x.\n",
5373 partnr, /* XXX assumed to be current number during setup */
5374 curpart->mdr_filesyssize,
5375 MDR_DIRSTART+curpart->mdr_dfilenr*MDR_DIRENTRYSIZE);
5376 err_print(b);
5377 if (!curpart->master){
5378 return -1;
5379 }
5380 }
5381 /* 3) mdr_filenr <= mdr_dfilenr */
5382 if (curpart->mdr_filenr>curpart->mdr_dfilenr){
5383 char b[128];
5384 sprintf(b,"error: filenumber in partition %02x too large (%04x).\n maximum %04x.\n",
5385 partnr, /* XXX assumed to be current number during setup */
5386 curpart->mdr_filenr,
5387 curpart->mdr_dfilenr);
5388 err_print(b);
5389 if (!curpart->master){
5390 return -1;
5391 }
5392 }
5393
5394 /* 4) XXX should check bitmap now: */
5395 /* clusters outside mdr_filesyssize should be marked as used */
5396 /* last incomplete cluster should be marked as used */
5397 /* must check these cluster(s): */
5398 /* a) marked unused in bitmap => problem */
5399 /* b) marked used but also used in filesystem => problem */
5400 /* this is very difficult to verify */
5401 }else{
5402 /* OS9 */
5403
5404 curpart->bitmapstart=(curpart->lsn0->dd_maplsn[0]<<24)
5405 +(curpart->lsn0->dd_maplsn[1]<<16)
5406 +(curpart->lsn0->dd_maplsn[2]<<8)
5407 +curpart->lsn0->dd_maplsn[3];
5408 if (curpart->bitmapstart==0){
5409 curpart->bitmapstart=OS9L2_BMAPSTART;
5410 }
5411 /*curpart->bitmapsize=(curpart->lsn0->dd_map[0]<<8)+curpart->lsn0->dd_map[1];*/ /* already done! */
5412 curpart->clustersize=(curpart->lsn0->dd_bit[0]<<8)+curpart->lsn0->dd_bit[1];
5413 curpart->filesyssize=curpart->clustersize*curpart->bitmapsize*8; /* first guess */
5414 /* Note: clustersize*bitmapsize can be larger than totsize: */
5415 /* last clusters should be marked used in bitmap and */
5416 /* not be used by any file/directory/descriptor! */
5417 /* we will simply ignore these clusters */
5418
5419 curpart->rootdirsec=(curpart->lsn0->dd_dir[0]<<16)
5420 +(curpart->lsn0->dd_dir[1]<<8)
5421 +curpart->lsn0->dd_dir[2];
5422
5423 curpart->bootsec=(curpart->lsn0->dd_bt[0]<<16)
5424 +(curpart->lsn0->dd_bt[1]<<8)
5425 +curpart->lsn0->dd_bt[2];
5426 curpart->bootsize=(curpart->lsn0->dd_bsz[0]<<8)
5427 +curpart->lsn0->dd_bsz[1];
5428
5429 /* basic filesystem checks: */
5430
5431 /* 1) truncate filesyssize <= totsize */
5432 if (curpart->filesyssize>curpart->totsize){
5433 /* XXX this is no error */
5434 #ifdef PEDANTICSETUP
5435 char b[128];
5436 sprintf(b,"warning: filesystem in partition %02x might be too large (%08x).\n clipped to partition size %08x.\n",
5437 partnr, /* XXX assumed to be current number during setup */
5438 curpart->filesyssize,curpart->totsize);
5439 err_print(b);
5440 #endif
5441
5442 curpart->filesyssize=curpart->totsize; /* "clip" nonexistent clusters */
5443 }
5444
5445 /* 2) XXX should check bitmap now: */
5446 /* clusters outside filesyssize should be marked as used */
5447 /* last incomplete cluster should be marked as used */
5448 /* must check these cluster(s): */
5449 /* a) marked unused in bitmap => problem */
5450 /* b) marked used but also used in filesystem => problem */
5451 /* this is very difficult to verify */
5452 }
5453
5454 return 0;
5455 }
5456
5457 /* general */
5458 void
printlsn0(void)5459 printlsn0(void)
5460 {
5461
5462 printf("devname: %s\n",curpart->devname);
5463 printf("blocksize: %u bytes\n",curpart->blksiz);
5464
5465 if (curpart->type==PARTTYPE_QDOS){
5466 /* QDOS */
5467 struct qdos_did_s *qp;
5468 u_int i;
5469
5470 qp=QDOS_LSN0_P(curpart->lsn0);
5471
5472 printf("--- QDOS ---\n");
5473 printf("did_id: ");
5474 printnstr(qp->did_id,8);
5475 printf("\ndid_vn: %c%c\ndid_rn: %c%c\n",
5476 isprint(qp->did_vn[0])?qp->did_vn[0]:'?',
5477 isprint(qp->did_vn[1])?qp->did_vn[1]:'?',
5478 isprint(qp->did_rn[0])?qp->did_rn[0]:'?',
5479 isprint(qp->did_rn[1])?qp->did_rn[1]:'?');
5480 printf("did_dt: %c%c-%c%c-%c%c\ndid_nm: ",
5481 isprint(qp->did_dt[0])?qp->did_dt[0]:'?',
5482 isprint(qp->did_dt[1])?qp->did_dt[1]:'?',
5483 isprint(qp->did_dt[2])?qp->did_dt[2]:'?',
5484 isprint(qp->did_dt[3])?qp->did_dt[3]:'?',
5485 isprint(qp->did_dt[4])?qp->did_dt[4]:'?',
5486 isprint(qp->did_dt[5])?qp->did_dt[5]:'?');
5487 printnstr(qp->did_nm,20);
5488 printf("\n");
5489 for (i=0;i<QDOS_DID_RBNR;i++){
5490 printf("did_rb[%02x]: %02x%02x\n",i,qp->did_rb[i][0],qp->did_rb[i][1]);
5491 }
5492 printf("did_btsec: %02x%02x\n",qp->did_btsec[0],qp->did_btsec[1]);
5493 printf("did_btsiz: %02x%02x\n",qp->did_btsiz[0],qp->did_btsiz[1]);
5494 printf("did_btloa: %02x%02x\n",qp->did_btloa[0],qp->did_btloa[1]);
5495 printf("did_slin: ");
5496 printf("(%c) ",isprint(qp->did_slinflag)?qp->did_slinflag:'-');
5497 printnstr(qp->did_slin,69);
5498 printf("\n");
5499 return;
5500 }else if (curpart->type!=PARTTYPE_OS9MDR){
5501 return;
5502 }
5503
5504 /* now OS9 or MDR-DOS */
5505 if (curpart->master){ /* master partition? */
5506 printf("master partition\n");
5507 }else{
5508 printf("ptab size: %06x (%u bytes)\n",curpart->psize,curpart->psize*curpart->blksiz);
5509 }
5510
5511 /*printf("curpart->lsn0:\n");*/
5512 printf("dd_tot: %06x (%u bytes)\n",curpart->totsize,curpart->totsize*curpart->blksiz);
5513 if (!curpart->mdr){
5514 printf("--- OS9 ---\n");
5515 printf("dd_tks: %02x\n",curpart->lsn0->dd_tks);
5516 printf("dd_map: %04x\n",curpart->bitmapsize);
5517 printf("dd_bit: %04x\n",curpart->clustersize);
5518 printf("dd_dir: %06x\n",curpart->rootdirsec);
5519 printf("dd_own: %02x%02x\n",curpart->lsn0->dd_own[0],curpart->lsn0->dd_own[1]);
5520 printf("dd_att: %02x (",curpart->lsn0->dd_att);
5521 printatt(curpart->lsn0->dd_att);
5522 printf(")\ndd_dsk: %02x%02x\n",curpart->lsn0->dd_dsk[0],curpart->lsn0->dd_dsk[1]);
5523 printf("dd_fmt: %02x\n",curpart->lsn0->dd_fmt);
5524 printf("dd_spt: %02x%02x\n",curpart->lsn0->dd_spt[0],curpart->lsn0->dd_spt[1]);
5525 printf("dd_res: %02x%02x\n",curpart->lsn0->dd_res[0],curpart->lsn0->dd_res[1]);
5526 printf("dd_bt: %06x\n",curpart->bootsec);
5527 printf("dd_bsz: %04x\n",curpart->bootsize);
5528 printf("dd_ptabstart: %06x\n",curpart->ptabsec);
5529 printf("dd_pnr: %04x\n",curpart->pnr);
5530 printf("dd_date: %02i-%02i-%02i %02i:%02i\n",
5531 curpart->lsn0->dd_date[0]%100,curpart->lsn0->dd_date[1]%100,curpart->lsn0->dd_date[2]%100,
5532 curpart->lsn0->dd_date[3]%100,curpart->lsn0->dd_date[4]%100);
5533 printf("dd_name: \"");
5534 /* XXX use printname here for convenience: */
5535 /* XXX Could miss last chars: FILENAMELEN==29 but dd_name[32]! */
5536 printname(curpart->lsn0->dd_name);
5537 printf("\"\n");
5538 printf("dd_maplsn: %08x\n",curpart->bitmapstart);
5539 printf("dd_lsnsize: %04x\n",curpart->blksiz);
5540 printf("dd_versid: %02x%02x\n",
5541 curpart->lsn0->dd_versid[0],
5542 curpart->lsn0->dd_versid[1]);
5543 if (curpart->master){
5544 printf("dd_ptabstart: %06x\n",curpart->ptabsec);
5545 printf("dd_pnr: %02x\n",curpart->lsn0->dd_pnr);
5546 printf("dd_qdosstart: %02x%02x%02x\n",
5547 curpart->lsn0->dd_qdosstart[0],curpart->lsn0->dd_qdosstart[1],curpart->lsn0->dd_qdosstart[2]);
5548 printf("dd_qdosnr: %02x%02x\n",
5549 curpart->lsn0->dd_qdosnr[0],curpart->lsn0->dd_qdosnr[1]);
5550 printf("dd_cmistart: %02x%02x%02x\n",
5551 curpart->lsn0->dd_cmistart[0],curpart->lsn0->dd_cmistart[1],curpart->lsn0->dd_cmistart[2]);
5552 printf("dd_cminr: %02x%02x\n",
5553 curpart->lsn0->dd_cminr[0],curpart->lsn0->dd_cminr[1]);
5554 }
5555 printf("filesys size: %08x\n",curpart->filesyssize);
5556 }else{
5557 printf("--- MDR-DOS ---\n");
5558 printf("mdr_clsz: %08x\n",curpart->mdr_clustersize);
5559 printf("mdr_clnr: %04x\n",curpart->mdr_clusternr);
5560 printf("mdr_dfnr: %04x\n",curpart->mdr_dfilenr);
5561 printf("mdr_fnr: %04x\n",curpart->mdr_filenr);
5562 printf("mdr_name: \"");
5563 /* XXX use printname here for convenience: */
5564 printname(MDR_LSN0_P(curpart->lsn0)->mdr_name);
5565 printf("\"\n");
5566 printf("filesys size: %08x\n",curpart->mdr_filesyssize);
5567 }
5568 printf("\n");
5569 }
5570
5571 /* general */
5572 /* setup partitions */
5573 int
partsetup(int fdes,u_int devid,int forceqdosnr)5574 partsetup(int fdes,u_int devid,int forceqdosnr)
5575 {
5576 u_int startsec,size;
5577 u_int i,partnrmax;
5578 u_int ptabstart,pnr;
5579 static u_char pbuf[OS9MAX_BLOCKSIZE]; /* XXX enough for 1 block */
5580 struct parttabent_s *parttab;
5581 struct part_s *masterp;
5582 u_int master_blocksize;
5583 u_int qdosstart,qdos_partnr;
5584 u_int cmistart,cmi_partnr;
5585
5586 master_blocksize=OS9L2_BLOCKSIZE; /* default */
5587 if (forceqdosnr<=0){
5588 /* OS9/MDR-DOS master partition */
5589 curpart=&part[partnr];
5590 bzero(curpart,sizeof(struct part_s)); /* invalidate everything */
5591 curpart->fdes=fdes;
5592 curpart->lsn0=&lsn0[partnr];
5593 curpart->type=PARTTYPE_OS9MDR;
5594 curpart->master=1;
5595 curpart->startsec=0; /* needed for READBLOCK_CURPART in readlsn0 */
5596 curpart->psize=1; /* preliminary for readlsn0 */
5597 /* set name */
5598 sprintf(curpart->devname,"sc%02x",devid);
5599 /* get master partition */
5600 if (readlsn0(master_blocksize)<0){
5601 /* fatal: at least LSN0 of master partition should be accessible */
5602 err_print("partsetup: cannot access LSN0 of master partition\n");
5603 return -1;
5604 }
5605 master_blocksize=curpart->blksiz;
5606 #ifdef DEBUG
5607 printf("master: %02x: startsec: %06x size: %06x\n",
5608 partnr,curpart->startsec,curpart->psize);
5609 printlsn0();
5610 #endif
5611
5612 /* partition table information from master partition */
5613 ptabstart=(curpart->lsn0->dd_ptabstart[0]<<16)
5614 +(curpart->lsn0->dd_ptabstart[1]<<8)
5615 +curpart->lsn0->dd_ptabstart[2];
5616 curpart->ptabsec=ptabstart;
5617 pnr=curpart->lsn0->dd_pnr;
5618 curpart->pnr=pnr;
5619
5620 masterp=curpart;
5621
5622 partnr++; /* master partition setup */
5623 if (partnr>=PARTITION_NR){
5624 err_print("error: too many partitions.\n");
5625 return -1;
5626 }
5627
5628 /* further OS9/MDR-DOS partitions */
5629
5630 partnrmax=pnr;
5631 if (partnrmax>PARTTAB_NR){
5632 err_print("partsetup: too many partitions\n");
5633 #ifdef PEDANTICSETUP
5634 return -1;
5635 #else
5636 partnrmax=0; /* assume corrupt partition table */
5637 err_print("partsetup: ignoring partition table\n");
5638 #endif
5639 }
5640 if (partnrmax>0){
5641 bzero(pbuf,OS9MAX_BLOCKSIZE);
5642 parttab=(struct parttabent_s *)pbuf;
5643 /* read parttab file */
5644 i=(PARTTAB_NR*sizeof(struct parttabent_s)+curpart->blksiz-1)
5645 /curpart->blksiz;
5646 if (READBLOCK_CURPART(ptabstart,parttab,i)<0){
5647 err_print("partsetup: READBLOCK_CURPART(parttab)\n");
5648 #ifdef PEDANTICSETUP
5649 return -1;
5650 #else
5651 partnrmax=0; /* assume corrupt partition table */
5652 err_print("partsetup: ignoring partition table\n");
5653 #endif
5654 }
5655
5656 /* setup partition table */
5657 for (i=0;i<partnrmax;i++){
5658 if (parttab[i].index!=0){
5659 /* partition has entry in partition table */
5660 startsec=(parttab[i].startsec[0]<<16)
5661 +(parttab[i].startsec[1]<<8)
5662 +parttab[i].startsec[2]; /* in master_blocksize!!! */
5663 size=(parttab[i].size[0]<<16)
5664 +(parttab[i].size[1]<<8)
5665 +parttab[i].size[2]; /* in master_blocksize!!! */
5666 /* check if partition valid */
5667 if (size<=0){
5668 continue; /* skip partnr++; next entry */
5669 }
5670 #ifdef DEBUG
5671 printf("parttab: %02x: startsec: %06x size: %06x\n",
5672 partnr,startsec,psize);
5673 #endif
5674
5675 /* setup partition */
5676 curpart=&part[partnr];
5677 bzero(curpart,sizeof(struct part_s)); /* invalidate everything */
5678 curpart->fdes=fdes;
5679 curpart->lsn0=&lsn0[partnr];
5680 curpart->type=PARTTYPE_OS9MDR;
5681 /* Note: blocksize for parttab is master_blocksize! */
5682 curpart->startsec=startsec; /* needed for READBLOCK_CURPART in readlsn0 */
5683 curpart->psize=size; /* size of partition according to parttab */
5684 /* check if partition fits into disk (i.e. master partition!) */
5685 if (startsec+size>masterp->totsize){ /* in master_blocksize */
5686 curpart->psize=0; /* mark unusable for readlsn0 */
5687 }
5688
5689 /* set name */
5690 if ((parttab[i].index>0)&&(parttab[i].index<9)){
5691 sprintf(curpart->devname,"c%02x%u",devid,parttab[i].index-1);
5692 }else if (parttab[i].index<17){
5693 sprintf(curpart->devname,"k%02x%u",devid,parttab[i].index-9);
5694 }else{
5695 sprintf(curpart->devname,"?%02x%u",devid,parttab[i].index-9);
5696 }
5697
5698 /* get partition */
5699 /* read LSN0 */
5700 if (readlsn0(master_blocksize)<0){
5701 char b[128];
5702 sprintf(b,"partsetup: readlsn0(%02x)\n",i+1);
5703 err_print(b);
5704 #ifdef PEDANTICSETUP
5705 return -1;
5706 #else
5707 /* XXX instead of returning an error, we simply mark */
5708 /* the partition as size 0, which should prevent */
5709 /* it from being used!!! */
5710 /* This could be useful for a device/image file */
5711 /* that has an invalid partition table. */
5712 curpart->totsize=0; /* non-usable */
5713 sprintf(b,"partsetup: partition %02x not accessible\n",i+1);
5714 err_print(b);
5715 #endif
5716 }
5717
5718 /* further checks for partition: */
5719 /* Note: must compare quantities of same blocksize!!! */
5720
5721 /* XXX should check for overlap with other partitions */
5722
5723 #ifdef DEBUG
5724 printlsn0();
5725 #endif
5726
5727 partnr++;
5728 if (partnr>=PARTITION_NR){
5729 err_print("error: too many partitions.\n");
5730 return -1;
5731 }
5732 }
5733 }
5734 }
5735 }
5736
5737 /* QDOS partitions */
5738
5739 if (forceqdosnr>0){
5740 /* forced QDOS-only */
5741 qdosstart=0;
5742 qdos_partnr=forceqdosnr;
5743 cmistart=0;
5744 cmi_partnr=0;
5745 /* Note: master_blocksize now irrelevant */
5746 }else{
5747 qdosstart=(masterp->lsn0->dd_qdosstart[0]<<16)
5748 +(masterp->lsn0->dd_qdosstart[1]<<8)
5749 +masterp->lsn0->dd_qdosstart[2]; /* in master_blocksize!!! */
5750 qdos_partnr=(masterp->lsn0->dd_qdosnr[0]<<8)
5751 +masterp->lsn0->dd_qdosnr[1];
5752 cmistart=(masterp->lsn0->dd_cmistart[0]<<16)
5753 +(masterp->lsn0->dd_cmistart[1]<<8)
5754 +masterp->lsn0->dd_cmistart[2]; /* in master_blocksize!!! */
5755 cmi_partnr=(masterp->lsn0->dd_cminr[0]<<8)
5756 +masterp->lsn0->dd_cminr[1];
5757 }
5758
5759 /* setup QDOS partitions */
5760 /* read QDOS disk IDs */
5761 for (i=0;i<qdos_partnr+cmi_partnr;i++){
5762 /* setup partition */
5763 curpart=&part[partnr];
5764 bzero(curpart,sizeof(struct part_s)); /* invalidate everything */
5765 curpart->fdes=fdes;
5766 curpart->lsn0=&lsn0[partnr];
5767 curpart->type=PARTTYPE_QDOS;
5768 curpart->blksiz=QDOS_BLOCKSIZE;
5769 size=QDOS_PBLKS; /* in QDOS blocksize!!! */
5770 curpart->totsize=size;
5771 curpart->psize=size; /* set equal to totsize for QDOS partition! */
5772 if (i<qdos_partnr){
5773 startsec=qdosstart*(master_blocksize/curpart->blksiz)
5774 +i*size; /* in QDOS blocksize now!!! */
5775 }else{
5776 startsec=cmistart*(master_blocksize/curpart->blksiz)
5777 +(i-qdos_partnr)*size; /* in QDOS blocksize now!!! */
5778 }
5779 curpart->startsec=startsec; /* needed for READBLOCK_CURPART */
5780 /* set name */
5781 sprintf(curpart->devname,"q%02x%u",devid,i);
5782
5783 /* XXX check if startsec and size are valid */
5784 /* read disk ID at logical sector 0 */
5785 /* Note: qdos_did_s fits into lsn0_s!!! */
5786 if (READBLOCK_CURPART(0,curpart->lsn0,1)<0){
5787 char b[128];
5788 sprintf(b,"partsetup: READBLOCK_CURPART(QDOS[%u])\n",i);
5789 err_print(b);
5790 curpart->totsize=0; /* non-usable */
5791 }else{
5792 /* XXX check validity of partition */
5793 /* XXX set other elements in curpart */
5794 }
5795
5796 partnr++;
5797 if (partnr>=PARTITION_NR){
5798 err_print("error: too many partitions.\n");
5799 return -1;
5800 }
5801 }
5802
5803 /* XXX */
5804
5805 return 0;
5806 }
5807
5808
5809
5810 /* OS9 */
5811 int
partmodif(struct parttabent_s * parttab,u_int index,u_int size,u_int startsec,int clearall)5812 partmodif(struct parttabent_s *parttab,u_int index,u_int size,u_int startsec,int clearall)
5813 {
5814 u_int i;
5815
5816 if (parttab==NULL){
5817 return -1;
5818 }
5819 if (curpart->type!=PARTTYPE_OS9MDR){
5820 return -1;
5821 }
5822 if (curpart->mdr){
5823 return -1;
5824 }
5825
5826 if (curpart->ptabsec==0){
5827 err_print("partmodif: no partition table in current partition\n");
5828 /* XXX actually, partition table only in master makes sense... */
5829 return -1;
5830 }
5831
5832 if (clearall){
5833 bzero(parttab,OS9MAX_BLOCKSIZE);
5834 }else{
5835 if (index>curpart->pnr){ /* XXX or PARTTAB_NR??? */
5836 char b[128];
5837 sprintf(b,"partmodif: invalid index (should be 1-%i)\n",curpart->pnr);
5838 err_print(b);
5839 return -1;
5840 }
5841 bzero(&parttab[index-1],sizeof(struct parttabent_s));
5842 parttab[index-1].index=index;
5843 /* XXX check for valid size */
5844 parttab[index-1].size[2]=size;
5845 parttab[index-1].size[1]=size>>8;
5846 parttab[index-1].size[0]=size>>16;
5847 /* XXX check for valid startsec */
5848 parttab[index-1].startsec[2]=startsec;
5849 parttab[index-1].startsec[1]=startsec>>8;
5850 parttab[index-1].startsec[0]=startsec>>16;
5851 }
5852
5853 /* write new partition table */
5854 i=(PARTTAB_NR*sizeof(struct parttabent_s)+curpart->blksiz-1)
5855 /curpart->blksiz;
5856 if (WRITEBLOCK_CURPART(curpart->ptabsec,parttab,i)<0){
5857 err_print("partmodif: cannot write partition table\n");
5858 /* XXX cannot undo previous actions */
5859 return -1;
5860 }
5861
5862 return 0;
5863 /* must restart after this to activate new partition table!!! */
5864 }
5865
5866
5867
5868 /* general */
5869 struct part_s *
partchange2(char * name,int check)5870 partchange2(char *name,int check)
5871 {
5872 struct part_s *pp;
5873 u_int i;
5874
5875 if (name==NULL){
5876 return NULL;
5877 }
5878 if (strlen(name)==0){
5879 return NULL;
5880 }
5881
5882 /* scan alias table */
5883 for (i=0;;i++){
5884 if ((devalias[i].alias==NULL)||(devalias[i].equ==NULL)){
5885 break; /* end */
5886 }
5887 if (strcasecmp(name,devalias[i].alias)==0){
5888 name=devalias[i].equ; /* translated name */
5889 break; /* done */
5890 }
5891 }
5892
5893 /* scan partition table */
5894 pp=NULL; /* nothing found yet */
5895 for (i=0;i<partnr;i++){
5896 if (strcasecmp(name,part[i].devname)==0){
5897 pp=&part[i];
5898 break; /* done */
5899 }
5900 }
5901
5902 if ((pp!=NULL)&&check){
5903 /* check if psize>0 and totsize>0 */
5904 if ((pp->psize<=0)||(pp->totsize<=0)){
5905 err_print("partchange2: invalid filesystem\n");
5906 pp=NULL; /* invalid filesystem, entrance to partition filesystem denied! */
5907 }
5908 /* XXX other checks */
5909 }
5910
5911 if (pp==NULL){
5912 err_print("partchange2: invalid partition\n");
5913 }else{
5914 /* switch to new partition */
5915 curpart=pp;
5916 #ifdef DEBUG
5917 printf("curpart: %02x: startsec: %06x size: %06x\n",
5918 i,curpart->startsec,curpart->psize);
5919 printlsn0();
5920 #endif
5921 }
5922
5923 return pp;
5924 }
5925
5926
5927
5928 /* general */
5929 int
printpartinfo(char * partp,u_int seekstart,u_int minsize,int mode)5930 printpartinfo(char *partp,u_int seekstart,u_int minsize,int mode)
5931 {
5932 struct part_s *savecurpart;
5933 u_int segstart;
5934 u_int segsize;
5935 u_int lsegstart;
5936 u_int lsegsize;
5937 u_int segnr;
5938 int totfree;
5939
5940 if (partp==NULL){
5941 return -1;
5942 }
5943
5944 /* save state */
5945 savecurpart=curpart;
5946
5947 if (partchange2(partp,1)==NULL){ /* 1: check */
5948 err_print("printpartinfo: cannot change partition\n");
5949 return -1;
5950 }
5951
5952 if (mode&1){
5953 printlsn0();
5954 }
5955
5956 if (curpart->type==PARTTYPE_QDOS){
5957 /* QDOS partition */
5958 totfree=qdos_findfree(seekstart,minsize,
5959 &segstart,&segsize,
5960 &lsegstart,&lsegsize,&segnr,
5961 NULL,0,1); /* full scan */
5962 if (totfree<0){
5963 /* restore state */
5964 curpart=savecurpart;
5965 return -1;
5966 }
5967
5968 if (mode&2){
5969 printf("QDOS free:\n");
5970 printf("seekstart: %06x minsize: %06x\n",seekstart,minsize);
5971 printf(" totfree: %06x\n",totfree);
5972 printf("segstart: %06x segsize: %06x\n",segstart,segsize);
5973 printf("lsegstart: %06x lsegsize: %06x\n",lsegstart);
5974 printf("segnr: %06x\n",segnr);
5975 printf("total: %06x\n\n",totfree);
5976 }else{
5977 printf("%06x",totfree);
5978 }
5979 }else if (curpart->type!=PARTTYPE_OS9MDR){
5980 err_print("printpartinfo: invalid partition type\n");
5981 /* restore state */
5982 curpart=savecurpart;
5983 return -1;
5984 }else{
5985 /* now OS9 or MDR-DOS */
5986 if (!curpart->mdr){
5987 totfree=findfree(seekstart,minsize,
5988 &segstart,&segsize,
5989 &lsegstart,&lsegsize,&segnr,
5990 NULL,0,1); /* full scan */
5991 if (totfree<0){
5992 /* restore state */
5993 curpart=savecurpart;
5994 return -1;
5995 }
5996
5997 if (mode&2){
5998 printf("OS9 free:\n");
5999 printf("seekstart: %06x minsize: %06x\n",seekstart,minsize);
6000 printf(" totfree: %06x\n",totfree);
6001 printf("segstart: %06x segsize: %06x\n",segstart,segsize);
6002 printf("lsegstart: %06x lsegsize: %06x\n",lsegstart,lsegsize);
6003 printf("segnr: %06x\n",segnr);
6004 printf("total: %06x\n\n",totfree);
6005 }else{
6006 printf("%06x",totfree);
6007 }
6008 }else{
6009 #if 1
6010 totfree=mdr_findfree(seekstart,minsize,
6011 &segstart,&segsize,
6012 &lsegstart,&lsegsize,&segnr,
6013 NULL,0,1); /* full scan */
6014
6015 if (mode&2){
6016 printf("MDR-DOS free:\n");
6017 printf("seekstart: %06x minsize: %06x\n",seekstart,minsize);
6018 printf(" totfree: %06x\n",totfree);
6019 printf("segstart: %06x segsize: %06x\n",segstart,segsize);
6020 printf("lsegstart: %06x lsegsize: %06x\n",lsegstart,lsegsize);
6021 printf("segnr: %06x\n",segnr);
6022 printf("total: %06x\n\n",totfree);
6023 }else{
6024 printf("%06x",totfree);
6025 }
6026 #else
6027 totfree=mdr_countfree()*(curpart->mdr_clustersize);
6028
6029 if (mode&2){
6030 printf("MDR-DOS free:\n");
6031 printf("total: %06x\n\n",totfree);
6032 }else{
6033 printf("%06x",totfree);
6034 }
6035 #endif
6036 }
6037 }
6038
6039 /* restore state */
6040 curpart=savecurpart;
6041
6042 if (mode==0)
6043 return totfree;
6044 return 0;
6045 }
6046
6047 /* general */
6048 void
printpartlist(int mode)6049 printpartlist(int mode)
6050 {
6051 u_int i;
6052 u_int os9mdrpartnr,qdospartnr;
6053 int totfree;
6054
6055 /* count partitions */
6056 os9mdrpartnr=0;
6057 qdospartnr=0;
6058 for (i=0;i<partnr;i++){
6059 if (part[i].type==PARTTYPE_OS9MDR){
6060 os9mdrpartnr++;
6061 }else if (part[i].type==PARTTYPE_QDOS){
6062 qdospartnr++;
6063 }
6064 }
6065
6066 if (os9mdrpartnr>0){
6067 /* OS9/MDR-DOS partitions */
6068 printf("OS9/MDR-DOS partitions: %02x\n",os9mdrpartnr);
6069 if (mode){
6070 printf("partition b blk start ptsize totsize mdr name\n");
6071 printf("-------------------------------------------------------------------------------\n");
6072 }else{
6073 printf("partition mdr filesys free used\n");
6074 printf("----------------------------------\n");
6075 }
6076
6077 for (i=0;i<partnr;i++){
6078 if (part[i].type!=PARTTYPE_OS9MDR){
6079 continue;
6080 }
6081 if (mode){
6082 printf("/%s (%02x): ",part[i].devname,i);
6083 if ((part[i].bootsize)!=0){ /* bootable? */
6084 printf("*");
6085 }else{
6086 printf(" ");
6087 }
6088 printf(" %04x",part[i].blksiz);
6089 printf(" %06x %06x %06x ",
6090 part[i].startsec,
6091 part[i].psize, /* partition table entry */
6092 part[i].totsize); /* dd_tot in partition */
6093 if ((part[i].psize>0)&&(part[i].totsize>0)){
6094 if (part[i].mdr){
6095 printf("* ");
6096 printname(MDR_LSN0_P(part[i].lsn0)->mdr_name);
6097 }else{
6098 printf(" ");
6099 printname(lsn0[i].dd_name);
6100 }
6101 }
6102 printf("\n");
6103 }else{
6104 printf("/%s ",part[i].devname);
6105 if (part[i].mdr){
6106 printf("(%02x): * %06x ",
6107 i,part[i].mdr_filesyssize);
6108 if ((part[i].totsize>0)&&(part[i].mdr_filesyssize>0)){
6109 totfree=printpartinfo(part[i].devname,0,0,0);
6110 /* check if printpartinfo was successful */
6111 if (totfree>=0){
6112 printf(" %3i%%",100-(100*totfree)/part[i].mdr_filesyssize);
6113 }
6114 }
6115 }else{
6116 printf("(%02x):",i);
6117 printf(" %06x ",
6118 part[i].filesyssize);
6119 if ((part[i].totsize>0)&&(part[i].filesyssize>0)){
6120 totfree=printpartinfo(part[i].devname,0,0,0);
6121 /* check if printpartinfo was successful */
6122 if (totfree>=0){
6123 printf(" %3i%%",100-(100*totfree)/part[i].filesyssize);
6124 }
6125 }
6126 }
6127 printf("\n");
6128 }
6129 }
6130 if (mode){
6131 printf("-------------------------------------------------------------------------------\n\n");
6132 }else{
6133 printf("----------------------------------\n\n");
6134 }
6135 }
6136
6137 if (qdospartnr>0){
6138 /* QDOS partitions */
6139 printf("QDOS partitions: %02x\n",
6140 qdospartnr);
6141 if (mode){
6142 printf("partition b blk start ptsize id vn rn date user\n");
6143 printf("-------------------------------------------------------------------------------\n");
6144 }else{
6145 printf("partition filesys free used\n");
6146 printf("----------------------------------\n");
6147 }
6148 for (i=0;i<partnr;i++){
6149 if (part[i].type!=PARTTYPE_QDOS){
6150 continue;
6151 }
6152 if (mode){
6153 struct qdos_did_s *qp;
6154 u_int btsiz;
6155
6156 qp=QDOS_LSN0_P(part[i].lsn0);
6157 if (part[i].totsize!=0){
6158 printf("/%s (%02x): ",part[i].devname,i);
6159 btsiz=(qp->did_btsiz[0]<<8)+qp->did_btsiz[1];
6160 if (btsiz!=0){ /* bootable? */
6161 printf("*");
6162 }else{
6163 printf(" ");
6164 }
6165 printf(" %04x",part[i].blksiz);
6166 printf(" %06x ",part[i].startsec);
6167 printf("%06x ",QDOS_PSIZE/part[i].blksiz);
6168 printnstr(qp->did_id,8);
6169 printf(" %c%c %c%c",
6170 isprint(qp->did_vn[0])?qp->did_vn[0]:'?',
6171 isprint(qp->did_vn[1])?qp->did_vn[1]:'?',
6172 isprint(qp->did_rn[0])?qp->did_rn[0]:'?',
6173 isprint(qp->did_rn[1])?qp->did_rn[1]:'?');
6174 printf(" %c%c-%c%c-%c%c ",
6175 isprint(qp->did_dt[0])?qp->did_dt[0]:'?',
6176 isprint(qp->did_dt[1])?qp->did_dt[1]:'?',
6177 isprint(qp->did_dt[2])?qp->did_dt[2]:'?',
6178 isprint(qp->did_dt[3])?qp->did_dt[3]:'?',
6179 isprint(qp->did_dt[4])?qp->did_dt[4]:'?',
6180 isprint(qp->did_dt[5])?qp->did_dt[5]:'?');
6181 printnstr(qp->did_nm,20);
6182 putchar('\n');
6183 /* XXX */
6184 }else{
6185 printf("/%s ????????\n",part[i].devname);
6186 /* XXX */
6187 }
6188 }else{
6189 printf("/%s ",part[i].devname);
6190 printf("(%02x):",i);
6191 printf(" %06x ",
6192 part[i].totsize); /* totsize!!! */
6193 if (part[i].totsize>0){
6194 totfree=printpartinfo(part[i].devname,0,0,0);
6195 /* check if printpartinfo was successful */
6196 if (totfree>=0){
6197 printf(" %3i%%",100-(100*totfree)/part[i].totsize); /* totsize!!! */
6198 }
6199 }
6200 printf("\n");
6201 }
6202 }
6203 if (mode){
6204 printf("-------------------------------------------------------------------------------\n\n");
6205 }else{
6206 printf("----------------------------------\n\n");
6207 }
6208 }
6209 }
6210
6211
6212
6213 /* general */
6214 int
findfile3(char * path,u_int * startsecp,struct part_s ** partp)6215 findfile3(char *path,u_int *startsecp,struct part_s **partp)
6216 {
6217 struct part_s *savecurpart;
6218 u_int savecurdirsec;
6219 int abspathflag;
6220 char *p,*pnext;
6221 int startsec;
6222 struct part_s *pp;
6223 int ret;
6224 char *pathbuf;
6225
6226 if (path==NULL){
6227 return -1;
6228 }
6229
6230 if ((strlen(path)==0)||(path[strlen(path)-1]=='/')){
6231 #ifdef DEBUG
6232 printf("findfile3: invalid path\n");
6233 #endif
6234 return -1;
6235 }
6236
6237 /* parse path string */
6238 abspathflag=0;
6239 if (path[0]=='/'){
6240 /* absolute path */
6241 abspathflag=1;
6242 path++; /* remove '/' */
6243 }else{
6244 pp=curpart; /* remains the same */
6245 }
6246
6247 /* save path string since strtok destroys it! */
6248 pathbuf=(char *)malloc(strlen(path)+1); /* +1 for '\0' */
6249 if (pathbuf==NULL){
6250 perror("findfile3: malloc");
6251 return -1;
6252 }
6253 bcopy(path,pathbuf,strlen(path)+1); /* +1 for '\0' */
6254
6255 p=strtok(pathbuf,"/"); /* first token */
6256 if (p==NULL){
6257 #ifdef DEBUG
6258 printf("findfile3: invalid path\n");
6259 #endif
6260 free(pathbuf);
6261 return -1;
6262 }
6263
6264 /* save current state */
6265 savecurpart=curpart;
6266 /* for OS9 */
6267 savecurdirsec=curdirsec;
6268
6269 ret=0; /* no error yet */
6270 while (1){
6271 /* if we arrive here => p!=NULL */
6272
6273 #ifdef DEBUG
6274 printf("findfile3: token=\"%s\"\n",p);
6275 #endif
6276
6277 /* get next token in advance */
6278 pnext=strtok(NULL,"/");
6279
6280 if (abspathflag){
6281 /* change partition */
6282 pp=partchange2(p,1); /* 1: check */
6283 if (pp==NULL){
6284 #ifdef DEBUG
6285 err_print("findfile3: invalid partition\n");
6286 #endif
6287 ret=-1;
6288 goto findfile3_done; /* done */
6289 }
6290
6291 /* check if this is the last token */
6292 if (pnext==NULL){
6293 if (curpart->type==PARTTYPE_QDOS){
6294 /* QDOS */
6295 /* we are in root directory after the partition change */
6296 /* OK */
6297 startsec=0; /* symbolic value for root directory */
6298 }else if (curpart->type==PARTTYPE_OS9MDR){
6299 if (curpart->mdr){
6300 /* MDR-DOS */
6301 /* we are in root directory after the partition change */
6302 /* OK */
6303 startsec=0; /* symbolic value for root directory */
6304 }else{
6305 /* OS9 */
6306 /* return startsec of root directory */
6307 startsec=curpart->rootdirsec;
6308 }
6309 }else{
6310 #ifdef DEBUG
6311 err_print("findfile3: invalid partition type\n");
6312 #endif
6313 ret=-1;
6314 goto findfile3_done; /* done */
6315 }
6316 goto findfile3_done; /* done */
6317 }else{
6318 if (curpart->type==PARTTYPE_QDOS){
6319 /* QDOS */
6320 /* we are in root directory */
6321 /* OK */
6322 }else if (curpart->type==PARTTYPE_OS9MDR){
6323 if (curpart->mdr){
6324 /* MDR-DOS */
6325 /* we are in root directory */
6326 /* OK */
6327 }else{
6328 /* OS9 */
6329 /* change to root directory */
6330 curdirsec=curpart->rootdirsec;
6331 }
6332 }else{
6333 #ifdef DEBUG
6334 err_print("findfile3: invalid partition type\n");
6335 #endif
6336 ret=-1;
6337 goto findfile3_done; /* done */
6338 }
6339 }
6340 /* if we arrive here => pnext!=NULL */
6341
6342 abspathflag=0;
6343 }else{
6344 if (curpart->type==PARTTYPE_QDOS){
6345 /* QDOS */
6346 /* no directories except root in QDOS */
6347 /* => this must be the last token */
6348 /* check if this is not the last token */
6349 if (pnext!=NULL){
6350 #ifdef DEBUG
6351 err_print("findfile3: no sub-directories in QDOS\n");
6352 #endif
6353 ret=-1;
6354 goto findfile3_done; /* done */
6355 }
6356 /* now p is the name of file we are looking for */
6357 if (strcmp(p,".")==0){
6358 startsec=0; /* symbolic value for root directory */
6359 }else{
6360 /* find QDOS file */
6361 startsec=qdos_findfile(p); /* file number+1 !!! */
6362 if (startsec<0){
6363 ret=-1;
6364 goto findfile3_done; /* done */
6365 }
6366 }
6367 goto findfile3_done; /* done */
6368 }else if (curpart->type==PARTTYPE_OS9MDR){
6369 if (curpart->mdr){
6370 /* MDR-DOS */
6371 /* no directories except root in MDR-DOS */
6372 /* => this must be the last token */
6373 /* check if this is not the last token */
6374 if (pnext!=NULL){
6375 #ifdef DEBUG
6376 err_print("findfile3: no sub-directories in MDR-DOS\n");
6377 #endif
6378 ret=-1;
6379 goto findfile3_done; /* done */
6380 }
6381 /* now p is the name of file we are looking for */
6382 if (strcmp(p,".")==0){
6383 startsec=0; /* symbolic value for root directory */
6384 }else{
6385 /* find MDR-DOS file */
6386 startsec=mdr_findfile(p); /* file number+1 !!! */
6387 if (startsec<0){
6388 ret=-1;
6389 goto findfile3_done; /* done */
6390 }
6391 }
6392 goto findfile3_done; /* done */
6393 }
6394
6395 /* OS9 */
6396 /* check if this is the last token */
6397 if (pnext==NULL){
6398 /* now p is the name of file we are looking for */
6399 startsec=findfile(p,0,NULL); /* file descriptor */
6400 if (startsec<0){
6401 #ifdef DEBUG
6402 err_print("findfile3: invalid file descriptor\n");
6403 #endif
6404 ret=-1;
6405 goto findfile3_done; /* done */
6406 }
6407 goto findfile3_done; /* done */
6408 }else{
6409 /* change directory */
6410 if (changedir2(p)<0){
6411 err_print("findfile3: invalid directory\n");
6412 ret=-1;
6413 goto findfile3_done; /* done */
6414 }
6415 }
6416 }else{
6417 #ifdef DEBUG
6418 err_print("findfile3: invalid partition type\n");
6419 #endif
6420 ret=-1;
6421 goto findfile3_done; /* done */
6422 }
6423 /* if we arrive here => pnext!=NULL */
6424 }
6425 /* if we arrive here => pnext!=NULL */
6426 p=pnext;
6427 /* if we arrive here => p!=NULL */
6428 }
6429 /* should be never reached */
6430 /* fall through */
6431
6432 findfile3_done:
6433 if (startsecp!=NULL){
6434 *startsecp=startsec; /* return start sector */
6435 /* OS9: file descriptor, MDR-DOS: directory entry */
6436 }
6437 if (partp!=NULL){
6438 *partp=pp; /* return pointer to partition */
6439 }
6440
6441 /* restore state */
6442 curpart=savecurpart;
6443 /* for OS9 */
6444 curdirsec=savecurdirsec;
6445
6446 free(pathbuf);
6447 return ret;
6448 }
6449
6450 /* general */
6451 /* same algorithm as in findfile3! */
6452 /* the following could be done by findfile3 */
6453 /* But: if it fails, dirlist would be corrupt! */
6454 /* we assume here that path is vaild */
6455 int
dirlistupdate3(char * path)6456 dirlistupdate3(char *path)
6457 {
6458 int abspathflag;
6459 char *p,*pnext;
6460 char *pathbuf;
6461
6462 if (path==NULL){
6463 return -1;
6464 }
6465
6466 if ((strlen(path)==0)||(path[strlen(path)-1]=='/')){
6467 err_print("dirlistupdate3: invalid path\n");
6468 return -1;
6469 }
6470
6471 /* parse path string */
6472 abspathflag=0;
6473 if (path[0]=='/'){
6474 /* absolute path */
6475 abspathflag=1;
6476 path++; /* remove '/' */
6477 }
6478
6479 /* save path string since strtok destroys it! */
6480 pathbuf=(char *)malloc(strlen(path)+1); /* +1 for '\0' */
6481 if (pathbuf==NULL){
6482 perror("dirlistupdate3: malloc");
6483 return -1;
6484 }
6485 bcopy(path,pathbuf,strlen(path)+1); /* +1 for '\0' */
6486
6487 p=strtok(pathbuf,"/"); /* first token */
6488 if (p==NULL){
6489 err_print("dirlistupdate3: invalid path\n");
6490 free(pathbuf);
6491 return -1;
6492 }
6493
6494 while (1){
6495 /* if we arrive here => p!=NULL */
6496
6497 #ifdef DEBUG
6498 printf("dirlistupdate3: token=\"%s\"\n",p);
6499 #endif
6500
6501 /* get next token in advance */
6502 pnext=strtok(NULL,"/");
6503
6504 if (abspathflag){
6505 /* change to root directory */
6506 dirlevel=0;
6507 /* check if this is the last token */
6508 if (pnext==NULL){
6509 goto dirlistupdate3_done; /* done */
6510 }
6511 /* if we arrive here => pnext!=NULL */
6512
6513 abspathflag=0;
6514 }else{
6515 /* now p is the name of the directory */
6516 /* interpret p */
6517 if (strcmp(p,".")==0){
6518 /* nothing */
6519 }else if (strcmp(p,"..")==0){
6520 /* one up */
6521 if (dirlevel>0){
6522 dirlevel--;
6523 }
6524 }else{
6525 /* one down */
6526 /* space left? */
6527 if (dirlevel<DIRLEVELNR){
6528 /* save name */
6529 strcpy(dirlist[dirlevel],p);
6530 }
6531 dirlevel++;
6532 }
6533
6534 /* check if this is the last token */
6535 if (pnext==NULL){
6536 goto dirlistupdate3_done; /* done */
6537 }
6538 /* if we arrive here => pnext!=NULL */
6539 }
6540 /* if we arrive here => pnext!=NULL */
6541 p=pnext;
6542 /* if we arrive here => p!=NULL */
6543 }
6544 /* should be never reached */
6545 /* fall through */
6546
6547 dirlistupdate3_done:
6548
6549 free(pathbuf);
6550 return 0;
6551 }
6552
6553
6554
6555 /* general */
6556 void
printdirlist(void)6557 printdirlist(void)
6558 {
6559 int i,imax;
6560
6561 printf("/%s",curpart->devname);
6562
6563 if (curpart->type==PARTTYPE_QDOS){
6564 printf(" (QDOS)");
6565 return;
6566 }else if (curpart->type!=PARTTYPE_OS9MDR){
6567 printf(" (???)");
6568 return;
6569 }
6570
6571 if (curpart->mdr){
6572 printf(" (MDR-DOS)");
6573 return;
6574 }
6575
6576 /* OS9 */
6577 if (dirlevel>DIRLEVELNR){
6578 imax=DIRLEVELNR;
6579 }else{
6580 imax=dirlevel;
6581 }
6582 for (i=0;i<imax;i++){
6583 printf("/%s",dirlist[i]);
6584 }
6585 if (dirlevel>DIRLEVELNR){
6586 printf("/...(%i)...",dirlevel-DIRLEVELNR);
6587 }
6588 printf(" (OS9)");
6589 }
6590
6591
6592
6593 /* general */
6594 int
changedir3(char * path,int update)6595 changedir3(char *path,int update)
6596 {
6597 u_int startsec;
6598 static struct part_s *pp;
6599
6600 if (path==NULL){
6601 return -1;
6602 }
6603
6604 /* find directory file */
6605 if (findfile3(path,&startsec,&pp)<0){
6606 err_print("changedir3: cannot find directory\n");
6607 return -1;
6608 }
6609 /* change partition */
6610 curpart=pp;
6611
6612 if (curpart->type==PARTTYPE_QDOS){
6613 /* QDOS */
6614 /* only root directory allowed */
6615 if (startsec!=0){ /* symbolic value, see findfile3! */
6616 err_print("changedir3: no sub-directories in QDOS\n");
6617 return -1;
6618 }
6619 }else if (curpart->type==PARTTYPE_OS9MDR){
6620 /* now OS9 or MDR-DOS */
6621 if (curpart->mdr){
6622 /* MDR-DOS */
6623 /* only root directory allowed */
6624 if (startsec!=0){ /* symbolic value, see findfile3! */
6625 err_print("changedir3: no sub-directories in MDR-DOS\n");
6626 return -1;
6627 }
6628 }else{
6629 /* OS9 */
6630 static struct filedes_s curdirdes;
6631
6632 /* check if valid directory */
6633 if (getdir(startsec,&curdirdes,NULL)<0){
6634 err_print("changedir3: cannot change directory\n");
6635 return -1;
6636 }
6637 /* change directory */
6638 curdirsec=startsec;
6639 }
6640 }else{
6641 err_print("changedir3: invalid partition type\n");
6642 return -1;
6643 }
6644
6645 /* the following could be done by findfile3 */
6646 /* But: if it fails, dirlist would be corrupt! */
6647 /* so we can assume here that path is vaild */
6648 /* update dirlist? */
6649 if (update){
6650 return dirlistupdate3(path);
6651 }
6652
6653 return 0;
6654 }
6655
6656
6657
6658 /* general */
6659 int
creatfile3(char * path,u_int bytesize,int dir,struct genfile_s * tmplt)6660 creatfile3(char *path,u_int bytesize,int dir,struct genfile_s *tmplt)
6661 {
6662 struct part_s *savecurpart;
6663 u_int savecurdirsec;
6664 int ret;
6665 char *pathbuf;
6666 char *filenam;
6667
6668 if (path==NULL){
6669 return -1;
6670 }
6671
6672 /* save path string! */
6673 pathbuf=(char *)malloc(strlen(path)+1); /* +1 for '\0' */
6674 if (pathbuf==NULL){
6675 perror("creatfile3: malloc");
6676 return -1;
6677 }
6678 bcopy(path,pathbuf,strlen(path)+1); /* +1 for '\0' */
6679
6680 /* save current state */
6681 savecurpart=curpart;
6682 /* for OS9 */
6683 savecurdirsec=curdirsec;
6684
6685 /* extract device/directory-path and name */
6686 filenam=strrchr(pathbuf,'/'); /* last '/' in pathbuf */
6687 if (filenam==NULL){
6688 /* '/' not found */
6689 filenam=pathbuf;
6690 }else if (filenam==pathbuf){
6691 /* only one occurcence of '/' and this at the beginning */
6692 /* => invalid file path */
6693 err_print("creatfile3: invalid path\n");
6694 ret=-1;
6695 goto creatfile3_exit;
6696 }else{
6697 *filenam='\0'; /* terminate newpath */
6698 filenam++;
6699 ret=changedir3(pathbuf,0);
6700 if (ret<0){
6701 err_print("creatfile3: path not found\n");
6702 ret=-1;
6703 goto creatfile3_exit;
6704 }
6705 }
6706 if (strlen(filenam)==0){
6707 err_print("creatfile3: invalid file name\n");
6708 ret=-1;
6709 goto creatfile3_exit;
6710 }
6711
6712 /* check if contents of tmplt fit to partition type */
6713 if (tmplt!=NULL){
6714 if (tmplt->part->type!=curpart->type){
6715 tmplt=NULL; /* XXX should convert */
6716 }else if (tmplt->part->type==PARTTYPE_OS9MDR){
6717 if (tmplt->part->mdr!=curpart->mdr){
6718 tmplt=NULL; /* XXX should convert */
6719 }
6720 }
6721 }
6722 /* XXX no check if tmplt is directory!!! */
6723
6724 /* parse partition type */
6725 ret=0; /* no error yet */
6726 if (curpart->type==PARTTYPE_OS9MDR){
6727 if (!curpart->mdr){
6728 /* OS9 */
6729 ret=creatfile(filenam,bytesize,dir,&tmplt->fdes.os9);
6730 }else{
6731 /* MDR-DOS */
6732 if (dir){
6733 err_print("creatfile3: cannot create directory in MDR-DOS partition\n");
6734 ret=-1;
6735 }else{
6736 ret=mdr_creatfile(filenam,bytesize,&tmplt->fdes.mdrdos);
6737 }
6738 }
6739 }else if (curpart->type==PARTTYPE_QDOS){
6740 /* QDOS */
6741 if (dir){
6742 err_print("creatfile3: cannot create directory in QDOS partition\n");
6743 ret=-1;
6744 }else{
6745 ret=qdos_creatfile(filenam,bytesize,&tmplt->fdes.qdos);
6746 }
6747 }else{
6748 ret=-1;
6749 }
6750
6751 creatfile3_exit:
6752 /* restore state */
6753 curpart=savecurpart;
6754 /* for OS9 */
6755 curdirsec=savecurdirsec;
6756
6757 free(pathbuf);
6758 return ret;
6759 }
6760
6761
6762
6763 /* general */
6764 /* size via pointer instead of return: want to have full 2^32!!! */
6765 int
readfiledes3(char * path,union genfdes_u * fp,u_int * typep,u_int * mdrp,u_int * startsecp,struct part_s ** partp,u_int * fdessecp,int pchg,u_int * sizep,int touch)6766 readfiledes3(char *path,union genfdes_u *fp,u_int *typep,u_int *mdrp,
6767 u_int *startsecp,struct part_s **partp,u_int *fdessecp,
6768 int pchg,u_int *sizep,int touch)
6769 {
6770 struct part_s *savecurpart;
6771 static u_int startsec;
6772 static struct part_s *pp;
6773 int ret;
6774 u_int size;
6775
6776 if ((path==NULL)||(fp==NULL)){
6777 return -1;
6778 }
6779
6780 if (findfile3(path,&startsec,&pp)<0){
6781 err_print("readfiledes3: cannot find file\n");
6782 return -1;
6783 }
6784 if (startsecp!=NULL){
6785 *startsecp=startsec; /* see findfile3 for meaning of startsec!!! */
6786 }
6787 if (partp!=NULL){
6788 *partp=pp;
6789 }
6790
6791 if (!pchg){
6792 /* save state */
6793 savecurpart=curpart;
6794 }
6795 /* change partition */
6796 curpart=pp;
6797
6798 if (typep!=NULL)
6799 *typep=curpart->type;
6800 if (mdrp!=NULL)
6801 *mdrp=curpart->mdr;
6802
6803 ret=0; /* no error yet */
6804 if (curpart->type==PARTTYPE_OS9MDR){
6805 if (!curpart->mdr){
6806 /* OS9 */
6807 struct filedes_s *fdesp;
6808
6809 fdesp=&fp->os9;
6810
6811 if (fdessecp!=NULL){
6812 *fdessecp=startsec; /* sector of file descriptor */
6813 }
6814
6815 /* read file descriptor */
6816 ret=READBLOCK_CURPART(startsec,fdesp,1);
6817
6818 if (ret<0){
6819 err_print("readfiledes3: cannot read file descriptor\n");
6820 goto readfiledes3_exit;
6821 }
6822
6823 size=(fdesp->fd_fsize[0]<<24)
6824 +(fdesp->fd_fsize[1]<<16)
6825 +(fdesp->fd_fsize[2]<<8)
6826 +fdesp->fd_fsize[3];
6827 if (touch){
6828 /* update modif date */
6829 setdate(fdesp,0); /* 0: not creat */
6830 /* write file descriptor */
6831 ret=WRITEBLOCK_CURPART(startsec,fdesp,1);
6832 if (ret<0){
6833 err_print("readfiledes3: cannot update file descriptor\n");
6834 goto readfiledes3_exit;
6835 }
6836 }
6837 }else{
6838 /* MDR-DOS */
6839 struct mdr_dirent_s *direntp;
6840 u_int fsec;
6841
6842 /* Note: findfile3 returns 0 as symbolic value for root directory in startsec for MDR-DOS!!! */
6843 if (startsec==0){
6844 /* MDR-DOS root directory: not a file! */
6845 err_print("readfiledes3: MDR-DOS root directory not allowed\n");
6846 ret=-1;
6847 goto readfiledes3_exit;
6848 }
6849
6850 direntp=&fp->mdrdos;
6851
6852 /* read mdr_dirent_s */
6853 /* Note: findfile3 returns file number+1 in startsec for MDR-DOS!!! */
6854 fsec=MDR_DIRSTART+(startsec-1)*MDR_DIRENTRYSIZE;
6855 ret=READBLOCK_CURPART(fsec,direntp,MDR_DIRENTRYSIZE);
6856 if (ret<0){
6857 err_print("readfiledes3: cannot read directory entry\n");
6858 goto readfiledes3_exit;
6859 }
6860 if (fdessecp!=NULL){
6861 *fdessecp=fsec; /* sector of directory entry */
6862 }
6863
6864 size=(direntp->size[0]<<24)
6865 +(direntp->size[1]<<16)
6866 +(direntp->size[2]<<8)
6867 +direntp->size[3];
6868 if (touch){
6869 /* update modif date */
6870 mdr_setdate(direntp,0); /* 0: not creat */
6871 /* write mdr_dirent_s */
6872 ret=WRITEBLOCK_CURPART(fsec,direntp,MDR_DIRENTRYSIZE);
6873 if (ret<0){
6874 err_print("readfiledes3: cannot touch directory entry\n");
6875 goto readfiledes3_exit;
6876 }
6877 }
6878 }
6879 }else if (curpart->type==PARTTYPE_QDOS){
6880 /* QDOS */
6881 struct qdos_fdes_s *qfdesp;
6882 struct qdos_dir_s *qdirp;
6883 struct qdos_rib_s *qribp;
6884 u_char dirbuf[QDOS_DIRSIZE*QDOS_BLOCKSIZE];
6885 struct qdos_dir_s *qbufp;
6886 u_int fsec;
6887
6888 /* Note: findfile3 returns 0 as symbolic value for root directory in startsec for QDOS!!! */
6889 if (startsec==0){
6890 /* QDOS root directory: not a file! */
6891 err_print("readfiledes3: QDOS root directory not allowed\n");
6892 ret=-1;
6893 goto readfiledes3_exit;
6894 }
6895
6896 /* read directory */
6897 if (READBLOCK_CURPART(QDOS_DIRSTART,(void *)dirbuf,QDOS_DIRSIZE)<0){
6898 err_print("readfiledes3: cannot read directory\n");
6899 ret=-1;
6900 goto readfiledes3_exit;
6901 }
6902 qfdesp=&fp->qdos;
6903 qdirp=&qfdesp->dir;
6904 qribp=&qfdesp->rib;
6905
6906 qbufp=(struct qdos_dir_s *)dirbuf;
6907
6908 /* read RIB (QDOS_BLOCKSIZE!!!) */
6909 /* Note: findfile3 returns file number+1 in startsec for QDOS!!! */
6910 fsec=(qbufp[startsec-1].dir_rb[0]<<8)+qbufp[startsec-1].dir_rb[1];
6911 if (fsec==0){
6912 err_print("readfiledes3: invalid RIB sector\n");
6913 ret=-1;
6914 goto readfiledes3_exit;
6915 }
6916 if (fdessecp!=NULL){
6917 *fdessecp=fsec; /* sector of RIB */
6918 }
6919 ret=READBLOCK_CURPART(fsec,qribp,1);
6920 if (ret<0){
6921 err_print("readfiledes3: cannot read RIB\n");
6922 goto readfiledes3_exit;
6923 }
6924 size=qdos_fsize(qribp);
6925
6926 if (touch){
6927 /* set/clear ATT_CON flag in directory entry if file is contiguous: */
6928 /* Note: findfile3 returns file number+1 in startsec for QDOS!!! */
6929 ret=qdos_setattr(qribp,startsec-1,dirbuf,NULL);
6930 if (ret<0){
6931 err_print("readfiledes3: cannot set/clear ATT_CON\n");
6932 goto readfiledes3_exit;
6933 }
6934 }
6935
6936 /* get (possibly modified) directory entry */
6937 /* Note: findfile3 returns file number+1 in startsec for QDOS!!! */
6938 bcopy(&qbufp[startsec-1],qdirp,sizeof(struct qdos_dir_s));
6939 }else{
6940 ret=-1;
6941 }
6942
6943
6944 readfiledes3_exit:
6945 if (!pchg){
6946 /* restore state */
6947 curpart=savecurpart;
6948 }
6949 if (ret<0){
6950 size=0;
6951 }
6952
6953 #ifdef DEBUG
6954 printf("readfiledes3: size=%08x\n",size);
6955 #endif
6956 if (sizep!=NULL)
6957 *sizep=size;
6958
6959 return ret;
6960 }
6961
6962
6963
6964 /* general */
6965 int
extendfile3(char * path,u_int bytesize)6966 extendfile3(char *path,u_int bytesize)
6967 {
6968 struct part_s *savecurpart;
6969 union genfdes_u fdes;
6970 u_int srctype,srcmdr;
6971 struct part_s *pp;
6972 u_int startsec;
6973 u_int fdessec;
6974 int ret;
6975 u_int fsize;
6976 u_int spaceadd;
6977 u_int blknr;
6978
6979 if (path==NULL){
6980 return -1;
6981 }
6982 if (bytesize==0){
6983 /* nothing to append, done. */
6984 return 0;
6985 }
6986
6987 /* 1: touch! */
6988 if (readfiledes3(path,&fdes,&srctype,&srcmdr,&startsec,&pp,&fdessec,0,&fsize,1)<0){
6989 err_print("extendfile3: invalid path\n");
6990 return -1;
6991 }
6992
6993 /* save current state */
6994 savecurpart=curpart;
6995 /* change partition */
6996 curpart=pp;
6997
6998 /* parse partition type */
6999 ret=0; /* no error yet */
7000 if (curpart->type==PARTTYPE_OS9MDR){
7001 /* XXX 32-Bit fsize limit: */
7002 if ((((OFF_T)fsize)+((OFF_T)bytesize))>0xffffffffUL){
7003 err_print("extendfile3: invalid bytesize\n");
7004 return -1;
7005 }
7006 if (!curpart->mdr){
7007 /* OS9 */
7008 if (fdes.os9.fd_att&ATT_D){
7009 err_print("extendfile3: directory not allowed\n");
7010 ret=-1;
7011 goto extendfile3_exit;
7012 }
7013 spaceadd=curpart->blksiz*countseg(&fdes.os9.fd_seg[0],FILEDES_SEGNR,NULL);
7014 if (spaceadd<fsize){
7015 /* XXX corrupt fsize!!! */
7016 fsize=spaceadd;
7017 err_print("extendfile3: corrupt file size corrected\n");
7018 }
7019 /* bytes left */
7020 spaceadd-=fsize;
7021 if (spaceadd<bytesize){
7022 /* must allocate new block(s) */
7023 spaceadd=bytesize-spaceadd;
7024 /* round up to blocksize */
7025 /* XXX 32-Bit overflow protection */
7026 blknr=(u_int)((((OFF_T)spaceadd)+((OFF_T)curpart->blksiz-1))
7027 /((OFF_T)curpart->blksiz));
7028 ret=filecreat(&fdes.os9,blknr,1); /* 1: extend */
7029 if (ret<0){
7030 goto extendfile3_exit;
7031 }
7032 }
7033 /* update file descriptor */
7034 fsize+=bytesize;
7035 fdes.os9.fd_fsize[0]=0xff&(fsize>>24);
7036 fdes.os9.fd_fsize[1]=0xff&(fsize>>16);
7037 fdes.os9.fd_fsize[2]=0xff&(fsize>>8);
7038 fdes.os9.fd_fsize[3]=0xff&fsize;
7039 /* write updated file descriptor */
7040 if (WRITEBLOCK_CURPART(fdessec,&fdes.os9,1)<0){
7041 err_print("extendfile3: cannot write updated file descriptor\n");
7042 ret=-1;
7043 goto extendfile3_exit;
7044 }
7045 }else{
7046 /* MDR-DOS */
7047
7048 /* Note: findfile3 returns 0 as symbolic value for root directory in startsec for MDR-DOS!!! */
7049 if (startsec==0){
7050 /* MDR-DOS root directory: not a file! */
7051 err_print("extendfile3: MDR-DOS root directory not allowed\n");
7052 ret=-1;
7053 goto extendfile3_exit;
7054 }
7055
7056 spaceadd=curpart->blksiz*curpart->mdr_clustersize
7057 *mdr_countclu(&fdes.mdrdos,MDR_FILECLNR,NULL);
7058 if (spaceadd<fsize){
7059 /* XXX corrupt fsize!!! */
7060 fsize=spaceadd;
7061 err_print("extendfile3: corrupt file size corrected\n");
7062 }
7063 /* bytes left */
7064 spaceadd-=fsize;
7065 if (spaceadd<bytesize){
7066 /* must allocate new block(s) */
7067 spaceadd=bytesize-spaceadd;
7068 /* round up to cluster size */
7069 /* XXX 32-Bit overflow protection */
7070 blknr=(u_int)((((OFF_T)spaceadd)+((OFF_T)curpart->mdr_clustersize*curpart->blksiz-1))
7071 /((OFF_T)curpart->mdr_clustersize*curpart->blksiz));
7072 ret=mdr_filecreat(&fdes.mdrdos,blknr,1); /* 1: extend */
7073 if (ret<0){
7074 goto extendfile3_exit;
7075 }
7076 }
7077 /* update directory entry */
7078 fsize+=bytesize;
7079 fdes.mdrdos.size[0]=0xff&(fsize>>24);
7080 fdes.mdrdos.size[1]=0xff&(fsize>>16);
7081 fdes.mdrdos.size[2]=0xff&(fsize>>8);
7082 fdes.mdrdos.size[3]=0xff&fsize;
7083 /* write updated directory entry */
7084 if (WRITEBLOCK_CURPART(fdessec,&fdes.mdrdos,MDR_DIRENTRYSIZE)<0){
7085 err_print("extendfile3: cannot write updated directory entry\n");
7086 ret=-1;
7087 goto extendfile3_exit;
7088 }
7089 }
7090 }else if (curpart->type==PARTTYPE_QDOS){
7091 /* QDOS */
7092 u_int ribsec,qsiz;
7093
7094 /* Note: findfile3 returns 0 as symbolic value for root directory in startsec for QDOS!!! */
7095 if (startsec==0){
7096 /* QDOS root directory: not a file! */
7097 err_print("extendfile3: QDOS root directory not allowed\n");
7098 ret=-1;
7099 goto extendfile3_exit;
7100 }
7101
7102 spaceadd=curpart->blksiz*QDOS_CSIZE
7103 *qdos_countseg(&fdes.qdos.rib,QDOS_RIB_SDWNR,NULL);
7104 /* Note: first block of file allocation is used for RIB!!! */
7105 if (spaceadd<curpart->blksiz*QDOS_CSIZE){
7106 err_print("extendfile3: corrupt allocation size\n");
7107 ret=-1;
7108 goto extendfile3_exit;
7109 }
7110 spaceadd-=curpart->blksiz;
7111 if (spaceadd<fsize){
7112 /* XXX corrupt fsize!!! */
7113 fsize=spaceadd;
7114 err_print("extendfile3: corrupt file size corrected\n");
7115 }
7116 /* bytes left */
7117 spaceadd-=fsize;
7118 if (spaceadd<bytesize){
7119 /* must allocate new block(s) */
7120 spaceadd=bytesize-spaceadd;
7121 /* round up to blocksize */
7122 /* XXX 32-Bit overflow protection not necessary for QDOS */
7123 blknr=(spaceadd+curpart->blksiz-1)/curpart->blksiz;
7124 ret=qdos_filecreat(&fdes.qdos.rib,blknr,1); /* 1: extend */
7125 if (ret<0){
7126 goto extendfile3_exit;
7127 }
7128 }
7129 /* update file size in RIB */
7130 fsize+=bytesize;
7131 ret=qdos_setfsize(&fdes.qdos.rib,fsize);
7132 if (ret<0){
7133 err_print("extendfile3: corrupt RIB\n");
7134 goto extendfile3_exit;
7135 }
7136 /* Note: first block of file allocation is used for RIB!!! */
7137 qdos_getseg(&fdes.qdos.rib,0,&ribsec,&qsiz);
7138 if (qsiz==0){
7139 /* empty first segment => corrupt RIB!!! */
7140 err_print("extendfile3: corrupt RIB\n");
7141 ret=-1;
7142 goto extendfile3_exit;
7143 }
7144 ribsec*=QDOS_CSIZE;
7145 /* write updated RIB */
7146 if (WRITEBLOCK_CURPART(ribsec,&fdes.qdos.rib,1)<0){
7147 err_print("extendfile3: cannot write updated RIB\n");
7148 ret=-1;
7149 goto extendfile3_exit;
7150 }
7151 /* set/clear ATT_CON flag in directory entry if file is contiguous: */
7152 /* Note: findfile3 returns file number+1 in startsec for QDOS!!! */
7153 ret=qdos_setattr(&fdes.qdos.rib,startsec-1,NULL,NULL);
7154 if (ret<0){
7155 err_print("extendfile3: cannot set/clear ATT_CON\n");
7156 goto extendfile3_exit;
7157 }
7158 }else{
7159 ret=-1;
7160 }
7161
7162 extendfile3_exit:
7163 /* restore state */
7164 curpart=savecurpart;
7165 return ret;
7166 }
7167
7168
7169
7170 /* general */
7171 int
lsn0reset(void)7172 lsn0reset(void)
7173 {
7174 static u_char buf[OS9MAX_BLOCKSIZE];
7175
7176 /* Note: OS9MAX_BLOCKSIZE is also enough for QDOS_BLOCKSIZE */
7177
7178 /* clear */
7179 bzero(buf,OS9MAX_BLOCKSIZE);
7180 /* save new LSN0 */
7181 if (WRITEBLOCK_CURPART(0,buf,1)<0){
7182 err_print("lsn0reset: cannot write LSN0\n");
7183 /* XXX can't undo previous actions */
7184 return -1;
7185 }
7186
7187 return 0;
7188 /* Note: must restart program after modification of LSN0!!! */
7189 }
7190
7191 /* OS9 */
7192 int
lsn0bootfile(char * path,int bsz)7193 lsn0bootfile(char *path,int bsz)
7194 {
7195 static u_int size,bstart,dummy;
7196 static struct part_s *pp;
7197 static struct filedes_s fdes;
7198
7199 if (curpart->type!=PARTTYPE_OS9MDR){
7200 return -1;
7201 }
7202 if (curpart->mdr){
7203 err_print("lsn0bootfile: must be OS9 filesystem\n");
7204 return -1;
7205 }
7206
7207 if (path!=NULL){
7208 /* set bootfile entry */
7209
7210 /* find file and check if file is in master partition */
7211 if (findfile3(path,NULL,&pp)<0){
7212 err_print("lsn0bootfile: cannot find file\n");
7213 return -1;
7214 }
7215 if (pp!=curpart){ /* must be in same partition */
7216 err_print("lsn0bootfile: file not in same partition\n");
7217 return -1;
7218 }
7219
7220 /* read file descriptor */
7221 if (readfiledes3(path,(union genfdes_u *)&fdes,NULL,NULL,NULL,NULL,NULL,0,&size,0)<0){
7222 err_print("lsn0bootfile: cannot read file descriptor\n");
7223 return -1;
7224 }
7225 /* check if file size is valid */
7226 if (bsz>=0){ /* given size */
7227 if (bsz>0xffff){ /* dd_bsz has 2 bytes! */
7228 err_print("lsn0bootfile: bsz too large\n");
7229 return -1;
7230 }
7231 if (size<(u_int)bsz){
7232 err_print("lsn0bootfile: warning: file might be too small\n");
7233 /* XXX no error */
7234 }
7235 size=bsz; /* take given value */
7236 }else{
7237 if (size>0xffff){ /* dd_bsz has 2 bytes! */
7238 err_print("lsn0bootfile: file too large\n");
7239 return -1;
7240 }
7241 }
7242 /* check if file is contiguous */
7243 getseg(&fdes.fd_seg[1],NULL,&dummy);
7244 if (dummy!=0){
7245 err_print("lsn0bootfile: file not contiguous\n");
7246 return -1;
7247 }
7248 /* get start block of data */
7249 getseg(&fdes.fd_seg[0],&bstart,NULL);
7250 }else{
7251 /* clear bootfile entry */
7252
7253 bstart=0;
7254 size=0;
7255 }
7256
7257 /* set curpart... */
7258 curpart->bootsec=bstart;
7259 curpart->bootsize=size;
7260 /* set LSN0 bootfile entries */
7261 curpart->lsn0->dd_bsz[1]=size;
7262 curpart->lsn0->dd_bsz[0]=size>>8;
7263 curpart->lsn0->dd_bt[2]=bstart;
7264 curpart->lsn0->dd_bt[1]=bstart>>8;
7265 curpart->lsn0->dd_bt[0]=bstart>>16;
7266 /* save new LSN0 */
7267 if (WRITEBLOCK_CURPART(0,curpart->lsn0,1)<0){
7268 err_print("lsn0bootfile: cannot write LSN0\n");
7269 /* XXX can't undo previous actions */
7270 return -1;
7271 }
7272
7273 return 0;
7274 }
7275
7276 /* OS9 */
7277 int
lsn0partfile(char * path)7278 lsn0partfile(char *path)
7279 {
7280 static u_int size,pstart,pn,dummy;
7281 static struct part_s *pp;
7282 static struct filedes_s fdes;
7283
7284 if (curpart->type!=PARTTYPE_OS9MDR){
7285 return -1;
7286 }
7287 if (curpart->mdr){
7288 err_print("lsn0partfile: must be OS9 filesystem\n");
7289 return -1;
7290 }
7291
7292 if (path!=NULL){
7293 /* set partfile entry */
7294
7295 /* find file and check if file is in master partition */
7296 if (findfile3(path,NULL,&pp)<0){
7297 err_print("lsn0partfile: cannot find file\n");
7298 return -1;
7299 }
7300 if (pp!=curpart){ /* must be in same partition */
7301 err_print("lsn0partfile: file not in same partition\n");
7302 return -1;
7303 }
7304
7305 /* read file descriptor */
7306 if (readfiledes3(path,(union genfdes_u *)&fdes,NULL,NULL,NULL,NULL,NULL,0,&size,0)<0){
7307 err_print("lsn0partfile: cannot read file descriptor\n");
7308 return -1;
7309 }
7310 /* check if file size is valid */
7311 if (size!=PARTTAB_NR*sizeof(struct parttabent_s)){
7312 char b[128];
7313 sprintf(b,"lsn0partfile: file size invalid (must be 0x%x bytes)\n",
7314 PARTTAB_NR*sizeof(struct parttabent_s));
7315 err_print(b);
7316 return -1;
7317 }
7318 /* check if file is contiguous */
7319 getseg(&fdes.fd_seg[1],NULL,&dummy);
7320 if (dummy!=0){
7321 err_print("lsn0partfile: file not contiguous\n");
7322 return -1;
7323 }
7324 /* get start block of data */
7325 getseg(&fdes.fd_seg[0],&pstart,NULL);
7326 pn=PARTTAB_NR; /* partition-slots in partfile */
7327 }else{
7328 /* clear partfile entry */
7329
7330 pstart=0;
7331 pn=0;
7332 }
7333
7334 /* set curpart... */
7335 curpart->ptabsec=pstart;
7336 curpart->pnr=pn;
7337 /* set LSN0 partfile entries */
7338 curpart->lsn0->dd_ptabstart[2]=pstart;
7339 curpart->lsn0->dd_ptabstart[1]=pstart>>8;
7340 curpart->lsn0->dd_ptabstart[0]=pstart>>16;
7341 curpart->lsn0->dd_pnr=pn;
7342 /* save new LSN0 */
7343 if (WRITEBLOCK_CURPART(0,curpart->lsn0,1)<0){
7344 err_print("lsn0bootfile: cannot write LSN0\n");
7345 /* XXX can't undo previous actions */
7346 return -1;
7347 }
7348
7349 return 0;
7350 /* must restart now to get new partition table!!! */
7351 }
7352
7353 /* QDOS */
7354 int
qdos_ovfile(char * path,u_int ovnr)7355 qdos_ovfile(char *path,u_int ovnr)
7356 {
7357 struct part_s *pp;
7358 struct qdos_fdes_s qfdes;
7359 u_int ovrib;
7360
7361 if (curpart->type!=PARTTYPE_QDOS){
7362 return -1;
7363 }
7364 if (ovnr>=QDOS_DID_RBNR){
7365 err_print("qdos_ovfile: invalid ovnr\n");
7366 return -1;
7367 }
7368
7369 if (path!=NULL){
7370 /* set overlay file entry */
7371
7372 /* find file and check if file is in master partition */
7373 if (findfile3(path,NULL,&pp)<0){
7374 err_print("qdos_ovfile: cannot find file\n");
7375 return -1;
7376 }
7377 if (pp!=curpart){ /* must be in same partition */
7378 err_print("qdos_ovfile: file not in same partition\n");
7379 return -1;
7380 }
7381 /* get file RIB */
7382 if (readfiledes3(path,(union genfdes_u *)&qfdes,NULL,NULL,NULL,NULL,&ovrib,0,NULL,0)<0){
7383 err_print("qdos_ovfile: cannot get RIB\n");
7384 return -1;
7385 }
7386 }else{
7387 /* clear overlay file entry */
7388
7389 ovrib=0;
7390 }
7391
7392 /* set curpart... */
7393 QDOS_LSN0_P(curpart->lsn0)->did_rb[ovnr][0]=0xff&(ovrib>>8);
7394 QDOS_LSN0_P(curpart->lsn0)->did_rb[ovnr][1]=0xff&ovrib;
7395 /* save new DID */
7396 if (WRITEBLOCK_CURPART(0,curpart->lsn0,1)<0){
7397 err_print("qdos_ovfile: cannot write DID\n");
7398 /* XXX can't undo previous actions */
7399 return -1;
7400 }
7401 return 0;
7402 }
7403
7404 /* QDOS */
7405 int
qdos_setboot(u_int btsec,u_int btsiz,u_int btloa)7406 qdos_setboot(u_int btsec,u_int btsiz,u_int btloa)
7407 {
7408
7409 if (curpart->type!=PARTTYPE_QDOS){
7410 return -1;
7411 }
7412
7413 /* set curpart... */
7414 QDOS_LSN0_P(curpart->lsn0)->did_btsec[0]=0xff&(btsec>>8);
7415 QDOS_LSN0_P(curpart->lsn0)->did_btsec[1]=0xff&btsec;
7416 QDOS_LSN0_P(curpart->lsn0)->did_btsiz[0]=0xff&(btsiz>>8);
7417 QDOS_LSN0_P(curpart->lsn0)->did_btsiz[1]=0xff&btsiz;
7418 QDOS_LSN0_P(curpart->lsn0)->did_btloa[0]=0xff&(btloa>>8);
7419 QDOS_LSN0_P(curpart->lsn0)->did_btloa[1]=0xff&btloa;
7420 /* save new DID */
7421 if (WRITEBLOCK_CURPART(0,curpart->lsn0,1)<0){
7422 err_print("qdos_bootfile: cannot write LSN0\n");
7423 /* XXX can't undo previous actions */
7424 return -1;
7425 }
7426 return 0;
7427 }
7428
7429
7430
7431 /* OS9 */
7432 int
listdirtree(int (* recfct)(char * name,int rec,int arg),int arg)7433 listdirtree(int (*recfct)(char *name,int rec,int arg),int arg)
7434 {
7435 /* recursive: variables must not be static!!! */
7436 struct filedes_s curdirdes;
7437 u_int curdirsize;
7438 struct dirent_s *curdirp;
7439 u_int blknr;
7440 u_int i,j;
7441 char namebuf[FILENAMELEN+1];
7442 struct filedes_s fdes;
7443 int ret;
7444 u_int fsize,asize,corrupt;
7445
7446 static u_int reclevel=0; /* static recursion level */
7447 static u_int maxreclevel=0; /* static recursion level */
7448 static u_int totfiles; /* static for recursion! */
7449 static u_int totdirs; /* static for recursion! */
7450 static u_int totsize; /* static for recursion! */
7451 static u_int totalloc; /* static for recursion! */
7452 static u_int corruptcount; /* static for recursion! */
7453
7454 if (curpart->type!=PARTTYPE_OS9MDR){
7455 return -1;
7456 }
7457 if (curpart->mdr){
7458 return -1;
7459 }
7460
7461 /* must be recursive */
7462 if (recfct==NULL){
7463 return -1;
7464 }
7465
7466 if (reclevel==0){
7467 /* reset */
7468 totfiles=0;
7469 totdirs=0;
7470 totsize=0;
7471 totalloc=0;
7472 corruptcount=0;
7473 }
7474
7475 /* XXX read whole directory file */
7476
7477 if (getdir(curdirsec,&curdirdes,&curdirsize)<0){
7478 return -1;
7479 }
7480 if (curdirsize==0){
7481 #if 0
7482 err_print("listdirtree: directory empty\n");
7483 return -1;
7484 #else
7485 corruptcount++;
7486 printf("*** empty directory ***\n");
7487 return 0; /* XXX non-fatal */
7488 #endif
7489 }
7490
7491 /* read directory file */
7492 /* XXX 32-Bit overflow protection */
7493 blknr=(u_int)((((OFF_T)curdirsize)+((OFF_T)curpart->blksiz-1))
7494 /((OFF_T)curpart->blksiz));
7495
7496 /* allocate memory for directory file */
7497 curdirp=(struct dirent_s *)malloc(blknr*curpart->blksiz);
7498 if (curdirp==NULL){
7499 perror("listdirtree: malloc");
7500 return -1;
7501 }
7502
7503 /* read directory file */
7504 if (fileread((union genfdes_u *)&curdirdes,(void *)curdirp,0,blknr)!=(int)blknr){
7505 #if 0
7506 err_print("listdirtree: fileread(curdirdes)\n");
7507 free((void *)curdirp);
7508 return -1;
7509 #else
7510 corruptcount++;
7511 printf("*** cannot read directory ***\n");
7512 free((void *)curdirp);
7513 return 0; /* XXX non-fatal */
7514 #endif
7515 }
7516
7517 /* scan directory entries */
7518 for (i=0;i<curdirsize/sizeof(struct dirent_s);i++){
7519 if (curdirp[i].dir_name[0]==0){
7520 continue; /* skip entry */
7521 }
7522
7523 /* get file-descriptor */
7524 translatename(curdirp[i].dir_name,namebuf);
7525 /* skip "." and ".." */
7526 if ((strcmp(namebuf,".")==0)||(strcmp(namebuf,"..")==0)){
7527 continue; /* skip entry */
7528 }
7529 if (readfiledes3(namebuf,(union genfdes_u *)&fdes,NULL,NULL,NULL,NULL,NULL,0,NULL,0)<0){
7530 #if 0
7531 err_print("listdirtree: readfiledes3\n");
7532 free((void *)curdirp);
7533 return -1;
7534 #else
7535 corruptcount++;
7536 printf(" *** cannot access file/directory: %s ***\n",namebuf);
7537 continue; /* skip entry */
7538 #endif
7539 }
7540
7541 /* file size */
7542 fsize=(fdes.fd_fsize[0]<<24)
7543 +(fdes.fd_fsize[1]<<16)
7544 +(fdes.fd_fsize[2]<<8)
7545 +fdes.fd_fsize[3];
7546 /* allocated */
7547 asize=countseg(&(fdes.fd_seg[0]),FILEDES_SEGNR,NULL);
7548 /* check if corrupt */
7549 corrupt=(fsize>asize*curpart->blksiz)||(asize>curpart->filesyssize);
7550 if (corrupt){
7551 corruptcount++;
7552 }else{
7553 totsize+=fsize;
7554 totalloc+=asize;
7555 }
7556
7557 /* print entry */
7558 for (j=0;j<reclevel;j++){
7559 printf(" ");
7560 }
7561 printf("%s",namebuf);
7562 if (corrupt){
7563 printf(" *** invalid size ***");
7564 }
7565 if (fdes.fd_att&ATT_D){ /* directory? */
7566 printf("/");
7567 }
7568 printf("\n");
7569
7570 /* directory? */
7571 if (fdes.fd_att&ATT_D){
7572 if (!corrupt){
7573 totdirs++;
7574
7575 reclevel++;
7576 if (reclevel>maxreclevel){
7577 maxreclevel=reclevel;
7578 }
7579 #define MAX_RECLEVEL 4 /* XXX set VC++ linker option /STACK:0x1000000 */
7580 if (reclevel<=MAX_RECLEVEL){
7581 ret=recfct(namebuf,1,arg); /* 1: recursive */
7582 }else{
7583 printf("*** MAX_RECLEVEL ***\n");
7584 }
7585 reclevel--;
7586 /* check for error */
7587 if (ret<0){
7588 printf("*** ERROR ***\n");
7589 return -1;
7590 }
7591 }
7592 }else{
7593 totfiles++;
7594 }
7595 }
7596
7597 if (reclevel==0){
7598 printf("\ntotal\n----------------------------------------------\n");
7599 printf("files: %11u\n",totfiles);
7600 printf("directories: %11u\n",totdirs);
7601 printf("maxreclevel: %11u\n",maxreclevel);
7602 printf("damaged: %11u\n",corruptcount);
7603 printf("data size: %11u bytes\n",totsize);
7604 printf(" allocated: %11u bytes (%06x blocks)\n\n",
7605 totalloc*curpart->blksiz,totalloc);
7606 }
7607
7608 free((void *)curdirp);
7609
7610 return 0;
7611 }
7612
7613 /* MDR-DOS */
7614 int
mdr_listdir(void)7615 mdr_listdir(void)
7616 {
7617 static struct mdr_dirent_s dirent;
7618 u_int fnr;
7619 u_int fsize;
7620 u_int cnr;
7621
7622 if (curpart->type!=PARTTYPE_OS9MDR){
7623 return -1;
7624 }
7625 if (!curpart->mdr){
7626 return -1;
7627 }
7628
7629 printf("fnr creat/bk modif size type name\n");
7630 printf("-------------------------------------------------------------------------------\n");
7631
7632 /* scan directory */
7633 for (fnr=0;fnr<curpart->mdr_filenr;fnr++){ /* XXX first mdr_filenr entries */
7634 /* read directory entry */
7635 if (READBLOCK_CURPART(MDR_DIRSTART+fnr*MDR_DIRENTRYSIZE,
7636 (void *)&dirent,MDR_DIRENTRYSIZE)<0){
7637 err_print("mdr_listdir: READBLOCK_CURPART\n");
7638 return -1;
7639 }
7640
7641 /* file size in clusters */
7642 fsize=(dirent.size[0]<<24)
7643 +(dirent.size[1]<<16)
7644 +(dirent.size[2]<<8)
7645 +dirent.size[3];
7646
7647 /* check if entry not used */
7648 if (dirent.name[0]==0)
7649 continue; /* next */
7650
7651 /* print entry */
7652 printf("%4i ",fnr);
7653 printf("%02i-%02i-%02i ",
7654 dirent.back[0]%100,dirent.back[1]%100,dirent.back[2]%100);
7655 /* XXX don't print backup times */
7656 printf("%02i-%02i-%02i %02i:%02i ",
7657 dirent.modif[0]%100,dirent.modif[1]%100,dirent.modif[2]%100,
7658 dirent.modif[3]%100,dirent.modif[4]%100);
7659 /* XXX don't print modif seconds */
7660 /* count used clusters */
7661 cnr=mdr_countclu(&dirent,MDR_FILECLNR,NULL);
7662 if (fsize>cnr*curpart->mdr_clustersize*curpart->blksiz){
7663 printf("???????? ");
7664 }else{
7665 printf("%08x ",fsize);
7666 }
7667 printf("%c%c%c%c ",
7668 dirent.type[0],dirent.type[1],dirent.type[2],dirent.type[3]);
7669 printf("%s\n",dirent.name); /* XXX no length check */
7670 }
7671 printf("-------------------------------------------------------------------------------\n\n");
7672
7673 return 0;
7674 }
7675
7676 /* QDOS */
7677 int
qdos_listdir(void)7678 qdos_listdir(void)
7679 {
7680 u_int fnr;
7681 u_char dirbuf[QDOS_DIRSIZE*QDOS_BLOCKSIZE];
7682 struct qdos_dir_s *qdp;
7683 u_int ribblk;
7684 struct qdos_rib_s qr;
7685 u_int cnr;
7686 u_int fsize;
7687
7688 if (curpart->type!=PARTTYPE_QDOS){
7689 return -1;
7690 }
7691
7692 printf("fnr rib ov lb sl la sa size att fmt name\n");
7693 printf("---------------------------------------------------------------------\n");
7694
7695 /* read directory */
7696 if (READBLOCK_CURPART(QDOS_DIRSTART,(void *)dirbuf,QDOS_DIRSIZE)<0){
7697 err_print("qdos_listdir: READBLOCK_CURPART\n");
7698 return -1;
7699 }
7700 qdp=(struct qdos_dir_s *)dirbuf;
7701
7702 /* scan directory */
7703 for (fnr=0;fnr<QDOS_DIRENTRYNR;fnr++){
7704 /* check if entry not used */
7705 if (qdp[fnr].dir_nm[0]==QDOS_DIR_VACANT){
7706 /* vacant directory entry */
7707 continue; /* next */
7708 }
7709 if (qdp[fnr].dir_nm[0]==QDOS_DIR_DELETED){
7710 /* unused directory entry */
7711 continue; /* next */
7712 }
7713
7714 /* print entry */
7715 printf("%3i ",fnr);
7716
7717 /* read RIB */
7718 ribblk=(qdp[fnr].dir_rb[0]<<8)+qdp[fnr].dir_rb[1];
7719 if (ribblk==0){
7720 printf("???? ?? ???? ???? ???? ?????? ?????? ");
7721 }else{
7722 struct qdos_did_s *qp;
7723 u_int ov;
7724
7725 printf("%04x ",ribblk);
7726 /* check if overlay */
7727 qp=QDOS_LSN0_P(curpart->lsn0);
7728 for (ov=0;ov<QDOS_DID_RBNR;ov++){
7729 if ((qp->did_rb[ov][0]==qdp[fnr].dir_rb[0])
7730 &&(qp->did_rb[ov][1]==qdp[fnr].dir_rb[1])){
7731 break; /* found */
7732 }
7733 }
7734 if (ov<QDOS_DID_RBNR){
7735 printf("%02x ",ov);
7736 }else{
7737 printf(" ");
7738 }
7739
7740 if (READBLOCK_CURPART(ribblk,(void *)&qr,1)<0){
7741 printf(" ?? ???? ???? ???? ?????? ");
7742 }else{
7743 /* print RIB */
7744 printf(" %02x%",qr.rib_lb);
7745 printf(" %02x%02x",qr.rib_sl[0],qr.rib_sl[1]);
7746 printf(" %02x%02x",qr.rib_la[0],qr.rib_la[1]);
7747 printf(" %02x%02x",qr.rib_sa[0],qr.rib_sa[1]);
7748 fsize=qdos_fsize(&qr);
7749 cnr=qdos_countseg(&qr,QDOS_RIB_SDWNR,NULL); /* number of allocated clusters */
7750 /* Note: first block of file allocation is used for RIB!!! */
7751 if (cnr<1){
7752 printf(" ?????? ");
7753 }else{
7754 if (fsize>(cnr*QDOS_CSIZE*curpart->blksiz-curpart->blksiz)){
7755 printf(" ?????? ");
7756 }else{
7757 printf(" %06x ",fsize);
7758 }
7759 }
7760 }
7761 }
7762
7763 /* print entry (continued)*/
7764 qdos_printatt0(qdp[fnr].dir_at[0]);
7765 #if 0
7766 printf(" (%02x%02x) ",qdp[fnr].dir_at[0],qdp[fnr].dir_at[1]);
7767 #endif
7768 printf(" ");
7769 printnstr(qdp[fnr].dir_nm,8);
7770 printf(".");
7771 printnstr(qdp[fnr].dir_sx,2);
7772 printf("\n");
7773 }
7774 printf("---------------------------------------------------------------------\n\n");
7775
7776 return 0;
7777 }
7778
7779 /* general */
7780 int
listdir(int (* recfct)(char * name,int rec,int arg),int arg)7781 listdir(int (*recfct)(char *name,int rec,int arg),int arg)
7782 {
7783 /* recursive: variables must not be static!!! */
7784 struct filedes_s curdirdes;
7785 u_int curdirsize;
7786 struct dirent_s *curdirp;
7787 u_int blknr;
7788 u_int i;
7789 char namebuf[FILENAMELEN+1];
7790 struct filedes_s fdes;
7791 u_int fsize,totsize;
7792 int ret;
7793
7794 if (curpart->type==PARTTYPE_QDOS){
7795 return qdos_listdir(); /* non-recursive, end here! */
7796 }else if (curpart->type!=PARTTYPE_OS9MDR){
7797 return -1;
7798 }
7799
7800 /* now OS9 or MDR-DOS */
7801 if (curpart->mdr){
7802 return mdr_listdir(); /* non-recursive, end here! */
7803 }
7804
7805 /* XXX read whole directory file */
7806
7807 if (getdir(curdirsec,&curdirdes,&curdirsize)<0){
7808 return -1;
7809 }
7810 if (curdirsize==0){
7811 if (recfct==NULL){
7812 err_print("listdir: directory empty\n");
7813 return -1;
7814 }else{
7815 printf("*** empty directory ***\n");
7816 return 0; /* XXX non-fatal */
7817 }
7818 }
7819
7820 /* read directory file */
7821 /* XXX 32-Bit overflow protection */
7822 blknr=(u_int)((((OFF_T)curdirsize)+((OFF_T)curpart->blksiz-1))
7823 /((OFF_T)curpart->blksiz));
7824
7825 /* allocate memory for directory file */
7826 curdirp=(struct dirent_s *)malloc(blknr*curpart->blksiz);
7827 if (curdirp==NULL){
7828 perror("listdir: malloc");
7829 return -1;
7830 }
7831
7832 /* read directory file */
7833 if (fileread((union genfdes_u *)&curdirdes,(void *)curdirp,0,blknr)!=(int)blknr){
7834 if (recfct==NULL){
7835 err_print("listdir: fileread(curdirdes)\n");
7836 free((void *)curdirp);
7837 return -1;
7838 }else{
7839 printf("*** cannot read directory ***\n");
7840 free((void *)curdirp);
7841 return 0; /* XXX non-fatal */
7842 }
7843 }
7844
7845 /* recursive? */
7846 if (recfct!=NULL){
7847 /* scan directory entries for sub-directories */
7848 for (i=0;i<curdirsize/sizeof(struct dirent_s);i++){
7849 if (curdirp[i].dir_name[0]==0){
7850 continue; /* skip entry */
7851 }
7852
7853 /* get file-descriptor */
7854 translatename(curdirp[i].dir_name,namebuf);
7855 /* skip "." and ".." */
7856 if ((strcmp(namebuf,".")==0)||(strcmp(namebuf,"..")==0)){
7857 continue; /* skip entry */
7858 }
7859 if (readfiledes3(namebuf,(union genfdes_u *)&fdes,NULL,NULL,NULL,NULL,NULL,0,NULL,0)<0){
7860 #if 0
7861 err_print("listdir: readfiledes3\n");
7862 free((void *)curdirp);
7863 return -1;
7864 #else
7865 printf("*** cannot access file/directory: %s ***\n",namebuf);
7866 continue; /* skip entry */
7867 #endif
7868 }
7869 /* skip non-directory */
7870 if (!(fdes.fd_att&ATT_D)){
7871 continue; /* skip entry */
7872 }
7873
7874 printf("entering %s\n\n",namebuf);
7875 ret=recfct(namebuf,1,arg); /* 1: recursive */
7876 printf("leaving %s\n\n",namebuf);
7877 /* check for error */
7878 if (ret<0){
7879 printf("*** ERROR ***\n");
7880 return -1;
7881 }
7882 }
7883 }
7884
7885 /* print path */
7886 /* printdirlist();*/ /* XXX not working yet */
7887 printf("curdirsec: %06x curdirsize: %08x (%u bytes)\n",
7888 curdirsec,curdirsize,curdirsize);
7889 printf("own att creat modif lnk size fdes name\n");
7890 printf("-------------------------------------------------------------------------------\n");
7891
7892 /* scan directory entries */
7893 totsize=0;
7894 for (i=0;i<curdirsize/sizeof(struct dirent_s);i++){
7895 if (curdirp[i].dir_name[0]==0){
7896 continue; /* skip entry */
7897 }
7898
7899 /* get file-descriptor */
7900 translatename(curdirp[i].dir_name,namebuf);
7901 if (readfiledes3(namebuf,(union genfdes_u *)&fdes,NULL,NULL,NULL,NULL,NULL,0,NULL,0)<0){
7902 #if 0
7903 err_print("listdir: readfiledes3\n");
7904 free((void *)curdirp);
7905 return -1;
7906 #else
7907 printf("*** %s ***\n",namebuf);
7908 continue; /* skip entry */
7909 #endif
7910 }
7911
7912 /* print entry */
7913 {
7914 fsize=printfiledes(curpart,&fdes,0);
7915 printf(" %02x%02x%02x ",
7916 curdirp[i].dir_addr[0],
7917 curdirp[i].dir_addr[1],
7918 curdirp[i].dir_addr[2]);
7919 printf(" %s",namebuf);
7920 if (fsize==-7){ /* corrupt? */
7921 printf(" ***");
7922 /* don't count this file */
7923 }else{
7924 totsize+=fsize;
7925 }
7926 printf("\n");
7927 }
7928 }
7929 printf("-------------------------------------------------------------------------------\n");
7930 printf("total: %08x (%u bytes)\n\n",totsize,totsize);
7931
7932 free((void *)curdirp);
7933
7934 return 0;
7935 }
7936
7937 /* general */
7938 int
printdir3(char * path,int recursive,int tree)7939 printdir3(char *path,int recursive,int tree)
7940 {
7941 /* recursive via listdir: variables must not be static! */
7942 struct part_s *savecurpart;
7943 u_int savecurdirsec;
7944 int ret;
7945
7946 if (path==NULL){
7947 return -1;
7948 }
7949
7950 /* XXX not needed for "." */
7951 /* save current state */
7952 savecurpart=curpart;
7953 /* for OS9 */
7954 savecurdirsec=curdirsec;
7955
7956 ret=changedir3(path,0); /* 0: no dirlist update */
7957
7958 if (ret<0){
7959 err_print("printdir3: cannot change directory\n");
7960 return -1;
7961 }
7962
7963 if (curpart->type==PARTTYPE_QDOS){
7964 /* QDOS has no directories except root! */
7965 recursive=0;
7966 tree=0;
7967 }else if (curpart->type==PARTTYPE_OS9MDR){
7968 /* now OS9 or MDR-DOS */
7969 if (curpart->mdr){
7970 /* MDR-DOS has no directories except root! */
7971 recursive=0;
7972 tree=0;
7973 }
7974 }else{
7975 return -1;
7976 }
7977
7978 if (tree){
7979 ret=listdirtree(&printdir3,tree);
7980 }else{
7981 ret=listdir(recursive?(&printdir3):NULL,tree);
7982 }
7983
7984 /* restore state */
7985 curpart=savecurpart;
7986 /* for OS9 */
7987 curdirsec=savecurdirsec;
7988
7989 return ret; /* ret: if error... */
7990 }
7991
7992
7993
7994 /* general */
7995 int
openfile3(char * path,struct genfile_s * fp,int touch)7996 openfile3(char *path,struct genfile_s *fp,int touch)
7997 {
7998
7999 if ((path==NULL)||(fp==NULL)){
8000 return -1;
8001 }
8002
8003 /* get file descriptor */
8004 /* 0: do not change partition! */
8005 return readfiledes3(path,
8006 &fp->fdes,
8007 NULL, /* type: this informtion is within fp->part! */
8008 NULL, /* mdr: this informtion is within fp->part! */
8009 &fp->startsec,
8010 &fp->part,
8011 &fp->fdessec,
8012 0,
8013 &fp->size,
8014 touch);
8015 }
8016
8017 /* general */
8018 /* bytestart and buffer allocation must be multiples of filesystem blocksize!!! */
8019 int
readfile4(struct genfile_s * fp,char * buf,u_int bytestart,u_int bytenr)8020 readfile4(struct genfile_s *fp,char *buf,u_int bytestart,u_int bytenr)
8021 {
8022 struct part_s *savecurpart;
8023 u_int blkstart,blknr,blknract;
8024 int ret;
8025
8026 if ((fp==NULL)||(buf==NULL)){
8027 return -1;
8028 }
8029 if (fp->part==NULL){
8030 return -1;
8031 }
8032
8033 /* save state */
8034 savecurpart=curpart;
8035
8036 /* change partition */
8037 curpart=fp->part;
8038
8039 /* read file */
8040 ret=-1;
8041 if (curpart->blksiz!=0){ /* XXX should be OK */
8042 blkstart=bytestart/curpart->blksiz; /* round down! */
8043 /* XXX 32-Bit overflow protection */
8044 blknr=(u_int)((((OFF_T)bytenr)+((OFF_T)curpart->blksiz-1))
8045 /((OFF_T)curpart->blksiz));
8046 blknract=(u_int)fileread(&fp->fdes,buf,blkstart,blknr);
8047 if (blknract==blknr){
8048 ret=0; /* success */
8049 }else{
8050 err_print("readfile4: not full count read\n");
8051 }
8052 }
8053
8054 /* restore state */
8055 curpart=savecurpart;
8056
8057 return ret;
8058 }
8059
8060 /* general */
8061 /* bytestart and buffer allocation must be multiples of filesystem blocksize!!! */
8062 int
writefile4(struct genfile_s * fp,char * buf,u_int bytestart,u_int bytenr)8063 writefile4(struct genfile_s *fp,char *buf,u_int bytestart,u_int bytenr)
8064 {
8065 struct part_s *savecurpart;
8066 u_int blkstart,blknr,blknract;
8067 int ret;
8068
8069 if ((fp==NULL)||(buf==NULL)){
8070 return -1;
8071 }
8072 if (fp->part==NULL){
8073 return -1;
8074 }
8075
8076 /* save state */
8077 savecurpart=curpart;
8078
8079 /* change partition */
8080 curpart=fp->part;
8081
8082 /* write file */
8083 ret=-1;
8084 if (curpart->blksiz!=0){ /* XXX should be OK */
8085 blkstart=bytestart/curpart->blksiz; /* round down! */
8086 /* XXX 32-Bit overflow protection */
8087 blknr=(u_int)((((OFF_T)bytenr)+((OFF_T)curpart->blksiz-1))
8088 /((OFF_T)curpart->blksiz));
8089 blknract=(u_int)filewrite(&fp->fdes,buf,blkstart,blknr);
8090 if (blknract==blknr){
8091 ret=0; /* success */
8092 }else{
8093 err_print("writefile4: not full count written\n");
8094 }
8095 }
8096
8097 /* restore state */
8098 curpart=savecurpart;
8099
8100 return ret;
8101 }
8102
8103
8104
8105 /* general */
8106 int
movefile3(char * path1,char * path2,int link)8107 movefile3(char *path1,char *path2,int link)
8108 {
8109 struct part_s *savecurpart;
8110 u_int savecurdirsec;
8111 u_int olddirsec;
8112 u_int newdirsec;
8113 int ret;
8114 char *oldname,*oldpath,*newname,*newpath;
8115 struct part_s *oldpart,*newpart;
8116
8117 if ((path1==NULL)||(path2==NULL)||
8118 (strlen(path1)==0)||(strlen(path2)==0)){
8119 return -1;
8120 }
8121 /* check if path1 exists */
8122 if (findfile3(path1,NULL,NULL)<0){
8123 err_print("movefile3: source path not found\n");
8124 return -1;
8125 }
8126 /* check if path2 already exists */
8127 if (findfile3(path2,NULL,NULL)>=0){
8128 err_print("movefile3: destination path already used\n");
8129 return -1;
8130 }
8131 err_reset(); /* XXX clear findfile3 error! */
8132
8133 /* save path string! */
8134 oldpath=(char *)malloc(strlen(path1)+1); /* +1 for '\0' */
8135 if (oldpath==NULL){
8136 perror("movefile3: malloc");
8137 return -1;
8138 }
8139 bcopy(path1,oldpath,strlen(path1)+1); /* +1 for '\0' */
8140 /* save path string! */
8141 newpath=(char *)malloc(strlen(path2)+1); /* +1 for '\0' */
8142 if (newpath==NULL){
8143 perror("movefile3: malloc");
8144 free(oldpath);
8145 return -1;
8146 }
8147 bcopy(path2,newpath,strlen(path2)+1); /* +1 for '\0' */
8148
8149 /* save current state */
8150 savecurpart=curpart;
8151 /* for OS9 */
8152 savecurdirsec=curdirsec;
8153
8154 /* extract device/directory-path and name */
8155 newname=strrchr(newpath,'/');
8156 if (newname==NULL){
8157 /* '/' not found */
8158 newname=newpath;
8159 }else if (newname==newpath){
8160 /* only one occurcence of '/' and this at the beginning */
8161 /* => invalid file path */
8162 err_print("movefile3: invalid destination path\n");
8163 ret=-1;
8164 goto movefile3_exit;
8165 }else{
8166 *newname='\0'; /* terminate newpath */
8167 newname++;
8168 ret=changedir3(newpath,0);
8169 if (ret<0){
8170 err_print("movefile3: destination path not found\n");
8171 ret=-1;
8172 goto movefile3_exit;
8173 }
8174 }
8175 if (strlen(newname)==0){
8176 err_print("movefile3: invalid destination file name\n");
8177 ret=-1;
8178 goto movefile3_exit;
8179 }
8180 newpart=curpart;
8181 /* for OS9 */
8182 newdirsec=curdirsec;
8183 /* now we are in newpart!!! */
8184
8185 /* extract device/directory-path and name */
8186 oldname=strrchr(oldpath,'/');
8187 if (oldname==NULL){
8188 /* '/' not found */
8189 oldname=oldpath;
8190 /* restore state */
8191 curpart=savecurpart;
8192 /* for OS9 */
8193 curdirsec=savecurdirsec;
8194 }else if (oldname==oldpath){
8195 /* only one occurcence of '/' and this at the beginning */
8196 /* => invalid file path */
8197 err_print("movefile3: invalid source path\n");
8198 ret=-1;
8199 goto movefile3_exit;
8200 }else{
8201 *oldname='\0'; /* terminate oldpath */
8202 oldname++;
8203 ret=changedir3(oldpath,0);
8204 if (ret<0){
8205 err_print("movefile3: source path not found\n");
8206 ret=-1;
8207 goto movefile3_exit;
8208 }
8209 }
8210 if (strlen(oldname)==0){
8211 err_print("movefile3: invalid source file name\n");
8212 ret=-1;
8213 goto movefile3_exit;
8214 }
8215 oldpart=curpart;
8216 /* for OS9 */
8217 olddirsec=curdirsec;
8218 /* now we are in oldpart!!! */
8219
8220 #ifdef DEBUG
8221 printf("movefile3: path1: %s\n",path1);
8222 if (oldpath!=NULL){
8223 printf("movefile3: oldpath: %s\n",oldpath);
8224 }else{
8225 printf("movefile3: oldpath: (none)\n");
8226 }
8227 printf("movefile3: oldname: %s\n",oldname);
8228 printf("movefile3: path2: %s\n",path2);
8229 if (newpath!=NULL){
8230 printf("movefile3: newpath: %s\n",newpath);
8231 }else{
8232 printf("movefile3: newpath: (none)\n");
8233 }
8234 printf("movefile3: newname: %s\n",newname);
8235 #endif
8236
8237 /* check if in same partition */
8238 if (oldpart!=newpart){
8239 err_print("movefile3: must be in same partition\n");
8240 ret=-1;
8241 goto movefile3_exit;
8242 }
8243
8244 /* parse partition type */
8245 /* Note: now we are in oldpart!!! */
8246 ret=0; /* no error yet */
8247 if (curpart->type==PARTTYPE_QDOS){
8248 /* QDOS */
8249 /* this is just a "rename" */
8250 u_int fnr1;
8251 u_char dirbuf[QDOS_DIRSIZE*QDOS_BLOCKSIZE];
8252 struct qdos_dir_s *qdp;
8253 char qnewname[11]; /* NNNNNNNNSS with terminating '\0' */
8254
8255 if (link){
8256 err_print("movefile3: cannot link for QDOS\n");
8257 ret=-1;
8258 goto movefile3_exit;
8259 }
8260
8261 /* Note: now we are in oldpart!!! */
8262 /* find directory entry for file */
8263 if ((fnr1=qdos_findfile(oldname))<=0){
8264 err_print("movefile3: cannot find oldname\n");
8265 ret=-1;
8266 goto movefile3_exit;
8267 }
8268
8269 /* read directory */
8270 if (READBLOCK_CURPART(QDOS_DIRSTART,(void *)dirbuf,QDOS_DIRSIZE)<0){
8271 err_print("movefile3: cannot read directory\n");
8272 ret=-1;
8273 goto movefile3_exit;
8274 }
8275 qdp=(struct qdos_dir_s *)dirbuf;
8276
8277 /* convert newname into QDOS-conformant name */
8278 qdos_makefname(newname,qnewname);
8279
8280 /* rename */
8281 /* Note: dir_sx[2] directly follows dir_nm[8] in struct qdos_dir_s!!! */
8282 bcopy(qnewname,qdp[fnr1-1].dir_nm,10);
8283
8284 /* write directory */
8285 if (WRITEBLOCK_CURPART(QDOS_DIRSTART,(void *)dirbuf,QDOS_DIRSIZE)<0){
8286 err_print("movefile3: cannot write directory\n");
8287 ret=-1;
8288 goto movefile3_exit;
8289 }
8290 }else if (curpart->type==PARTTYPE_OS9MDR){
8291 if (!curpart->mdr){
8292 /* OS9 */
8293 int startsec;
8294 static struct filedes_s fdes;
8295
8296 /* Note: now we are in oldpart!!! */
8297 /* check for "." and ".." */
8298 if ((strcmp(oldname,".")==0)||(strcmp(oldname,"..")==0)
8299 ||(strcmp(newname,".")==0)||(strcmp(newname,"..")==0)){
8300 err_print("movefile3: . or .. not allowed\n");
8301 ret=-1;
8302 goto movefile3_exit;
8303 }
8304
8305 /* find oldname */
8306 startsec=findfile(oldname,0,NULL);
8307 if (startsec<0){
8308 err_print("movefile3: cannot find oldname\n");
8309 ret=-1;
8310 goto movefile3_exit;
8311 }
8312
8313 /* read file descriptor */
8314 if (READBLOCK_CURPART(startsec,&fdes,1)<0){
8315 err_print("movefile3: cannot read file descriptor\n");
8316 ret=-1;
8317 goto movefile3_exit;
8318 }
8319
8320 /* delete old entry? */
8321 if (!link){
8322 /* delete directory entry */
8323 if (deldirent(oldname,-1)<0){ /* -1: don't check file type */
8324 err_print("movefile3: cannot delete oldname\n");
8325 ret=-1;
8326 goto movefile3_exit;
8327 }
8328 /* link count for file descriptor remains the same! */
8329 }else{
8330 /* keep old directory entry */
8331 /* -> must increment link count in file descriptor! */
8332 /* increment link count */
8333 if (fdes.fd_link==0xff){ /* overflow? */
8334 err_print("movefile3: link count overflow\n");
8335 ret=-1;
8336 goto movefile3_exit;
8337 }else{
8338 fdes.fd_link++;
8339 if (fdes.fd_link<=1){
8340 /* should be at least 2 now! */
8341 fdes.fd_link=2;
8342 }
8343 }
8344 }
8345
8346 #if 0
8347 /* update modif date */
8348 setdate(&fdes,0); /* 0: not creat */
8349 #endif
8350 /* write updated file descriptor */
8351 if (WRITEBLOCK_CURPART(startsec,&fdes,1)<0){
8352 err_print("movefile3: cannot write updated file descriptor\n");
8353 ret=-1;
8354 goto movefile3_exit;
8355 }
8356
8357 /* change to destination state */
8358 curpart=newpart;
8359 /* for OS9 */
8360 curdirsec=newdirsec;
8361
8362 /* create directory entry */
8363 if (creatdirent(newname,startsec)<0){
8364 err_print("movefile3: cannot create new entry\n");
8365 if (!link){
8366 /* try to recreate old entry */
8367 /* change to source state */
8368 curpart=oldpart;
8369 /* for OS9 */
8370 curdirsec=olddirsec;
8371 creatdirent(oldname,startsec);
8372 }
8373 ret=-1;
8374 goto movefile3_exit;
8375 }
8376 }else{
8377 /* MDR-DOS */
8378 /* this is just a "rename" */
8379 struct mdr_dirent_s dirent;
8380 int fsec,fnr1;
8381
8382 if (link){
8383 err_print("movefile3: cannot link for MDR-DOS\n");
8384 ret=-1;
8385 goto movefile3_exit;
8386 }
8387
8388 /* Note: now we are in oldpart!!! */
8389 /* find directory entry for file */
8390 if ((fnr1=mdr_findfile(oldname))<=0){
8391 err_print("movefile3: cannot find oldname\n");
8392 ret=-1;
8393 goto movefile3_exit;
8394 }
8395 fsec=MDR_DIRSTART+(fnr1-1)*MDR_DIRENTRYSIZE;
8396
8397 /* read directory entry */
8398 if (READBLOCK_CURPART(fsec,&dirent,MDR_DIRENTRYSIZE)<0){
8399 err_print("movefile3: cannot read directory\n");
8400 ret=-1;
8401 goto movefile3_exit;
8402 }
8403
8404 /* rename */
8405 /* XXX no check for invalid newpath */
8406 /* set name without translation!!! */
8407 bcopy(newname,&(dirent.name[0]),FILENAMELEN+1);
8408
8409 #if 0
8410 /* update modif date */
8411 mdr_setdate(&dirent,0); /* 0: not creat */
8412 #endif
8413 /* write dirent */
8414 if (WRITEBLOCK_CURPART(fsec,&dirent,MDR_DIRENTRYSIZE)<0){
8415 err_print("movefile3: cannot write directory entry\n");
8416 ret=-1;
8417 goto movefile3_exit;
8418 }
8419 }
8420 }else{
8421 err_print("movefile3: invalid partition type\n");
8422 ret=-1;
8423 }
8424
8425 movefile3_exit:
8426 /* restore state */
8427 curpart=savecurpart;
8428 /* for OS9 */
8429 curdirsec=savecurdirsec;
8430
8431 free(oldpath);
8432 free(newpath);
8433 return ret;
8434 }
8435
8436 int
delfile3(char * path,int dir)8437 delfile3(char *path,int dir)
8438 {
8439 struct part_s *savecurpart;
8440 u_int savecurdirsec;
8441 char *dirpath,*name;
8442 int ret;
8443
8444 if (path==NULL){
8445 return -1;
8446 }
8447
8448 /* save path string! */
8449 dirpath=(char *)malloc(strlen(path)+1); /* +1 for '\0' */
8450 if (dirpath==NULL){
8451 perror("delfile3: malloc");
8452 return -1;
8453 }
8454 bcopy(path,dirpath,strlen(path)+1); /* +1 for '\0' */
8455
8456 /* save current state */
8457 savecurpart=curpart;
8458 /* for OS9 */
8459 savecurdirsec=curdirsec;
8460
8461 /* extract device/directory-path and name */
8462 name=strrchr(dirpath,'/');
8463 if (name==NULL){
8464 /* '/' not found */
8465 name=dirpath;
8466 }else if (name==dirpath){
8467 /* only one occurcence of '/' and this at the beginning */
8468 /* => invalid file path */
8469 err_print("delfile3: invalid path\n");
8470 ret=-1;
8471 goto delfile3_exit;
8472 }else{
8473 *name='\0'; /* terminate newpath */
8474 name++;
8475 ret=changedir3(dirpath,0);
8476 if (ret<0){
8477 err_print("delfile3: path not found\n");
8478 ret=-1;
8479 goto delfile3_exit;
8480 }
8481 }
8482
8483 /* parse partition type */
8484 /* Note: now we are in oldpart!!! */
8485 ret=0; /* no error yet */
8486 if (curpart->type==PARTTYPE_QDOS){
8487 /* QDOS */
8488 if (dir){
8489 err_print("delfile3: no directories for QDOS\n");
8490 ret=-1;
8491 goto delfile3_exit;
8492 }
8493 ret=qdos_delfile(name);
8494 }else if (curpart->type==PARTTYPE_OS9MDR){
8495 if (!curpart->mdr){
8496 /* OS9 */
8497 ret=delfile(name,dir);
8498 }else{
8499 /* MDR-DOS */
8500 if (dir){
8501 err_print("delfile3: no directories for MDR-DOS\n");
8502 ret=-1;
8503 goto delfile3_exit;
8504 }
8505 ret=mdr_delfile(name);
8506 }
8507 }else{
8508 err_print("delfile3: invalid partition type\n");
8509 ret=-1;
8510 }
8511
8512 delfile3_exit:
8513 /* restore state */
8514 curpart=savecurpart;
8515 /* for OS9 */
8516 curdirsec=savecurdirsec;
8517
8518 free(dirpath);
8519 return ret;
8520 }
8521
8522 /* OS9 */
8523 int
filesetattr3(char * path,char * str,int own)8524 filesetattr3(char *path,char *str,int own)
8525 {
8526 struct part_s *savecurpart;
8527 int ret;
8528 u_int startsec,fdessec;
8529 union genfdes_u fdes;
8530
8531 if (path==NULL){
8532 return -1;
8533 }
8534 if ((str==NULL)&&(own<0)){
8535 /* nothing to do */
8536 return -1;
8537 }
8538
8539 /* save state */
8540 savecurpart=curpart;
8541
8542 /* read file descriptor */
8543 /* 1: change partition! */
8544 if (readfiledes3(path,&fdes,NULL,NULL,&startsec,NULL,&fdessec,1,NULL,0)<0){
8545 err_print("filesetattr3: cannot find file\n");
8546 ret=-1;
8547 goto filesetattr3_exit;
8548 }
8549
8550 /* parse partition type */
8551 ret=0; /* no error yet */
8552 if (curpart->type==PARTTYPE_QDOS){
8553 /* QDOS */
8554 u_int x;
8555 int ribmod;
8556
8557 if (str==NULL){
8558 ret=-1;
8559 goto filesetattr3_exit;
8560 }
8561
8562 /* Note: readfiledes3 returns 0 as symbolic value for root directory in startsec for QDOS!!! */
8563 if (startsec==0){
8564 /* QDOS root directory: not a file! */
8565 err_print("filesetattr3: QDOS root directory not allowed\n");
8566 ret=-1;
8567 goto filesetattr3_exit;
8568 }
8569
8570 /* interpret str */
8571 ribmod=0; /* RIB not modified yet */
8572 if ((strlen(str)>3)&&(strncmp(str,"sl=",3)==0)){
8573 sscanf(str+3,"%x",&x);
8574 fdes.qdos.rib.rib_sl[0]=(x>>8)&0xff;
8575 fdes.qdos.rib.rib_sl[1]=x&0xff;
8576 ribmod=1;
8577 }else if ((strlen(str)>3)&&(strncmp(str,"la=",3)==0)){
8578 sscanf(str+3,"%x",&x);
8579 fdes.qdos.rib.rib_la[0]=(x>>8)&0xff;
8580 fdes.qdos.rib.rib_la[1]=x&0xff;
8581 ribmod=1;
8582 }else if ((strlen(str)>3)&&(strncmp(str,"sa=",3)==0)){
8583 sscanf(str+3,"%x",&x);
8584 fdes.qdos.rib.rib_sa[0]=(x>>8)&0xff;
8585 fdes.qdos.rib.rib_sa[1]=x&0xff;
8586 ribmod=1;
8587 }else{
8588 /* set/clear attributes */
8589 /* Note: readfiledes3 returns file number+1 in startsec for QDOS!!! */
8590 if (qdos_setattr(&fdes.qdos.rib,startsec-1,NULL,str)<0){
8591 ret=-1;
8592 goto filesetattr3_exit;
8593 }
8594 /* RIB not modified! */
8595 }
8596 if (ribmod){
8597 /* write updated RIB */
8598 if (WRITEBLOCK_CURPART(fdessec,&fdes.qdos.rib,1)<0){
8599 err_print("filesetattr3: cannot write RIB\n");
8600 ret=-1;
8601 goto filesetattr3_exit;
8602 }
8603 }
8604 }else if (curpart->type==PARTTYPE_OS9MDR){
8605 if (!curpart->mdr){
8606 /* OS9 */
8607
8608 /* XXX check owner and permission for permission to modify file!!! */
8609 /* XXX allow "." and ".." */
8610
8611 if (str!=NULL){
8612 /* set/clear attributes */
8613 if (setattr(&fdes.os9,str)<0){
8614 ret=-1;
8615 goto filesetattr3_exit;
8616 }
8617 }
8618 if (own>=0){
8619 fdes.os9.fd_own[1]=(u_char)own;
8620 fdes.os9.fd_own[0]=((u_int)own)>>8;
8621 }
8622
8623 /* write file descriptor */
8624 if (WRITEBLOCK_CURPART(fdessec,&fdes.os9,1)<0){
8625 err_print("filesetattr3: cannot write file descriptor\n");
8626 ret=-1;
8627 goto filesetattr3_exit;
8628 }
8629 }else{
8630 /* MDR-DOS */
8631
8632 if (str==NULL){
8633 ret=-1;
8634 goto filesetattr3_exit;
8635 }
8636 if (strlen(str)!=4){
8637 err_print("filesetattr3: invalid type string size\n");
8638 ret=-1;
8639 goto filesetattr3_exit;
8640 }
8641
8642 /* set MDR-DOS type */
8643 bcopy(str,&fdes.mdrdos.type[0],4);
8644
8645 /* write updated directory entry */
8646 if (WRITEBLOCK_CURPART(fdessec,&fdes.mdrdos,MDR_DIRENTRYSIZE)<0){
8647 err_print("filesetattr3: cannot write updated directory entry\n");
8648 ret=-1;
8649 goto filesetattr3_exit;
8650 }
8651 }
8652 }else{
8653 err_print("filesetattr3: invalid partition type\n");
8654 ret=-1;
8655 }
8656
8657 filesetattr3_exit:
8658 /* restore state */
8659 curpart=savecurpart;
8660 return ret;
8661 }
8662
8663
8664
8665 /* XXX partdefrag */
8666
8667 /* XXX filetrunc */
8668
8669
8670
8671 /* EOF */
8672