/* * Copyright (C) 2001, 2002, 2003, 2004, 2005 K. M. Indlekofer * * M.Indlekofer@fz-juelich.de * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* XXX make buffers and large structs static (if non-recursive) to prevent from stack overflow!?! */ #include "cmios9_err.h" #include "cmios9_io.h" #include "cmios9.h" /* general */ struct lsn0_s lsn0[PARTITION_NR]; struct part_s part[PARTITION_NR]; u_int partnr; /* number of used partitions */ /* current partition */ struct part_s *curpart; u_int curowner; /* who we are */ /* OS9 */ /* current directory */ u_int curdirsec; /* general */ int dirlevel; /* 0: root, level index to dirlist=dirlevel-1 */ char dirlist[DIRLEVELNR][FILENAMELEN]; /* general */ /* device aliases */ struct devalias_s devalias[]={ "k0","k000", "k1","k001", "k2","k002", "k3","k003", "k4","k004", "k5","k005", "k6","k006", "k7","k007", "c0","c000", "c1","c001", "c2","c002", "c3","c003", "c4","c004", "c5","c005", "c6","c006", "c7","c007", "d0","k000", "d1","k001", "d2","k002", "d3","k003", "f0","k000", "f1","k001", "f2","k002", "f3","k003", "cmif","c000", "tape","sc10", "xtape","sc50", "w0","sc30", "w1","sc40", "w2","sc50", "w3","sc60", "w4","sc70", "u0","c000", "u1","c200", "u2","c300", "u3","c400", "u4","c500", "u5","c600", "u6","c700", "q0","q000", "q1","q001", "q2","q002", "q3","q003", "q4","q004", "q5","q005", "q6","q006", "q7","q007", NULL,NULL /* end */ }; /* general */ void translatename(char *name,char *buf) { int i; u_char u; if ((name==NULL)||(buf==NULL)){ return; } for (i=0;itype!=PARTTYPE_OS9MDR){ return -1; } if (name==NULL){ return -1; } if (strlen(name)>FILENAMELEN){ /* XXX good for OS9 and MDR-DOS LSN0! */ err_print("lsn0label: name too long\n"); return -1; } if (curpart->mdr){ /* MDR-DOS */ /* null-terminated */ bcopy(name,MDR_LSN0_P(curpart->lsn0)->mdr_name,strlen(name)+1); }else{ /* OS9 */ /* Bit-7-terminated */ translatebackname(name,(curpart->lsn0)->dd_name,strlen(name)); } /* save new LSN0 */ if (WRITEBLOCK_CURPART(0,curpart->lsn0,1)<0){ err_print("lsn0label: cannot write LSN0\n"); /* XXX can't undo previous actions */ return -1; } return 0; } /* QDOS */ int qdos_didlabel(char *id,char *vnrn,char *date,char *user) { struct qdos_did_s *qp; int i,imax; if (curpart->type!=PARTTYPE_QDOS){ return -1; } if ((id==NULL)&&(vnrn==NULL)&&(date==NULL)&&(user==NULL)){ return -1; } qp=QDOS_LSN0_P(curpart->lsn0); if (id!=NULL){ /* ID */ imax=strlen(id); if (imax>8) imax=8; for (i=0;idid_id[i]=toupper(id[i]); } for (;i<8;i++){ qp->did_id[i]=' '; } } if (vnrn!=NULL){ /* vnrn */ imax=strlen(vnrn); if (imax>4) imax=4; /* Note: did_vn[2],did_rn[2] are contiguous! */ for (i=0;idid_vn[i]=toupper(vnrn[i]); } for (;i<4;i++){ qp->did_vn[i]=' '; } } if (date!=NULL){ /* date */ imax=strlen(date); if (imax>6) imax=6; for (i=0;idid_dt[i]=toupper(date[i]); } for (;i<6;i++){ qp->did_dt[i]=' '; } } if (user!=NULL){ /* user */ imax=strlen(user); if (imax>20) imax=20; for (i=0;idid_nm[i]=toupper(user[i]); } for (;i<20;i++){ qp->did_nm[i]=' '; } } /* save new DID */ if (WRITEBLOCK_CURPART(0,curpart->lsn0,1)<0){ err_print("qdos_didlabel: cannot write DID\n"); /* XXX can't undo previous actions */ return -1; } return 0; } /* OS9 */ void setdate(struct filedes_s *fd,int cre) { time_t tt; struct tm *tmp; if (fd==NULL) return; tt=time(NULL); tmp=localtime(&tt); if (tmp==NULL) return; if (cre){ fd->fd_creat[0]=tmp->tm_year; fd->fd_creat[1]=tmp->tm_mon+1; fd->fd_creat[2]=tmp->tm_mday; } fd->fd_dat[0]=tmp->tm_year; fd->fd_dat[1]=tmp->tm_mon+1; fd->fd_dat[2]=tmp->tm_mday; fd->fd_dat[3]=tmp->tm_hour; fd->fd_dat[4]=tmp->tm_min; } /* OS9 */ void lsn0setdate(struct lsn0_s *pp) { time_t tt; struct tm *tmp; if (pp==NULL) return; tt=time(NULL); tmp=localtime(&tt); if (tmp==NULL) return; pp->dd_date[0]=tmp->tm_year; pp->dd_date[1]=tmp->tm_mon+1; pp->dd_date[2]=tmp->tm_mday; pp->dd_date[3]=tmp->tm_hour; pp->dd_date[4]=tmp->tm_min; } /* MDR-DOS */ void mdr_setdate(struct mdr_dirent_s *fd,int cre) { time_t tt; struct tm *tmp; if (fd==NULL) return; tt=time(NULL); tmp=localtime(&tt); if (tmp==NULL) return; if (cre){ fd->back[0]=tmp->tm_year; fd->back[1]=tmp->tm_mon+1; fd->back[2]=tmp->tm_mday; fd->back[3]=tmp->tm_hour; fd->back[4]=tmp->tm_min; fd->back[5]=tmp->tm_sec; } fd->modif[0]=tmp->tm_year; fd->modif[1]=tmp->tm_mon+1; fd->modif[2]=tmp->tm_mday; fd->modif[3]=tmp->tm_hour; fd->modif[4]=tmp->tm_min; fd->modif[5]=tmp->tm_sec; } /* OS9 */ int setseg(struct seg_s *seglist,u_int start,u_int size) { if (seglist==NULL){ return -1; } /* XXX check size overflow */ seglist->addr[0]=start>>16; seglist->addr[1]=start>>8; seglist->addr[2]=start; seglist->size[0]=size>>8; seglist->size[1]=size; return 0; } /* OS9 */ int getseg(struct seg_s *seglist,u_int *startp,u_int *sizep) { if (seglist==NULL){ return -1; } if (startp!=NULL){ *startp=(seglist->addr[0]<<16) +(seglist->addr[1]<<8) +seglist->addr[2]; } if (sizep!=NULL){ *sizep=(seglist->size[0]<<8) +seglist->size[1]; } return 0; } /* OS9 */ u_int countseg(struct seg_s *seglist,u_int segnr,u_int *contblp) { u_int i; u_int count,ccount; int ccountend; u_int addr,size; u_int oldaddr,oldsize; if (seglist==NULL){ return 0; } count=0; ccount=0; ccountend=0; for (i=0;iclist[i][0]<<8)+(direntp->clist[i][1]); if (clu==0){ break; /* end of clist */ } if (!ccountend){ if ((i==0)||(clu==oldclu+1)){ /* contiguous clusters */ ccount++; oldclu=clu; }else{ ccountend=1; /* end of cont.clusters */ } } } if (contclp!=NULL){ *contclp=ccount; /* number of contiguous clusters */ } return i; /* number of clusters */ } /* QDOS */ int qdos_setseg(struct qdos_rib_s *ribp,u_int seg,u_int start,u_int size) { u_int r; if (ribp==NULL){ return -1; } if (seg>=QDOS_RIB_SDWNR){ return -1; } /* XXX check size overflow */ if (size==0){ /* mark end */ /* Note: SEGTOTSIZ is in QDOS_BLOCKSIZE! */ r=QDOS_RIB_SDWEND|start; /* special: mark end, save SEGTOTSIZ(in start)!!! */ }else{ r=(QDOS_RIB_SDWOFF&start) |(QDOS_RIB_SDWSIZ&((size-1)<<10)); /* -1 !!! */ } ribp->rib_sdw[seg][0]=(r>>8)&0xff; ribp->rib_sdw[seg][1]=r&0xff; return 0; } /* QDOS */ int qdos_getseg(struct qdos_rib_s *ribp,u_int seg,u_int *startp,u_int *sizep) { u_int r; if (ribp==NULL){ return -1; } if (seg>=QDOS_RIB_SDWNR){ if (sizep!=NULL){ *sizep=0; /* end */ } return -1; } r=(ribp->rib_sdw[seg][0]<<8)+ribp->rib_sdw[seg][1]; if (r&QDOS_RIB_SDWEND){ /* end of list */ if (startp!=NULL){ /* Note: totsiz is in QDOS_BLOCKSIZE! */ *startp=(QDOS_RIB_SDWTOTSIZ&r)+1; /* special: get SEGTOTSIZ+1(in *startp)!!! */ } if (sizep!=NULL){ *sizep=0; /* end */ } }else{ if (startp!=NULL){ *startp=r&QDOS_RIB_SDWOFF; } if (sizep!=NULL){ *sizep=((r&QDOS_RIB_SDWSIZ)>>10)+1; /* +1 !!! */ } } return 0; } /* QDOS */ u_int qdos_countseg(struct qdos_rib_s *ribp,u_int segnr,u_int *contclp) { u_int i; u_int count,ccount; int ccountend; u_int addr,size; u_int oldaddr,oldsize; if (ribp==NULL){ return 0; } count=0; ccount=0; ccountend=0; for (i=0;irib_sdw[i][0]<<8)+ribp->rib_sdw[i][1]; if (r&QDOS_RIB_SDWEND){ /* end of list */ /* Note: SEGTOTSIZ is in QDOS_BLOCKSIZE! */ totsiz=curpart->blksiz*((QDOS_RIB_SDWTOTSIZ&r)+1); /* +1 !!! */ /* correct for unused bytes in last block: */ totsiz-=curpart->blksiz; if (ribp->rib_lb==0){ /* 0 means full block */ totsiz+=curpart->blksiz; }else if (ribp->rib_lb>curpart->blksiz){ /* XXX corrupt RIB, take full block */ totsiz+=curpart->blksiz; }else{ /* MDOS requires rib_lb%8==0 */ totsiz+=ribp->rib_lb; /* bytes in last block */ } return totsiz; /* in bytes */ } } return 0; /* corrupt RIB, no end flag found */ } /* QDOS */ int qdos_setfsize(struct qdos_rib_s *ribp,u_int fsize) { int i; u_int r; u_int totsiz; u_int lb; if (ribp==NULL){ return -1; } /* XXX check for totsiz overflow */ /* find end segment */ for (i=0;irib_sdw[i][0]<<8)+ribp->rib_sdw[i][1]; if (r&QDOS_RIB_SDWEND){ /* end of list */ /* Note: SEGTOTSIZ is in QDOS_BLOCKSIZE! */ /* XXX 32-Bit overflow protection not necessary for QDOS */ totsiz=(fsize+curpart->blksiz-1)/curpart->blksiz; /* round up! */ if (totsiz<1){ totsiz=1; } totsiz--; /* -1 !!! */ ribp->rib_sdw[i][0]=((totsiz|QDOS_RIB_SDWEND)>>8)&0xff; /* end mark */ ribp->rib_sdw[i][1]=totsiz&0xff; lb=fsize-totsiz*curpart->blksiz; /* bytes in last block */ /* MDOS requires rib_lb%8==0 */ lb=8*((lb+7)/8); /* round up */ if (lb>=curpart->blksiz){ /* XXX > should never happen */ #if 1 ribp->rib_lb=curpart->blksiz; #else /* 0 means full block */ ribp->rib_lb=0; #endif }else{ ribp->rib_lb=lb; } return 0; } } return -1; /* corrupt RIB, no end flag found */ } /* OS9 */ int bitmaptranslate(u_int sec,u_int *bmapbitp,u_int *bmapbytep,u_int *bmapblkp) { if (curpart->type!=PARTTYPE_OS9MDR){ return -1; } if (curpart->mdr){ return -1; } if ((bmapbitp==NULL)||(bmapbytep==NULL)||(bmapblkp==NULL)){ return -1; } /* calculate block,byte,bit for current block sec */ *bmapbitp=sec/(curpart->clustersize); *bmapbytep=*bmapbitp/8; if (*bmapbytep>=(curpart->bitmapsize)){ err_print("bitmaptranslate: out of bitmap\n"); return -1; } *bmapblkp=curpart->bitmapstart+*bmapbytep/curpart->blksiz; *bmapbitp%=8; /* used Bit: lower Bit corresponds higher block! */ *bmapbitp=7-*bmapbitp; *bmapbytep%=curpart->blksiz; return 0; } /* MDR-DOS */ int mdr_bitmaptranslate(u_int sec,u_int *bmapbitp,u_int *bmapbytep,u_int *bmapblkp) { if (curpart->type!=PARTTYPE_OS9MDR){ return -1; } if (!curpart->mdr){ return -1; } if ((bmapbitp==NULL)||(bmapbytep==NULL)||(bmapblkp==NULL)){ return -1; } /* calculate block,byte,bit for current block sec */ *bmapbitp=sec/(curpart->mdr_clustersize); *bmapbytep=*bmapbitp/8; if (*bmapbytep>=MDR_BMAPSIZE*curpart->blksiz){ err_print("mdr_bitmaptranslate: out of bitmap\n"); return -1; } *bmapblkp=MDR_BMAPSTART+*bmapbytep/curpart->blksiz; *bmapbitp%=8; /* used Bit: lower Bit corresponds higher block! */ *bmapbitp=7-*bmapbitp; *bmapbytep%=curpart->blksiz; return 0; } /* QDOS */ int qdos_bitmaptranslate(u_int sec,u_int *bmapbitp,u_int *bmapbytep) { if ((bmapbitp==NULL)||(bmapbytep==NULL)){ return -1; } /* calculate block,byte,bit for current block sec */ *bmapbitp=sec/QDOS_CSIZE; *bmapbytep=*bmapbitp/8; if (*bmapbytep>=curpart->blksiz){ /* 1 block! */ err_print("qdos_bitmaptranslate: out of bitmap\n"); return -1; } *bmapbitp%=8; /* used Bit: lower Bit corresponds higher block! */ *bmapbitp=7-*bmapbitp; *bmapbytep%=curpart->blksiz; return 0; } /* OS9 */ int markbitmap2(u_int startblk,u_int size,int markused,int check) { u_int blk,bmapblk,bmapbyte,bmapbit; static char bmapbuf[OS9MAX_BLOCKSIZE]; int bmapbufblk; int bmapbufchanged; u_char used,newused; if (curpart->type!=PARTTYPE_OS9MDR){ return -1; } if (curpart->mdr){ return -1; } if (size==0){ return 0; } if (check){ if (startblk+size>curpart->totsize){ err_print("markbitmap2: startblk+size out of partition\n"); return -1; } if ((!markused)&&(startblkbitmapstart +(curpart->bitmapsize+curpart->blksiz-1)/curpart->blksiz)){ err_print("markbitmap2: must not mark unused in system area\n"); return -1; } } bmapbufblk=-1; /* invalid bitmap block */ bmapbufchanged=0; /* nothing changed yet */ /* scan blocks */ /* not necessarily cluster-oriented!!! -> must scan all blocks here! */ for (blk=startblk;blk=0)&&bmapbufchanged){ /* write block */ if (WRITEBLOCK_CURPART(bmapbufblk,bmapbuf,1)<0){ err_print("markbitmap2: cannot write bitmap block\n"); return -1; } } /* read block */ if (READBLOCK_CURPART(bmapblk,bmapbuf,1)<0){ err_print("markbitmap2: cannot read bitmap block\n"); return -1; } bmapbufblk=bmapblk; bmapbufchanged=0; /* nothing changed yet */ } /* check if used */ used=1&(bmapbuf[bmapbyte]>>bmapbit); newused=1<=0)&&(bmapbufchanged)){ /* write block */ if (WRITEBLOCK_CURPART(bmapbufblk,bmapbuf,1)<0){ err_print("markbitmap2: cannot write bitmap block\n"); return -1; } } return 0; } /* OS9 */ int markbitmap(struct seg_s *seglist,u_int segnr,int markused) { u_int startblk,size; u_int seg; if (curpart->type!=PARTTYPE_OS9MDR){ return -1; } if (curpart->mdr){ return -1; } if (seglist==NULL){ return -1; } for (seg=0;segtype!=PARTTYPE_OS9MDR){ return -1; } if (!curpart->mdr){ return -1; } if (size==0){ return 0; } if (check){ if (startblk+size>curpart->totsize){ err_print("mdr_markbitmap2: startblk+size out of partition\n"); return -1; } if ((!markused)&&(startblkmdr_dfilenr*MDR_DIRENTRYSIZE)){ err_print("mdr_markbitmap2: must not mark unused in system area\n"); return -1; } } bmapbufblk=-1; /* invalid bitmap block */ bmapbufchanged=0; /* nothing changed yet */ /* scan blocks */ /* XXX actually, first block of each cluster should be OK if cluster-oriented startblk,size! */ for (blk=startblk;blk=0)&&bmapbufchanged){ /* write block */ if (WRITEBLOCK_CURPART(bmapbufblk,bmapbuf,1)<0){ err_print("mdr_markbitmap2: cannot write bitmap block\n"); return -1; } } /* read block */ if (READBLOCK_CURPART(bmapblk,bmapbuf,1)<0){ err_print("mdr_markbitmap2: cannot read bitmap block\n"); return -1; } bmapbufblk=bmapblk; bmapbufchanged=0; /* nothing changed yet */ } /* check if used */ used=1&(bmapbuf[bmapbyte]>>bmapbit); newused=1<=0)&&(bmapbufchanged)){ /* write block */ if (WRITEBLOCK_CURPART(bmapbufblk,bmapbuf,1)<0){ err_print("mdr_markbitmap2: cannot write bitmap block\n"); return -1; } } return 0; } /* MDR-DOS */ int mdr_markbitmap(struct mdr_dirent_s *direntp,u_int fclunr,int markused) { u_int startblk,size; u_int clu; if (curpart->type!=PARTTYPE_OS9MDR){ return -1; } if (!curpart->mdr){ return -1; } if (direntp==NULL){ return -1; } size=curpart->mdr_clustersize; /* fixed */ for (clu=0;clumdr_clustersize *((direntp->clist[clu][0]<<8)+(direntp->clist[clu][1])); #ifdef DEBUG printf("mdr_markbitmap: clu: %04x startblk: %06x mark: %i\n",clu,startblk,markused); #endif /* stop at first cluster in dirent which is 0!!! */ if (startblk==0){ /* XXX check if direntp->size is consistent */ /* with number of clusters counted so far */ break; /* file end: OK */ } /* mark bitmap */ if (mdr_markbitmap2(startblk,size,markused,1)<0){ /* 1: check */ return -1; } } return 0; } /* QDOS */ int qdos_markbitmap2(u_int startblk,u_int size,int markused,int check,int lcat) { u_char catbuf[QDOS_BLOCKSIZE]; u_char lcatbuf[QDOS_BLOCKSIZE]; u_int blk; u_int bmapbit,bmapbyte; int catbufchanged,lcatbufchanged; u_char used,newused; if (curpart->type!=PARTTYPE_QDOS){ return -1; } if (size==0){ return 0; } if (check){ if (startblk+size>curpart->totsize){ err_print("qdos_markbitmap2: startblk+size out of partition\n"); return -1; } if ((!markused)&&(startblk>bmapbit); newused=1<>bmapbit); newused=1<type!=PARTTYPE_QDOS){ return -1; } if (ribp==NULL){ return -1; } for (seg=0;segtype!=PARTTYPE_OS9MDR){ return -1; } if (curpart->mdr){ return -1; } if (curpart->clustersize==0){ return -1; } /* XXX curpart->filesyssize, curpart->clustersize, curpart->bitmapsize must be set! */ /* mark everything used */ for (i=0;ibitmapsize is in bytes! */ /* round up to blocks, in blocks now! */ size=(curpart->bitmapsize+curpart->blksiz-1)/curpart->blksiz; /* write bitmap */ #ifdef DEBUG printf("initbitmap: size: %06x\n",size); #endif for (i=0;ibitmapstart+i,bmapbuf,1)<0){ /* 1: one block */ err_print("initbitmap: cannot write bitmap\n"); return -1; } } /* used for all clusters up to bitmap (inclusive) */ start=curpart->bitmapstart+size; /* now, start is new rootdirsec */ /* Note: start might not be cluster-aligned now! doesn´t matter... */ newrootdirsec=start; #ifdef DEBUG printf("initbitmap: newrootdirsec: %06x\n",newrootdirsec); #endif /* max. number of blocks in one segment */ /* setup fake seg_s for rest of filesystem */ size=(int)curpart->filesyssize-start; if (size<2){ /* at least 2 for minimal root directory (filedes_s and 2x dirent_s) */ err_print("initbitmap: filesyssize too small\n"); return -1; } /* round down to cluster size */ size=curpart->clustersize*(size/curpart->clustersize); #ifdef DEBUG printf("initbitmap: start: %06x size: %06x\n",start,size); #endif /* mark unused in bitmap */ if (markbitmap2(start,size,0,0)<0){ /* 0: unused!, 0: no check */ return -1; } /* XXX must set curpart->rootdirsec and create root directory by hand now! */ /* XXX must update and write LSN0 */ return newrootdirsec; } /* MDR-DOS */ int mdr_initbitmap(void) { u_char bmapbuf[MDR_BMAPSIZE*MDR_BLOCKSIZE]; int i; int cstart,csize; if (curpart->type!=PARTTYPE_OS9MDR){ return -1; } if (!curpart->mdr){ return -1; } /* XXX curpart->mdr_clustersize, curpart->mdr_clusternr, curpart->mdr_dfilenr must be set! */ /* mark everything used */ for (i=0;imdr_dfilenr*MDR_DIRENTRYSIZE; /* in blocks!!! */ /* round up to cluster size */ cstart=(cstart+curpart->mdr_clustersize-1)/curpart->mdr_clustersize; /* in clusters */ /* rest of partition */ csize=curpart->mdr_clusternr-cstart; if (csize<=0){ /* ==0: no filesystem space left! */ err_print("mdr_initbitmap: totsize too small\n"); return -1; } #ifdef DEBUG printf("mdr_initbitmap: cstart: %06x csize: %06x\n",cstart,csize); #endif /* mark unused in bitmap */ if (mdr_markbitmap2(cstart*curpart->mdr_clustersize, csize*curpart->mdr_clustersize, 0,0)<0){ /* 0: unused!, 0: no check */ return -1; } /* XXX must create directory by hand now! */ /* XXX must update and write LSN0 */ return 0; } /* QDOS */ int qdos_initbitmap(int single,int newlcat) { u_char bmapbuf[QDOS_BLOCKSIZE]; int i; if (curpart->type!=PARTTYPE_QDOS){ return -1; } if (newlcat){ /* mark everything free (1 block!) */ bzero(bmapbuf,QDOS_BLOCKSIZE); }else{ /* read existing LCAT (1 block!) */ if (READBLOCK_CURPART(QDOS_LCATSTART,bmapbuf,1)<0){ err_print("qdos_initbitmap: cannot read LCAT\n"); return -1; } } /* mark used up to directory: */ /* starts at block 3, 0x15 blocks */ /* => first 6 clusters: */ bmapbuf[0x00]|=0xfc; /* XXX */ if (!single){ /* double-sided floppy: */ /* 4004 blocks == 512512 bytes == QDOS_PSIZE!!! */ /* => last 23 clusters of 1024 in bitmap non-usable: */ bmapbuf[0x7d]|=0x7f; /* XXX */ bmapbuf[0x7e]|=0xff; /* XXX */ bmapbuf[0x7f]|=0xff; /* XXX */ }else{ /* single-sided floppy: */ /* 2002 blocks == 256256 bytes */ /* => last 524 clusters of 1024 in bitmap non-usable: */ /* 4 clusters: */ bmapbuf[496/8]|=0x0f; /* XXX */ /* 520 clusters: */ for (i=504/8;i<1024/8;i++){ bmapbuf[i]|=0xff; /* XXX */ } } /* write CAT (1 block!) */ if (WRITEBLOCK_CURPART(QDOS_CATSTART,bmapbuf,1)<0){ err_print("qdos_initbitmap: cannot write CAT\n"); return -1; } if (newlcat){ /* write new LCAT (1 block!) */ if (WRITEBLOCK_CURPART(QDOS_LCATSTART,bmapbuf,1)<0){ err_print("qdos_initbitmap: cannot write LCAT\n"); return -1; } } return 0; } /* OS9 */ u_int fixblksiz(u_int blksiz) { u_int b; if (blksiz>=OS9MAX_BLOCKSIZE){ return OS9MAX_BLOCKSIZE; } /* form 2^N and >= OS9L2_BLOCKSIZE */ for (b=OS9MAX_BLOCKSIZE;b>=(OS9L2_BLOCKSIZE<<1);b>>=1){ if (b&blksiz){ break; /* found leading 1 */ } } return b; } /* OS9 */ int newfs(u_int blksiz,u_int totsize,u_int clustersize,u_int filesyssize,int floppyflag) { int newrootsec,blknr; static struct filedes_s newrootfdes; static u_char newrootdent[OS9MAX_BLOCKSIZE]; /* enough space for 2x dirent (".." and ".") */ struct dirent_s *newrootdentp; struct seg_s fakeseg; u_int bitmapsize; if (curpart->type!=PARTTYPE_OS9MDR){ return -1; } if (curpart->mdr){ return -1; } if (totsize==0){ return -1; } if (clustersize==0){ return -1; } if (filesyssize==0){ return -1; } filesyssize=clustersize*(filesyssize/clustersize); /* round down to clustersize!!! */ if (filesyssize>totsize){ err_print("newfs: totsizepsize */ /* set curpart->... elements */ if (blksiz==0){ curpart->blksiz=OS9L2_BLOCKSIZE; /* XXX default */ }else{ /* fix if necessary */ blksiz=fixblksiz(blksiz); curpart->blksiz=blksiz; } curpart->totsize=totsize; /* in blocks */ curpart->clustersize=clustersize; /* in blocks */ curpart->filesyssize=filesyssize; /* in blocks */ /* Note: filesyssize already cluster-aligned, see above!!! */ curpart->bitmapstart=OS9L2_BMAPSTART; /* XXX default */ bitmapsize=(filesyssize+clustersize-1)/clustersize; /* one Bit per cluster, round up */ bitmapsize=(bitmapsize+7)/8; /* in bytes, round up */ if (bitmapsize==0){ err_print("newfs: bitmapsize==0 (perhaps clustersize too large)\n"); return -1; } if (bitmapsize>=0xffff){ /* XXX 16Bit max. value */ err_print("newfs: bitmapsize too large (perhaps clustersize too small)\n"); return -1; } curpart->bitmapsize=bitmapsize; /* in bytes */ /* initialize bitmap */ /* curpart->filesyssize, curpart->clustersize, curpart->bitmapsize must be set! */ if ((newrootsec=initbitmap())<0){ err_print("newfs: cannot initialize bitmap\n"); return -1; } /* Note: newrootsec might not be cluster-aligned now! doesn´t matter... */ /* set LSN0 elements */ bzero(curpart->lsn0,sizeof(struct lsn0_s)); /* reset all! */ curpart->lsn0->dd_tot[2]=totsize; curpart->lsn0->dd_tot[1]=totsize>>8; curpart->lsn0->dd_tot[0]=totsize>>16; curpart->lsn0->dd_map[1]=bitmapsize; /* dd_map!=0 for OS9 partition! */ curpart->lsn0->dd_map[0]=bitmapsize>>8; curpart->lsn0->dd_bit[1]=clustersize; curpart->lsn0->dd_bit[0]=clustersize>>8; curpart->lsn0->dd_dir[2]=newrootsec; curpart->lsn0->dd_dir[1]=newrootsec>>8; curpart->lsn0->dd_dir[0]=newrootsec>>16; curpart->lsn0->dd_own[1]=0; /* XXX */ curpart->lsn0->dd_own[0]=0; /* XXX */ curpart->lsn0->dd_att=0xff; /* XXX */ lsn0setdate(curpart->lsn0); if (floppyflag){ curpart->lsn0->dd_fmt=0x03; /* double sided, double density (not track0,side0) */ /* Note: track0,side0 set via firmware to 01: double sided, single density */ curpart->lsn0->dd_spt[0]=0x00; curpart->lsn0->dd_spt[1]=0x1c; /* 28 sectors/track (not track0,side0) */ /* Note: track0,side0 set via firmware to 0x10: 16 sectors/track */ } /*curpart->lsn0->dd_maplsn=0;*/ /* XXX default */ curpart->lsn0->dd_lsnsize[1]=blksiz; curpart->lsn0->dd_lsnsize[0]=blksiz>>8; /* XXX other elements */ /* save new LSN0 */ if (WRITEBLOCK_CURPART(0,curpart->lsn0,1)<0){ err_print("newfs: cannot write LSN0\n"); /* XXX can't undo previous actions */ return -1; } /* create and initialize minimal root directory */ /* enough space guaranteeded by initbitmap: 2 blocks */ /* mark used */ blknr=2; /* one for file descriptor + one for directory data, see below */ /* In order not to waste blocks for root directory (if newrootsec not cluster-aligned): */ blknr+=newrootsec; /* last block+1 */ blknr=clustersize*((blknr+clustersize-1)/clustersize); /* round up to clustersize */ blknr-=newrootsec; /* blocks we can mark used */ #ifdef DEBUG printf("newfs: newrootsec: %06x, blknr: %06x\n",newrootsec,blknr); #endif setseg(&fakeseg,newrootsec,blknr); if (markbitmap(&fakeseg,1,1)<0){ /* 1: one seg_s, 1: mark used */ err_print("newfs: cannot mark root directory\n"); /* XXX can't undo previous actions */ return -1; } /* setup root file descriptor */ bzero(&newrootfdes,sizeof(struct filedes_s)); /* clear */ /* set attributes */ newrootfdes.fd_att=ATT_R|ATT_W|ATT_E|ATT_D; /* owner only, directory */ /* set creation and modified date */ setdate(&newrootfdes,1); /* 1: create */ /* set link count */ newrootfdes.fd_link=0; /* XXX must be 0? */ /* set size */ newrootfdes.fd_fsize[0]=0; newrootfdes.fd_fsize[1]=0; newrootfdes.fd_fsize[2]=0; newrootfdes.fd_fsize[3]=2*sizeof(struct dirent_s); /* ".." and "." */ setseg(&newrootfdes.fd_seg[0],newrootsec+1,blknr-1); /* data directly behind descriptor! */ /* save */ if (WRITEBLOCK_CURPART(newrootsec,&newrootfdes,1)<0){ err_print("newfs: cannot write root directory descriptor\n"); /* XXX can't undo previous actions */ return -1; } /* setup root 2x dirent_s for ".." and "." */ newrootdentp=(struct dirent_s *)newrootdent; bzero(newrootdent,OS9MAX_BLOCKSIZE); /* clear */ /* ".." pointing back to us */ newrootdentp[0].dir_addr[2]=newrootsec; newrootdentp[0].dir_addr[1]=newrootsec>>8; newrootdentp[0].dir_addr[0]=newrootsec>>16; translatebackname("..",newrootdentp[0].dir_name,FILENAMELEN); /* "." pointing back to us */ newrootdentp[1].dir_addr[2]=newrootsec; newrootdentp[1].dir_addr[1]=newrootsec>>8; newrootdentp[1].dir_addr[0]=newrootsec>>16; translatebackname(".",newrootdentp[1].dir_name,FILENAMELEN); /* save */ if (WRITEBLOCK_CURPART(newrootsec+1,newrootdent,1)<0){ /* +1: directly behind descriptor! */ err_print("newfs: cannot write root directory\n"); /* XXX can't undo previous actions */ return -1; } return 0; /* Note: must restart program after modification of LSN0!!! */ } /* MDR-DOS */ int mdr_newfs(u_int totsize,u_int clustersize,u_int dfilenr) { u_int i; struct mdr_dirent_s zerodirent; /* should be MDR_DIRENTRYSIZE blocks */ u_int clusternr; if (curpart->type!=PARTTYPE_OS9MDR){ return -1; } if (!curpart->mdr){ return -1; } if (totsize==0){ return -1; } /* adjust clustersize to granularity of MDR_CLUSTERSIZE blocks */ clustersize=MDR_CLUSTERSIZE*((clustersize+MDR_CLUSTERSIZE-1)/MDR_CLUSTERSIZE); if (clustersize==0){ return -1; } if (dfilenr==0){ return -1; } /* XXX check if new clustersize valid */ /* XXX check if dfilenr valid */ /* XXX check if new totsize compatible with curpart->psize */ /* set curpart->... elements */ curpart->blksiz=MDR_BLOCKSIZE; curpart->totsize=totsize; /* in blocks */ curpart->mdr_clustersize=clustersize; /* in blocks */ curpart->mdr_dfilenr=dfilenr; /* use whole partition for MDR-DOS filesystem: set clusternr to max. */ clusternr=totsize/clustersize; /* rounded down to fit in totsize!!! */ if (clusternr==0){ err_print("mdr_newfs: clusternr==0 (perhaps clustersize too large)\n"); return -1; } curpart->mdr_clusternr=clusternr; /* initialize bitmap */ /* curpart->mdr_clustersize, curpart->mdr_clusternr, curpart->mdr_dfilenr must be set! */ if (mdr_initbitmap()<0){ err_print("mdr_newfs: cannot initialize bitmap\n"); return -1; } /* initialize directory */ bzero(&zerodirent,MDR_DIRENTRYSIZE*MDR_BLOCKSIZE); /* erase entry */ for (i=0;imdr_dfilenr;i++){ if (WRITEBLOCK_CURPART(MDR_DIRSTART+i*MDR_DIRENTRYSIZE,&zerodirent,MDR_DIRENTRYSIZE)<0){ err_print("mdr_newfs: cannot write directory entry\n"); /* XXX can't undo previous actions */ return -1; } } /* set LSN0 elements */ bzero(curpart->lsn0,sizeof(struct lsn0_s)); /* reset all! */ MDR_LSN0_P(curpart->lsn0)->mdr_tot[2]=totsize; MDR_LSN0_P(curpart->lsn0)->mdr_tot[1]=totsize>>8; MDR_LSN0_P(curpart->lsn0)->mdr_tot[0]=totsize>>16; MDR_LSN0_P(curpart->lsn0)->mdr_clsz=clustersize/MDR_CLUSTERSIZE; /* !!! */ MDR_LSN0_P(curpart->lsn0)->mdr_clnr[1]=clusternr; MDR_LSN0_P(curpart->lsn0)->mdr_clnr[0]=clusternr>>8; MDR_LSN0_P(curpart->lsn0)->mdr_dfnr[1]=dfilenr; MDR_LSN0_P(curpart->lsn0)->mdr_dfnr[0]=dfilenr>>8; MDR_LSN0_P(curpart->lsn0)->mdr_fnr[1]=0; /* reset! */ MDR_LSN0_P(curpart->lsn0)->mdr_fnr[0]=0; MDR_LSN0_P(curpart->lsn0)->zero1[1]=0; /* mdr_zero1==0 for MDR-DOS partition! */ MDR_LSN0_P(curpart->lsn0)->zero1[0]=0; /* XXX other elements */ /* save new LSN0 */ if (WRITEBLOCK_CURPART(0,curpart->lsn0,1)<0){ err_print("mdr_newfs: cannot write LSN0\n"); /* XXX can't undo previous actions */ return -1; } return 0; /* Note: must restart program after modification of LSN0!!! */ } /* QDOS */ int qdos_newfs(int single,int newlcat) { u_char dirbuf[QDOS_DIRSIZE*QDOS_BLOCKSIZE]; int i; if (curpart->type!=PARTTYPE_QDOS){ return -1; } /* set curpart->... elements */ curpart->blksiz=QDOS_BLOCKSIZE; curpart->totsize=QDOS_PSIZE; /* in QDOS blocks */ /* initialize bitmap */ if (qdos_initbitmap(single,newlcat)<0){ err_print("qdos_newfs: cannot initialize bitmap\n"); return -1; } /* initialize directory */ bzero(dirbuf,QDOS_DIRSIZE*QDOS_BLOCKSIZE); /* erase entry */ for (i=0;ilsn0,QDOS_BLOCKSIZE); /* reset all! */ /* did_id,did_vn,did_rn,did_dt,did_nm: */ bcopy("QDOS 0000010101QDOS ", (char *)curpart->lsn0,38); /* XXX */ /* XXX other elements */ /* save new LSN0 */ if (WRITEBLOCK_CURPART(0,curpart->lsn0,1)<0){ err_print("qdos_newfs: cannot write LSN0\n"); /* XXX can't undo previous actions */ return -1; } return 0; /* Note: must restart program after modification of LSN0!!! */ } /* OS9 */ 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) { u_int sec,bmapblk,bmapbyte,bmapbit; static char bmapbuf[OS9MAX_BLOCKSIZE]; int bmapbufblk; int used; u_int totfree; u_int segfree; int segstart; int lsegstart; u_int lsegfree; int cursegstart; u_int cursegfree; u_int segnr; if (curpart->type!=PARTTYPE_OS9MDR){ return -1; } if (curpart->mdr){ return -1; } if (seekstart>=curpart->totsize){ return -1; } /* we must be careful to construct segments aligned to clusters */ /* because algorithm below assumes this (not markbitmap)! */ /* round down */ seekstart=(seekstart/(curpart->clustersize))*(curpart->clustersize); /* round up to cluster size */ minsize=((minsize+curpart->clustersize-1) /(curpart->clustersize))*(curpart->clustersize); bmapbufblk=-1; /* invalid bitmap block */ /* scan bitmap */ totfree=0; /* nothing found yet */ segfree=0; /* nothing found yet */ segstart=-1; /* invalid block */ lsegfree=0; /* nothing found yet */ lsegstart=-1; /* invalid block */ cursegfree=0; /* nothing found yet */ cursegstart=-1; /* invalid block */ segnr=0; /* nothing found yet */ for (sec=seekstart;sec<=curpart->filesyssize;sec++){ if (sec<(curpart->filesyssize)){ /* calculate block,byte,bit for current block sec */ if (bitmaptranslate(sec,&bmapbit,&bmapbyte,&bmapblk)<0){ err_print("findfree: invalid block\n"); return -1; } /* need to load bitmap block? */ if (((int)bmapblk)!=bmapbufblk){ /* read block */ if (READBLOCK_CURPART(bmapblk,bmapbuf,1)<0){ err_print("findfree: cannot read bitmap block\n"); return -1; } bmapbufblk=bmapblk; } /* check if used */ used=1&(bmapbuf[bmapbyte]>>bmapbit); /* check skiplist */ if ((skiplist!=NULL)&&(!used)){ u_int i; u_int start,size; /* see if block is in skiplist */ for (i=0;ifilesyssize)){ /* used block or end => end of segment */ /* is there a segment? */ if (cursegstart>=0){ /* largest segment stuff */ /* is this segment larger? */ if (cursegfree>lsegfree){ lsegfree=cursegfree; lsegstart=cursegstart; } /* first large enough segment stuff */ /* still looking for large enough segment? */ if (segstart<0){ /* check if current segment is large enough */ if (cursegfree>=minsize){ segfree=cursegfree; segstart=cursegstart; } } /* reset current segment */ cursegfree=0; /* nothing found yet */ cursegstart=-1; /* invalid block */ } }else{ /* free block */ totfree++; /* current segment stuff */ cursegfree++; /* first block of current segment? */ if (cursegstart<0){ cursegstart=sec; segnr++; /* one more segment */ } /* no full scan needed? */ if (!fullscan){ /* check if current (partial) segment is large enough */ if (cursegfree>=minsize){ segfree=cursegfree; /* we stop searching, so: round up to cluster size */ segfree=((segfree+curpart->clustersize-1) /(curpart->clustersize))*(curpart->clustersize); segstart=cursegstart; /* largest segment stuff */ /* is this segment larger? */ if (cursegfree>lsegfree){ lsegfree=cursegfree; lsegstart=cursegstart; } /* note that totfree,lsegfree are not complete, only what we found so far */ break; /* done */ } } } } /* since bitmapstranslate gives cluster alignment and the start blocks */ /* in our search are also cluster aligned => xxxfree and xxxstart also! */ /* -> doesn´t waste blocks */ if (segstartp!=NULL){ *segstartp=segstart; } if (segsizep!=NULL){ *segsizep=segfree; } if (lsegstartp!=NULL){ *lsegstartp=lsegstart; } if (lsegsizep!=NULL){ *lsegsizep=lsegfree; } if (segnrp!=NULL){ *segnrp=segnr; } return totfree; } /* MDR-DOS */ 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) { u_int sec,bmapblk,bmapbyte,bmapbit; char bmapbuf[MDR_BLOCKSIZE]; int bmapbufblk; int used; u_int totfree; u_int segfree; int segstart; int lsegstart; u_int lsegfree; int cursegstart; u_int cursegfree; u_int segnr; if (curpart->type!=PARTTYPE_OS9MDR){ return -1; } if (!curpart->mdr){ return -1; } if (seekstart>=curpart->totsize){ return -1; } /* we must be careful to construct segments aligned to clusters */ /* because algorithm below assumes this (not mdr_markbitmap)! */ /* round down */ seekstart=(seekstart/(curpart->mdr_clustersize))*(curpart->mdr_clustersize); /* round up to cluster size */ minsize=((minsize+curpart->mdr_clustersize-1) /(curpart->mdr_clustersize))*(curpart->mdr_clustersize); bmapbufblk=-1; /* invalid bitmap block */ /* scan bitmap */ totfree=0; /* nothing found yet */ segfree=0; /* nothing found yet */ segstart=-1; /* invalid block */ lsegfree=0; /* nothing found yet */ lsegstart=-1; /* invalid block */ cursegfree=0; /* nothing found yet */ cursegstart=-1; /* invalid block */ segnr=0; /* nothing found yet */ for (sec=seekstart;sec<=curpart->mdr_filesyssize;sec++){ if (sec<(curpart->mdr_filesyssize)){ /* calculate block,byte,bit for current block sec */ if (mdr_bitmaptranslate(sec,&bmapbit,&bmapbyte,&bmapblk)<0){ err_print("mdr_findfree: invalid block\n"); return -1; } /* need to load bitmap block? */ if (((int)bmapblk)!=bmapbufblk){ /* read block */ if (READBLOCK_CURPART(bmapblk,bmapbuf,1)<0){ err_print("mdr_findfree: cannot read bitmap block\n"); return -1; } bmapbufblk=bmapblk; } /* check if used */ used=1&(bmapbuf[bmapbyte]>>bmapbit); /* check skipdirentp */ if ((skipdirentp!=NULL)&&(!used)){ u_int i; u_int skipclu; /* see if block is in skipdirentp */ for (i=0;iclist[i][0]<<8)+skipdirentp->clist[i][1]; if (skipclu==0){ /* end */ break; /* done */ } if (skipclu==sec/curpart->mdr_clustersize){ used=1; break; /* used, done */ } } } } /* check if used or scan complete */ if (used||(sec==curpart->mdr_filesyssize)){ /* used block or end => end of segment */ /* is there a segment? */ if (cursegstart>=0){ /* largest segment stuff */ /* is this segment larger? */ if (cursegfree>lsegfree){ lsegfree=cursegfree; lsegstart=cursegstart; } /* first large enough segment stuff */ /* still looking for large enough segment? */ if (segstart<0){ /* check if current segment is large enough */ if (cursegfree>=minsize){ segfree=cursegfree; segstart=cursegstart; } } /* reset current segment */ cursegfree=0; /* nothing found yet */ cursegstart=-1; /* invalid block */ } }else{ /* free block */ totfree++; /* current segment stuff */ cursegfree++; /* first block of current segment? */ if (cursegstart<0){ cursegstart=sec; segnr++; /* one more segment */ } /* no full scan needed? */ if (!fullscan){ /* check if current (partial) segment is large enough */ if (cursegfree>=minsize){ segfree=cursegfree; /* we stop searching, so: round up to cluster size */ segfree=((segfree+curpart->mdr_clustersize-1) /(curpart->mdr_clustersize))*(curpart->mdr_clustersize); segstart=cursegstart; /* largest segment stuff */ /* is this segment larger? */ if (cursegfree>lsegfree){ lsegfree=cursegfree; lsegstart=cursegstart; } /* note that totfree,lsegfree are not complete, only what we found so far */ break; /* done */ } } } } /* since bitmapstranslate gives cluster alignment and the start blocks */ /* in our search are also cluster aligned => xxxfree and xxxstart also! */ /* -> doesn´t waste blocks */ if (segstartp!=NULL){ *segstartp=segstart; } if (segsizep!=NULL){ *segsizep=segfree; } if (lsegstartp!=NULL){ *lsegstartp=lsegstart; } if (lsegsizep!=NULL){ *lsegsizep=lsegfree; } if (segnrp!=NULL){ *segnrp=segnr; } return totfree; } /* QDOS */ 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) { u_int sec,bmapbyte,bmapbit; char bmapbuf[QDOS_BLOCKSIZE]; int used; u_int totfree; u_int segfree; int segstart; int lsegstart; u_int lsegfree; int cursegstart; u_int cursegfree; u_int segnr; if (curpart->type!=PARTTYPE_QDOS){ return -1; } if (seekstart>=curpart->totsize){ return -1; } /* we must be careful to construct segments aligned to clusters */ /* because algorithm below assumes this (not qdos_markbitmap)! */ /* round down */ seekstart=(seekstart/QDOS_CSIZE)*QDOS_CSIZE; /* round up to cluster size */ minsize=((minsize+QDOS_CSIZE-1)/QDOS_CSIZE)*QDOS_CSIZE; /* read CAT block */ if (READBLOCK_CURPART(QDOS_CATSTART,bmapbuf,1)<0){ err_print("qdos_findfree: cannot read bitmap block\n"); return -1; } /* scan bitmap */ totfree=0; /* nothing found yet */ segfree=0; /* nothing found yet */ segstart=-1; /* invalid block */ lsegfree=0; /* nothing found yet */ lsegstart=-1; /* invalid block */ cursegfree=0; /* nothing found yet */ cursegstart=-1; /* invalid block */ segnr=0; /* nothing found yet */ for (sec=seekstart;sec<=curpart->totsize;sec++){ /* totsize!!! */ if (sectotsize){ /* totsize!!! */ /* calculate block,byte,bit for current block sec */ if (qdos_bitmaptranslate(sec,&bmapbit,&bmapbyte)<0){ err_print("qdos_findfree: invalid block\n"); return -1; } /* check if used */ used=1&(bmapbuf[bmapbyte]>>bmapbit); /* check skipribp */ if ((skipribp!=NULL)&&(!used)){ u_int i; u_int start,size; /* see if block is in skiplist */ for (i=0;itotsize)){ /* totsize!!! */ /* used block or end => end of segment */ /* is there a segment? */ if (cursegstart>=0){ /* largest segment stuff */ /* is this segment larger? */ if (cursegfree>lsegfree){ lsegfree=cursegfree; lsegstart=cursegstart; } /* first large enough segment stuff */ /* still looking for large enough segment? */ if (segstart<0){ /* check if current segment is large enough */ if (cursegfree>=minsize){ segfree=cursegfree; segstart=cursegstart; } } /* reset current segment */ cursegfree=0; /* nothing found yet */ cursegstart=-1; /* invalid block */ } }else{ /* free block */ totfree++; /* current segment stuff */ cursegfree++; /* first block of current segment? */ if (cursegstart<0){ cursegstart=sec; segnr++; /* one more segment */ } /* no full scan needed? */ if (!fullscan){ /* check if current (partial) segment is large enough */ if (cursegfree>=minsize){ segfree=cursegfree; /* we stop searching, so: round up to cluster size */ segfree=((segfree+QDOS_CSIZE-1)/QDOS_CSIZE)*QDOS_CSIZE; segstart=cursegstart; /* largest segment stuff */ /* is this segment larger? */ if (cursegfree>lsegfree){ lsegfree=cursegfree; lsegstart=cursegstart; } /* note that totfree,lsegfree are not complete, only what we found so far */ break; /* done */ } } } } /* since qdos_bitmapstranslate gives cluster alignment and the start blocks */ /* in our search are also cluster aligned => xxxfree and xxxstart also! */ /* -> doesn´t waste blocks */ if (segstartp!=NULL){ *segstartp=segstart; } if (segsizep!=NULL){ *segsizep=segfree; } if (lsegstartp!=NULL){ *lsegstartp=lsegstart; } if (lsegsizep!=NULL){ *lsegsizep=lsegfree; } if (segnrp!=NULL){ *segnrp=segnr; } return totfree; } /* OS9 */ int findfreelist(struct seg_s *seglist,u_int segnr, u_int startblk,u_int blknr) { u_int segstart; u_int segsize; u_int lsegstart; u_int lsegsize; int totfree; u_int seg; if (curpart->type!=PARTTYPE_OS9MDR){ return -1; } if (curpart->mdr){ return -1; } if (seglist==NULL){ return -1; } if (segnr==0){ return -1; } if (blknr==0){ return 0; } if (startblk+blknr>curpart->totsize){ startblk=0; /* XXX */ } /* we must be careful to construct segments aligned to clusters (see findfree) */ /* round down */ startblk=(startblk/(curpart->clustersize))*(curpart->clustersize); /* round up to cluster size */ blknr=((blknr+curpart->clustersize-1) /(curpart->clustersize))*(curpart->clustersize); /* scan segments */ /* first try with given startblk */ for (seg=0;seg0){ /* search above was not for whole partition? */ /* one more try with startblk=0 */ startblk=0; /* searches whole partition */ goto findfreelist_again; }else{ err_print("findfreelist: not enough blocks\n"); return -1; } } /* truncate segment sizes: */ if (segsize>SEG_S_SIZEMAX){ segsize=SEG_S_SIZEMAX; } if (lsegsize>SEG_S_SIZEMAX){ lsegsize=SEG_S_SIZEMAX; } startblk=0; /* in the following searches: whole partition */ /* is there one segment large enough? */ if (segsize>=blknr){ /* set segment */ setseg(seglist+seg,segstart,blknr); /* fill rest of seglist */ { u_int i; for (i=seg+1;itype!=PARTTYPE_OS9MDR){ return -1; } if (!curpart->mdr){ return -1; } if (direntp==NULL){ return -1; } if (fclunr>MDR_FILECLNR){ return -1; } if (startfclu+fclunr>MDR_FILECLNR){ return -1; } if (blknr==0){ return 0; } if (startblk+blknr>curpart->totsize){ startblk=0; /* XXX */ } if (curpart->mdr_clustersize==0){ return -1; } /* we must be careful to construct segments aligned to clusters (see mdr_findfree) */ /* round down */ startblk=(startblk/(curpart->mdr_clustersize))*(curpart->mdr_clustersize); /* round up to cluster size */ blknr=((blknr+curpart->mdr_clustersize-1) /(curpart->mdr_clustersize))*(curpart->mdr_clustersize); if (fclunr*curpart->mdr_clustersize0){ /* search above was not for whole partition? */ /* one more try with startblk=0 */ startblk=0; /* searches whole partition */ goto mdr_findfreelist_again; }else{ err_print("mdr_findfreelist: not enough blocks\n"); return -1; } } startblk=0; /* in the following searches: whole partition */ /* is there one segment large enough? */ if (segsize>=blknr){ /* set segment */ for (c=0,clu=segstart/curpart->mdr_clustersize; cmdr_clustersize;c++,clu++,fclu++){ direntp->clist[fclu][0]=clu>>8; direntp->clist[fclu][1]=clu&0xff; } /* Note: fclu++ above => now fclu==last used fclu+1 !!! */ /* fill rest of direntp */ for (c=fclu;cclist[c][0]=0; direntp->clist[c][1]=0; } return fclu-startfclu; /* return number of clusters */ } /* if we arrive here: lsegsizemdr_clustersize; cmdr_clustersize;c++,clu++,fclu++){ direntp->clist[fclu][0]=clu>>8; direntp->clist[fclu][1]=clu&0xff; } /* remaining blocks */ blknr-=lsegsize; } /* XXX should never arrive here, see check for fclunr large enough for blknr above!!! */ err_print("mdr_findfreelist: internal error!!!\n"); return -1; } /* QDOS */ int qdos_findfreelist(struct qdos_rib_s *ribp,u_int startseg,u_int segnr, u_int startblk,u_int blknr) { u_int segstart; u_int segsize; u_int lsegstart; u_int lsegsize; int totfree; u_int seg; if (curpart->type!=PARTTYPE_QDOS){ return -1; } if (ribp==NULL){ return -1; } /* must have at least one segment to terminate RIB!!! */ if (segnr<1){ return -1; } if (segnr>QDOS_RIB_SDWNR){ return -1; } if (startseg+segnr>QDOS_RIB_SDWNR){ return -1; } if (blknr==0){ return 0; } if (startblk+blknr>curpart->totsize){ startblk=0; /* XXX */ } /* we must be careful to construct segments aligned to clusters (see findfree) */ /* round down */ startblk=(startblk/QDOS_CSIZE)*QDOS_CSIZE; /* round up to cluster size */ blknr=((blknr+QDOS_CSIZE-1)/QDOS_CSIZE)*QDOS_CSIZE; /* scan segments */ /* first try with given startblk */ /* one segment to terminate RIB!!! => segnr-1: */ for (seg=startseg;seg0){ /* search above was not for whole partition? */ /* one more try with startblk=0 */ startblk=0; /* searches whole partition */ goto qdos_findfreelist_again; }else{ err_print("qdos_findfreelist: not enough blocks\n"); return -1; } } /* truncate segment sizes: */ if (segsize>QDOS_RIB_SDWSIZMAX*QDOS_CSIZE){ segsize=QDOS_RIB_SDWSIZMAX*QDOS_CSIZE; } if (lsegsize>QDOS_RIB_SDWSIZMAX*QDOS_CSIZE){ lsegsize=QDOS_RIB_SDWSIZMAX*QDOS_CSIZE; } startblk=0; /* in the following searches: whole partition */ /* is there one segment large enough? */ if (segsize>=blknr){ /* set segment */ qdos_setseg(ribp,seg,segstart/QDOS_CSIZE,blknr/QDOS_CSIZE); /* terminate RIB */ /* Note: segnr-1 above => seg+1type!=PARTTYPE_OS9MDR){ return -1; } if (curpart->mdr){ return -1; } if (seglist==NULL){ return -1; } if (blknr==0){ return 0; /* number of appended segments */ } /* at least two segments */ if (segnr<2){ return -1; } /* get seglist[0] */ getseg(seglist,&startblk,&size); if (size==0){ /* segment[0] is empty */ segstart=seglist; seekstart=0; seeknr=segnr; }else{ /* seglist[0] is non-empty */ segstart=seglist+1; seekstart=startblk+size; /* directly behind end of seglist[0] */ seeknr=segnr-1; } /* append blknr new segments, starting at segstart */ /* use seekstart as a hint for findfreelist to get contiguous blocks (if possible) */ seg=findfreelist(segstart,seeknr,seekstart,blknr); if (seg<=0){ err_print("appendfreelist: cannot find free blocks\n"); return -1; } if (segstart==seglist+1){ /* seglist[0] was non-empty? */ /* get segment 1 */ getseg(seglist+1,&startblk2,&size2); /* check if segment 1 is adjacent to segment 0 */ if (startblk2==startblk+size){ if (size+size2<=SEG_S_SIZEMAX){ /* fits into one segment? */ /* merge segment 0 and 1 into 0 */ setseg(seglist,startblk,size+size2); /* shift remaining segments */ for (i=1;i<((int)segnr)-1;i++){ getseg(seglist+i+1,&startblk,&size); setseg(seglist+i,startblk,size); } /* clear last segment */ setseg(seglist+segnr-1,0,0); seg--; /* Note: might become 0 now which is OK! */ } } } return seg; /* return number of appended segments */ } /* MDR-DOS */ int mdr_appendfreelist(struct mdr_dirent_s *direntp,u_int startfclu,u_int fclunr,u_int blknr) { int ret; u_int startblk; u_int fclu1; u_int seekstart,seeknr; if (curpart->type!=PARTTYPE_OS9MDR){ return -1; } if (!curpart->mdr){ return -1; } if (direntp==NULL){ return -1; } if (blknr==0){ return 0; /* number of appended clusters */ } /* at least 2 clusters */ if (fclunr<2){ return -1; } if (startfclu+fclunr>MDR_FILECLNR){ return -1; } /* get clist[startfclu] */ startblk=curpart->mdr_clustersize *((direntp->clist[startfclu][0]<<8)+(direntp->clist[startfclu][1])); if (startblk==0){ /* clist[startfclu] is empty */ fclu1=startfclu; seekstart=0; seeknr=fclunr; }else{ /* clist[startfclu] is non-empty */ fclu1=startfclu+1; seekstart=startblk+curpart->mdr_clustersize; /* directly behind end of clist[0] */ seeknr=fclunr-1; } /* append blknr new clusters, starting at index flcu1 */ /* use seekstart as a hint for mdr_findfreelist to get contiguous blocks (if possible) */ ret=mdr_findfreelist(direntp,fclu1,seeknr,seekstart,blknr); if (ret<=0){ err_print("mdr_appendfreelist: cannot find free blocks\n"); return -1; } return ret; /* return number of appended clusters */ } /* QDOS */ int qdos_appendfreelist(struct qdos_rib_s *ribp,u_int startseg,u_int segnr,u_int blknr) { u_int startblk,size; u_int startblk2,size2; int i; int seg; u_int seg1; u_int seekstart,seeknr; if (curpart->type!=PARTTYPE_QDOS){ return -1; } if (ribp==NULL){ return -1; } if (blknr==0){ return 0; /* number of appended segments */ } /* at least three segments */ /* must have at least one segment to terminate RIB!!! */ if (segnr<3){ return -1; } if (startseg+segnr>QDOS_RIB_SDWNR){ return -1; } /* get ribp->rib_sdw[startseg] */ qdos_getseg(ribp,startseg,&startblk,&size); if (size==0){ /* segment[startseg] is end */ seg1=startseg; seekstart=0; seeknr=segnr; }else{ /* seglist[startseg] is non-end */ startblk*=QDOS_CSIZE; size*=QDOS_CSIZE; seg1=startseg+1; seekstart=startblk+size; /* directly behind end of ribp->rib_sdw[startseg] */ seeknr=segnr-1; } /* append blknr new segments, starting at seg1 */ /* use seekstart as a hint for qdos_findfreelist to get contiguous blocks (if possible) */ seg=qdos_findfreelist(ribp,seg1,seeknr,seekstart,blknr); if (seg<=0){ err_print("qdos_appendfreelist: cannot find free blocks\n"); return -1; } if (seg1==startseg+1){ /* ribp->rib_sdw[startseg] was non-end? */ /* get segment startseg+1 */ qdos_getseg(ribp,startseg+1,&startblk2,&size2); startblk2*=QDOS_CSIZE; size2*=QDOS_CSIZE; /* check if segment startseg+1 is adjacent to segment startseg */ if (startblk2==startblk+size){ if (size+size2<=QDOS_RIB_SDWSIZMAX*QDOS_CSIZE){ /* fits into one segment? */ /* merge segment startseg and startseg+1 into startseg */ qdos_setseg(ribp,startseg,startblk/QDOS_CSIZE,(size+size2)/QDOS_CSIZE); /* shift remaining segments */ for (i=startseg+1;i<((int)(startseg+segnr))-1;i++){ qdos_getseg(ribp,i+1,&startblk,&size); qdos_setseg(ribp,i,startblk,size); } /* terminate last segment */ /* XXX actually not necessary (qdos_findfreelist already did for previous segment) */ qdos_setseg(ribp,startseg+segnr-1,0,0); /* mark end */ seg--; /* Note: might become 0 now which is OK! */ } } } return seg; /* return number of appended segments */ } /* QDOS */ void qdos_printatt0(u_char att) { u_char fmt; if (att&QDOS_ATT_WRT){ putchar('w'); }else{ putchar('-'); } if (att&QDOS_ATT_DEL){ putchar('d'); }else{ putchar('-'); } if (att&QDOS_ATT_SYS){ putchar('s'); }else{ putchar('-'); } if (att&QDOS_ATT_CON){ putchar('c'); }else{ putchar('-'); } if (att&QDOS_ATT_NCS){ putchar('n'); }else{ putchar('-'); } putchar(' '); fmt=att&QDOS_ATT_FMM; switch (fmt){ case QDOS_ATT_FMU: printf("UserDef"); break; case QDOS_ATT_FMD: printf("DefRec "); break; case QDOS_ATT_FML: printf("BinLoad"); break; case QDOS_ATT_FMB: printf("BinRec "); break; case QDOS_ATT_FMA: printf("ARec "); break; case QDOS_ATT_FMC: printf("ABinRec"); break; default: printf("???????"); break; } } /* OS9 */ void printatt(u_char att) { if (att&ATT_D){ putchar('D'); }else{ putchar('-'); } if (att&ATT_S){ putchar('S'); }else{ putchar('-'); } if (att&ATT_PE){ putchar('E'); }else{ putchar('-'); } if (att&ATT_PW){ putchar('W'); }else{ putchar('-'); } if (att&ATT_PR){ putchar('R'); }else{ putchar('-'); } if (att&ATT_E){ putchar('e'); }else{ putchar('-'); } if (att&ATT_W){ putchar('w'); }else{ putchar('-'); } if (att&ATT_R){ putchar('r'); }else{ putchar('-'); } } /* OS9 */ int setattr(struct filedes_s *fdes,char *str) { u_int i; int set; u_char att[2]; if (fdes==NULL){ return -1; } if (str==NULL){ return -1; } /* scan string */ set=-1; /* nothing */ att[0]=0; att[1]=0; for (i=0;ifd_att|=att[1]; /* set */ fdes->fd_att&=~att[0]; /* clear */ /* XXX don´t forget to save fdes */ return 0; } /* set/clear ATT_CON flag in directory entry if file is contiguous */ int qdos_setattr(struct qdos_rib_s *ribp,u_int fnr,void *indirp,char *attstr) { u_int alloc,contig; u_char dirbuf[QDOS_DIRSIZE*QDOS_BLOCKSIZE]; struct qdos_dir_s *qdp; if (ribp==0){ return -1; } if (curpart->type!=PARTTYPE_QDOS){ return -1; } if (fnr>=QDOS_DIRENTRYNR){ return -1; } if (indirp==NULL){ /* read directory */ if (READBLOCK_CURPART(QDOS_DIRSTART,(void *)dirbuf,QDOS_DIRSIZE)<0){ err_print("qdos_setattr: cannot read directory\n"); return -1; } qdp=(struct qdos_dir_s *)dirbuf; }else{ /* directory already read */ qdp=(struct qdos_dir_s *)indirp; } /* set/clear ATT_CON extra!!! */ alloc=qdos_countseg(ribp,QDOS_RIB_SDWNR,&contig); if ((alloc!=0)&&(alloc==contig)){ qdp[fnr].dir_at[0]|=QDOS_ATT_CON; /* set flag */ }else{ qdp[fnr].dir_at[0]&=~QDOS_ATT_CON; /* clear flag */ } if (attstr!=NULL){ /* first check for format strings */ if (strcasecmp(attstr,"userdef")==0){ qdp[fnr].dir_at[0]=(qdp[fnr].dir_at[0]&QDOS_ATT_FLM)|QDOS_ATT_FMU; }else if (strcasecmp(attstr,"defrec")==0){ qdp[fnr].dir_at[0]=(qdp[fnr].dir_at[0]&QDOS_ATT_FLM)|QDOS_ATT_FMD; }else if (strcasecmp(attstr,"binload")==0){ qdp[fnr].dir_at[0]=(qdp[fnr].dir_at[0]&QDOS_ATT_FLM)|QDOS_ATT_FML; }else if (strcasecmp(attstr,"binrec")==0){ qdp[fnr].dir_at[0]=(qdp[fnr].dir_at[0]&QDOS_ATT_FLM)|QDOS_ATT_FMB; }else if (strcasecmp(attstr,"arec")==0){ qdp[fnr].dir_at[0]=(qdp[fnr].dir_at[0]&QDOS_ATT_FLM)|QDOS_ATT_FMA; }else if (strcasecmp(attstr,"abinrec")==0){ qdp[fnr].dir_at[0]=(qdp[fnr].dir_at[0]&QDOS_ATT_FLM)|QDOS_ATT_FMC; }else{ u_int i; int set; u_char att[2]; /* scan string */ set=-1; /* nothing */ att[0]=0; att[1]=0; for (i=0;ifd_fsize[0]<<24) +(fdes->fd_fsize[1]<<16) +(fdes->fd_fsize[2]<<8) +fdes->fd_fsize[3]; /* size according to directory entry */ asize=countseg(&(fdes->fd_seg[0]),FILEDES_SEGNR,&contbl); /* allocated */ /* check if corrupt */ if (pp->type!=PARTTYPE_OS9MDR){ return -1; } if (pp->mdr) return -1; corrupt=(fsize>asize*pp->blksiz)||(asize>pp->filesyssize); if (verbose){ printf("fd_att: %02x (",fdes->fd_att); printatt(fdes->fd_att); printf(")\nfd_own: %02x%02x\n",fdes->fd_own[0],fdes->fd_own[1]); printf("fd_dat: %02i-%02i-%02i %02i:%02i\n", fdes->fd_dat[0]%100,fdes->fd_dat[1]%100,fdes->fd_dat[2]%100, fdes->fd_dat[3]%100,fdes->fd_dat[4]%100); printf("fd_link: %02x\n",fdes->fd_link); printf("fd_fsize: %08x (%u bytes)\n",fsize,fsize); printf(" alloc: %08x (%u bytes)\n",asize*pp->blksiz,asize*pp->blksiz); printf(" contig: %08x (%u bytes)\n",contbl*pp->blksiz,contbl*pp->blksiz); printf("fd_creat: %02i-%02i-%02i\n", fdes->fd_creat[0]%100,fdes->fd_creat[1]%100,fdes->fd_creat[2]%100); for (i=0;ifd_seg[i].size[0]==0)&&(fdes->fd_seg[i].size[1]==0)){ break; /* end of list */ } printf("fd_seg[%02x]: addr: %02x%02x%02x size: %02x%02x\n", i, fdes->fd_seg[i].addr[0], fdes->fd_seg[i].addr[1], fdes->fd_seg[i].addr[2], fdes->fd_seg[i].size[0],fdes->fd_seg[i].size[1]); } if (corrupt){ printf("*** corrupt file size/allocation size ***\n"); } printf("\n"); }else{ printf("%02x%02x ",fdes->fd_own[0],fdes->fd_own[1]); printatt(fdes->fd_att); printf(" %02i-%02i-%02i", fdes->fd_creat[0]%100,fdes->fd_creat[1]%100,fdes->fd_creat[2]%100); printf(" %02i-%02i-%02i %02i:%02i", fdes->fd_dat[0]%100,fdes->fd_dat[1]%100,fdes->fd_dat[2]%100, fdes->fd_dat[3]%100,fdes->fd_dat[4]%100); printf(" %02x",fdes->fd_link); printf(" %08x",fsize); } if (corrupt) return -7; /* corrupt */ return fsize; } /* MDR-DOS */ void mdr_printdirent(struct mdr_dirent_s *direntp) { u_int i,iold,istart; u_int pblk,pblkold,pblkstart; u_int fsize; u_int cnr,contcl; if (direntp==NULL){ return; } /* check if entry not used */ if (direntp->name[0]==0){ printf("*** unused directory entry ***\n"); return; } printf("name: %s\n",direntp->name); /* XXX no length check */ printf("type: %c%c%c%c\n", direntp->type[0],direntp->type[1],direntp->type[2],direntp->type[3]); fsize=(direntp->size[0]<<24) +(direntp->size[1]<<16) +(direntp->size[2]<<8) +direntp->size[3]; printf("size: %08x (%u bytes)\n",fsize,fsize); cnr=mdr_countclu(direntp,MDR_FILECLNR,&contcl); printf("alloc: %08x (%u bytes)\n", cnr*curpart->mdr_clustersize*curpart->blksiz, cnr*curpart->mdr_clustersize*curpart->blksiz); printf("conti: %08x (%u bytes)\n", contcl*curpart->mdr_clustersize*curpart->blksiz, contcl*curpart->mdr_clustersize*curpart->blksiz); printf("back: %02i-%02i-%02i %02i:%02i:%02i\n", direntp->back[0]%100,direntp->back[1]%100,direntp->back[2]%100, direntp->back[3]%100,direntp->back[4]%100,direntp->back[5]%100); printf("modif: %02i-%02i-%02i %02i:%02i:%02i\n", direntp->modif[0]%100,direntp->modif[1]%100,direntp->modif[2]%100, direntp->modif[3]%100,direntp->modif[4]%100,direntp->modif[5]%100); /* scan clusters */ pblkstart=0; /* invalid pblkstart */ for (i=0;iclist[i][0]<<8)+direntp->clist[i][1]; if (pblk==0){ /* end if clist */ /* check if segment present */ if (pblkstart!=0){ /* valid pblkstart? */ if (iold>istart){ printf("clist[%04x-%04x] -> %04x-%04x\n", istart,iold,pblkstart,pblkold); }else{ printf("clist[%04x] -> %04x\n", istart,pblkstart); } } break; } /* Note: pblk!=0 now!!! */ if (pblkstart==0){ /* invalid pblkstart? */ /* new segment start */ pblkstart=pblk; istart=i; }else if (pblk!=pblkold+1){ /* pblk is not contiguous => end of current segment */ if (iold>istart){ printf("clist[%04x-%04x] -> %04x-%04x\n", istart,iold,pblkstart,pblkold); }else{ printf("clist[%04x] -> %04x\n", istart,pblkstart); } /* new segment start */ pblkstart=pblk; istart=i; } /* save current block */ pblkold=pblk; iold=i; } printf("\n"); } /* QDOS */ void qdos_printfdes(struct qdos_dir_s *dirp,struct qdos_rib_s *ribp) { u_int i; u_int off,size; u_int fsize,cnr,contcl; if (dirp!=NULL){ /* check if entry not used */ if (dirp->dir_nm[0]==0){ printf("*** unused directory entry ***\n"); return; } printf("dir_nm: "); printnstr(dirp->dir_nm,8); printf("."); printnstr(dirp->dir_sx,2); printf("\ndir_rb: %02x%02x\n",dirp->dir_rb[0],dirp->dir_rb[1]); printf("dir_at: %02x%02x (",dirp->dir_at[0],dirp->dir_at[1]); qdos_printatt0(dirp->dir_at[0]); printf(")\n"); } if (ribp!=NULL){ printf("rib_lb: %02x%\n",ribp->rib_lb); printf("rib_sl: %02x%02x\n",ribp->rib_sl[0],ribp->rib_sl[1]); printf("rib_la: %02x%02x\n",ribp->rib_la[0],ribp->rib_la[1]); printf("rib_sa: %02x%02x\n",ribp->rib_sa[0],ribp->rib_sa[1]); /* scan segments */ for (i=0;iblksiz, cnr*QDOS_CSIZE*curpart->blksiz); /* Note: first block of file allocation is used for RIB!!! */ printf("contig: %06x (%u bytes)\n", contcl*QDOS_CSIZE*curpart->blksiz-curpart->blksiz, contcl*QDOS_CSIZE*curpart->blksiz-curpart->blksiz); printf("\n"); } } /* general */ /* Note: blocks in filesystem blksiz!!! */ /* Note: we allow lseek within allocated data-area of file!!! */ int filelseek(union genfdes_u *fp,u_int lblk,u_int *contblksp) { if (fp==NULL){ return -1; } if (curpart->type==PARTTYPE_QDOS){ /* QDOS */ int i; u_int blknr; u_int addr,size; struct qdos_rib_s *ribp; ribp=&fp->qdos.rib; lblk++; /* first block of file allocation is used for RIB!!! */ blknr=0; /* block counter */ for (i=0;ilblk){ /* lblk is within this segment */ break; /* found */ } blknr+=size; } if (i>=QDOS_RIB_SDWNR){ /* end of list but lblk not reached */ return -1; /* beyond end of file! */ } if (contblksp!=NULL){ u_int oldaddr,oldsize,addr2,size2,cblknr; /* number of following contiguous blocks in this segment */ cblknr=blknr+size-lblk; /* scan following segments if also contiguous */ oldaddr=addr; oldsize=size; i++; /* must start scan with next segment! */ for (;itype!=PARTTYPE_OS9MDR){ err_print("filelseek: invalid partition type\n"); return -1; } /* now OS9 or MDR-DOS */ if (!curpart->mdr){ /* OS9 */ int i; u_int blknr; u_int addr,size; struct filedes_s *fdes; fdes=&fp->os9; blknr=0; /* block counter */ for (i=0;ifd_seg[i],&addr,&size); if (size==0){ /* end of list but lblk not reached */ return -1; } if (blknr+size>lblk){ /* lblk is within this segment */ break; /* found */ } blknr+=size; } if (i>=FILEDES_SEGNR){ /* end of list but lblk not reached */ return -1; /* beyond end of file! */ } if (contblksp!=NULL){ u_int oldaddr,oldsize,addr2,size2,cblknr; /* number of following contiguous blocks in this segment */ cblknr=blknr+size-lblk; /* scan following segments if also contiguous */ oldaddr=addr; oldsize=size; for (;ifd_seg[i],&addr2,&size2); if (size2==0){ /* end of list */ break; } if (addr2!=oldaddr+oldsize){ /* not contiguous to previous segment */ break; } cblknr+=size2; /* contiguous */ oldaddr=addr2; oldsize=size2; } *contblksp=cblknr; } return addr+lblk-blknr; /* physical start block */ }else{ /* MDR-DOS */ u_int c; u_int fclu; u_int clu; u_int blknr; struct mdr_dirent_s *direntp; direntp=(struct mdr_dirent_s *)fp; /* index for logical block lblk in direntp->clist */ fclu=lblk/curpart->mdr_clustersize; if (fclu>=MDR_FILECLNR){ return -1; /* beyond end of file! */ } /* important: must check number of used&&valid cluster entries in clist!!! */ for (c=0;cclist[c][0]<<8)+(direntp->clist[c][1]); if (clu==0){ break; /* end of clist */ } } if (fclu>=c){ return -1; /* beyond end of file! */ } /* physical cluster */ clu=(direntp->clist[fclu][0]<<8)+(direntp->clist[fclu][1]); /* Note: now, clu!=0 and valid after check above! */ /* physical block */ blknr=curpart->mdr_clustersize*clu +lblk%curpart->mdr_clustersize; if (contblksp!=NULL){ u_int i,newclu,oldclu,size; /* number of remaining blocks following lblk in cluster fclu: */ size=curpart->mdr_clustersize-(lblk%curpart->mdr_clustersize); /* scan starting at cluster fclu+1: */ oldclu=clu; /* physical cluster for fclu */ for (i=fclu+1;iclist[i][0]<<8)+(direntp->clist[i][1]); if ((newclu==0)||(newclu!=oldclu+1)){ break; /* end of contiguous physical blocks */ } size+=curpart->mdr_clustersize; oldclu++; } /* number of following contiguous blocks */ *contblksp=size; } return blknr; /* physical start block */ } } /* general */ /* Note: blocks in filesystem blksiz!!! */ int fileread(union genfdes_u *fp,void *buf,u_int lblkstart,u_int lblknr) { u_int i; int blk; u_int contblks; if ((fp==NULL)||(buf==NULL)){ return -1; } /* Note: filelseek below will return error for blocks that are beyond file allocation! */ #ifdef FILEDEBUG printf("fileread: lblkstart=%06x lblknr=%06x\n", lblkstart,lblknr); #endif contblks=0; for (i=0;i blk=%06x contblks=%06x\n", lblkstart+i,blk,contblks); #endif if ((blk<0)||(contblks==0)){ return i; /* number of blocks read */ } /* truncate if necessary */ if ((lblknr-i)blksiz,contblks)<0){ return i; /* number of blocks read */ } } return lblknr; /* number of blocks read */ } /* general */ /* Note: blocks in filesystem blksiz!!! */ int filewrite(union genfdes_u *fp,void *buf,u_int lblkstart,u_int lblknr) { u_int i; int blk; u_int contblks; if ((fp==NULL)||(buf==NULL)){ return -1; } /* Note: filelseek below will return error for blocks that are beyond file allocation! */ #ifdef FILEDEBUG printf("filewrite: lblkstart=%06x lblknr=%06x\n", lblkstart,lblknr); #endif contblks=0; for (i=0;i blk=%06x contblks=%06x\n", lblkstart+i,blk,contblks); #endif if ((blk<0)||(contblks==0)){ return i; /* number of blocks written */ } /* truncate if necessary */ if ((lblknr-i)blksiz,contblks)<0){ return i; /* number of blocks written */ } } return lblknr; /* number of blocks written */ } /* OS9 */ int filedel(u_int fdessec) { static struct filedes_s fdes; struct seg_s fdesseg; static u_int bstart; if (curpart->type!=PARTTYPE_OS9MDR){ return -1; } if (curpart->mdr){ return -1; } /* read file descriptor */ if (READBLOCK_CURPART(fdessec,&fdes,1)<0){ err_print("filedel: cannot read file descriptor\n"); return -1; } #ifdef DEBUG printf("filedel:\n"); printfiledes(curpart,&fdes,1); #endif /* warn if bootfile */ getseg(&fdes.fd_seg[0],&bstart,NULL); if ((curpart->bootsize!=0)&&(bstart==curpart->bootsec)){ err_print("filedel: warning: was bootfile\n"); /* XXX it´s too late if deldirent already called!!! */ } /* warn if partition table file */ if ((curpart->pnr!=0)&&(bstart==curpart->ptabsec)){ err_print("filedel: warning: was partfile\n"); /* XXX it´s too late if deldirent already called!!! */ } /* check if link count <=1 (0 also OK) */ if (fdes.fd_link<=1){ /* delete data segments */ if (markbitmap(&(fdes.fd_seg[0]),FILEDES_SEGNR,0)<0){ err_print("filedel: cannot delete segments\n"); return -1; } /* delete file descriptor as well! */ /* set file descriptor block */ /* delete whole cluster */ setseg(&fdesseg,fdessec,curpart->clustersize); /* delete file descriptor block */ if (markbitmap(&fdesseg,1,0)<0){ err_print("filedel: cannot delete file descriptor\n"); return -1; } }else{ /* linked elsewhere, must decrement link count only! */ fdes.fd_link--; /* unlink */ /* write updated file descriptor */ if (WRITEBLOCK_CURPART(fdessec,&fdes,1)<0){ err_print("filedel: cannot write updated file descriptor\n"); return -1; } } /* don't forget to delete directory entry */ return 0; } /* MDR-DOS */ int mdr_filedel(struct mdr_dirent_s *direntp) { if (curpart->type!=PARTTYPE_OS9MDR){ return -1; } if (!curpart->mdr){ return -1; } #ifdef DEBUG printf("mdr_filedel\n"); #endif /* delete clusters */ if (mdr_markbitmap(direntp,MDR_FILECLNR,0)<0){ err_print("mdr_filedel: cannot delete clusters\n"); return -1; } return 0; /* don't forget to delete directory entry */ } /* QDOS */ int qdos_filedel(struct qdos_rib_s *qrib) { if (curpart->type!=PARTTYPE_QDOS){ return -1; } #ifdef DEBUG printf("qdos_filedel\n"); #endif /* delete segments */ /* Note: first block of file allocation is used for RIB!!! */ if (qdos_markbitmap(qrib,QDOS_RIB_SDWNR,0)<0){ err_print("qdos_filedel: cannot delete segments\n"); return -1; } return 0; /* don't forget to delete directory entry */ } /* OS9 */ int filecreat(struct filedes_s *fdes,u_int blknr,int extend) { u_int fdesblk; u_int s; if (curpart->type!=PARTTYPE_OS9MDR){ return -1; } if (curpart->mdr){ return -1; } if (fdes==NULL){ return -1; } /* at least one block */ if (blknr==0) blknr=1; fdesblk=0; /* new file? */ if (!extend){ /* create segment list */ /* allocate one extra block for file descriptor (see below)!!! */ /* Note: to allocate the file descriptor this way is not mandatory but convenient! */ if (findfreelist(&(fdes->fd_seg[0]),FILEDES_SEGNR,0,blknr+1)<0){ err_print("filecreat: cannot create segment list\n"); return -1; } }else{ int i; u_int size; /* extend segment list */ /* find end of segment list in file descriptor */ for (i=0;ifd_seg[i]),NULL,&size); if (size==0){ /* found free segment */ break; } } if (i>=FILEDES_SEGNR){ /* no free segment */ err_print("filecreat: no free segment for extension\n"); return -1; } /* now i is first free index */ if (i==0){ /* first segment is free => create segment list */ if (findfreelist(&(fdes->fd_seg[0]),FILEDES_SEGNR,0,blknr)<0){ err_print("filecreat: cannot create segment list\n"); return -1; } }else{ /* append blocks */ if (appendfreelist(&(fdes->fd_seg[i-1]),FILEDES_SEGNR-i+1,blknr)<0){ err_print("filecreat: cannot extend segment list\n"); return -1; } } } #ifdef DEBUG printf("filecreat: blknr: %06x\n",blknr); printfiledes(curpart,fdes,1); #endif /* allocate segments */ if (markbitmap(&(fdes->fd_seg[0]),FILEDES_SEGNR,1)<0){ err_print("filecreat: cannot allocate segments\n"); return -1; } /* new file? */ if (!extend){ /* Note: we have allocated blknr+1 above! */ /* get new file descriptor block: take first block in first segment */ getseg(&(fdes->fd_seg[0]),&fdesblk,&s); /* remove this block from file-data area */ if (s==0){ /* XXX should never happen!!! */ err_print("filecreat: internal error: s==0\n"); return -1; } s--; if (s==0){ u_int i,startblk,size; /* must shift remaining segments */ for (i=1;ifd_seg[i+1],&startblk,&size); setseg(&fdes->fd_seg[i],startblk,size); } /* clear last segment */ setseg(&fdes->fd_seg[i],0,0); }else{ setseg(&fdes->fd_seg[0],fdesblk+1,s); /* see s-- above! */ } } return fdesblk; /* don't forget to set elements of file descriptor */ /* don't forget to write file descriptor */ /* don't forget to create directory entry! */ } /* MDR-DOS */ int mdr_filecreat(struct mdr_dirent_s *direntp,u_int blknr,int extend) { if (curpart->type!=PARTTYPE_OS9MDR){ return -1; } if (!curpart->mdr){ return -1; } if (direntp==NULL){ return -1; } /* at least one block */ if (blknr==0) blknr=1; /* new file? */ if (!extend){ /* create new direntp->clist */ if (mdr_findfreelist(direntp,0,MDR_FILECLNR,0,blknr)<0){ err_print("mdr_filecreat: cannot allocate space\n"); return -1; } }else{ u_int fclu; /* find end cluster index of file */ for (fclu=0;fcluclist[fclu][0]==0)&&(direntp->clist[fclu][1]==0)){ break; /* found end */ } } /* no index free? */ if (fclu==MDR_FILECLNR){ err_print("mdr_filecreat: no cluster free in directory entry\n"); return -1; } /* now fclu is first free index */ if (fclu==0){ /* first cluster is free => create cluster list */ if (mdr_findfreelist(direntp,0,MDR_FILECLNR,0,blknr)<0){ err_print("mdr_filecreat: cannot allocate space\n"); return -1; } }else{ /* append blocks */ if (mdr_appendfreelist(direntp,fclu-1,MDR_FILECLNR-fclu+1,blknr)<0){ err_print("mdr_filecreat: cannot append space\n"); return -1; } } } #ifdef DEBUG printf("mdr_filecreat: blknr: %06x\n",blknr); #endif /* allocate in bitmp */ if (mdr_markbitmap(direntp,MDR_FILECLNR,1)<0){ err_print("mdr_filecreat: cannot allocate in bitmap\n"); return -1; } return 0; /* don't forget to set elements of direntp */ /* don't forget to create directory entry! */ } /* QDOS */ int qdos_filecreat(struct qdos_rib_s *ribp,u_int blknr,int extend) { if (curpart->type!=PARTTYPE_QDOS){ return -1; } /* at least one block for data */ if (blknr==0) blknr=1; /* new file? */ if (!extend){ /* create segment list */ /* allocate one extra block for RIB!!! */ /* Note: first block of file allocation is used for RIB!!! */ if (qdos_findfreelist(ribp,0,QDOS_RIB_SDWNR,0,blknr+1)<0){ err_print("qdos_filecreat: cannot create segment list\n"); return -1; } }else{ int i; u_int size; /* extend segment list */ /* find end of segment list in file descriptor */ for (i=0;i=QDOS_RIB_SDWNR){ /* no free segment */ err_print("qdos_filecreat: no free segment for extension\n"); return -1; } /* now i is first free index */ if (i==0){ /* first segment is free => create segment list */ /* allocate one extra block for RIB!!! */ /* Note: first block of file allocation is used for RIB!!! */ if (qdos_findfreelist(ribp,0,QDOS_RIB_SDWNR,0,blknr+1)<0){ err_print("qdos_filecreat: cannot create segment list\n"); return -1; } }else{ /* append blocks */ if (qdos_appendfreelist(ribp,i-1,QDOS_RIB_SDWNR-i+1,blknr)<0){ err_print("qdos_filecreat: cannot extend segment list\n"); return -1; } } } #ifdef DEBUG printf("qdos_filecreat: blknr: %06x\n",blknr); #endif /* allocate segments */ if (qdos_markbitmap(ribp,QDOS_RIB_SDWNR,1)<0){ err_print("qdos_filecreat: cannot allocate segments\n"); return -1; } return 0; /* don't forget to set elements of RIB */ /* don't forget to write RIB to first allocated block! */ /* don't forget to create directory entry! */ } /* OS9 */ int getdir(u_int newdirsec,struct filedes_s *curdirdesp,u_int *curdirsizep) { if (curpart->type!=PARTTYPE_OS9MDR){ return -1; } if (curpart->mdr){ return -1; } if (curdirdesp==NULL){ return -1; } if (newdirsec==0){ /* invalid sec for directory file descriptor */ err_print("getdir: invalid directory\n"); return -1; } /* read directory file descriptor */ if (READBLOCK_CURPART(newdirsec,curdirdesp,1)<0){ err_print("getdir: READBLOCK_CURPART(newdirsec)\n"); return -1; } /* check if directory file */ if ((curdirdesp->fd_att&ATT_D)==0){ err_print("getdir: file is no directory\n"); return -1; } if (curdirsizep!=NULL){ *curdirsizep=(curdirdesp->fd_fsize[0]<<24) +(curdirdesp->fd_fsize[1]<<16) +(curdirdesp->fd_fsize[2]<<8) +curdirdesp->fd_fsize[3]; } return 0; } /* OS9 */ /* returns sector of file descriptor */ int findfile(char *name,int countfree,u_int *freeentp) { static struct filedes_s curdirdes; u_int curdirsize; struct dirent_s *curdirp; u_int blknr; u_int i; static char tmpname[FILENAMELEN+1]; u_int startsec; int countonly,count; if (curpart->type!=PARTTYPE_OS9MDR){ return -1; } if (curpart->mdr) return -1; if (name==NULL){ countonly=1; count=0; }else{ if((strlen(name)==0)||(strlen(name)>FILENAMELEN)){ return -1; } countonly=0; } if (getdir(curdirsec,&curdirdes,&curdirsize)<0){ return -1; } /* in findfile we allow totally empty directories!!! */ if (curdirsize==0){ if (countonly){ return 0; } return -1; /* file not found */ } /* XXX read whole directory file */ /* read directory file */ /* XXX 32-Bit overflow protection */ blknr=(u_int)((((OFF_T)curdirsize)+((OFF_T)curpart->blksiz-1)) /((OFF_T)curpart->blksiz)); /* allocate memory for directory file */ curdirp=(struct dirent_s *)malloc(blknr*curpart->blksiz); if (curdirp==NULL){ perror("findfile: malloc"); return -1; } /* read directory file */ if (fileread((union genfdes_u *)&curdirdes,(void *)curdirp,0,blknr)!=(int)blknr){ err_print("findfile: fileread(curdirdes)\n"); free((void *)curdirp); return -1; } /* scan directory entries */ for (i=0;itype!=PARTTYPE_OS9MDR){ return -1; } if (!curpart->mdr){ return -1; } if (name==NULL){ return -1; } /* scan directory */ /* up to mdr_filenr (and not mdr_dfilenr) */ for (fnr=0;fnrmdr_filenr;fnr++){ /* read directory entry */ if (READBLOCK_CURPART(MDR_DIRSTART+fnr*MDR_DIRENTRYSIZE, (void *)&dirent,MDR_DIRENTRYSIZE)<0){ err_print("mdr_findfile: READBLOCK_CURPART\n"); return -1; } /* check if entry not used */ if (dirent.name[0]==0) continue; /* next */ /* compare name */ if (strcasecmp(name,dirent.name)==0){ /* name found */ return fnr+1; } } return -1; /* file not found */ } /* QDOS */ /* returns file number+1 !!! */ /* Note: 0 is used as symbolic value for root directory in findfile3!!! */ int qdos_findfile(char *name) { u_int fnr; u_char dirbuf[QDOS_DIRSIZE*QDOS_BLOCKSIZE]; struct qdos_dir_s *qdp; int i; char qname[11],dname[11]; /* NNNNNNNNSS with terminating '\0' */ if (curpart->type!=PARTTYPE_QDOS){ return -1; } if (name==NULL){ return -1; } /* read directory */ if (READBLOCK_CURPART(QDOS_DIRSTART,(void *)dirbuf,QDOS_DIRSIZE)<0){ err_print("qdos_findfile: READBLOCK_CURPART\n"); return -1; } qdp=(struct qdos_dir_s *)dirbuf; /* convert name into QDOS-conformant name */ qdos_makefname(name,qname); /* scan directory */ for (fnr=0;fnrtype!=PARTTYPE_OS9MDR){ return -1; } if (curpart->mdr){ return -1; } if ((name==NULL)||(strlen(name)==0)){ return -1; } /* check for "." and ".." */ if ((strcmp(name,".")==0)||(strcmp(name,"..")==0)){ err_print("deldirent: . or .. not allowed\n"); return -1; } if (getdir(curdirsec,&curdirdes,&curdirsize)<0){ return -1; } /* XXX read whole directory file */ if (curdirsize==0){ err_print("deldirent: directoy empty\n"); return -1; } /* read directory file */ /* XXX 32-Bit overflow protection */ blknr=(u_int)((((OFF_T)curdirsize)+((OFF_T)curpart->blksiz-1)) /((OFF_T)curpart->blksiz)); /* allocate memory for directory file */ curdirp=(struct dirent_s *)malloc(blknr*curpart->blksiz); if (curdirp==NULL){ perror("deldirent: malloc"); return -1; } /* read directory file */ if (fileread((union genfdes_u *)&curdirdes,(void *)curdirp,0,blknr)!=(int)blknr){ err_print("deldirent: fileread(curdirdes)\n"); free((void *)curdirp); return -1; } /* scan directory entries */ for (i=0;i=0){ /* read file descriptor */ if (READBLOCK_CURPART(startsec,&fdes,1)<0){ err_print("deldirent: cannot read file descriptor\n"); free((void *)curdirp); return -1; } /* check if directory file? */ if (dir){ /* must be directory */ /* check if directory file */ if ((fdes.fd_att&ATT_D)==0){ err_print("deldirent: file is no directory\n"); free((void *)curdirp); return -1; } }else{ /* must not be directory */ /* check if directory file */ if (fdes.fd_att&ATT_D){ err_print("deldirent: file is directory\n"); free((void *)curdirp); return -1; } } } /* delete directory entry */ curdirp[i].dir_name[0]=0; /* write modified directory block */ /* blocksize must be integer multiple of sizeof(struct dirent_s) */ dirblk=(i*sizeof(struct dirent_s))/curpart->blksiz; /* block in file */ if (filewrite((union genfdes_u *)&curdirdes, ((char *)(curdirp))+dirblk*curpart->blksiz, dirblk,1)!=1){ err_print("deldirent: cannot write directory\n"); free((void *)curdirp); return -1; } /* update of directory size not necessary */ /* XXX should search for unused blocks at the end and release them */ /* update modif time of current directory */ setdate(&curdirdes,0); /* 0: not creat */ /* write updated file descriptor */ if (WRITEBLOCK_CURPART(curdirsec,&curdirdes,1)<0){ err_print("deldirent: cannot write updated file descriptor\n"); return -1; } free((void *)curdirp); return startsec; /* file whose entry was deleted */ } } free((void *)curdirp); err_print("deldirent: file not found\n"); return -1; } /* OS9 */ int creatdirent(char *name,u_int startsec) { static struct filedes_s curdirdes; u_int curdirsize; int entfree; u_int freeent; int space; static char buf[OS9MAX_BLOCKSIZE]; u_int entblk,entoff; struct dirent_s *direntp; if (curpart->type!=PARTTYPE_OS9MDR){ return -1; } if (curpart->mdr){ return -1; } if ((name==NULL)||(strlen(name)==0)){ return -1; } if (strlen(name)>FILENAMELEN){ err_print("creatdirent: name too long\n"); return -1; } /* don't refuse . and .. so we can use creatdirent for them!!! */ /* check if file with this name already exists */ if (findfile(name,0,NULL)>=0){ err_print("creatdirent: name already used\n"); return -1; } /* check if startsec valid */ if (startsec>=curpart->totsize){ err_print("creatdirent: invalid startsec\n"); return -1; } /* see how many entries free in current directory */ entfree=findfile(NULL,1,&freeent); if (entfree<0){ err_print("creatdirent: findfile\n"); return -1; } if (getdir(curdirsec,&curdirdes,&curdirsize)<0){ return -1; } #ifdef DEBUG printf("creatdirent: entfree: %i freeent: %06x\n",entfree,freeent); printfiledes(curpart,&curdirdes,1); #endif if (entfree>0){ /* free entry found */ #ifdef DEBUG printf("creatdirent: free entry found\n"); #endif /* read directory block with free entry */ entblk=(freeent*sizeof(struct dirent_s))/curpart->blksiz; /* read entblk from current directory file */ if (fileread((union genfdes_u *)&curdirdes,buf,entblk,1)!=1){ err_print("creatdirent: fileread(curdirdes)\n"); return -1; } /* entry index offset in block */ entoff=((freeent*sizeof(struct dirent_s))%curpart->blksiz) /sizeof(struct dirent_s); }else{ /* no free entries found */ #ifdef DEBUG printf("creatdirent: no free entry found\n"); #endif /* see if space in last segment is left in current directory */ space=(int)countseg(&(curdirdes.fd_seg[0]),FILEDES_SEGNR,NULL)*curpart->blksiz -curdirsize; /* curdirsize should be integer multiple of sizeof(struct dirent_s) */ if ((curdirsize%sizeof(struct dirent_s)!=0)||(space<0)){ /* should not happen */ err_print("creatdirent: directory size corrupt\n"); return -1; } if (space>0){ /* free space */ #ifdef DEBUG printf("creatdirent: free space: %06x\n",space); #endif /* read directory block corresponding to curdirsize+1 */ /* note: fileread doesn't check for block outside official file size! */ /* as long as it is within the file's allocated space!!! */ entblk=(curdirsize+1)/curpart->blksiz; /* read entblk from current directory file */ if (fileread((union genfdes_u *)&curdirdes,buf,entblk,1)!=1){ err_print("creatdirent: fileread(curdirdes)\n"); return -1; } /* entry index offset in block */ entoff=(curdirsize%curpart->blksiz)/sizeof(struct dirent_s); /* the following is probably not necessary */ /* clear rest of block */ /* note: 0 => directory entry free */ bzero(buf+(curdirsize%curpart->blksiz), curpart->blksiz-(curdirsize%curpart->blksiz)); }else{ /* no free space */ #ifdef DEBUG printf("creatdirent: no free space\n"); #endif /* extend directory file */ /* XXX DIRBLKS blocks */ if (filecreat(&curdirdes,DIRBLKS,1)<0){ /* 1:extend */ err_print("creatdirent: cannot extend directory file\n"); return -1; } /* new entry is at beginning of block corresponding to curdirsize+1 */ /* no need to load block from disk */ entblk=(curdirsize+1)/curpart->blksiz; /* entry index offset in block */ entoff=0; /* first entry in new block */ /* the following is probably not necessary */ /* clear block */ bzero(buf,curpart->blksiz); /* note: 0 => directory entry free */ } /* update directory size */ curdirsize+=sizeof(struct dirent_s); /* modify curdirdes.fd_fsize and write to disk */ curdirdes.fd_fsize[0]=curdirsize>>24; curdirdes.fd_fsize[1]=curdirsize>>16; curdirdes.fd_fsize[2]=curdirsize>>8; curdirdes.fd_fsize[3]=curdirsize; /* XXX update last modified date */ /* write file descriptor of current directory */ if (WRITEBLOCK_CURPART(curdirsec,&curdirdes,1)<0){ err_print("creatdirent: cannot write file descriptor\n"); return -1; } } /* now buf contains block entblk with entry at entoff to be used */ #ifdef DEBUG printf("creatdirent: entblk: %06x entoff: %02x\n",entblk,entoff); #endif /* set new entry at entoff in buf */ direntp=&(((struct dirent_s *)buf)[entoff]); /* set name */ translatebackname(name,&(direntp->dir_name[0]), FILENAMELEN); /* set startsec */ direntp->dir_addr[0]=startsec>>16; direntp->dir_addr[1]=startsec>>8; direntp->dir_addr[2]=startsec; /* write entblk to current directory file */ if (filewrite((union genfdes_u *)&curdirdes,buf,entblk,1)!=1){ err_print("creatdirent: filewrite(curdirdes)\n"); return -1; } /* update modif time of current directory */ setdate(&curdirdes,0); /* 0: not creat */ /* write updated file descriptor */ if (WRITEBLOCK_CURPART(curdirsec,&curdirdes,1)<0){ err_print("creatdirent: cannot write updated file descriptor\n"); return -1; } /* if name is "..", must increment link count of parent directory??? */ /* XXX */ return 0; } /* OS9 */ int changedir2(char *name) { int startsec; static struct filedes_s curdirdes; if (curpart->type!=PARTTYPE_OS9MDR){ return -1; } if (curpart->mdr) return -1; if (name==NULL){ return -1; } startsec=findfile(name,0,NULL); if (startsec<0){ err_print("changedir2: directory not found\n"); return -1; } /* check if valid directory: */ if (getdir(startsec,&curdirdes,NULL)<0){ err_print("changedir2: not a directory\n"); return -1; } /* change directory: */ curdirsec=startsec; return 0; } /* OS9 */ int delfile(char *name,int dir) { int startsec; int ret; u_int savecurdirsec; if (curpart->type!=PARTTYPE_OS9MDR){ return -1; } if (curpart->mdr){ return -1; } if (name==NULL){ return -1; } /* check if name is directory and check if it is empty */ /* otherwise all files within this directory are lost forever */ /* (if not linked elsewhere), still consuming disk space!!! */ /* see deldirent below!!! */ if (dir>0){ /* save state */ savecurdirsec=curdirsec; if (changedir2(name)<0){ /* e.g. not a directory! */ err_print("delfile: cannot test directory\n"); return -1; } ret=findfile(NULL,0,NULL); /* count used entries (except . and ..) */ /* restore state */ curdirsec=savecurdirsec; if (ret<0){ err_print("delfile: findfile failed\n"); return -1; } if (ret>0){ err_print("delfile: directory not empty\n"); return -1; } /* now name is a directory and is empty */ /* now must decrement link count of parent directory ".."??? */ /* XXX */ } /* delete directory entry */ /* Note: deldirent will not proceed if name is directory but dir==0 (see above)!!! */ startsec=deldirent(name,dir); if (startsec<0){ err_print("delfile: deldirent failed\n"); return -1; } /* unlink or delete file descriptor + data segments */ if (filedel(startsec)<0){ err_print("delfile: filedel failed\n"); return -1; } return 0; } /* MDR-DOS */ int mdr_updatefilenr(void) { struct mdr_dirent_s dirent; int i; if (curpart->type!=PARTTYPE_OS9MDR){ return -1; } if (!curpart->mdr){ return -1; } if (curpart->mdr_filenr>curpart->mdr_dfilenr){ /* XXX should never happen! */ err_print("mdr_updatefilenr: mdr_filenr corrupt\n"); curpart->mdr_filenr=curpart->mdr_dfilenr; } /* start with mdr_filenr-1 (if >=0) */ for (i=((int)curpart->mdr_filenr)-1;i>=0;i--){ /* read directory entry */ if (READBLOCK_CURPART(MDR_DIRSTART+i*MDR_DIRENTRYSIZE,&dirent,MDR_DIRENTRYSIZE)<0){ err_print("mdr_updatefilenr: cannot read directory\n"); return -1; } /* slot unused? */ if (dirent.name[0]=='\0'){ curpart->mdr_filenr=(u_int)i; }else{ /* first used slot in our scan downwards => end of empty slots */ break; } } /* set curpart->lsn0 */ MDR_LSN0_P(curpart->lsn0)->mdr_fnr[0]=curpart->mdr_filenr>>8; MDR_LSN0_P(curpart->lsn0)->mdr_fnr[1]=curpart->mdr_filenr&0xff; /* write updated curpart->lsn0 */ if (WRITEBLOCK_CURPART(0,curpart->lsn0,1)<0){ err_print("mdr_updatefilenr: cannot write updated LSN0\n"); return -1; } return 0; } /* MDR-DOS */ int mdr_delfile(char *name) { struct mdr_dirent_s dirent; int fsec,fnr1; if (curpart->type!=PARTTYPE_OS9MDR){ return -1; } if (!curpart->mdr){ return -1; } if (name==NULL){ return -1; } /* find directory entry for file */ if ((fnr1=mdr_findfile(name))<0){ err_print("mdr_delfile: cannot find file\n"); return -1; } fsec=MDR_DIRSTART+(fnr1-1)*MDR_DIRENTRYSIZE; /* read directory entry */ if (READBLOCK_CURPART(fsec,&dirent,MDR_DIRENTRYSIZE)<0){ err_print("mdr_delfile: cannot read directory\n"); return -1; } /* deallocate in bitmap */ if (mdr_filedel(&dirent)<0){ err_print("mdr_delfile: mdr_filedel\n"); return -1; } /* delete directory entry */ dirent.name[0]='\0'; /* write dirent */ if (WRITEBLOCK_CURPART(fsec,&dirent,MDR_DIRENTRYSIZE)<0){ err_print("mdr_delfile: cannot write directory entry\n"); return -1; } /* update mdr_filenr */ /* Note: might have removed last file behind a gap */ /* => must rescan for new mdr_filenr! */ if (mdr_updatefilenr()<0){ return -1; } return 0; } /* QDOS */ int qdos_delfile(char *name) { u_char dirbuf[QDOS_DIRSIZE*QDOS_BLOCKSIZE]; struct qdos_dir_s *qbufp; int fnr1; u_int ribsec; struct qdos_rib_s qrib; if (curpart->type!=PARTTYPE_QDOS){ return -1; } /* find directory entry for file */ if ((fnr1=qdos_findfile(name))<0){ err_print("qdos_delfile: cannot find file\n"); return -1; } /* read directory */ if (READBLOCK_CURPART(QDOS_DIRSTART,(void *)dirbuf,QDOS_DIRSIZE)<0){ err_print("qdos_delfile: cannot read directory\n"); return -1; } qbufp=(struct qdos_dir_s *)dirbuf; /* read RIB */ ribsec=(qbufp[fnr1-1].dir_rb[0]<<8)+qbufp[fnr1-1].dir_rb[1]; if (ribsec!=0){ if (READBLOCK_CURPART(ribsec,&qrib,1)<0){ err_print("qdos_delfile: cannot read RIB\n"); return -1; } /* deallocate */ if (qdos_filedel(&qrib)<0){ err_print("qdos_delfile: qdos_filedel\n"); return -1; } }else{ err_print("qdos_delfile: warning: invalid RIB sector\n"); } /* mark directory entry deleted */ qbufp[fnr1-1].dir_nm[0]=QDOS_DIR_DELETED; #if 1 qbufp[fnr1-1].dir_nm[1]=QDOS_DIR_DELETED; /* XXX */ #endif /* write updated directory */ if (WRITEBLOCK_CURPART(QDOS_DIRSTART,(void *)dirbuf,QDOS_DIRSIZE)<0){ err_print("qdos_delfile: cannot write directory\n"); return -1; } return 0; } /* OS9 */ int creatfile(char *name,u_int bytesize,int dir,struct filedes_s *tmplt) { int startsec; static struct filedes_s fdes; u_int blknr; if (curpart->type!=PARTTYPE_OS9MDR){ return -1; } if (curpart->mdr){ return -1; } if ((name==NULL)||(strlen(name)==0)){ return -1; } if (strlen(name)>FILENAMELEN){ err_print("creatfile: name too long\n"); return -1; } /* check for "." and ".." */ if ((strcmp(name,".")==0)||(strcmp(name,"..")==0)){ err_print("creatfile: . or .. not allowed\n"); return -1; } /* check if file with this name already exists */ if (findfile(name,0,NULL)>=0){ err_print("creatfile: name already used\n"); return -1; } /* set new file descriptor */ if (tmplt==NULL){ bzero(&fdes,sizeof(struct filedes_s)); fdes.fd_att|=ATT_R|ATT_W|ATT_E; /* XXX owner only */ /* owner */ fdes.fd_own[1]=curowner; fdes.fd_own[0]=curowner>>8; /* set creation and modified date */ setdate(&fdes,1); /* 1: creat */ }else{ bcopy(tmplt,&fdes,sizeof(struct filedes_s)); /* clear segment list */ bzero(&(fdes.fd_seg[0]),FILEDES_SEGNR*sizeof(struct seg_s)); #if 0 /* update modif date */ setdate(&fdes,0); /* 0: not creat */ #endif } /* set attributes */ if (dir){ fdes.fd_att|=ATT_D; }else{ fdes.fd_att&=~ATT_D; } /* set link count */ fdes.fd_link=1; if (dir){ bytesize=0; /* directory still empty */ } /* set size */ fdes.fd_fsize[0]=bytesize>>24; fdes.fd_fsize[1]=bytesize>>16; fdes.fd_fsize[2]=bytesize>>8; fdes.fd_fsize[3]=bytesize; /* number of blocks */ if (dir){ /* XXX DIRBLKS granularity */ blknr=DIRBLKS; }else{ /* round up */ /* XXX 32-Bit overflow protection */ blknr=(u_int)((((OFF_T)bytesize)+((OFF_T)curpart->blksiz-1)) /((OFF_T)curpart->blksiz)); } /* create file */ startsec=filecreat(&fdes,blknr,0); /* 0:create */ if (startsec<0){ err_print("creatfile: filecreat\n"); return -1; } /* write file descriptor */ if (WRITEBLOCK_CURPART(startsec,&fdes,1)<0){ err_print("creatfile: cannot write file descriptor\n"); /* try to remove file again */ filedel(startsec); return -1; } /* create directory entry */ if (creatdirent(name,startsec)<0){ err_print("creatfile: creatdirent\n"); /* try to remove file again */ filedel(startsec); return -1; } /* directory? */ if (dir){ u_int savecurdirsec; /* create . and .. entries */ /* save state */ savecurdirsec=curdirsec; /* change to new directory */ curdirsec=startsec; /* .. */ if (creatdirent("..",savecurdirsec)<0){ /* that's the old current dir. */ err_print("creatfile: cannot create ..\n"); /* try to remove file */ delfile(name,1); /* 1:dir */ /* restore state */ curdirsec=savecurdirsec; return -1; } /* . */ if (creatdirent(".",startsec)<0){ /* that's us */ err_print("creatfile: cannot create .\n"); /* try to remove file */ delfile(name,1); /* 1:dir */ /* restore state */ curdirsec=savecurdirsec; return -1; } /* restore state */ curdirsec=savecurdirsec; } return startsec; /* start sector of new file */ } /* MDR-DOS */ int mdr_creatfile(char *name,u_int bytesize,struct mdr_dirent_s *tmplt) { u_int fnr; static struct mdr_dirent_s dirent; u_int blknr; if (curpart->type!=PARTTYPE_OS9MDR){ return -1; } if (!curpart->mdr){ return -1; } if ((name==NULL)||(strlen(name)==0)){ return -1; } if (strlen(name)>FILENAMELEN){ /* good for MDR-DOS dirent */ err_print("mdr_creatfile: name too long\n"); return -1; } #if 0 /* XXX check for "." and ".." */ if ((strcmp(name,".")==0)||(strcmp(name,"..")==0)){ err_print("mdr_creatfile: . or .. not allowed\n"); return -1; } #endif /* check if file with this name already exists */ if (mdr_findfile(name)>=0){ err_print("mdr_creatfile: name already used\n"); return -1; } /* find empty directory entry */ /* up to mdr_filenr (and not mdr_dfilenr) */ for (fnr=0;fnrmdr_filenr;fnr++){ /* read directory entry */ if (READBLOCK_CURPART(MDR_DIRSTART+MDR_DIRENTRYSIZE*fnr,&dirent,MDR_DIRENTRYSIZE)<0){ err_print("mdr_creatfile: cannot read directory\n"); return -1; } /* file slot free? */ if (dirent.name[0]=='\0'){ break; /* found free slot */ } } /* Note: if no empty slot below mdr_filenr */ /* => fnr==mdr_filenr, which is what we need in this case! */ /* no free slot found? */ if (fnr>=curpart->mdr_dfilenr){ err_print("mdr_creatfile: no free directory slot\n"); return -1; } #ifdef DEBUG printf("mdr_creatfile: mdr_filenr=%04x fnr=%04x\n", curpart->mdr_filenr,fnr); #endif /* set new directory entry */ if (tmplt==NULL){ bzero(&dirent,sizeof(struct mdr_dirent_s)); /* set MDR-DOS type */ bcopy(MDR_MDOSTYPE,&(dirent.type[0]),4); /* set creation and modified date */ mdr_setdate(&dirent,1); /* 1: creat */ }else{ bcopy(tmplt,&dirent,sizeof(struct mdr_dirent_s)); /* clear cluster list */ bzero(&(dirent.clist[0]),MDR_FILECLNR*2); #if 0 /* update modif date */ mdr_setdate(&dirent,0); /* 0: not creat */ #endif } /* set size */ dirent.size[0]=bytesize>>24; dirent.size[1]=bytesize>>16; dirent.size[2]=bytesize>>8; dirent.size[3]=bytesize; /* set name without translation!!! */ bcopy(name,&(dirent.name[0]),strlen(name)+1); /* XXX set other elements */ /* number of blocks */ /* round up */ /* XXX 32-Bit overflow protection */ blknr=(u_int)((((OFF_T)bytesize)+((OFF_T)curpart->blksiz-1)) /((OFF_T)curpart->blksiz)); /* create file */ if (mdr_filecreat(&dirent,blknr,0)<0){ /* 0:create */ err_print("mdr_creatfile: mdr_filecreat\n"); return -1; } /* write dirent */ if (WRITEBLOCK_CURPART(MDR_DIRSTART+MDR_DIRENTRYSIZE*fnr,&dirent,MDR_DIRENTRYSIZE)<0){ err_print("mdr_creatfile: cannot write directory entry\n"); /* try to remove file again */ mdr_filedel(&dirent); return -1; } /* update mdr_filenr */ /* Note: fnr=curpart->mdr_filenr){ curpart->mdr_filenr=fnr+1; /* => mdr_filenr<=mdr_dfilenr !!! */ } /* always update, just in case mdr_filenr is too large somehow */ if (mdr_updatefilenr()<0){ return -1; } return fnr; /* number of new file in directory */ } /* QDOS */ int qdos_creatfile(char *name,u_int bytesize,struct qdos_fdes_s *tmplt) { u_char dirbuf[QDOS_DIRSIZE*QDOS_BLOCKSIZE]; struct qdos_dir_s *qbufp; u_int fnr; struct qdos_rib_s qrib; struct qdos_dir_s qdir; u_int blknr; u_int ribsec,qsiz; char qname[11]; /* NNNNNNNNSS with terminating '\0' */ u_int alloc,contig; if (curpart->type!=PARTTYPE_QDOS){ return -1; } if ((name==NULL)||(strlen(name)==0)){ return -1; } #if 0 /* XXX check for "." and ".." */ if ((strcmp(name,".")==0)||(strcmp(name,"..")==0)){ err_print("qdos_creatfile: . or .. not allowed\n"); return -1; } #endif /* check if file with this name already exists */ if (qdos_findfile(name)>=0){ err_print("qdos_creatfile: name already used\n"); return -1; } /* read directory */ if (READBLOCK_CURPART(QDOS_DIRSTART,(void *)dirbuf,QDOS_DIRSIZE)<0){ err_print("qdos_creatfile: cannot read directory\n"); return -1; } qbufp=(struct qdos_dir_s *)dirbuf; /* find empty directory entry */ for (fnr=0;fnr=QDOS_DIRENTRYNR){ err_print("qdos_creatfile: no free directory slot\n"); return -1; } /* set new directory entry */ if (tmplt==NULL){ bzero(&qrib,sizeof(struct qdos_rib_s)); bzero(&qdir,sizeof(struct qdos_dir_s)); qdir.dir_at[0]=QDOS_ATT_FMU; /* user-defined */ }else{ bcopy(&tmplt->rib,&qrib,sizeof(struct qdos_rib_s)); bcopy(&tmplt->dir,&qdir,sizeof(struct qdos_dir_s)); } /* set name */ qdos_makefname(name,qname); /* convert name into QDOS-conformant name */ /* Note: dir_sx[2] directly follows dir_nm[8] in struct qdos_dir_s!!! */ bcopy(qname,qdir.dir_nm,10); /* number of blocks */ /* round up */ /* XXX 32-Bit overflow protection not necessary for QDOS */ blknr=(bytesize+curpart->blksiz-1)/curpart->blksiz; /* create file */ if (qdos_filecreat(&qrib,blknr,0)<0){ /* 0:create */ err_print("qdos_creatfile: qdos_filecreat\n"); return -1; } /* set file size in RIB */ if (qdos_setfsize(&qrib,bytesize)<0){ err_print("qdos_creatfile: corrupt RIB\n"); /* try to remove file again */ qdos_filedel(&qrib); return -1; } /* write RIB */ /* Note: first block of file allocation is used for RIB!!! */ qdos_getseg(&qrib,0,&ribsec,&qsiz); if ((qsiz==0)||(ribsec==0)){ /* empty or corrupt RIB!!! */ err_print("qdos_creatfile: corrupt RIB\n"); /* try to remove file again */ qdos_filedel(&qrib); return -1; } ribsec*=QDOS_CSIZE; if (WRITEBLOCK_CURPART(ribsec,&qrib,1)<0){ err_print("qdos_creatfile: cannot write RIB\n"); /* try to remove file again */ qdos_filedel(&qrib); return -1; } /* set/clear ATT_CON flag in directory entry if file is contiguous: */ alloc=qdos_countseg(&qrib,QDOS_RIB_SDWNR,&contig); if ((alloc!=0)&&(alloc==contig)){ qdir.dir_at[0]|=QDOS_ATT_CON; /* set flag */ }else{ qdir.dir_at[0]&=~QDOS_ATT_CON; /* clear flag */ } /* set RIB address in directory entry */ qdir.dir_rb[0]=(ribsec>>8)&0xff; qdir.dir_rb[1]=ribsec&0xff; /* save new directory entry */ bcopy(&qdir,&qbufp[fnr],sizeof(struct qdos_dir_s)); /* write updated directory */ if (WRITEBLOCK_CURPART(QDOS_DIRSTART,(void *)dirbuf,QDOS_DIRSIZE)<0){ err_print("qdos_creatfile: cannot write directory\n"); /* try to remove file again */ qdos_filedel(&qrib); return -1; } #ifdef DEBUG printf("qdos_creatfile:\n"); qdos_printfdes(&qdir,&qrib); #endif return fnr; /* number of new file in directory */ } /* OS9/MDR-DOS */ int readlsn0(u_int blocksize0) { if (curpart->type!=PARTTYPE_OS9MDR){ return -1; } if (curpart->psize==0){ curpart->totsize=0; /* mark unusable */ return -1; } if (blocksize0==0){ blocksize0=OS9L2_BLOCKSIZE; /* default */ } /* Note: current curpart->startsec,psize are for blocksize0! */ curpart->blksiz=blocksize0; /* premininary */ curpart->totsize=1; /* for READBLOCK_CURPART below: at least LSN0 */ /* XXX for the case that READBLOCK_CURPART doesn't return an error */ /* although lseek went beyond device/image file limits */ /* (e.g., as the case for OSF1 with /sc00 image file!) */ /* we set dd_tot in curpart->lsn0 to 0, to avoid that partition */ bzero(curpart->lsn0,sizeof(struct lsn0_s)); /* esp. dd_tot=0 */ if (READBLOCK_CURPART(0,curpart->lsn0,1)<0){ /*err_print("readlsn0: READBLOCK_CURPART(curpart->lsn0)\n");*/ /* don't complain here */ return -1; /* we must avoid this partition */ } /* OS9 bitmap size: needed as criterion for type! */ curpart->bitmapsize=(curpart->lsn0->dd_map[0]<<8)+curpart->lsn0->dd_map[1]; /* size of partition dd_tot */ curpart->totsize=(curpart->lsn0->dd_tot[0]<<16) +(curpart->lsn0->dd_tot[1]<<8) +curpart->lsn0->dd_tot[2]; /* partition type: */ /* MDR-DOS partition: bitmapsize==0 but totsize>0 */ if ((curpart->bitmapsize==0)&&(curpart->totsize>0)){ curpart->mdr=1; /* MDR-DOS */ curpart->blksiz=MDR_BLOCKSIZE; }else{ u_int bb,bb1; curpart->mdr=0; /* OS9 */ bb=(curpart->lsn0->dd_lsnsize[0]<<8) +curpart->lsn0->dd_lsnsize[1]; if (bb==0){ bb1=OS9L2_BLOCKSIZE; }else{ bb1=fixblksiz(bb); if (bb1!=bb){ char b[128]; sprintf(b,"warning: invalid lsnsize in partition %02x (%04x).\n set to reasonable size %04x.\n", partnr, /* XXX assumed to be current number during setup */ bb,bb1); err_print(b); } } curpart->blksiz=bb1; } /* convert to partition blocksize: */ /* XXX 32-Bit overflow protection */ curpart->startsec=(u_int)((((OFF_T)curpart->startsec)*((OFF_T)blocksize0)) /((OFF_T)curpart->blksiz)); curpart->psize=(u_int)((((OFF_T)curpart->psize)*((OFF_T)blocksize0)) /((OFF_T)curpart->blksiz)); /* check partition size with partition table: */ /* totsize <= size according to parttab entry! */ /* Note: totsize will be used for partition limit checks during operation */ /* this must be <= size according to parttab entry! */ if (!curpart->master){ /* check psize only for non-master! */ if (curpart->totsize>curpart->psize){ char b[128]; sprintf(b,"error: partition %02x too large.\n",partnr); err_print(b); return -1; } }else{ /* master */ curpart->psize=curpart->totsize; /* set equal to dd_tot for master! */ } /* partition type: */ if (curpart->mdr){ /* MDR-DOS */ curpart->mdr_clustersize=MDR_CLUSTERSIZE*MDR_LSN0_P(curpart->lsn0)->mdr_clsz; curpart->mdr_clusternr=(MDR_LSN0_P(curpart->lsn0)->mdr_clnr[0]<<8) +MDR_LSN0_P(curpart->lsn0)->mdr_clnr[1]; curpart->mdr_filesyssize=curpart->mdr_clustersize*curpart->mdr_clusternr; curpart->mdr_dfilenr=(MDR_LSN0_P(curpart->lsn0)->mdr_dfnr[0]<<8) +MDR_LSN0_P(curpart->lsn0)->mdr_dfnr[1]; curpart->mdr_filenr=(MDR_LSN0_P(curpart->lsn0)->mdr_fnr[0]<<8) +MDR_LSN0_P(curpart->lsn0)->mdr_fnr[1]; /* basic filesystem checks: */ /* 1) mdr_filesyssize <= totsize */ if (curpart->mdr_filesyssize>curpart->totsize){ char b[128]; sprintf(b,"error: filesystem in partition %02x too large (%08x).\n partition size (%08x).\n", partnr, /* XXX assumed to be current number during setup */ curpart->mdr_filesyssize,curpart->totsize); err_print(b); if (!curpart->master){ return -1; } } /* 2) mdr_filesyssize >= MDR_DIRSTART+mdr_dfilenr*MDR_DIRENTRYSIZE */ if (curpart->mdr_filesyssize <(MDR_DIRSTART+curpart->mdr_dfilenr*MDR_DIRENTRYSIZE)){ char b[128]; sprintf(b,"error: filesystem in partition %02x too small (%08x).\n needed at least %08x.\n", partnr, /* XXX assumed to be current number during setup */ curpart->mdr_filesyssize, MDR_DIRSTART+curpart->mdr_dfilenr*MDR_DIRENTRYSIZE); err_print(b); if (!curpart->master){ return -1; } } /* 3) mdr_filenr <= mdr_dfilenr */ if (curpart->mdr_filenr>curpart->mdr_dfilenr){ char b[128]; sprintf(b,"error: filenumber in partition %02x too large (%04x).\n maximum %04x.\n", partnr, /* XXX assumed to be current number during setup */ curpart->mdr_filenr, curpart->mdr_dfilenr); err_print(b); if (!curpart->master){ return -1; } } /* 4) XXX should check bitmap now: */ /* clusters outside mdr_filesyssize should be marked as used */ /* last incomplete cluster should be marked as used */ /* must check these cluster(s): */ /* a) marked unused in bitmap => problem */ /* b) marked used but also used in filesystem => problem */ /* this is very difficult to verify */ }else{ /* OS9 */ curpart->bitmapstart=(curpart->lsn0->dd_maplsn[0]<<24) +(curpart->lsn0->dd_maplsn[1]<<16) +(curpart->lsn0->dd_maplsn[2]<<8) +curpart->lsn0->dd_maplsn[3]; if (curpart->bitmapstart==0){ curpart->bitmapstart=OS9L2_BMAPSTART; } /*curpart->bitmapsize=(curpart->lsn0->dd_map[0]<<8)+curpart->lsn0->dd_map[1];*/ /* already done! */ curpart->clustersize=(curpart->lsn0->dd_bit[0]<<8)+curpart->lsn0->dd_bit[1]; curpart->filesyssize=curpart->clustersize*curpart->bitmapsize*8; /* first guess */ /* Note: clustersize*bitmapsize can be larger than totsize: */ /* last clusters should be marked used in bitmap and */ /* not be used by any file/directory/descriptor! */ /* we will simply ignore these clusters */ curpart->rootdirsec=(curpart->lsn0->dd_dir[0]<<16) +(curpart->lsn0->dd_dir[1]<<8) +curpart->lsn0->dd_dir[2]; curpart->bootsec=(curpart->lsn0->dd_bt[0]<<16) +(curpart->lsn0->dd_bt[1]<<8) +curpart->lsn0->dd_bt[2]; curpart->bootsize=(curpart->lsn0->dd_bsz[0]<<8) +curpart->lsn0->dd_bsz[1]; /* basic filesystem checks: */ /* 1) truncate filesyssize <= totsize */ if (curpart->filesyssize>curpart->totsize){ /* XXX this is no error */ #ifdef PEDANTICSETUP char b[128]; sprintf(b,"warning: filesystem in partition %02x might be too large (%08x).\n clipped to partition size %08x.\n", partnr, /* XXX assumed to be current number during setup */ curpart->filesyssize,curpart->totsize); err_print(b); #endif curpart->filesyssize=curpart->totsize; /* "clip" nonexistent clusters */ } /* 2) XXX should check bitmap now: */ /* clusters outside filesyssize should be marked as used */ /* last incomplete cluster should be marked as used */ /* must check these cluster(s): */ /* a) marked unused in bitmap => problem */ /* b) marked used but also used in filesystem => problem */ /* this is very difficult to verify */ } return 0; } /* general */ void printlsn0(void) { printf("devname: %s\n",curpart->devname); printf("blocksize: %u bytes\n",curpart->blksiz); if (curpart->type==PARTTYPE_QDOS){ /* QDOS */ struct qdos_did_s *qp; u_int i; qp=QDOS_LSN0_P(curpart->lsn0); printf("--- QDOS ---\n"); printf("did_id: "); printnstr(qp->did_id,8); printf("\ndid_vn: %c%c\ndid_rn: %c%c\n", isprint(qp->did_vn[0])?qp->did_vn[0]:'?', isprint(qp->did_vn[1])?qp->did_vn[1]:'?', isprint(qp->did_rn[0])?qp->did_rn[0]:'?', isprint(qp->did_rn[1])?qp->did_rn[1]:'?'); printf("did_dt: %c%c-%c%c-%c%c\ndid_nm: ", isprint(qp->did_dt[0])?qp->did_dt[0]:'?', isprint(qp->did_dt[1])?qp->did_dt[1]:'?', isprint(qp->did_dt[2])?qp->did_dt[2]:'?', isprint(qp->did_dt[3])?qp->did_dt[3]:'?', isprint(qp->did_dt[4])?qp->did_dt[4]:'?', isprint(qp->did_dt[5])?qp->did_dt[5]:'?'); printnstr(qp->did_nm,20); printf("\n"); for (i=0;idid_rb[i][0],qp->did_rb[i][1]); } printf("did_btsec: %02x%02x\n",qp->did_btsec[0],qp->did_btsec[1]); printf("did_btsiz: %02x%02x\n",qp->did_btsiz[0],qp->did_btsiz[1]); printf("did_btloa: %02x%02x\n",qp->did_btloa[0],qp->did_btloa[1]); printf("did_slin: "); printf("(%c) ",isprint(qp->did_slinflag)?qp->did_slinflag:'-'); printnstr(qp->did_slin,69); printf("\n"); return; }else if (curpart->type!=PARTTYPE_OS9MDR){ return; } /* now OS9 or MDR-DOS */ if (curpart->master){ /* master partition? */ printf("master partition\n"); }else{ printf("ptab size: %06x (%u bytes)\n",curpart->psize,curpart->psize*curpart->blksiz); } /*printf("curpart->lsn0:\n");*/ printf("dd_tot: %06x (%u bytes)\n",curpart->totsize,curpart->totsize*curpart->blksiz); if (!curpart->mdr){ printf("--- OS9 ---\n"); printf("dd_tks: %02x\n",curpart->lsn0->dd_tks); printf("dd_map: %04x\n",curpart->bitmapsize); printf("dd_bit: %04x\n",curpart->clustersize); printf("dd_dir: %06x\n",curpart->rootdirsec); printf("dd_own: %02x%02x\n",curpart->lsn0->dd_own[0],curpart->lsn0->dd_own[1]); printf("dd_att: %02x (",curpart->lsn0->dd_att); printatt(curpart->lsn0->dd_att); printf(")\ndd_dsk: %02x%02x\n",curpart->lsn0->dd_dsk[0],curpart->lsn0->dd_dsk[1]); printf("dd_fmt: %02x\n",curpart->lsn0->dd_fmt); printf("dd_spt: %02x%02x\n",curpart->lsn0->dd_spt[0],curpart->lsn0->dd_spt[1]); printf("dd_res: %02x%02x\n",curpart->lsn0->dd_res[0],curpart->lsn0->dd_res[1]); printf("dd_bt: %06x\n",curpart->bootsec); printf("dd_bsz: %04x\n",curpart->bootsize); printf("dd_ptabstart: %06x\n",curpart->ptabsec); printf("dd_pnr: %04x\n",curpart->pnr); printf("dd_date: %02i-%02i-%02i %02i:%02i\n", curpart->lsn0->dd_date[0]%100,curpart->lsn0->dd_date[1]%100,curpart->lsn0->dd_date[2]%100, curpart->lsn0->dd_date[3]%100,curpart->lsn0->dd_date[4]%100); printf("dd_name: \""); /* XXX use printname here for convenience: */ /* XXX Could miss last chars: FILENAMELEN==29 but dd_name[32]! */ printname(curpart->lsn0->dd_name); printf("\"\n"); printf("dd_maplsn: %08x\n",curpart->bitmapstart); printf("dd_lsnsize: %04x\n",curpart->blksiz); printf("dd_versid: %02x%02x\n", curpart->lsn0->dd_versid[0], curpart->lsn0->dd_versid[1]); if (curpart->master){ printf("dd_ptabstart: %06x\n",curpart->ptabsec); printf("dd_pnr: %02x\n",curpart->lsn0->dd_pnr); printf("dd_qdosstart: %02x%02x%02x\n", curpart->lsn0->dd_qdosstart[0],curpart->lsn0->dd_qdosstart[1],curpart->lsn0->dd_qdosstart[2]); printf("dd_qdosnr: %02x%02x\n", curpart->lsn0->dd_qdosnr[0],curpart->lsn0->dd_qdosnr[1]); printf("dd_cmistart: %02x%02x%02x\n", curpart->lsn0->dd_cmistart[0],curpart->lsn0->dd_cmistart[1],curpart->lsn0->dd_cmistart[2]); printf("dd_cminr: %02x%02x\n", curpart->lsn0->dd_cminr[0],curpart->lsn0->dd_cminr[1]); } printf("filesys size: %08x\n",curpart->filesyssize); }else{ printf("--- MDR-DOS ---\n"); printf("mdr_clsz: %08x\n",curpart->mdr_clustersize); printf("mdr_clnr: %04x\n",curpart->mdr_clusternr); printf("mdr_dfnr: %04x\n",curpart->mdr_dfilenr); printf("mdr_fnr: %04x\n",curpart->mdr_filenr); printf("mdr_name: \""); /* XXX use printname here for convenience: */ printname(MDR_LSN0_P(curpart->lsn0)->mdr_name); printf("\"\n"); printf("filesys size: %08x\n",curpart->mdr_filesyssize); } printf("\n"); } /* general */ /* setup partitions */ int partsetup(int fdes,u_int devid,int forceqdosnr) { u_int startsec,size; u_int i,partnrmax; u_int ptabstart,pnr; static u_char pbuf[OS9MAX_BLOCKSIZE]; /* XXX enough for 1 block */ struct parttabent_s *parttab; struct part_s *masterp; u_int master_blocksize; u_int qdosstart,qdos_partnr; u_int cmistart,cmi_partnr; master_blocksize=OS9L2_BLOCKSIZE; /* default */ if (forceqdosnr<=0){ /* OS9/MDR-DOS master partition */ curpart=&part[partnr]; bzero(curpart,sizeof(struct part_s)); /* invalidate everything */ curpart->fdes=fdes; curpart->lsn0=&lsn0[partnr]; curpart->type=PARTTYPE_OS9MDR; curpart->master=1; curpart->startsec=0; /* needed for READBLOCK_CURPART in readlsn0 */ curpart->psize=1; /* preliminary for readlsn0 */ /* set name */ sprintf(curpart->devname,"sc%02x",devid); /* get master partition */ if (readlsn0(master_blocksize)<0){ /* fatal: at least LSN0 of master partition should be accessible */ err_print("partsetup: cannot access LSN0 of master partition\n"); return -1; } master_blocksize=curpart->blksiz; #ifdef DEBUG printf("master: %02x: startsec: %06x size: %06x\n", partnr,curpart->startsec,curpart->psize); printlsn0(); #endif /* partition table information from master partition */ ptabstart=(curpart->lsn0->dd_ptabstart[0]<<16) +(curpart->lsn0->dd_ptabstart[1]<<8) +curpart->lsn0->dd_ptabstart[2]; curpart->ptabsec=ptabstart; pnr=curpart->lsn0->dd_pnr; curpart->pnr=pnr; masterp=curpart; partnr++; /* master partition setup */ if (partnr>=PARTITION_NR){ err_print("error: too many partitions.\n"); return -1; } /* further OS9/MDR-DOS partitions */ partnrmax=pnr; if (partnrmax>PARTTAB_NR){ err_print("partsetup: too many partitions\n"); #ifdef PEDANTICSETUP return -1; #else partnrmax=0; /* assume corrupt partition table */ err_print("partsetup: ignoring partition table\n"); #endif } if (partnrmax>0){ bzero(pbuf,OS9MAX_BLOCKSIZE); parttab=(struct parttabent_s *)pbuf; /* read parttab file */ i=(PARTTAB_NR*sizeof(struct parttabent_s)+curpart->blksiz-1) /curpart->blksiz; if (READBLOCK_CURPART(ptabstart,parttab,i)<0){ err_print("partsetup: READBLOCK_CURPART(parttab)\n"); #ifdef PEDANTICSETUP return -1; #else partnrmax=0; /* assume corrupt partition table */ err_print("partsetup: ignoring partition table\n"); #endif } /* setup partition table */ for (i=0;ifdes=fdes; curpart->lsn0=&lsn0[partnr]; curpart->type=PARTTYPE_OS9MDR; /* Note: blocksize for parttab is master_blocksize! */ curpart->startsec=startsec; /* needed for READBLOCK_CURPART in readlsn0 */ curpart->psize=size; /* size of partition according to parttab */ /* check if partition fits into disk (i.e. master partition!) */ if (startsec+size>masterp->totsize){ /* in master_blocksize */ curpart->psize=0; /* mark unusable for readlsn0 */ } /* set name */ if ((parttab[i].index>0)&&(parttab[i].index<9)){ sprintf(curpart->devname,"c%02x%u",devid,parttab[i].index-1); }else if (parttab[i].index<17){ sprintf(curpart->devname,"k%02x%u",devid,parttab[i].index-9); }else{ sprintf(curpart->devname,"?%02x%u",devid,parttab[i].index-9); } /* get partition */ /* read LSN0 */ if (readlsn0(master_blocksize)<0){ char b[128]; sprintf(b,"partsetup: readlsn0(%02x)\n",i+1); err_print(b); #ifdef PEDANTICSETUP return -1; #else /* XXX instead of returning an error, we simply mark */ /* the partition as size 0, which should prevent */ /* it from being used!!! */ /* This could be useful for a device/image file */ /* that has an invalid partition table. */ curpart->totsize=0; /* non-usable */ sprintf(b,"partsetup: partition %02x not accessible\n",i+1); err_print(b); #endif } /* further checks for partition: */ /* Note: must compare quantities of same blocksize!!! */ /* XXX should check for overlap with other partitions */ #ifdef DEBUG printlsn0(); #endif partnr++; if (partnr>=PARTITION_NR){ err_print("error: too many partitions.\n"); return -1; } } } } } /* QDOS partitions */ if (forceqdosnr>0){ /* forced QDOS-only */ qdosstart=0; qdos_partnr=forceqdosnr; cmistart=0; cmi_partnr=0; /* Note: master_blocksize now irrelevant */ }else{ qdosstart=(masterp->lsn0->dd_qdosstart[0]<<16) +(masterp->lsn0->dd_qdosstart[1]<<8) +masterp->lsn0->dd_qdosstart[2]; /* in master_blocksize!!! */ qdos_partnr=(masterp->lsn0->dd_qdosnr[0]<<8) +masterp->lsn0->dd_qdosnr[1]; cmistart=(masterp->lsn0->dd_cmistart[0]<<16) +(masterp->lsn0->dd_cmistart[1]<<8) +masterp->lsn0->dd_cmistart[2]; /* in master_blocksize!!! */ cmi_partnr=(masterp->lsn0->dd_cminr[0]<<8) +masterp->lsn0->dd_cminr[1]; } /* setup QDOS partitions */ /* read QDOS disk IDs */ for (i=0;ifdes=fdes; curpart->lsn0=&lsn0[partnr]; curpart->type=PARTTYPE_QDOS; curpart->blksiz=QDOS_BLOCKSIZE; size=QDOS_PBLKS; /* in QDOS blocksize!!! */ curpart->totsize=size; curpart->psize=size; /* set equal to totsize for QDOS partition! */ if (iblksiz) +i*size; /* in QDOS blocksize now!!! */ }else{ startsec=cmistart*(master_blocksize/curpart->blksiz) +(i-qdos_partnr)*size; /* in QDOS blocksize now!!! */ } curpart->startsec=startsec; /* needed for READBLOCK_CURPART */ /* set name */ sprintf(curpart->devname,"q%02x%u",devid,i); /* XXX check if startsec and size are valid */ /* read disk ID at logical sector 0 */ /* Note: qdos_did_s fits into lsn0_s!!! */ if (READBLOCK_CURPART(0,curpart->lsn0,1)<0){ char b[128]; sprintf(b,"partsetup: READBLOCK_CURPART(QDOS[%u])\n",i); err_print(b); curpart->totsize=0; /* non-usable */ }else{ /* XXX check validity of partition */ /* XXX set other elements in curpart */ } partnr++; if (partnr>=PARTITION_NR){ err_print("error: too many partitions.\n"); return -1; } } /* XXX */ return 0; } /* OS9 */ int partmodif(struct parttabent_s *parttab,u_int index,u_int size,u_int startsec,int clearall) { u_int i; if (parttab==NULL){ return -1; } if (curpart->type!=PARTTYPE_OS9MDR){ return -1; } if (curpart->mdr){ return -1; } if (curpart->ptabsec==0){ err_print("partmodif: no partition table in current partition\n"); /* XXX actually, partition table only in master makes sense... */ return -1; } if (clearall){ bzero(parttab,OS9MAX_BLOCKSIZE); }else{ if (index>curpart->pnr){ /* XXX or PARTTAB_NR??? */ char b[128]; sprintf(b,"partmodif: invalid index (should be 1-%i)\n",curpart->pnr); err_print(b); return -1; } bzero(&parttab[index-1],sizeof(struct parttabent_s)); parttab[index-1].index=index; /* XXX check for valid size */ parttab[index-1].size[2]=size; parttab[index-1].size[1]=size>>8; parttab[index-1].size[0]=size>>16; /* XXX check for valid startsec */ parttab[index-1].startsec[2]=startsec; parttab[index-1].startsec[1]=startsec>>8; parttab[index-1].startsec[0]=startsec>>16; } /* write new partition table */ i=(PARTTAB_NR*sizeof(struct parttabent_s)+curpart->blksiz-1) /curpart->blksiz; if (WRITEBLOCK_CURPART(curpart->ptabsec,parttab,i)<0){ err_print("partmodif: cannot write partition table\n"); /* XXX cannot undo previous actions */ return -1; } return 0; /* must restart after this to activate new partition table!!! */ } /* general */ struct part_s * partchange2(char *name,int check) { struct part_s *pp; u_int i; if (name==NULL){ return NULL; } if (strlen(name)==0){ return NULL; } /* scan alias table */ for (i=0;;i++){ if ((devalias[i].alias==NULL)||(devalias[i].equ==NULL)){ break; /* end */ } if (strcasecmp(name,devalias[i].alias)==0){ name=devalias[i].equ; /* translated name */ break; /* done */ } } /* scan partition table */ pp=NULL; /* nothing found yet */ for (i=0;i0 and totsize>0 */ if ((pp->psize<=0)||(pp->totsize<=0)){ err_print("partchange2: invalid filesystem\n"); pp=NULL; /* invalid filesystem, entrance to partition filesystem denied! */ } /* XXX other checks */ } if (pp==NULL){ err_print("partchange2: invalid partition\n"); }else{ /* switch to new partition */ curpart=pp; #ifdef DEBUG printf("curpart: %02x: startsec: %06x size: %06x\n", i,curpart->startsec,curpart->psize); printlsn0(); #endif } return pp; } /* general */ int printpartinfo(char *partp,u_int seekstart,u_int minsize,int mode) { struct part_s *savecurpart; u_int segstart; u_int segsize; u_int lsegstart; u_int lsegsize; u_int segnr; int totfree; if (partp==NULL){ return -1; } /* save state */ savecurpart=curpart; if (partchange2(partp,1)==NULL){ /* 1: check */ err_print("printpartinfo: cannot change partition\n"); return -1; } if (mode&1){ printlsn0(); } if (curpart->type==PARTTYPE_QDOS){ /* QDOS partition */ totfree=qdos_findfree(seekstart,minsize, &segstart,&segsize, &lsegstart,&lsegsize,&segnr, NULL,0,1); /* full scan */ if (totfree<0){ /* restore state */ curpart=savecurpart; return -1; } if (mode&2){ printf("QDOS free:\n"); printf("seekstart: %06x minsize: %06x\n",seekstart,minsize); printf(" totfree: %06x\n",totfree); printf("segstart: %06x segsize: %06x\n",segstart,segsize); printf("lsegstart: %06x lsegsize: %06x\n",lsegstart); printf("segnr: %06x\n",segnr); printf("total: %06x\n\n",totfree); }else{ printf("%06x",totfree); } }else if (curpart->type!=PARTTYPE_OS9MDR){ err_print("printpartinfo: invalid partition type\n"); /* restore state */ curpart=savecurpart; return -1; }else{ /* now OS9 or MDR-DOS */ if (!curpart->mdr){ totfree=findfree(seekstart,minsize, &segstart,&segsize, &lsegstart,&lsegsize,&segnr, NULL,0,1); /* full scan */ if (totfree<0){ /* restore state */ curpart=savecurpart; return -1; } if (mode&2){ printf("OS9 free:\n"); printf("seekstart: %06x minsize: %06x\n",seekstart,minsize); printf(" totfree: %06x\n",totfree); printf("segstart: %06x segsize: %06x\n",segstart,segsize); printf("lsegstart: %06x lsegsize: %06x\n",lsegstart,lsegsize); printf("segnr: %06x\n",segnr); printf("total: %06x\n\n",totfree); }else{ printf("%06x",totfree); } }else{ #if 1 totfree=mdr_findfree(seekstart,minsize, &segstart,&segsize, &lsegstart,&lsegsize,&segnr, NULL,0,1); /* full scan */ if (mode&2){ printf("MDR-DOS free:\n"); printf("seekstart: %06x minsize: %06x\n",seekstart,minsize); printf(" totfree: %06x\n",totfree); printf("segstart: %06x segsize: %06x\n",segstart,segsize); printf("lsegstart: %06x lsegsize: %06x\n",lsegstart,lsegsize); printf("segnr: %06x\n",segnr); printf("total: %06x\n\n",totfree); }else{ printf("%06x",totfree); } #else totfree=mdr_countfree()*(curpart->mdr_clustersize); if (mode&2){ printf("MDR-DOS free:\n"); printf("total: %06x\n\n",totfree); }else{ printf("%06x",totfree); } #endif } } /* restore state */ curpart=savecurpart; if (mode==0) return totfree; return 0; } /* general */ void printpartlist(int mode) { u_int i; u_int os9mdrpartnr,qdospartnr; int totfree; /* count partitions */ os9mdrpartnr=0; qdospartnr=0; for (i=0;i0){ /* OS9/MDR-DOS partitions */ printf("OS9/MDR-DOS partitions: %02x\n",os9mdrpartnr); if (mode){ printf("partition b blk start ptsize totsize mdr name\n"); printf("-------------------------------------------------------------------------------\n"); }else{ printf("partition mdr filesys free used\n"); printf("----------------------------------\n"); } for (i=0;i0)&&(part[i].totsize>0)){ if (part[i].mdr){ printf("* "); printname(MDR_LSN0_P(part[i].lsn0)->mdr_name); }else{ printf(" "); printname(lsn0[i].dd_name); } } printf("\n"); }else{ printf("/%s ",part[i].devname); if (part[i].mdr){ printf("(%02x): * %06x ", i,part[i].mdr_filesyssize); if ((part[i].totsize>0)&&(part[i].mdr_filesyssize>0)){ totfree=printpartinfo(part[i].devname,0,0,0); /* check if printpartinfo was successful */ if (totfree>=0){ printf(" %3i%%",100-(100*totfree)/part[i].mdr_filesyssize); } } }else{ printf("(%02x):",i); printf(" %06x ", part[i].filesyssize); if ((part[i].totsize>0)&&(part[i].filesyssize>0)){ totfree=printpartinfo(part[i].devname,0,0,0); /* check if printpartinfo was successful */ if (totfree>=0){ printf(" %3i%%",100-(100*totfree)/part[i].filesyssize); } } } printf("\n"); } } if (mode){ printf("-------------------------------------------------------------------------------\n\n"); }else{ printf("----------------------------------\n\n"); } } if (qdospartnr>0){ /* QDOS partitions */ printf("QDOS partitions: %02x\n", qdospartnr); if (mode){ printf("partition b blk start ptsize id vn rn date user\n"); printf("-------------------------------------------------------------------------------\n"); }else{ printf("partition filesys free used\n"); printf("----------------------------------\n"); } for (i=0;idid_btsiz[0]<<8)+qp->did_btsiz[1]; if (btsiz!=0){ /* bootable? */ printf("*"); }else{ printf(" "); } printf(" %04x",part[i].blksiz); printf(" %06x ",part[i].startsec); printf("%06x ",QDOS_PSIZE/part[i].blksiz); printnstr(qp->did_id,8); printf(" %c%c %c%c", isprint(qp->did_vn[0])?qp->did_vn[0]:'?', isprint(qp->did_vn[1])?qp->did_vn[1]:'?', isprint(qp->did_rn[0])?qp->did_rn[0]:'?', isprint(qp->did_rn[1])?qp->did_rn[1]:'?'); printf(" %c%c-%c%c-%c%c ", isprint(qp->did_dt[0])?qp->did_dt[0]:'?', isprint(qp->did_dt[1])?qp->did_dt[1]:'?', isprint(qp->did_dt[2])?qp->did_dt[2]:'?', isprint(qp->did_dt[3])?qp->did_dt[3]:'?', isprint(qp->did_dt[4])?qp->did_dt[4]:'?', isprint(qp->did_dt[5])?qp->did_dt[5]:'?'); printnstr(qp->did_nm,20); putchar('\n'); /* XXX */ }else{ printf("/%s ????????\n",part[i].devname); /* XXX */ } }else{ printf("/%s ",part[i].devname); printf("(%02x):",i); printf(" %06x ", part[i].totsize); /* totsize!!! */ if (part[i].totsize>0){ totfree=printpartinfo(part[i].devname,0,0,0); /* check if printpartinfo was successful */ if (totfree>=0){ printf(" %3i%%",100-(100*totfree)/part[i].totsize); /* totsize!!! */ } } printf("\n"); } } if (mode){ printf("-------------------------------------------------------------------------------\n\n"); }else{ printf("----------------------------------\n\n"); } } } /* general */ int findfile3(char *path,u_int *startsecp,struct part_s **partp) { struct part_s *savecurpart; u_int savecurdirsec; int abspathflag; char *p,*pnext; int startsec; struct part_s *pp; int ret; char *pathbuf; if (path==NULL){ return -1; } if ((strlen(path)==0)||(path[strlen(path)-1]=='/')){ #ifdef DEBUG printf("findfile3: invalid path\n"); #endif return -1; } /* parse path string */ abspathflag=0; if (path[0]=='/'){ /* absolute path */ abspathflag=1; path++; /* remove '/' */ }else{ pp=curpart; /* remains the same */ } /* save path string since strtok destroys it! */ pathbuf=(char *)malloc(strlen(path)+1); /* +1 for '\0' */ if (pathbuf==NULL){ perror("findfile3: malloc"); return -1; } bcopy(path,pathbuf,strlen(path)+1); /* +1 for '\0' */ p=strtok(pathbuf,"/"); /* first token */ if (p==NULL){ #ifdef DEBUG printf("findfile3: invalid path\n"); #endif free(pathbuf); return -1; } /* save current state */ savecurpart=curpart; /* for OS9 */ savecurdirsec=curdirsec; ret=0; /* no error yet */ while (1){ /* if we arrive here => p!=NULL */ #ifdef DEBUG printf("findfile3: token=\"%s\"\n",p); #endif /* get next token in advance */ pnext=strtok(NULL,"/"); if (abspathflag){ /* change partition */ pp=partchange2(p,1); /* 1: check */ if (pp==NULL){ #ifdef DEBUG err_print("findfile3: invalid partition\n"); #endif ret=-1; goto findfile3_done; /* done */ } /* check if this is the last token */ if (pnext==NULL){ if (curpart->type==PARTTYPE_QDOS){ /* QDOS */ /* we are in root directory after the partition change */ /* OK */ startsec=0; /* symbolic value for root directory */ }else if (curpart->type==PARTTYPE_OS9MDR){ if (curpart->mdr){ /* MDR-DOS */ /* we are in root directory after the partition change */ /* OK */ startsec=0; /* symbolic value for root directory */ }else{ /* OS9 */ /* return startsec of root directory */ startsec=curpart->rootdirsec; } }else{ #ifdef DEBUG err_print("findfile3: invalid partition type\n"); #endif ret=-1; goto findfile3_done; /* done */ } goto findfile3_done; /* done */ }else{ if (curpart->type==PARTTYPE_QDOS){ /* QDOS */ /* we are in root directory */ /* OK */ }else if (curpart->type==PARTTYPE_OS9MDR){ if (curpart->mdr){ /* MDR-DOS */ /* we are in root directory */ /* OK */ }else{ /* OS9 */ /* change to root directory */ curdirsec=curpart->rootdirsec; } }else{ #ifdef DEBUG err_print("findfile3: invalid partition type\n"); #endif ret=-1; goto findfile3_done; /* done */ } } /* if we arrive here => pnext!=NULL */ abspathflag=0; }else{ if (curpart->type==PARTTYPE_QDOS){ /* QDOS */ /* no directories except root in QDOS */ /* => this must be the last token */ /* check if this is not the last token */ if (pnext!=NULL){ #ifdef DEBUG err_print("findfile3: no sub-directories in QDOS\n"); #endif ret=-1; goto findfile3_done; /* done */ } /* now p is the name of file we are looking for */ if (strcmp(p,".")==0){ startsec=0; /* symbolic value for root directory */ }else{ /* find QDOS file */ startsec=qdos_findfile(p); /* file number+1 !!! */ if (startsec<0){ ret=-1; goto findfile3_done; /* done */ } } goto findfile3_done; /* done */ }else if (curpart->type==PARTTYPE_OS9MDR){ if (curpart->mdr){ /* MDR-DOS */ /* no directories except root in MDR-DOS */ /* => this must be the last token */ /* check if this is not the last token */ if (pnext!=NULL){ #ifdef DEBUG err_print("findfile3: no sub-directories in MDR-DOS\n"); #endif ret=-1; goto findfile3_done; /* done */ } /* now p is the name of file we are looking for */ if (strcmp(p,".")==0){ startsec=0; /* symbolic value for root directory */ }else{ /* find MDR-DOS file */ startsec=mdr_findfile(p); /* file number+1 !!! */ if (startsec<0){ ret=-1; goto findfile3_done; /* done */ } } goto findfile3_done; /* done */ } /* OS9 */ /* check if this is the last token */ if (pnext==NULL){ /* now p is the name of file we are looking for */ startsec=findfile(p,0,NULL); /* file descriptor */ if (startsec<0){ #ifdef DEBUG err_print("findfile3: invalid file descriptor\n"); #endif ret=-1; goto findfile3_done; /* done */ } goto findfile3_done; /* done */ }else{ /* change directory */ if (changedir2(p)<0){ err_print("findfile3: invalid directory\n"); ret=-1; goto findfile3_done; /* done */ } } }else{ #ifdef DEBUG err_print("findfile3: invalid partition type\n"); #endif ret=-1; goto findfile3_done; /* done */ } /* if we arrive here => pnext!=NULL */ } /* if we arrive here => pnext!=NULL */ p=pnext; /* if we arrive here => p!=NULL */ } /* should be never reached */ /* fall through */ findfile3_done: if (startsecp!=NULL){ *startsecp=startsec; /* return start sector */ /* OS9: file descriptor, MDR-DOS: directory entry */ } if (partp!=NULL){ *partp=pp; /* return pointer to partition */ } /* restore state */ curpart=savecurpart; /* for OS9 */ curdirsec=savecurdirsec; free(pathbuf); return ret; } /* general */ /* same algorithm as in findfile3! */ /* the following could be done by findfile3 */ /* But: if it fails, dirlist would be corrupt! */ /* we assume here that path is vaild */ int dirlistupdate3(char *path) { int abspathflag; char *p,*pnext; char *pathbuf; if (path==NULL){ return -1; } if ((strlen(path)==0)||(path[strlen(path)-1]=='/')){ err_print("dirlistupdate3: invalid path\n"); return -1; } /* parse path string */ abspathflag=0; if (path[0]=='/'){ /* absolute path */ abspathflag=1; path++; /* remove '/' */ } /* save path string since strtok destroys it! */ pathbuf=(char *)malloc(strlen(path)+1); /* +1 for '\0' */ if (pathbuf==NULL){ perror("dirlistupdate3: malloc"); return -1; } bcopy(path,pathbuf,strlen(path)+1); /* +1 for '\0' */ p=strtok(pathbuf,"/"); /* first token */ if (p==NULL){ err_print("dirlistupdate3: invalid path\n"); free(pathbuf); return -1; } while (1){ /* if we arrive here => p!=NULL */ #ifdef DEBUG printf("dirlistupdate3: token=\"%s\"\n",p); #endif /* get next token in advance */ pnext=strtok(NULL,"/"); if (abspathflag){ /* change to root directory */ dirlevel=0; /* check if this is the last token */ if (pnext==NULL){ goto dirlistupdate3_done; /* done */ } /* if we arrive here => pnext!=NULL */ abspathflag=0; }else{ /* now p is the name of the directory */ /* interpret p */ if (strcmp(p,".")==0){ /* nothing */ }else if (strcmp(p,"..")==0){ /* one up */ if (dirlevel>0){ dirlevel--; } }else{ /* one down */ /* space left? */ if (dirlevel pnext!=NULL */ } /* if we arrive here => pnext!=NULL */ p=pnext; /* if we arrive here => p!=NULL */ } /* should be never reached */ /* fall through */ dirlistupdate3_done: free(pathbuf); return 0; } /* general */ void printdirlist(void) { int i,imax; printf("/%s",curpart->devname); if (curpart->type==PARTTYPE_QDOS){ printf(" (QDOS)"); return; }else if (curpart->type!=PARTTYPE_OS9MDR){ printf(" (???)"); return; } if (curpart->mdr){ printf(" (MDR-DOS)"); return; } /* OS9 */ if (dirlevel>DIRLEVELNR){ imax=DIRLEVELNR; }else{ imax=dirlevel; } for (i=0;iDIRLEVELNR){ printf("/...(%i)...",dirlevel-DIRLEVELNR); } printf(" (OS9)"); } /* general */ int changedir3(char *path,int update) { u_int startsec; static struct part_s *pp; if (path==NULL){ return -1; } /* find directory file */ if (findfile3(path,&startsec,&pp)<0){ err_print("changedir3: cannot find directory\n"); return -1; } /* change partition */ curpart=pp; if (curpart->type==PARTTYPE_QDOS){ /* QDOS */ /* only root directory allowed */ if (startsec!=0){ /* symbolic value, see findfile3! */ err_print("changedir3: no sub-directories in QDOS\n"); return -1; } }else if (curpart->type==PARTTYPE_OS9MDR){ /* now OS9 or MDR-DOS */ if (curpart->mdr){ /* MDR-DOS */ /* only root directory allowed */ if (startsec!=0){ /* symbolic value, see findfile3! */ err_print("changedir3: no sub-directories in MDR-DOS\n"); return -1; } }else{ /* OS9 */ static struct filedes_s curdirdes; /* check if valid directory */ if (getdir(startsec,&curdirdes,NULL)<0){ err_print("changedir3: cannot change directory\n"); return -1; } /* change directory */ curdirsec=startsec; } }else{ err_print("changedir3: invalid partition type\n"); return -1; } /* the following could be done by findfile3 */ /* But: if it fails, dirlist would be corrupt! */ /* so we can assume here that path is vaild */ /* update dirlist? */ if (update){ return dirlistupdate3(path); } return 0; } /* general */ int creatfile3(char *path,u_int bytesize,int dir,struct genfile_s *tmplt) { struct part_s *savecurpart; u_int savecurdirsec; int ret; char *pathbuf; char *filenam; if (path==NULL){ return -1; } /* save path string! */ pathbuf=(char *)malloc(strlen(path)+1); /* +1 for '\0' */ if (pathbuf==NULL){ perror("creatfile3: malloc"); return -1; } bcopy(path,pathbuf,strlen(path)+1); /* +1 for '\0' */ /* save current state */ savecurpart=curpart; /* for OS9 */ savecurdirsec=curdirsec; /* extract device/directory-path and name */ filenam=strrchr(pathbuf,'/'); /* last '/' in pathbuf */ if (filenam==NULL){ /* '/' not found */ filenam=pathbuf; }else if (filenam==pathbuf){ /* only one occurcence of '/' and this at the beginning */ /* => invalid file path */ err_print("creatfile3: invalid path\n"); ret=-1; goto creatfile3_exit; }else{ *filenam='\0'; /* terminate newpath */ filenam++; ret=changedir3(pathbuf,0); if (ret<0){ err_print("creatfile3: path not found\n"); ret=-1; goto creatfile3_exit; } } if (strlen(filenam)==0){ err_print("creatfile3: invalid file name\n"); ret=-1; goto creatfile3_exit; } /* check if contents of tmplt fit to partition type */ if (tmplt!=NULL){ if (tmplt->part->type!=curpart->type){ tmplt=NULL; /* XXX should convert */ }else if (tmplt->part->type==PARTTYPE_OS9MDR){ if (tmplt->part->mdr!=curpart->mdr){ tmplt=NULL; /* XXX should convert */ } } } /* XXX no check if tmplt is directory!!! */ /* parse partition type */ ret=0; /* no error yet */ if (curpart->type==PARTTYPE_OS9MDR){ if (!curpart->mdr){ /* OS9 */ ret=creatfile(filenam,bytesize,dir,&tmplt->fdes.os9); }else{ /* MDR-DOS */ if (dir){ err_print("creatfile3: cannot create directory in MDR-DOS partition\n"); ret=-1; }else{ ret=mdr_creatfile(filenam,bytesize,&tmplt->fdes.mdrdos); } } }else if (curpart->type==PARTTYPE_QDOS){ /* QDOS */ if (dir){ err_print("creatfile3: cannot create directory in QDOS partition\n"); ret=-1; }else{ ret=qdos_creatfile(filenam,bytesize,&tmplt->fdes.qdos); } }else{ ret=-1; } creatfile3_exit: /* restore state */ curpart=savecurpart; /* for OS9 */ curdirsec=savecurdirsec; free(pathbuf); return ret; } /* general */ /* size via pointer instead of return: want to have full 2^32!!! */ 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) { struct part_s *savecurpart; static u_int startsec; static struct part_s *pp; int ret; u_int size; if ((path==NULL)||(fp==NULL)){ return -1; } if (findfile3(path,&startsec,&pp)<0){ err_print("readfiledes3: cannot find file\n"); return -1; } if (startsecp!=NULL){ *startsecp=startsec; /* see findfile3 for meaning of startsec!!! */ } if (partp!=NULL){ *partp=pp; } if (!pchg){ /* save state */ savecurpart=curpart; } /* change partition */ curpart=pp; if (typep!=NULL) *typep=curpart->type; if (mdrp!=NULL) *mdrp=curpart->mdr; ret=0; /* no error yet */ if (curpart->type==PARTTYPE_OS9MDR){ if (!curpart->mdr){ /* OS9 */ struct filedes_s *fdesp; fdesp=&fp->os9; if (fdessecp!=NULL){ *fdessecp=startsec; /* sector of file descriptor */ } /* read file descriptor */ ret=READBLOCK_CURPART(startsec,fdesp,1); if (ret<0){ err_print("readfiledes3: cannot read file descriptor\n"); goto readfiledes3_exit; } size=(fdesp->fd_fsize[0]<<24) +(fdesp->fd_fsize[1]<<16) +(fdesp->fd_fsize[2]<<8) +fdesp->fd_fsize[3]; if (touch){ /* update modif date */ setdate(fdesp,0); /* 0: not creat */ /* write file descriptor */ ret=WRITEBLOCK_CURPART(startsec,fdesp,1); if (ret<0){ err_print("readfiledes3: cannot update file descriptor\n"); goto readfiledes3_exit; } } }else{ /* MDR-DOS */ struct mdr_dirent_s *direntp; u_int fsec; /* Note: findfile3 returns 0 as symbolic value for root directory in startsec for MDR-DOS!!! */ if (startsec==0){ /* MDR-DOS root directory: not a file! */ err_print("readfiledes3: MDR-DOS root directory not allowed\n"); ret=-1; goto readfiledes3_exit; } direntp=&fp->mdrdos; /* read mdr_dirent_s */ /* Note: findfile3 returns file number+1 in startsec for MDR-DOS!!! */ fsec=MDR_DIRSTART+(startsec-1)*MDR_DIRENTRYSIZE; ret=READBLOCK_CURPART(fsec,direntp,MDR_DIRENTRYSIZE); if (ret<0){ err_print("readfiledes3: cannot read directory entry\n"); goto readfiledes3_exit; } if (fdessecp!=NULL){ *fdessecp=fsec; /* sector of directory entry */ } size=(direntp->size[0]<<24) +(direntp->size[1]<<16) +(direntp->size[2]<<8) +direntp->size[3]; if (touch){ /* update modif date */ mdr_setdate(direntp,0); /* 0: not creat */ /* write mdr_dirent_s */ ret=WRITEBLOCK_CURPART(fsec,direntp,MDR_DIRENTRYSIZE); if (ret<0){ err_print("readfiledes3: cannot touch directory entry\n"); goto readfiledes3_exit; } } } }else if (curpart->type==PARTTYPE_QDOS){ /* QDOS */ struct qdos_fdes_s *qfdesp; struct qdos_dir_s *qdirp; struct qdos_rib_s *qribp; u_char dirbuf[QDOS_DIRSIZE*QDOS_BLOCKSIZE]; struct qdos_dir_s *qbufp; u_int fsec; /* Note: findfile3 returns 0 as symbolic value for root directory in startsec for QDOS!!! */ if (startsec==0){ /* QDOS root directory: not a file! */ err_print("readfiledes3: QDOS root directory not allowed\n"); ret=-1; goto readfiledes3_exit; } /* read directory */ if (READBLOCK_CURPART(QDOS_DIRSTART,(void *)dirbuf,QDOS_DIRSIZE)<0){ err_print("readfiledes3: cannot read directory\n"); ret=-1; goto readfiledes3_exit; } qfdesp=&fp->qdos; qdirp=&qfdesp->dir; qribp=&qfdesp->rib; qbufp=(struct qdos_dir_s *)dirbuf; /* read RIB (QDOS_BLOCKSIZE!!!) */ /* Note: findfile3 returns file number+1 in startsec for QDOS!!! */ fsec=(qbufp[startsec-1].dir_rb[0]<<8)+qbufp[startsec-1].dir_rb[1]; if (fsec==0){ err_print("readfiledes3: invalid RIB sector\n"); ret=-1; goto readfiledes3_exit; } if (fdessecp!=NULL){ *fdessecp=fsec; /* sector of RIB */ } ret=READBLOCK_CURPART(fsec,qribp,1); if (ret<0){ err_print("readfiledes3: cannot read RIB\n"); goto readfiledes3_exit; } size=qdos_fsize(qribp); if (touch){ /* set/clear ATT_CON flag in directory entry if file is contiguous: */ /* Note: findfile3 returns file number+1 in startsec for QDOS!!! */ ret=qdos_setattr(qribp,startsec-1,dirbuf,NULL); if (ret<0){ err_print("readfiledes3: cannot set/clear ATT_CON\n"); goto readfiledes3_exit; } } /* get (possibly modified) directory entry */ /* Note: findfile3 returns file number+1 in startsec for QDOS!!! */ bcopy(&qbufp[startsec-1],qdirp,sizeof(struct qdos_dir_s)); }else{ ret=-1; } readfiledes3_exit: if (!pchg){ /* restore state */ curpart=savecurpart; } if (ret<0){ size=0; } #ifdef DEBUG printf("readfiledes3: size=%08x\n",size); #endif if (sizep!=NULL) *sizep=size; return ret; } /* general */ int extendfile3(char *path,u_int bytesize) { struct part_s *savecurpart; union genfdes_u fdes; u_int srctype,srcmdr; struct part_s *pp; u_int startsec; u_int fdessec; int ret; u_int fsize; u_int spaceadd; u_int blknr; if (path==NULL){ return -1; } if (bytesize==0){ /* nothing to append, done. */ return 0; } /* 1: touch! */ if (readfiledes3(path,&fdes,&srctype,&srcmdr,&startsec,&pp,&fdessec,0,&fsize,1)<0){ err_print("extendfile3: invalid path\n"); return -1; } /* save current state */ savecurpart=curpart; /* change partition */ curpart=pp; /* parse partition type */ ret=0; /* no error yet */ if (curpart->type==PARTTYPE_OS9MDR){ /* XXX 32-Bit fsize limit: */ if ((((OFF_T)fsize)+((OFF_T)bytesize))>0xffffffffUL){ err_print("extendfile3: invalid bytesize\n"); return -1; } if (!curpart->mdr){ /* OS9 */ if (fdes.os9.fd_att&ATT_D){ err_print("extendfile3: directory not allowed\n"); ret=-1; goto extendfile3_exit; } spaceadd=curpart->blksiz*countseg(&fdes.os9.fd_seg[0],FILEDES_SEGNR,NULL); if (spaceaddblksiz-1)) /((OFF_T)curpart->blksiz)); ret=filecreat(&fdes.os9,blknr,1); /* 1: extend */ if (ret<0){ goto extendfile3_exit; } } /* update file descriptor */ fsize+=bytesize; fdes.os9.fd_fsize[0]=0xff&(fsize>>24); fdes.os9.fd_fsize[1]=0xff&(fsize>>16); fdes.os9.fd_fsize[2]=0xff&(fsize>>8); fdes.os9.fd_fsize[3]=0xff&fsize; /* write updated file descriptor */ if (WRITEBLOCK_CURPART(fdessec,&fdes.os9,1)<0){ err_print("extendfile3: cannot write updated file descriptor\n"); ret=-1; goto extendfile3_exit; } }else{ /* MDR-DOS */ /* Note: findfile3 returns 0 as symbolic value for root directory in startsec for MDR-DOS!!! */ if (startsec==0){ /* MDR-DOS root directory: not a file! */ err_print("extendfile3: MDR-DOS root directory not allowed\n"); ret=-1; goto extendfile3_exit; } spaceadd=curpart->blksiz*curpart->mdr_clustersize *mdr_countclu(&fdes.mdrdos,MDR_FILECLNR,NULL); if (spaceaddmdr_clustersize*curpart->blksiz-1)) /((OFF_T)curpart->mdr_clustersize*curpart->blksiz)); ret=mdr_filecreat(&fdes.mdrdos,blknr,1); /* 1: extend */ if (ret<0){ goto extendfile3_exit; } } /* update directory entry */ fsize+=bytesize; fdes.mdrdos.size[0]=0xff&(fsize>>24); fdes.mdrdos.size[1]=0xff&(fsize>>16); fdes.mdrdos.size[2]=0xff&(fsize>>8); fdes.mdrdos.size[3]=0xff&fsize; /* write updated directory entry */ if (WRITEBLOCK_CURPART(fdessec,&fdes.mdrdos,MDR_DIRENTRYSIZE)<0){ err_print("extendfile3: cannot write updated directory entry\n"); ret=-1; goto extendfile3_exit; } } }else if (curpart->type==PARTTYPE_QDOS){ /* QDOS */ u_int ribsec,qsiz; /* Note: findfile3 returns 0 as symbolic value for root directory in startsec for QDOS!!! */ if (startsec==0){ /* QDOS root directory: not a file! */ err_print("extendfile3: QDOS root directory not allowed\n"); ret=-1; goto extendfile3_exit; } spaceadd=curpart->blksiz*QDOS_CSIZE *qdos_countseg(&fdes.qdos.rib,QDOS_RIB_SDWNR,NULL); /* Note: first block of file allocation is used for RIB!!! */ if (spaceaddblksiz*QDOS_CSIZE){ err_print("extendfile3: corrupt allocation size\n"); ret=-1; goto extendfile3_exit; } spaceadd-=curpart->blksiz; if (spaceaddblksiz-1)/curpart->blksiz; ret=qdos_filecreat(&fdes.qdos.rib,blknr,1); /* 1: extend */ if (ret<0){ goto extendfile3_exit; } } /* update file size in RIB */ fsize+=bytesize; ret=qdos_setfsize(&fdes.qdos.rib,fsize); if (ret<0){ err_print("extendfile3: corrupt RIB\n"); goto extendfile3_exit; } /* Note: first block of file allocation is used for RIB!!! */ qdos_getseg(&fdes.qdos.rib,0,&ribsec,&qsiz); if (qsiz==0){ /* empty first segment => corrupt RIB!!! */ err_print("extendfile3: corrupt RIB\n"); ret=-1; goto extendfile3_exit; } ribsec*=QDOS_CSIZE; /* write updated RIB */ if (WRITEBLOCK_CURPART(ribsec,&fdes.qdos.rib,1)<0){ err_print("extendfile3: cannot write updated RIB\n"); ret=-1; goto extendfile3_exit; } /* set/clear ATT_CON flag in directory entry if file is contiguous: */ /* Note: findfile3 returns file number+1 in startsec for QDOS!!! */ ret=qdos_setattr(&fdes.qdos.rib,startsec-1,NULL,NULL); if (ret<0){ err_print("extendfile3: cannot set/clear ATT_CON\n"); goto extendfile3_exit; } }else{ ret=-1; } extendfile3_exit: /* restore state */ curpart=savecurpart; return ret; } /* general */ int lsn0reset(void) { static u_char buf[OS9MAX_BLOCKSIZE]; /* Note: OS9MAX_BLOCKSIZE is also enough for QDOS_BLOCKSIZE */ /* clear */ bzero(buf,OS9MAX_BLOCKSIZE); /* save new LSN0 */ if (WRITEBLOCK_CURPART(0,buf,1)<0){ err_print("lsn0reset: cannot write LSN0\n"); /* XXX can't undo previous actions */ return -1; } return 0; /* Note: must restart program after modification of LSN0!!! */ } /* OS9 */ int lsn0bootfile(char *path,int bsz) { static u_int size,bstart,dummy; static struct part_s *pp; static struct filedes_s fdes; if (curpart->type!=PARTTYPE_OS9MDR){ return -1; } if (curpart->mdr){ err_print("lsn0bootfile: must be OS9 filesystem\n"); return -1; } if (path!=NULL){ /* set bootfile entry */ /* find file and check if file is in master partition */ if (findfile3(path,NULL,&pp)<0){ err_print("lsn0bootfile: cannot find file\n"); return -1; } if (pp!=curpart){ /* must be in same partition */ err_print("lsn0bootfile: file not in same partition\n"); return -1; } /* read file descriptor */ if (readfiledes3(path,(union genfdes_u *)&fdes,NULL,NULL,NULL,NULL,NULL,0,&size,0)<0){ err_print("lsn0bootfile: cannot read file descriptor\n"); return -1; } /* check if file size is valid */ if (bsz>=0){ /* given size */ if (bsz>0xffff){ /* dd_bsz has 2 bytes! */ err_print("lsn0bootfile: bsz too large\n"); return -1; } if (size<(u_int)bsz){ err_print("lsn0bootfile: warning: file might be too small\n"); /* XXX no error */ } size=bsz; /* take given value */ }else{ if (size>0xffff){ /* dd_bsz has 2 bytes! */ err_print("lsn0bootfile: file too large\n"); return -1; } } /* check if file is contiguous */ getseg(&fdes.fd_seg[1],NULL,&dummy); if (dummy!=0){ err_print("lsn0bootfile: file not contiguous\n"); return -1; } /* get start block of data */ getseg(&fdes.fd_seg[0],&bstart,NULL); }else{ /* clear bootfile entry */ bstart=0; size=0; } /* set curpart... */ curpart->bootsec=bstart; curpart->bootsize=size; /* set LSN0 bootfile entries */ curpart->lsn0->dd_bsz[1]=size; curpart->lsn0->dd_bsz[0]=size>>8; curpart->lsn0->dd_bt[2]=bstart; curpart->lsn0->dd_bt[1]=bstart>>8; curpart->lsn0->dd_bt[0]=bstart>>16; /* save new LSN0 */ if (WRITEBLOCK_CURPART(0,curpart->lsn0,1)<0){ err_print("lsn0bootfile: cannot write LSN0\n"); /* XXX can't undo previous actions */ return -1; } return 0; } /* OS9 */ int lsn0partfile(char *path) { static u_int size,pstart,pn,dummy; static struct part_s *pp; static struct filedes_s fdes; if (curpart->type!=PARTTYPE_OS9MDR){ return -1; } if (curpart->mdr){ err_print("lsn0partfile: must be OS9 filesystem\n"); return -1; } if (path!=NULL){ /* set partfile entry */ /* find file and check if file is in master partition */ if (findfile3(path,NULL,&pp)<0){ err_print("lsn0partfile: cannot find file\n"); return -1; } if (pp!=curpart){ /* must be in same partition */ err_print("lsn0partfile: file not in same partition\n"); return -1; } /* read file descriptor */ if (readfiledes3(path,(union genfdes_u *)&fdes,NULL,NULL,NULL,NULL,NULL,0,&size,0)<0){ err_print("lsn0partfile: cannot read file descriptor\n"); return -1; } /* check if file size is valid */ if (size!=PARTTAB_NR*sizeof(struct parttabent_s)){ char b[128]; sprintf(b,"lsn0partfile: file size invalid (must be 0x%x bytes)\n", PARTTAB_NR*sizeof(struct parttabent_s)); err_print(b); return -1; } /* check if file is contiguous */ getseg(&fdes.fd_seg[1],NULL,&dummy); if (dummy!=0){ err_print("lsn0partfile: file not contiguous\n"); return -1; } /* get start block of data */ getseg(&fdes.fd_seg[0],&pstart,NULL); pn=PARTTAB_NR; /* partition-slots in partfile */ }else{ /* clear partfile entry */ pstart=0; pn=0; } /* set curpart... */ curpart->ptabsec=pstart; curpart->pnr=pn; /* set LSN0 partfile entries */ curpart->lsn0->dd_ptabstart[2]=pstart; curpart->lsn0->dd_ptabstart[1]=pstart>>8; curpart->lsn0->dd_ptabstart[0]=pstart>>16; curpart->lsn0->dd_pnr=pn; /* save new LSN0 */ if (WRITEBLOCK_CURPART(0,curpart->lsn0,1)<0){ err_print("lsn0bootfile: cannot write LSN0\n"); /* XXX can't undo previous actions */ return -1; } return 0; /* must restart now to get new partition table!!! */ } /* QDOS */ int qdos_ovfile(char *path,u_int ovnr) { struct part_s *pp; struct qdos_fdes_s qfdes; u_int ovrib; if (curpart->type!=PARTTYPE_QDOS){ return -1; } if (ovnr>=QDOS_DID_RBNR){ err_print("qdos_ovfile: invalid ovnr\n"); return -1; } if (path!=NULL){ /* set overlay file entry */ /* find file and check if file is in master partition */ if (findfile3(path,NULL,&pp)<0){ err_print("qdos_ovfile: cannot find file\n"); return -1; } if (pp!=curpart){ /* must be in same partition */ err_print("qdos_ovfile: file not in same partition\n"); return -1; } /* get file RIB */ if (readfiledes3(path,(union genfdes_u *)&qfdes,NULL,NULL,NULL,NULL,&ovrib,0,NULL,0)<0){ err_print("qdos_ovfile: cannot get RIB\n"); return -1; } }else{ /* clear overlay file entry */ ovrib=0; } /* set curpart... */ QDOS_LSN0_P(curpart->lsn0)->did_rb[ovnr][0]=0xff&(ovrib>>8); QDOS_LSN0_P(curpart->lsn0)->did_rb[ovnr][1]=0xff&ovrib; /* save new DID */ if (WRITEBLOCK_CURPART(0,curpart->lsn0,1)<0){ err_print("qdos_ovfile: cannot write DID\n"); /* XXX can't undo previous actions */ return -1; } return 0; } /* QDOS */ int qdos_setboot(u_int btsec,u_int btsiz,u_int btloa) { if (curpart->type!=PARTTYPE_QDOS){ return -1; } /* set curpart... */ QDOS_LSN0_P(curpart->lsn0)->did_btsec[0]=0xff&(btsec>>8); QDOS_LSN0_P(curpart->lsn0)->did_btsec[1]=0xff&btsec; QDOS_LSN0_P(curpart->lsn0)->did_btsiz[0]=0xff&(btsiz>>8); QDOS_LSN0_P(curpart->lsn0)->did_btsiz[1]=0xff&btsiz; QDOS_LSN0_P(curpart->lsn0)->did_btloa[0]=0xff&(btloa>>8); QDOS_LSN0_P(curpart->lsn0)->did_btloa[1]=0xff&btloa; /* save new DID */ if (WRITEBLOCK_CURPART(0,curpart->lsn0,1)<0){ err_print("qdos_bootfile: cannot write LSN0\n"); /* XXX can't undo previous actions */ return -1; } return 0; } /* OS9 */ int listdirtree(int (*recfct)(char *name,int rec,int arg),int arg) { /* recursive: variables must not be static!!! */ struct filedes_s curdirdes; u_int curdirsize; struct dirent_s *curdirp; u_int blknr; u_int i,j; char namebuf[FILENAMELEN+1]; struct filedes_s fdes; int ret; u_int fsize,asize,corrupt; static u_int reclevel=0; /* static recursion level */ static u_int maxreclevel=0; /* static recursion level */ static u_int totfiles; /* static for recursion! */ static u_int totdirs; /* static for recursion! */ static u_int totsize; /* static for recursion! */ static u_int totalloc; /* static for recursion! */ static u_int corruptcount; /* static for recursion! */ if (curpart->type!=PARTTYPE_OS9MDR){ return -1; } if (curpart->mdr){ return -1; } /* must be recursive */ if (recfct==NULL){ return -1; } if (reclevel==0){ /* reset */ totfiles=0; totdirs=0; totsize=0; totalloc=0; corruptcount=0; } /* XXX read whole directory file */ if (getdir(curdirsec,&curdirdes,&curdirsize)<0){ return -1; } if (curdirsize==0){ #if 0 err_print("listdirtree: directory empty\n"); return -1; #else corruptcount++; printf("*** empty directory ***\n"); return 0; /* XXX non-fatal */ #endif } /* read directory file */ /* XXX 32-Bit overflow protection */ blknr=(u_int)((((OFF_T)curdirsize)+((OFF_T)curpart->blksiz-1)) /((OFF_T)curpart->blksiz)); /* allocate memory for directory file */ curdirp=(struct dirent_s *)malloc(blknr*curpart->blksiz); if (curdirp==NULL){ perror("listdirtree: malloc"); return -1; } /* read directory file */ if (fileread((union genfdes_u *)&curdirdes,(void *)curdirp,0,blknr)!=(int)blknr){ #if 0 err_print("listdirtree: fileread(curdirdes)\n"); free((void *)curdirp); return -1; #else corruptcount++; printf("*** cannot read directory ***\n"); free((void *)curdirp); return 0; /* XXX non-fatal */ #endif } /* scan directory entries */ for (i=0;iasize*curpart->blksiz)||(asize>curpart->filesyssize); if (corrupt){ corruptcount++; }else{ totsize+=fsize; totalloc+=asize; } /* print entry */ for (j=0;jmaxreclevel){ maxreclevel=reclevel; } #define MAX_RECLEVEL 4 /* XXX set VC++ linker option /STACK:0x1000000 */ if (reclevel<=MAX_RECLEVEL){ ret=recfct(namebuf,1,arg); /* 1: recursive */ }else{ printf("*** MAX_RECLEVEL ***\n"); } reclevel--; /* check for error */ if (ret<0){ printf("*** ERROR ***\n"); return -1; } } }else{ totfiles++; } } if (reclevel==0){ printf("\ntotal\n----------------------------------------------\n"); printf("files: %11u\n",totfiles); printf("directories: %11u\n",totdirs); printf("maxreclevel: %11u\n",maxreclevel); printf("damaged: %11u\n",corruptcount); printf("data size: %11u bytes\n",totsize); printf(" allocated: %11u bytes (%06x blocks)\n\n", totalloc*curpart->blksiz,totalloc); } free((void *)curdirp); return 0; } /* MDR-DOS */ int mdr_listdir(void) { static struct mdr_dirent_s dirent; u_int fnr; u_int fsize; u_int cnr; if (curpart->type!=PARTTYPE_OS9MDR){ return -1; } if (!curpart->mdr){ return -1; } printf("fnr creat/bk modif size type name\n"); printf("-------------------------------------------------------------------------------\n"); /* scan directory */ for (fnr=0;fnrmdr_filenr;fnr++){ /* XXX first mdr_filenr entries */ /* read directory entry */ if (READBLOCK_CURPART(MDR_DIRSTART+fnr*MDR_DIRENTRYSIZE, (void *)&dirent,MDR_DIRENTRYSIZE)<0){ err_print("mdr_listdir: READBLOCK_CURPART\n"); return -1; } /* file size in clusters */ fsize=(dirent.size[0]<<24) +(dirent.size[1]<<16) +(dirent.size[2]<<8) +dirent.size[3]; /* check if entry not used */ if (dirent.name[0]==0) continue; /* next */ /* print entry */ printf("%4i ",fnr); printf("%02i-%02i-%02i ", dirent.back[0]%100,dirent.back[1]%100,dirent.back[2]%100); /* XXX don't print backup times */ printf("%02i-%02i-%02i %02i:%02i ", dirent.modif[0]%100,dirent.modif[1]%100,dirent.modif[2]%100, dirent.modif[3]%100,dirent.modif[4]%100); /* XXX don't print modif seconds */ /* count used clusters */ cnr=mdr_countclu(&dirent,MDR_FILECLNR,NULL); if (fsize>cnr*curpart->mdr_clustersize*curpart->blksiz){ printf("???????? "); }else{ printf("%08x ",fsize); } printf("%c%c%c%c ", dirent.type[0],dirent.type[1],dirent.type[2],dirent.type[3]); printf("%s\n",dirent.name); /* XXX no length check */ } printf("-------------------------------------------------------------------------------\n\n"); return 0; } /* QDOS */ int qdos_listdir(void) { u_int fnr; u_char dirbuf[QDOS_DIRSIZE*QDOS_BLOCKSIZE]; struct qdos_dir_s *qdp; u_int ribblk; struct qdos_rib_s qr; u_int cnr; u_int fsize; if (curpart->type!=PARTTYPE_QDOS){ return -1; } printf("fnr rib ov lb sl la sa size att fmt name\n"); printf("---------------------------------------------------------------------\n"); /* read directory */ if (READBLOCK_CURPART(QDOS_DIRSTART,(void *)dirbuf,QDOS_DIRSIZE)<0){ err_print("qdos_listdir: READBLOCK_CURPART\n"); return -1; } qdp=(struct qdos_dir_s *)dirbuf; /* scan directory */ for (fnr=0;fnrlsn0); for (ov=0;ovdid_rb[ov][0]==qdp[fnr].dir_rb[0]) &&(qp->did_rb[ov][1]==qdp[fnr].dir_rb[1])){ break; /* found */ } } if (ov(cnr*QDOS_CSIZE*curpart->blksiz-curpart->blksiz)){ printf(" ?????? "); }else{ printf(" %06x ",fsize); } } } } /* print entry (continued)*/ qdos_printatt0(qdp[fnr].dir_at[0]); #if 0 printf(" (%02x%02x) ",qdp[fnr].dir_at[0],qdp[fnr].dir_at[1]); #endif printf(" "); printnstr(qdp[fnr].dir_nm,8); printf("."); printnstr(qdp[fnr].dir_sx,2); printf("\n"); } printf("---------------------------------------------------------------------\n\n"); return 0; } /* general */ int listdir(int (*recfct)(char *name,int rec,int arg),int arg) { /* recursive: variables must not be static!!! */ struct filedes_s curdirdes; u_int curdirsize; struct dirent_s *curdirp; u_int blknr; u_int i; char namebuf[FILENAMELEN+1]; struct filedes_s fdes; u_int fsize,totsize; int ret; if (curpart->type==PARTTYPE_QDOS){ return qdos_listdir(); /* non-recursive, end here! */ }else if (curpart->type!=PARTTYPE_OS9MDR){ return -1; } /* now OS9 or MDR-DOS */ if (curpart->mdr){ return mdr_listdir(); /* non-recursive, end here! */ } /* XXX read whole directory file */ if (getdir(curdirsec,&curdirdes,&curdirsize)<0){ return -1; } if (curdirsize==0){ if (recfct==NULL){ err_print("listdir: directory empty\n"); return -1; }else{ printf("*** empty directory ***\n"); return 0; /* XXX non-fatal */ } } /* read directory file */ /* XXX 32-Bit overflow protection */ blknr=(u_int)((((OFF_T)curdirsize)+((OFF_T)curpart->blksiz-1)) /((OFF_T)curpart->blksiz)); /* allocate memory for directory file */ curdirp=(struct dirent_s *)malloc(blknr*curpart->blksiz); if (curdirp==NULL){ perror("listdir: malloc"); return -1; } /* read directory file */ if (fileread((union genfdes_u *)&curdirdes,(void *)curdirp,0,blknr)!=(int)blknr){ if (recfct==NULL){ err_print("listdir: fileread(curdirdes)\n"); free((void *)curdirp); return -1; }else{ printf("*** cannot read directory ***\n"); free((void *)curdirp); return 0; /* XXX non-fatal */ } } /* recursive? */ if (recfct!=NULL){ /* scan directory entries for sub-directories */ for (i=0;itype==PARTTYPE_QDOS){ /* QDOS has no directories except root! */ recursive=0; tree=0; }else if (curpart->type==PARTTYPE_OS9MDR){ /* now OS9 or MDR-DOS */ if (curpart->mdr){ /* MDR-DOS has no directories except root! */ recursive=0; tree=0; } }else{ return -1; } if (tree){ ret=listdirtree(&printdir3,tree); }else{ ret=listdir(recursive?(&printdir3):NULL,tree); } /* restore state */ curpart=savecurpart; /* for OS9 */ curdirsec=savecurdirsec; return ret; /* ret: if error... */ } /* general */ int openfile3(char *path,struct genfile_s *fp,int touch) { if ((path==NULL)||(fp==NULL)){ return -1; } /* get file descriptor */ /* 0: do not change partition! */ return readfiledes3(path, &fp->fdes, NULL, /* type: this informtion is within fp->part! */ NULL, /* mdr: this informtion is within fp->part! */ &fp->startsec, &fp->part, &fp->fdessec, 0, &fp->size, touch); } /* general */ /* bytestart and buffer allocation must be multiples of filesystem blocksize!!! */ int readfile4(struct genfile_s *fp,char *buf,u_int bytestart,u_int bytenr) { struct part_s *savecurpart; u_int blkstart,blknr,blknract; int ret; if ((fp==NULL)||(buf==NULL)){ return -1; } if (fp->part==NULL){ return -1; } /* save state */ savecurpart=curpart; /* change partition */ curpart=fp->part; /* read file */ ret=-1; if (curpart->blksiz!=0){ /* XXX should be OK */ blkstart=bytestart/curpart->blksiz; /* round down! */ /* XXX 32-Bit overflow protection */ blknr=(u_int)((((OFF_T)bytenr)+((OFF_T)curpart->blksiz-1)) /((OFF_T)curpart->blksiz)); blknract=(u_int)fileread(&fp->fdes,buf,blkstart,blknr); if (blknract==blknr){ ret=0; /* success */ }else{ err_print("readfile4: not full count read\n"); } } /* restore state */ curpart=savecurpart; return ret; } /* general */ /* bytestart and buffer allocation must be multiples of filesystem blocksize!!! */ int writefile4(struct genfile_s *fp,char *buf,u_int bytestart,u_int bytenr) { struct part_s *savecurpart; u_int blkstart,blknr,blknract; int ret; if ((fp==NULL)||(buf==NULL)){ return -1; } if (fp->part==NULL){ return -1; } /* save state */ savecurpart=curpart; /* change partition */ curpart=fp->part; /* write file */ ret=-1; if (curpart->blksiz!=0){ /* XXX should be OK */ blkstart=bytestart/curpart->blksiz; /* round down! */ /* XXX 32-Bit overflow protection */ blknr=(u_int)((((OFF_T)bytenr)+((OFF_T)curpart->blksiz-1)) /((OFF_T)curpart->blksiz)); blknract=(u_int)filewrite(&fp->fdes,buf,blkstart,blknr); if (blknract==blknr){ ret=0; /* success */ }else{ err_print("writefile4: not full count written\n"); } } /* restore state */ curpart=savecurpart; return ret; } /* general */ int movefile3(char *path1,char *path2,int link) { struct part_s *savecurpart; u_int savecurdirsec; u_int olddirsec; u_int newdirsec; int ret; char *oldname,*oldpath,*newname,*newpath; struct part_s *oldpart,*newpart; if ((path1==NULL)||(path2==NULL)|| (strlen(path1)==0)||(strlen(path2)==0)){ return -1; } /* check if path1 exists */ if (findfile3(path1,NULL,NULL)<0){ err_print("movefile3: source path not found\n"); return -1; } /* check if path2 already exists */ if (findfile3(path2,NULL,NULL)>=0){ err_print("movefile3: destination path already used\n"); return -1; } err_reset(); /* XXX clear findfile3 error! */ /* save path string! */ oldpath=(char *)malloc(strlen(path1)+1); /* +1 for '\0' */ if (oldpath==NULL){ perror("movefile3: malloc"); return -1; } bcopy(path1,oldpath,strlen(path1)+1); /* +1 for '\0' */ /* save path string! */ newpath=(char *)malloc(strlen(path2)+1); /* +1 for '\0' */ if (newpath==NULL){ perror("movefile3: malloc"); free(oldpath); return -1; } bcopy(path2,newpath,strlen(path2)+1); /* +1 for '\0' */ /* save current state */ savecurpart=curpart; /* for OS9 */ savecurdirsec=curdirsec; /* extract device/directory-path and name */ newname=strrchr(newpath,'/'); if (newname==NULL){ /* '/' not found */ newname=newpath; }else if (newname==newpath){ /* only one occurcence of '/' and this at the beginning */ /* => invalid file path */ err_print("movefile3: invalid destination path\n"); ret=-1; goto movefile3_exit; }else{ *newname='\0'; /* terminate newpath */ newname++; ret=changedir3(newpath,0); if (ret<0){ err_print("movefile3: destination path not found\n"); ret=-1; goto movefile3_exit; } } if (strlen(newname)==0){ err_print("movefile3: invalid destination file name\n"); ret=-1; goto movefile3_exit; } newpart=curpart; /* for OS9 */ newdirsec=curdirsec; /* now we are in newpart!!! */ /* extract device/directory-path and name */ oldname=strrchr(oldpath,'/'); if (oldname==NULL){ /* '/' not found */ oldname=oldpath; /* restore state */ curpart=savecurpart; /* for OS9 */ curdirsec=savecurdirsec; }else if (oldname==oldpath){ /* only one occurcence of '/' and this at the beginning */ /* => invalid file path */ err_print("movefile3: invalid source path\n"); ret=-1; goto movefile3_exit; }else{ *oldname='\0'; /* terminate oldpath */ oldname++; ret=changedir3(oldpath,0); if (ret<0){ err_print("movefile3: source path not found\n"); ret=-1; goto movefile3_exit; } } if (strlen(oldname)==0){ err_print("movefile3: invalid source file name\n"); ret=-1; goto movefile3_exit; } oldpart=curpart; /* for OS9 */ olddirsec=curdirsec; /* now we are in oldpart!!! */ #ifdef DEBUG printf("movefile3: path1: %s\n",path1); if (oldpath!=NULL){ printf("movefile3: oldpath: %s\n",oldpath); }else{ printf("movefile3: oldpath: (none)\n"); } printf("movefile3: oldname: %s\n",oldname); printf("movefile3: path2: %s\n",path2); if (newpath!=NULL){ printf("movefile3: newpath: %s\n",newpath); }else{ printf("movefile3: newpath: (none)\n"); } printf("movefile3: newname: %s\n",newname); #endif /* check if in same partition */ if (oldpart!=newpart){ err_print("movefile3: must be in same partition\n"); ret=-1; goto movefile3_exit; } /* parse partition type */ /* Note: now we are in oldpart!!! */ ret=0; /* no error yet */ if (curpart->type==PARTTYPE_QDOS){ /* QDOS */ /* this is just a "rename" */ u_int fnr1; u_char dirbuf[QDOS_DIRSIZE*QDOS_BLOCKSIZE]; struct qdos_dir_s *qdp; char qnewname[11]; /* NNNNNNNNSS with terminating '\0' */ if (link){ err_print("movefile3: cannot link for QDOS\n"); ret=-1; goto movefile3_exit; } /* Note: now we are in oldpart!!! */ /* find directory entry for file */ if ((fnr1=qdos_findfile(oldname))<=0){ err_print("movefile3: cannot find oldname\n"); ret=-1; goto movefile3_exit; } /* read directory */ if (READBLOCK_CURPART(QDOS_DIRSTART,(void *)dirbuf,QDOS_DIRSIZE)<0){ err_print("movefile3: cannot read directory\n"); ret=-1; goto movefile3_exit; } qdp=(struct qdos_dir_s *)dirbuf; /* convert newname into QDOS-conformant name */ qdos_makefname(newname,qnewname); /* rename */ /* Note: dir_sx[2] directly follows dir_nm[8] in struct qdos_dir_s!!! */ bcopy(qnewname,qdp[fnr1-1].dir_nm,10); /* write directory */ if (WRITEBLOCK_CURPART(QDOS_DIRSTART,(void *)dirbuf,QDOS_DIRSIZE)<0){ err_print("movefile3: cannot write directory\n"); ret=-1; goto movefile3_exit; } }else if (curpart->type==PARTTYPE_OS9MDR){ if (!curpart->mdr){ /* OS9 */ int startsec; static struct filedes_s fdes; /* Note: now we are in oldpart!!! */ /* check for "." and ".." */ if ((strcmp(oldname,".")==0)||(strcmp(oldname,"..")==0) ||(strcmp(newname,".")==0)||(strcmp(newname,"..")==0)){ err_print("movefile3: . or .. not allowed\n"); ret=-1; goto movefile3_exit; } /* find oldname */ startsec=findfile(oldname,0,NULL); if (startsec<0){ err_print("movefile3: cannot find oldname\n"); ret=-1; goto movefile3_exit; } /* read file descriptor */ if (READBLOCK_CURPART(startsec,&fdes,1)<0){ err_print("movefile3: cannot read file descriptor\n"); ret=-1; goto movefile3_exit; } /* delete old entry? */ if (!link){ /* delete directory entry */ if (deldirent(oldname,-1)<0){ /* -1: don't check file type */ err_print("movefile3: cannot delete oldname\n"); ret=-1; goto movefile3_exit; } /* link count for file descriptor remains the same! */ }else{ /* keep old directory entry */ /* -> must increment link count in file descriptor! */ /* increment link count */ if (fdes.fd_link==0xff){ /* overflow? */ err_print("movefile3: link count overflow\n"); ret=-1; goto movefile3_exit; }else{ fdes.fd_link++; if (fdes.fd_link<=1){ /* should be at least 2 now! */ fdes.fd_link=2; } } } #if 0 /* update modif date */ setdate(&fdes,0); /* 0: not creat */ #endif /* write updated file descriptor */ if (WRITEBLOCK_CURPART(startsec,&fdes,1)<0){ err_print("movefile3: cannot write updated file descriptor\n"); ret=-1; goto movefile3_exit; } /* change to destination state */ curpart=newpart; /* for OS9 */ curdirsec=newdirsec; /* create directory entry */ if (creatdirent(newname,startsec)<0){ err_print("movefile3: cannot create new entry\n"); if (!link){ /* try to recreate old entry */ /* change to source state */ curpart=oldpart; /* for OS9 */ curdirsec=olddirsec; creatdirent(oldname,startsec); } ret=-1; goto movefile3_exit; } }else{ /* MDR-DOS */ /* this is just a "rename" */ struct mdr_dirent_s dirent; int fsec,fnr1; if (link){ err_print("movefile3: cannot link for MDR-DOS\n"); ret=-1; goto movefile3_exit; } /* Note: now we are in oldpart!!! */ /* find directory entry for file */ if ((fnr1=mdr_findfile(oldname))<=0){ err_print("movefile3: cannot find oldname\n"); ret=-1; goto movefile3_exit; } fsec=MDR_DIRSTART+(fnr1-1)*MDR_DIRENTRYSIZE; /* read directory entry */ if (READBLOCK_CURPART(fsec,&dirent,MDR_DIRENTRYSIZE)<0){ err_print("movefile3: cannot read directory\n"); ret=-1; goto movefile3_exit; } /* rename */ /* XXX no check for invalid newpath */ /* set name without translation!!! */ bcopy(newname,&(dirent.name[0]),FILENAMELEN+1); #if 0 /* update modif date */ mdr_setdate(&dirent,0); /* 0: not creat */ #endif /* write dirent */ if (WRITEBLOCK_CURPART(fsec,&dirent,MDR_DIRENTRYSIZE)<0){ err_print("movefile3: cannot write directory entry\n"); ret=-1; goto movefile3_exit; } } }else{ err_print("movefile3: invalid partition type\n"); ret=-1; } movefile3_exit: /* restore state */ curpart=savecurpart; /* for OS9 */ curdirsec=savecurdirsec; free(oldpath); free(newpath); return ret; } int delfile3(char *path,int dir) { struct part_s *savecurpart; u_int savecurdirsec; char *dirpath,*name; int ret; if (path==NULL){ return -1; } /* save path string! */ dirpath=(char *)malloc(strlen(path)+1); /* +1 for '\0' */ if (dirpath==NULL){ perror("delfile3: malloc"); return -1; } bcopy(path,dirpath,strlen(path)+1); /* +1 for '\0' */ /* save current state */ savecurpart=curpart; /* for OS9 */ savecurdirsec=curdirsec; /* extract device/directory-path and name */ name=strrchr(dirpath,'/'); if (name==NULL){ /* '/' not found */ name=dirpath; }else if (name==dirpath){ /* only one occurcence of '/' and this at the beginning */ /* => invalid file path */ err_print("delfile3: invalid path\n"); ret=-1; goto delfile3_exit; }else{ *name='\0'; /* terminate newpath */ name++; ret=changedir3(dirpath,0); if (ret<0){ err_print("delfile3: path not found\n"); ret=-1; goto delfile3_exit; } } /* parse partition type */ /* Note: now we are in oldpart!!! */ ret=0; /* no error yet */ if (curpart->type==PARTTYPE_QDOS){ /* QDOS */ if (dir){ err_print("delfile3: no directories for QDOS\n"); ret=-1; goto delfile3_exit; } ret=qdos_delfile(name); }else if (curpart->type==PARTTYPE_OS9MDR){ if (!curpart->mdr){ /* OS9 */ ret=delfile(name,dir); }else{ /* MDR-DOS */ if (dir){ err_print("delfile3: no directories for MDR-DOS\n"); ret=-1; goto delfile3_exit; } ret=mdr_delfile(name); } }else{ err_print("delfile3: invalid partition type\n"); ret=-1; } delfile3_exit: /* restore state */ curpart=savecurpart; /* for OS9 */ curdirsec=savecurdirsec; free(dirpath); return ret; } /* OS9 */ int filesetattr3(char *path,char *str,int own) { struct part_s *savecurpart; int ret; u_int startsec,fdessec; union genfdes_u fdes; if (path==NULL){ return -1; } if ((str==NULL)&&(own<0)){ /* nothing to do */ return -1; } /* save state */ savecurpart=curpart; /* read file descriptor */ /* 1: change partition! */ if (readfiledes3(path,&fdes,NULL,NULL,&startsec,NULL,&fdessec,1,NULL,0)<0){ err_print("filesetattr3: cannot find file\n"); ret=-1; goto filesetattr3_exit; } /* parse partition type */ ret=0; /* no error yet */ if (curpart->type==PARTTYPE_QDOS){ /* QDOS */ u_int x; int ribmod; if (str==NULL){ ret=-1; goto filesetattr3_exit; } /* Note: readfiledes3 returns 0 as symbolic value for root directory in startsec for QDOS!!! */ if (startsec==0){ /* QDOS root directory: not a file! */ err_print("filesetattr3: QDOS root directory not allowed\n"); ret=-1; goto filesetattr3_exit; } /* interpret str */ ribmod=0; /* RIB not modified yet */ if ((strlen(str)>3)&&(strncmp(str,"sl=",3)==0)){ sscanf(str+3,"%x",&x); fdes.qdos.rib.rib_sl[0]=(x>>8)&0xff; fdes.qdos.rib.rib_sl[1]=x&0xff; ribmod=1; }else if ((strlen(str)>3)&&(strncmp(str,"la=",3)==0)){ sscanf(str+3,"%x",&x); fdes.qdos.rib.rib_la[0]=(x>>8)&0xff; fdes.qdos.rib.rib_la[1]=x&0xff; ribmod=1; }else if ((strlen(str)>3)&&(strncmp(str,"sa=",3)==0)){ sscanf(str+3,"%x",&x); fdes.qdos.rib.rib_sa[0]=(x>>8)&0xff; fdes.qdos.rib.rib_sa[1]=x&0xff; ribmod=1; }else{ /* set/clear attributes */ /* Note: readfiledes3 returns file number+1 in startsec for QDOS!!! */ if (qdos_setattr(&fdes.qdos.rib,startsec-1,NULL,str)<0){ ret=-1; goto filesetattr3_exit; } /* RIB not modified! */ } if (ribmod){ /* write updated RIB */ if (WRITEBLOCK_CURPART(fdessec,&fdes.qdos.rib,1)<0){ err_print("filesetattr3: cannot write RIB\n"); ret=-1; goto filesetattr3_exit; } } }else if (curpart->type==PARTTYPE_OS9MDR){ if (!curpart->mdr){ /* OS9 */ /* XXX check owner and permission for permission to modify file!!! */ /* XXX allow "." and ".." */ if (str!=NULL){ /* set/clear attributes */ if (setattr(&fdes.os9,str)<0){ ret=-1; goto filesetattr3_exit; } } if (own>=0){ fdes.os9.fd_own[1]=(u_char)own; fdes.os9.fd_own[0]=((u_int)own)>>8; } /* write file descriptor */ if (WRITEBLOCK_CURPART(fdessec,&fdes.os9,1)<0){ err_print("filesetattr3: cannot write file descriptor\n"); ret=-1; goto filesetattr3_exit; } }else{ /* MDR-DOS */ if (str==NULL){ ret=-1; goto filesetattr3_exit; } if (strlen(str)!=4){ err_print("filesetattr3: invalid type string size\n"); ret=-1; goto filesetattr3_exit; } /* set MDR-DOS type */ bcopy(str,&fdes.mdrdos.type[0],4); /* write updated directory entry */ if (WRITEBLOCK_CURPART(fdessec,&fdes.mdrdos,MDR_DIRENTRYSIZE)<0){ err_print("filesetattr3: cannot write updated directory entry\n"); ret=-1; goto filesetattr3_exit; } } }else{ err_print("filesetattr3: invalid partition type\n"); ret=-1; } filesetattr3_exit: /* restore state */ curpart=savecurpart; return ret; } /* XXX partdefrag */ /* XXX filetrunc */ /* EOF */