diff options
author | cc4b05f61e2d8f77114750386c9f9a60 <cc4b05f61e2d8f7@7114750386c9f9a60> | 2023-05-12 08:39:37 +0000 |
---|---|---|
committer | cc4b05f61e2d8f77114750386c9f9a60 <cc4b05f61e2d8f7@7114750386c9f9a60> | 2023-07-19 21:05:39 +0000 |
commit | 177f9cba3e9813cf82ea764799a12128f65572cf (patch) | |
tree | 553e4086a588d18f0e27d5d607a34d5b9bcd0e04 /src/utils | |
parent | 5ad2bb7a6ac7e97c031908d2439808a00fff6214 (diff) | |
download | dmsdosnow-177f9cba3e9813cf82ea764799a12128f65572cf.tar.gz |
Build mcdmsdos
Diffstat (limited to 'src/utils')
-rw-r--r-- | src/utils/Makefile | 22 | ||||
-rw-r--r-- | src/utils/mcdmsdos.c | 409 |
2 files changed, 431 insertions, 0 deletions
diff --git a/src/utils/Makefile b/src/utils/Makefile new file mode 100644 index 0000000..89d3d1b --- /dev/null +++ b/src/utils/Makefile @@ -0,0 +1,22 @@ +CFLAGS := -c -Wall -D__DMSDOS_LIB__ +LDFLAGS := +SOURCES := mcdmsdos.c +BUILD_DIR := ./build +MAINSRC := mcdmsdos.c +LIBSRC := $(shell find ./lib/ -name '*.c') +SRC := $(MAINSRC) $(LIBSRC) +OBJS := $(SRC:%=$(BUILD_DIR)/%.o) + +EXECUTABLE := mcdmsdosnext + +all: $(SOURCES) $(EXECUTABLE) + +$(EXECUTABLE): $(OBJS) + $(CC) $(LDFLAGS) $(OBJS) -o $(BUILD_DIR)/$@ + +$(BUILD_DIR)/%.c.o: %.c + mkdir -p $(dir $@) + $(CC) $(CFLAGS) -c $< -o $@ + +clean: + rm -r $(BUILD_DIR) diff --git a/src/utils/mcdmsdos.c b/src/utils/mcdmsdos.c new file mode 100644 index 0000000..b2cb5d6 --- /dev/null +++ b/src/utils/mcdmsdos.c @@ -0,0 +1,409 @@ +/* + +mcdmsdos.c + +DMSDOS: external filesystem interface for Midnight Commander + +****************************************************************************** +DMSDOS (compressed MSDOS filesystem support) for Linux +written 1995-1998 by Frank Gockel and Pavel Pisa + + (C) Copyright 1995-1998 by Frank Gockel + (C) Copyright 1996-1998 by Pavel Pisa + +Some code of dmsdos has been copied from the msdos filesystem +so there are the following additional copyrights: + + (C) Copyright 1992,1993 by Werner Almesberger (msdos filesystem) + (C) Copyright 1994,1995 by Jacques Gelinas (mmap code) + (C) Copyright 1992-1995 by Linus Torvalds + +DMSDOS was inspired by the THS filesystem (a simple doublespace +DS-0-2 compressed read-only filesystem) written 1994 by Thomas Scheuermann. + +The DMSDOS code is distributed under the Gnu General Public Licence. +See file COPYING for details. +****************************************************************************** + +*/ + +#include<stdio.h> +#include<stdlib.h> +#include<string.h> +#include<ctype.h> + +#include"lib/dmsdos.h" +#include"lib/lib_interface.h" + +#define M_LIST 1 +#define M_OUT 2 +#define M_IN 3 + +/*this is not good - but currently we have only one CVF open at a time*/ +struct super_block*sb; +Dblsb*dblsb; + +int scan(char*text) +{ int v=0; + if(strncmp(text,"0x",2)==0||strncmp(text,"0X",2)==0) + sscanf(text+2,"%x",&v); + else + sscanf(text,"%d",&v); + return v; +} + +unsigned char* get_root_dir(void) +{ unsigned char* data; + struct buffer_head*bh; + int i; + + data=malloc(dblsb->s_rootdirentries*32); + if(data==NULL)return NULL; + + for(i=0;i<dblsb->s_rootdirentries*32/512;++i) + { bh=raw_bread(sb,dblsb->s_rootdir+i); + if(bh==NULL){free(data);return NULL;} + memcpy(data+i*512,bh->b_data,512); + raw_brelse(sb,bh); + } + return data; +} + +int copy_cluster_out(int nr, int len, FILE*f) +{ unsigned char*data; + int i,j; + + if(nr==0) + { data=get_root_dir(); + if(data==NULL)return -1; + i=dblsb->s_rootdirentries*32; + } + else + { data=malloc(dblsb->s_sectperclust*512); + if(data==NULL)return -1; + i=dmsdos_read_cluster(sb,data,nr); + if(i<0){free(data);return -1;} + } + if(len<=0||len>i)len=i; + + for(j=0;j<len;++j)fputc(data[j],f); + + free(data); + return ferror(f); +} + +int handle_dir_chain(int start,int rek,char*prefix); + +int display_dir_cluster(int nr, int rek, char*prefix) +{ unsigned char*data; + int i,j; + + /*printf("display_dir_cluster called with nr=%d rek=%d prefix=%s\n", + nr,rek,prefix);*/ + + if(nr==0) + { data=get_root_dir(); + if(data==NULL)return -1; + i=dblsb->s_rootdirentries*32; + } + else + { data=malloc(dblsb->s_sectperclust*512); + if(data==NULL)return -1; + i=dmsdos_read_cluster(sb,data,nr); + if(i<0){free(data);return -1;} + } + + for(j=0;j<dblsb->s_sectperclust*512;j+=32) + { unsigned char*pp; + unsigned int x; + char filename[15]=""; + int nstart; + long size; + char datestr[16][4]={"?00","Jan","Feb","Mar","Apr","May","Jun", + "Jul","Aug","Sep","Oct","Nov","Dec", + "?13","?14","?15"}; + if(data[j]==0)break; + if(data[j]==0xe5)continue; + if(data[j+11]&8)continue; + if(data[j]=='.')continue; + + for(i=0;i<11;++i) + { if(i==8&&data[j+i]!=' ')strcat(filename,"."); + if(data[j+i]!=' ')strncat(filename,&(data[j+i]),1); + } + for(i=0;i<strlen(filename);++i)filename[i]=tolower(filename[i]); + + if(data[j+11]&16)printf("dr");else printf("-r"); + if(data[j+11]&1)printf("-");else printf("w"); + printf("xr-xr-x 1 0 0"); /* bogus values :) */ + + /* + printf(" "); + if(data[j+11]&1)printf("R");else printf(" "); + if(data[j+11]&2)printf("H");else printf(" "); + if(data[j+11]&4)printf("S");else printf(" "); + if(data[j+11]&8)printf("V");else printf(" "); + if(data[j+11]&16)printf("D");else printf(" "); + if(data[j+11]&32)printf("A");else printf(" "); + if(data[j+11]&64)printf("?");else printf(" "); + if(data[j+11]&128)printf("?");else printf(" "); + */ + + pp=&(data[j+28]); + size=CHL(pp); + printf(" %7lu",size); + + pp=&(data[j+24]); + x=CHS(pp); + /*printf(" %02d.%02d.%02d",x&31,(x>>5)&15,(x>>9)+80);*/ + printf(" %s",datestr[(x>>5)&15]); + printf(" %02d",x&31); + printf(" %04d",(x>>9)+1980); /* y2k compliant :) */ + + pp=&(data[j+22]); + x=CHS(pp); + /*printf(" %02d:%02d:%02d",x>>11,(x>>5)&63,(x&31)<<1);*/ + printf(" %02d:%02d",x>>11,(x>>5)&63); + + pp=&(data[j+26]); + nstart=CHS(pp); + /*printf(" %5d",nstart);*/ + + printf(" %s%s\n",prefix,filename); + + if((data[j+11]&16)!=0&&rek!=0&&filename[0]!='.') + { char *nprefix; + nprefix=malloc(strlen(prefix)+20); + if(nprefix==NULL) + { fprintf(stderr,"out of memory\n"); + exit(3); + } + strcpy(nprefix,prefix); + strcat(nprefix,filename); + strcat(nprefix,"/"); + handle_dir_chain(nstart,rek,nprefix); + free(nprefix); + } + + } + + free(data); + return 0; +} + +int handle_dir_chain(int start,int rek,char*prefix) +{ int i,next; + + if(start==0)return display_dir_cluster(0,rek,prefix); + if(start==1||start<0||start>dblsb->s_max_cluster)return -1; + + do + { + next=dbl_fat_nextcluster(sb,start,NULL); + i=display_dir_cluster(start,rek,prefix); + if(i<0)return i; + start=next; + } + while(next>1&&next<=dblsb->s_max_cluster); + + if(next>=0) + { return -1; + } + + return 0; +} + +int handle_file_chain(int start, int len, FILE*f) +{ int i,next; + + if(start==0)return -1; /* never a file :) */ + if(start==1||start<0||start>dblsb->s_max_cluster)return -1; + + do + { + next=dbl_fat_nextcluster(sb,start,NULL); + i=copy_cluster_out(start,len,f); + if(i<0)return i; + len-=dblsb->s_sectperclust*512; + if(len<=0)break; + start=next; + } + while(next>1&&next<=dblsb->s_max_cluster); + + if(next>=0) + { return -1; + } + + return 0; +} + +int scan_dir(char*entry,int start,int*len) +{ char buf[]=" "; + /*12345678EXT*/ + int i; + int size; + unsigned char*data; + int next; + + if(strcmp(entry,".")==0)return start; + else if(strcmp(entry,"..")==0)strncpy(buf,"..",2); + else if(*entry=='.') return -1; + else + for(i=0;i<11;++i) + { if(*entry=='.'&&i<=7){i=7;++entry;continue;} + if(*entry=='.'&&i==8){i=7;++entry;continue;} + if(*entry=='.')break; + if(*entry=='\0')break; + buf[i]=toupper(*entry); + ++entry; + } + + do + { + /*printf("scan_dir: searching for %s in %d\n",buf,start);*/ + + if(start==0) + { data=get_root_dir(); + size=dblsb->s_rootdirentries; + next=-1; + } + else + { data=malloc(dblsb->s_sectperclust*512); + if(data!=NULL) + { i=dmsdos_read_cluster(sb,data,start); + if(i<0){free(data);data=NULL;} + size=i/32; + next=dbl_fat_nextcluster(sb,start,NULL); + if(next==0) + fprintf(stderr,"warning: cluster %d is marked as unused in FAT\n", + next); + } + } + if(data==NULL)return -1; + + for(i=0;i<size;++i) + { if(strncmp(&(data[i*32]),buf,11)==0) + { unsigned char*pp; + int cluster; + + pp=&(data[i*32+26]); + cluster=CHS(pp); + pp=&(data[i*32+28]); + if(len)*len=CHL(pp); + free(data); + return cluster; + } + } + + free(data); + start=next; + } + while(next>0&&next<=dblsb->s_max_cluster); + return -1; +} + +int scan_path(char*path,int start, int*len) +{ int i; + char*p; + + for(p=strtok(path,"/");p;p=strtok(NULL,"/")) + { i=scan_dir(p,start,len); + if(i<0) + { fprintf(stderr,"path component %s not found\n",p); + return -1; + } + start=i; + } + + return start; +} + +int main(int argc, char*argv[]) +{ int mode=0; + int cluster; + int i; + char*p; + int len; + FILE*f; + + fprintf(stderr,"mcdmsdos version 0.2.0 (for libdmsdos 0.9.x and newer)\n"); + if(argc<2) + { fprintf(stderr,"\nusage: mcdmsdos <mc-extfs-command> ...\n"); + fprintf(stderr,"where <mc-extfs-command> can be:\n"); + fprintf(stderr," list <CVF>\n"); + fprintf(stderr," copyout <CVF> <path/name_in_CVF> <outfile>\n"); + fprintf(stderr," copyin <CVF> <path/name_in_CVF> <infile> [*]\n"); + fprintf(stderr," [*] currently not implemented\n"); + return 1; + } + + /* check syntax */ + if(strcmp(argv[1],"list")==0) + { mode=M_LIST; + if(argc!=3) + { fprintf(stderr,"wrong number of arguments\n"); + return 1; + } + } + else if(strcmp(argv[1],"copyout")==0) + { mode=M_OUT; + if(argc!=5) + { fprintf(stderr,"wrong number of arguments\n"); + return 1; + } + } + else if(strcmp(argv[1],"copyin")==0) + { mode=M_IN; + if(argc!=5) + { fprintf(stderr,"wrong number of arguments\n"); + return 1; + } + fprintf(stderr,"copyin command is not implemented\n"); + return -2; + } + else + { fprintf(stderr,"unknown command\n"); + return -1; + } + + sb=open_cvf(argv[2],0/*read-only*/); + if(sb==NULL) + { printf("open CVF %s failed\n",argv[1]); + return 2; + } + dblsb=MSDOS_SB(sb)->private_data; + + + if(mode==M_LIST) + { i=handle_dir_chain(0,1,""); + } + + else if(mode==M_OUT) + { p=malloc(strlen(argv[3])+1); + strcpy(p,argv[3]); +#ifdef _WIN32 + /* convert to Unix style path */ + for(i=0;i<strlen(p);++i){if(p[i]=='\\')p[i]='/';} +#endif + if(*p=='/')++p; + cluster=scan_path(p,0,&len); + if(cluster<0) + { fprintf(stderr,"%s not found\n",argv[3]); + return 1; + } + + f=fopen(argv[4],"wb"); + if(f==NULL) + { perror("open write failed"); + i=-1; + } + else + { i=handle_file_chain(cluster,len,f); + fclose(f); + } + } + + close_cvf(sb); + + return i; +} |