X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=cpmfs.c;h=1d4524ed87aed0b5177c65e788cbbd475622df47;hb=4da0ef28bc10c3dfa72b8d2c7e7f8db7a186bcbc;hp=5962a6bffa69dcbc75a7d6f0ba540c3986c63e4d;hpb=d54e661a771b394610329fb0cd5e7b5002ae1708;p=debian%2Fcpmtools diff --git a/cpmfs.c b/cpmfs.c index 5962a6b..1d4524e 100644 --- a/cpmfs.c +++ b/cpmfs.c @@ -324,36 +324,6 @@ static int writeBlock(const struct cpmSuperBlock *d, int blockno, const char *bu /*}}}*/ /* directory management */ -/* readPhysDirectory -- read directory from drive */ /*{{{*/ -static int readPhysDirectory(const struct cpmSuperBlock *drive) -{ - int i,blocks,entry; - - blocks=(drive->maxdir*32+drive->blksiz-1)/drive->blksiz; - entry=0; - for (i=0; idir+entry),0,-1)==-1) return -1; - entry+=(drive->blksiz/32); - } - return 0; -} -/*}}}*/ -/* writePhysDirectory -- write directory to drive */ /*{{{*/ -static int writePhysDirectory(const struct cpmSuperBlock *drive) -{ - int i,blocks,entry; - - blocks=(drive->maxdir*32+drive->blksiz-1)/drive->blksiz; - entry=0; - for (i=0; idir+entry),0,-1)==-1) return -1; - entry+=(drive->blksiz/32); - } - return 0; -} -/*}}}*/ /* findFileExtent -- find first/next extent for a file */ /*{{{*/ static int findFileExtent(const struct cpmSuperBlock *sb, int user, const char *name, const char *ext, int start, int extno) { @@ -396,6 +366,7 @@ static void updateTimeStamps(const struct cpmInode *ino, int extent) unix2cpm_time(ino->mtime,&u_days,&u_hour,&u_min); if ((ino->sb->type==CPMFS_P2DOS || ino->sb->type==CPMFS_DR3) && (date=ino->sb->dir+(extent|3))->status==0x21) { + ino->sb->dirtyDirectory=1; switch (extent&3) { case 0: /* first entry */ /*{{{*/ @@ -473,6 +444,34 @@ static int diskdefReadSuper(struct cpmSuperBlock *d, const char *format) else if (strcmp(argv[0],"blocksize")==0) d->blksiz=strtol(argv[1],(char**)0,0); else if (strcmp(argv[0],"maxdir")==0) d->maxdir=strtol(argv[1],(char**)0,0); else if (strcmp(argv[0],"skew")==0) d->skew=strtol(argv[1],(char**)0,0); + else if (strcmp(argv[0],"skewtab")==0) + { + int pass,sectors; + + for (pass=0; pass<2; ++pass) + { + char *s; + + sectors=0; + for (s=argv[1]; *s; ) + { + int phys; + char *end; + + phys=strtol(s,&end,10); + if (pass==1) d->skewtab[sectors]=phys; + if (end==s) + { + fprintf(stderr,"%s: invalid skewtab `%s' at `%s'\n",cmd,argv[1],s); + exit(1); + } + s=end; + ++sectors; + if (*s==',') ++s; + } + if (pass==0) d->skewtab=malloc(sizeof(int)*sectors); + } + } else if (strcmp(argv[0],"boottrk")==0) d->boottrk=strtol(argv[1],(char**)0,0); else if (strcmp(argv[0],"logicalextents")==0) d->extents=strtol(argv[1],(char**)0,0); else if (strcmp(argv[0],"os")==0) @@ -494,6 +493,7 @@ static int diskdefReadSuper(struct cpmSuperBlock *d, const char *format) d->skew=1; d->extents=0; d->type=CPMFS_DR3; + d->skewtab=(int*)0; if (strcmp(argv[1],format)==0) found=1; } } @@ -551,6 +551,7 @@ static int amsReadSuper(struct cpmSuperBlock *d, const char *format) d->blksiz = 128 << boot_spec[6]; d->maxdir = (d->blksiz / 32) * boot_spec[7]; d->skew = 1; /* Amstrads skew at the controller level */ + d->skewtab = (int*)0; d->boottrk = boot_spec[5]; d->size = (d->secLength*d->sectrk*(d->tracks-d->boottrk))/d->blksiz; d->extents = ((d->size>=256 ? 8 : 16)*d->blksiz)/16384; @@ -666,26 +667,16 @@ int cpmReadSuper(struct cpmSuperBlock *d, struct cpmInode *root, const char *for if (strcmp(format, "amstrad")==0) amsReadSuper(d,format); else diskdefReadSuper(d,format); Device_setGeometry(&d->dev,d->secLength,d->sectrk,d->tracks); - /* generate skew table */ /*{{{*/ - if (( d->skewtab = malloc(d->sectrk*sizeof(int))) == (int*)0) - { - fprintf(stderr,"%s: can not allocate memory for skew sector table\n",cmd); - exit(1); - } - if (strcmp(format,"apple-do")==0) - { - static int skew[]={0,6,12,3,9,15,14,5,11,2,8,7,13,4,10,1}; - memcpy(d->skewtab,skew,d->sectrk*sizeof(int)); - } - else if (strcmp(format,"apple-po")==0) - { - static int skew[]={0,9,3,12,6,15,1,10,4,13,7,8,2,11,5,14}; - memcpy(d->skewtab,skew,d->sectrk*sizeof(int)); - } - else + if (d->skewtab==(int*)0) /* generate skew table */ /*{{{*/ { int i,j,k; + if (( d->skewtab = malloc(d->sectrk*sizeof(int))) == (int*)0) + { + fprintf(stderr,"%s: can not allocate memory for skew sector table\n",cmd); + exit(1); + } + memset(d->skewtab,0,d->sectrk*sizeof(int)); for (i=j=0; isectrk; ++i,j=(j+d->skew)%d->sectrk) { while (1) @@ -715,8 +706,24 @@ int cpmReadSuper(struct cpmSuperBlock *d, struct cpmInode *root, const char *for return -1; } /*}}}*/ - if (d->dev.opened==0) memset(d->dir,0xe5,d->maxdir*32); - else if (readPhysDirectory(d)==-1) return -1; + if (d->dev.opened==0) /* create empty directory in core */ /*{{{*/ + { + memset(d->dir,0xe5,d->maxdir*32); + } + /*}}}*/ + else /* read directory in core */ /*{{{*/ + { + int i,blocks,entry; + + blocks=(d->maxdir*32+d->blksiz-1)/d->blksiz; + entry=0; + for (i=0; idir+entry),0,-1)==-1) return -1; + entry+=(d->blksiz/32); + } + } + /*}}}*/ alvInit(d); if (d->type==CPMFS_DR3) /* read additional superblock information */ /*{{{*/ { @@ -922,7 +929,7 @@ int cpmNamei(const struct cpmInode *dir, const char *filename, struct cpmInode * u_days=((unsigned char)date->name[4])+(((unsigned char)date->name[5])<<8); u_hour=(unsigned char)date->name[6]; u_min=(unsigned char)date->name[7]; - protectMode=(unsigned char)date->name[8]; + protectMode=(unsigned char)date->ext[0]; break; } /*}}}*/ @@ -1044,12 +1051,12 @@ int cpmUnlink(const struct cpmInode *dir, const char *fname) drive=dir->sb; if (splitFilename(fname,dir->sb->type,name,extension,&user)==-1) return -1; if ((extent=findFileExtent(drive,user,name,extension,0,-1))==-1) return -1; + drive->dirtyDirectory=1; drive->dir[extent].status=(char)0xe5; do { drive->dir[extent].status=(char)0xe5; } while ((extent=findFileExtent(drive,user,name,extension,extent+1,-1))>=0); - if (writePhysDirectory(drive)==-1) return -1; alvInit(drive); return 0; } @@ -1080,11 +1087,11 @@ int cpmRename(const struct cpmInode *dir, const char *old, const char *new) } do { + drive->dirtyDirectory=1; drive->dir[extent].status=newuser; memcpy7(drive->dir[extent].name, newname, 8); memcpy7(drive->dir[extent].ext, newext, 3); } while ((extent=findFileExtent(drive,olduser,oldname,oldext,extent+1,-1))!=-1); - if (writePhysDirectory(drive)==-1) return -1; return 0; } /*}}}*/ @@ -1193,7 +1200,8 @@ int cpmReaddir(struct cpmFile *dir, struct cpmDirent *ent) } *bufp='\0'; /*}}}*/ - ent->reclen=strlen(buf); + assert(bufp<=buf+sizeof(buf)); + ent->reclen=bufp-buf; strcpy(ent->name,buf); ent->off=dir->pos; ++dir->pos; @@ -1381,6 +1389,7 @@ int cpmWrite(struct cpmFile *file, const char *buf, int count) } /*}}}*/ /* fill block and write it */ /*{{{*/ + file->ino->sb->dirtyDirectory=1; while (file->pos!=nextblockpos && count) { buffer[file->pos%blocksize]=*buf++; @@ -1415,14 +1424,12 @@ int cpmWrite(struct cpmFile *file, const char *buf, int count) if (file->pos==nextextpos) findext=1; else if (file->pos==nextblockpos) findblock=1; } - writePhysDirectory(file->ino->sb); return got; } /*}}}*/ /* cpmClose -- close */ /*{{{*/ int cpmClose(struct cpmFile *file) { - if (file->mode&O_WRONLY) return (writePhysDirectory(file->ino->sb)); return 0; } /*}}}*/ @@ -1448,6 +1455,7 @@ int cpmCreat(struct cpmInode *dir, const char *fname, struct cpmInode *ino, mode drive=dir->sb; if ((extent=findFreeExtent(dir->sb))==-1) return -1; ent=dir->sb->dir+extent; + drive->dirtyDirectory=1; memset(ent,0,32); ent->status=user; memcpy(ent->name,name,8); @@ -1460,15 +1468,14 @@ int cpmCreat(struct cpmInode *dir, const char *fname, struct cpmInode *ino, mode time(&ino->ctime); ino->sb=dir->sb; updateTimeStamps(ino,extent); - writePhysDirectory(dir->sb); return 0; } /*}}}*/ /* cpmAttrGet -- get CP/M attributes */ /*{{{*/ int cpmAttrGet(struct cpmInode *ino, cpm_attr_t *attrib) { - *attrib = ino->attr; - return 0; + *attrib = ino->attr; + return 0; } /*}}}*/ /* cpmAttrSet -- set CP/M attributes */ /*{{{*/ @@ -1484,6 +1491,7 @@ int cpmAttrSet(struct cpmInode *ino, cpm_attr_t attrib) drive = ino->sb; extent = ino->ino; + drive->dirtyDirectory=1; /* Strip off existing attribute bits */ memcpy7(name, drive->dir[extent].name, 8); memcpy7(extension, drive->dir[extent].ext, 3); @@ -1503,7 +1511,6 @@ int cpmAttrSet(struct cpmInode *ino, cpm_attr_t attrib) memcpy(drive->dir[extent].name, name, 8); memcpy(drive->dir[extent].ext, extension, 3); } while ((extent=findFileExtent(drive, user,name,extension,extent+1,-1))!=-1); - if (writePhysDirectory(drive)==-1) return -1; /* Update the stored (inode) copies of the file attributes and mode */ ino->attr=attrib; @@ -1524,14 +1531,28 @@ int cpmChmod(struct cpmInode *ino, mode_t mode) } /*}}}*/ /* cpmSync -- write directory back */ /*{{{*/ -int cpmSync(struct cpmSuperBlock *sb) +int cpmSync(struct cpmSuperBlock *d) { - return (writePhysDirectory(sb)); + if (d->dirtyDirectory) + { + int i,blocks,entry; + + blocks=(d->maxdir*32+d->blksiz-1)/d->blksiz; + entry=0; + for (i=0; idir+entry),0,-1)==-1) return -1; + entry+=(d->blksiz/32); + } + d->dirtyDirectory=0; + } + return 0; } /*}}}*/ /* cpmUmount -- free super block */ /*{{{*/ void cpmUmount(struct cpmSuperBlock *sb) { + cpmSync(sb); free(sb->alv); free(sb->skewtab); free(sb->dir);