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