os9@cbdkc1.UUCP (05/25/87)
OS-9 Discussions Monday, May 25th 1987 Volume 3 : Issue 5 Today's Topics: OS/9 68K "arc" - 1 of 3 -------------------------------------------------------------------------- Date: Sun, 24 May 87 18:43:06 EDT From: mnetor!lsuc!jimomura Subject: OS/9 68K "arc" - 1 of 3 87/05/24 This is Dieter Stoll's port of ARC from the MS-DOS version to OS-9 68K. It is posted to Usenet with the permission of Systems Enhancements Associates. If you wish to port ARC to another system or wish to re-distribute ARC, you should contact them for approval. I have found them to be quite reasonable. Cheers! -- Jim O. [Moderator's note: I have repackaged the code into 3 shar files to keep it within the limits of smaller Usenet machines. I have not yet tested the code on my machine. - JDD ] # This is a shell archive. Remove anything before this line, then # unpack it by saving it in a file and typing "sh file". (Files # unpacked will be owned by you and have default permissions.) # # This archive contains: # README makefile arc.h arcs.h arcadd.c arccode.c arccvt.c arcdel.c arcdir.c arcdos.c arcext.c arcio.c echo x - README cat > "README" << '//E*O*F README//' 87/05/24 This is Dieter Stoll's port of ARC from the MS-DOS version to OS-9 68K. It is posted to Usenet with the permission of Systems Enhancements Associates. If you wish to port ARC to another system or wish to re-distribute ARC, you should contact them for approval. I have found them to be quite reasonable. Cheers! -- Jim O. //E*O*F README// echo x - makefile cat > "makefile" << '//E*O*F makefile//' * CFLAGS = -ixt=/r0 HEADERS = arc.h arcs.h RDIR = rels * arc: arcmain.r arcadd.r arccode.r arccvt.r arcdel.r arcdir.r arcdos.r \ arcext.r arcio.r arclst.r arclzw.r arcmatch.r arcpack.r arcsq.r \ arcsvc.r arctst.r arcunp.r arcusq.r system.r chd $(RDIR); cc -f=arc -t=/r0 arcmain.r arcadd.r arccode.r arccvt.r arcdel.r \ arcdir.r arcdos.r arcext.r arcio.r arclst.r arclzw.r arcmatch.r \ arcpack.r arcsq.r arcsvc.r arctst.r arcunp.r arcusq.r system.r * arcmain.r: arcmain.c $(HEADERS) arcadd.r: arcadd.c $(HEADERS) arccode.r: arccode.c $(HEADERS) arccvt.r: arccvt.c $(HEADERS) arcdel.r: arcdel.c $(HEADERS) arcdir.r: arcdir.c $(HEADERS) arcdos.r: arcdos.c $(HEADERS) arcext.r: arcext.c $(HEADERS) arcio.r: arcio.c $(HEADERS) arclst.r: arclst.c $(HEADERS) arclzw.r: arclzw.c $(HEADERS) arcmatch.r: arcmatch.c $(HEADERS) arcpack.r: arcpack.c $(HEADERS) arcsq.r: arcsq.c $(HEADERS) arcsvc.r: arcsvc.c $(HEADERS) arctst.r: arctst.c $(HEADERS) arcunp.r: arcunp.c $(HEADERS) arcusq.r: arcusq.c $(HEADERS) system.r: system.c //E*O*F makefile// echo x - arc.h cat > "arc.h" << '//E*O*F arc.h//' /* ARC - Archive utility - ARC Header Version 2.14, created on 02/03/86 at 22:48:29 (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED By: Thom Henderson Description: This is the header file for the ARC archive utility. It defines global parameters and the references to the external data. Language: Computer Innovations Optimizing C86 */ #include "arcs.h" #ifndef fputc #define fputc(a,b) putc(a,b) #endif #define ARCMARK 26 /* special archive marker */ #define ARCVER 8 /* archive header version code */ #define STRLEN 100 /* system standard string length */ #define FNLEN 20 /* file name length */ #define MAXARG 25 /* maximum number of arguments */ #define READBIN "r" #define WRITEBIN "w" #define RWBIN "w+" #ifdef OSK EXTERN int ZivLempel; #endif EXTERN int keepbak; /* true if saving the old archive */ EXTERN int warn; /* true to print warnings */ EXTERN int note; /* true to print comments */ EXTERN int bose; /* true to be verbose */ EXTERN int nocomp; /* true to suppress compression */ EXTERN int kludge; /* kludge flag */ EXTERN char *arctemp; /* arc temp file prefix */ EXTERN char *password; /* encryption password pointer */ EXTERN int nerrs; /* number of errors encountered */ EXTERN char hdrver; /* header version */ EXTERN FILE *arc; /* the old archive */ EXTERN FILE *new; /* the new archive */ EXTERN char arcname[STRLEN]; /* storage for archive name */ EXTERN char bakname[STRLEN]; /* storage for backup copy name */ EXTERN char newname[STRLEN]; /* storage for new archive name */ EXTERN unsigned int arcdate; /* archive date stamp */ EXTERN unsigned int arctime; /* archive time stamp */ /* * entry points for the memory functions */ extern int rename(); /* change the name of a file */ extern char *setmem(); /* set a block of memory to a given value */ //E*O*F arc.h// echo x - arcs.h cat > "arcs.h" << '//E*O*F arcs.h//' /* ARC - Archive utility - Archive file header format Version 2.12, created on 12/17/85 at 14:40:26 (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED By: Thom Henderson Description: This file defines the format of an archive file header, excluding the archive marker and the header version number. Each entry in an archive begins with a one byte archive marker, which is set to 26. The marker is followed by a one byte header type code, from zero to 7. If the header type code is zero, then it is an end marker, and no more data should be read from the archive. If the header type code is in the range 2 to 7, then it is followed by a standard archive header, which is defined below. If the header type code is one, then it is followed by an older format archive header. The older format header does not contain the true length. A header should be read for a length of sizeof(struct heads)-sizeof(long). Then set length equal to size and change the header version to 2. Programming note: The crc value given in the header is based on the unpacked data. Language: Computer Innovations Optimizing C86 */ struct heads /* archive entry header format */ { char name[13]; /* file name */ long size; /* size of file, in bytes */ unsigned short date; /* creation date */ unsigned short time; /* creation time */ short crc; /* cyclic redundancy check */ long length; /* true file length */ } ; //E*O*F arcs.h// echo x - arcadd.c cat > "arcadd.c" << '//E*O*F arcadd.c//' /* ARC - Archive utility - ARCADD $define(tag,$$segment(@1,$$index(@1,=)+1))# $define(version,Version $tag( TED_VERSION DB =3.39), created on $tag( TED_DATE DB =02/05/86) at $tag( TED_TIME DB =22:21:53))# $undefine(tag)# $version (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED By: Thom Henderson Description: This file contains the routines used to add files to an archive. Language: Computer Innovations Optimizing C86 * * changed abort(...) to exit (_errmsg, (1,...)) */ #include <stdio.h> #define EXTERN extern #include "arc.h" addarc(num,arg,move,update,fresh) /* add files to archive */ int num; /* number of arguments */ char *arg[]; /* pointers to arguments */ int move; /* true if moving file */ int update; /* true if updating */ int fresh; /* true if freshening */ { char *d, *dir(); /* directory junk */ char buf[STRLEN]; /* pathname buffer */ char **path = NULL; /* pointer to pointers to paths */ char **name = NULL; /* pointer to pointers to names */ int nfiles = 0; /* number of files in lists */ int notemp; /* true until a template works */ int nowork = 1; /* true until files are added */ char *i, *rindex(); /* string indexing junk */ char *malloc(), *realloc(); /* memory allocators */ int m, n; /* indices */ unsigned int coreleft(); /* remaining memory reporter */ #ifdef DEBUG puts ("addarc"); printf ("num: %d arg[0]: %s move:%d update:%d fresh:%d\n", num, arg[0], move, update, fresh); #endif if(num<1) /* if no files named */ { num = 1; /* then fake one */ arg[0] = "*.*"; /* add everything */ } for(n=0; n<num; n++) /* for each template supplied */ { strcpy(buf,arg[n]); /* get ready to fix path */ if(!(i=rindex(buf,'\\'))) if(!(i=rindex(buf,'/'))) if(!(i=rindex(buf,':'))) i = buf-1; i++; /* pointer to where name goes */ notemp = 1; /* reset files flag */ for(d=dir(arg[n],0); *d; d=dir(NULL,0)) { notemp = 0; /* template is giving results */ nfiles++; /* add each matching file */ path = (char **)realloc(path,nfiles*sizeof(char **)); name = (char **)realloc(name,nfiles*sizeof(char **)); strcpy(i,d); /* put name in path */ path[nfiles-1] = malloc(strlen(buf)+1); strcpy(path[nfiles-1],buf); name[nfiles-1] = d; /* save name */ if(coreleft()<5120) { nfiles = addbunch(nfiles,path,name,move,update,fresh); nowork = nowork && !nfiles; while(nfiles) { free(path[--nfiles]); free(name[nfiles]); } free(path); free(name); path = name = NULL; } } if(notemp && warn) printf("No files match: %s\n",arg[n]); } if(nfiles) { nfiles = addbunch(nfiles,path,name,move,update,fresh); nowork = nowork && !nfiles; while(nfiles) { free(path[--nfiles]); free(name[nfiles]); } free(path); free(name); } if(nowork && warn) printf("No files were added.\n"); } int addbunch(nfiles,path,name,move,update,fresh) /* add a bunch of files */ int nfiles; /* number of files to add */ char **path; /* pointers to pathnames */ char **name; /* pointers to filenames */ int move; /* true if moving file */ int update; /* true if updating */ int fresh; /* true if freshening */ { char buf[STRLEN]; /* pathname buffer */ int m, n; /* indices */ char *d; /* swap pointer */ struct heads hdr; /* file header data storage */ #ifdef DEBUG puts ("addbunch"); printf ("nfiles:%d path[0]:%s name[0]:%s move:%d update:%d fresh:%d\n", nfiles, path[0], name[0], move, update, fresh); #endif for(n=0; n<nfiles-1; n++) /* sort the list of names */ { for(m=n+1; m<nfiles; m++) { if(strcmp(name[n],name[m])>0) { d = path[n]; path[n] = path[m]; path[m] = d; d = name[n]; name[n] = name[m]; name[m] = d; } } } for(n=0; n<nfiles-1; ) /* consolidate the list of names */ { if(!strcmp(path[n],path[n+1]) /* if duplicate names */ || !strcmp(path[n],arcname) /* or this archive */ || !strcmp(path[n],newname) /* or the new version */ || !strcmp(path[n],bakname)) /* or its backup */ { free(path[n]); /* then forget the file */ free(name[n]); for(m=n; m<nfiles-1; m++) { path[m] = path[m+1]; name[m] = name[m+1]; } nfiles--; } else n++; /* else test the next one */ } if(!strcmp(path[n],arcname) /* special check for last file */ || !strcmp(path[n],newname) /* courtesy of Rick Moore */ || !strcmp(path[n],bakname)) { free(path[n]); free(name[n]); nfiles--; } if(!nfiles) /* make sure we got some */ return 0; for(n=0; n<nfiles-1; n++) /* watch out for duplicate names */ if(!strcmp(name[n],name[n+1])) exit (_errmsg(1, "Duplicate filenames:\n %s\n %s",path[n],path[n+1])); openarc(1); /* open archive for changes */ for(n=0; n<nfiles; n++) /* add each file in the list */ addfile(path[n],name[n],update,fresh); /* now we must copy over all files that follow our additions */ while(readhdr(&hdr,arc)) /* while more entries to copy */ { #ifdef DEBUG printf("readhdr found something to copy\n"); #endif writehdr(&hdr,new); filecopy(arc,new,hdr.size); } hdrver = 0; /* archive EOF type */ #ifdef DEBUG printf ("writing zero header\n"); #endif writehdr(&hdr,new); /* write out our end marker */ closearc(1); /* close archive after changes */ if(move) /* if this was a move */ { for(n=0; n<nfiles; n++) /* then delete each file added */ { if(unlink(path[n]) && warn) { printf("Cannot unsave %s\n",path[n]); nerrs++; } } } return nfiles; /* say how many were added */ } static addfile(path,name,update,fresh) /* add named file to archive */ char *path; /* path name of file to add */ char *name; /* name of file to add */ int update; /* true if updating */ int fresh; /* true if freshening */ { struct heads nhdr; /* data regarding the new file */ struct heads ohdr; /* data regarding an old file */ FILE *f, *fopen(); /* file to add, opener */ long starts, ftell(); /* file locations */ int c; /* one char of file */ int upd = 0; /* true if replacing an entry */ int i; #ifdef OSK int tempsize; #endif #ifdef DEBUG puts ("addfile"); printf ("path:%s name:%s update:%d fresh:%d\n",path,name,update,fresh); #endif if(!(f=fopen(path,READBIN))) { if(warn) { printf("Cannot read file: %s\n",path); nerrs++; } return; } /* * for non-MSDOSes, check here if the name is the correct size!! */ if (strlen(name) > 12) exit (_errmsg (1,"File %s: name too long\n",name)); strcpy(nhdr.name,name); /* save name */ nhdr.size = 0; /* clear out size storage */ nhdr.crc = 0; /* clear out CRC check storage */ getstamp(f,&nhdr.date,&nhdr.time); /* position archive to spot for new file */ if(arc) /* if adding to existing archive */ { starts = ftell(arc); /* where are we? */ while(readhdr(&ohdr,arc)) /* while more files to check */ { if(!strcmp(ohdr.name,nhdr.name)) { upd = 1; /* replace existing entry */ if(update || fresh) /* if updating or freshening */ { if(nhdr.date<ohdr.date || (nhdr.date==ohdr.date && nhdr.time<=ohdr.time)) { fseek(arc,starts,0); fclose(f); return; /* skip if not newer */ } } } if(strcmp(ohdr.name,nhdr.name)>=0) break; /* found our spot */ writehdr(&ohdr,new); /* entry preceeds update; keep it */ filecopy(arc,new,ohdr.size); starts = ftell(arc); /* now where are we? */ } if(upd) /* if an update */ { if(note) printf("Updating file: %-12s ",name); fflush (stdout); fseek(arc,ohdr.size,1); } else if(fresh) /* else if freshening */ { fseek(arc,starts,0); /* then do not add files */ fclose(f); return; } else /* else adding a new file */ { if(note) printf("Adding file: %-12s ",name); fflush (stdout); fseek(arc,starts,0); /* reset for next time */ } } else /* no existing archive */ { if(fresh) /* cannot freshen nothing */ { fclose(f); return; } else if(note) /* else adding a file */ printf("Adding file: %-12s ",name); fflush (stdout); } starts = ftell(new); /* note where header goes */ hdrver = ARCVER; /* anything but end marker */ #ifdef DEBUG puts ("addfile before writehdr"); #endif writehdr(&nhdr,new); /* write out header skeleton */ #ifdef DEBUG puts ("addfile before pack"); #endif pack(f,new,&nhdr); /* pack file into archive */ #ifdef DEBUG puts ("addfile before fseek"); #endif fseek(new,starts,0); /* move back to header skeleton */ #ifdef OSK /* * get time stamp again because it may have been destroyed in pack()! */ getstamp(f,&nhdr.date,&nhdr.time); #endif #ifdef OSK /* * save hdr.size because nhdr will be garbled by writehdr() call! */ tempsize = nhdr.size; #endif writehdr(&nhdr,new); /* write out real header */ #ifdef OSK fseek (new, tempsize, 1); #else fseek(new,nhdr.size,1); /* skip over data to next header */ #endif fclose(f); /* all done with the file */ #ifdef DEBUG puts ("addfile returning"); #endif } unsigned int coreleft() { return (unsigned int)freemem(); } //E*O*F arcadd.c// echo x - arccode.c cat > "arccode.c" << '//E*O*F arccode.c//' /* ARC - Archive utility - ARCCODE $define(tag,$$segment(@1,$$index(@1,=)+1))# $define(version,Version $tag( TED_VERSION DB =1.02), created on $tag( TED_DATE DB =01/20/86) at $tag( TED_TIME DB =13:33:35))# $undefine(tag)# $version (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED By: Thom Henderson Description: This file contains the routines used to encrypt and decrypt data in an archive. The encryption method is nothing fancy, being just a routine XOR, but it is used on the packed data, and uses a variable length key. The end result is something that is in theory crackable, but I'd hate to try it. It should be more than sufficient for casual use. Language: Computer Innovations Optimizing C86 */ #include <stdio.h> #define EXTERN extern #include "arc.h" static char *p; /* password pointer */ setcode() /* get set for encoding/decoding */ { p = password; /* reset password pointer */ } int code(c) /* encode some character */ int c; /* character to encode */ { if(p) /* if password is in use */ { if(!*p) /* if we reached the end */ p = password; /* then wrap back to the start */ return c^*p++; /* very simple here */ } else return c; /* else no encryption */ } //E*O*F arccode.c// echo x - arccvt.c cat > "arccvt.c" << '//E*O*F arccvt.c//' /* ARC - Archive utility - ARCCVT $define(tag,$$segment(@1,$$index(@1,=)+1))# $define(version,Version $tag( TED_VERSION DB =1.16), created on $tag( TED_DATE DB =02/03/86) at $tag( TED_TIME DB =22:53:02))# $undefine(tag)# $version (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED By: Thom Henderson Description: This file contains the routines used to convert archives to use newer file storage methods. Language: Computer Innovations Optimizing C86 * * changed abort(..) to exit(_errmsg(1,...)) */ #include <stdio.h> #define EXTERN extern #include "arc.h" static char tempname[STRLEN]; /* temp file name */ cvtarc(num,arg) /* convert archive */ int num; /* number of arguments */ char *arg[]; /* pointers to arguments */ { struct heads hdr; /* file header */ int cvt; /* true to convert current file */ int did[MAXARG]; /* true when argument was used */ int n; /* index */ char *makefnam(); /* filename fixer */ FILE *fopen(); /* file opener */ if(arctemp) /* use temp area if specified */ #ifdef OSK sprintf(tempname,"%s/$ARCTEMP.CVT",arctemp); #else sprintf(tempname,"%s$ARCTEMP.CVT",arctemp); #endif else makefnam("$ARCTEMP.CVT",arcname,tempname); openarc(1); /* open archive for changes */ for(n=0; n<num; n++) /* for each argument */ did[n] = 0; /* reset usage flag */ rempath(num,arg); /* strip off paths */ if(num) /* if files were named */ { while(readhdr(&hdr,arc)) /* while more files to check */ { cvt = 0; /* reset convert flag */ for(n=0; n<num; n++) /* for each template given */ { if(match(hdr.name,arg[n])) { cvt = 1; /* turn on convert flag */ did[n] = 1; /* turn on usage flag */ break; /* stop looking */ } } if(cvt) /* if converting this one */ cvtfile(&hdr); /* then do it */ else /* else just copy it */ { writehdr(&hdr,new); filecopy(arc,new,hdr.size); } } } else while(readhdr(&hdr,arc)) /* else convert all files */ cvtfile(&hdr); hdrver = 0; /* archive EOF type */ writehdr(&hdr,new); /* write out our end marker */ closearc(1); /* close archive after changes */ if(note) { for(n=0; n<num; n++) /* report unused args */ { if(!did[n]) { printf("File not found: %s\n",arg[n]); nerrs++; } } } } static cvtfile(hdr) /* convert a file */ struct heads *hdr; /* pointer to header data */ { long starts, ftell(); /* where the file goes */ FILE *tmp, *fopen(); /* temporary file */ if(!(tmp=fopen(tempname,RWBIN))) exit (_errmsg(1,"Unable to create temporary file %s",tempname)); if(note) printf("Converting file: %-12s reading, ",hdr->name); fflush (stdout); unpack(arc,tmp,hdr); /* unpack the entry */ fseek(tmp,0L,0); /* reset temp for reading */ starts = ftell(new); /* note where header goes */ hdrver = ARCVER; /* anything but end marker */ writehdr(hdr,new); /* write out header skeleton */ pack(tmp,new,hdr); /* pack file into archive */ fseek(new,starts,0); /* move back to header skeleton */ writehdr(hdr,new); /* write out real header */ fseek(new,hdr->size,1); /* skip over data to next header */ fclose(tmp); /* all done with the file */ if(unlink(tempname) && warn) { printf("Cannot unsave %s\n",tempname); nerrs++; } } //E*O*F arccvt.c// echo x - arcdel.c cat > "arcdel.c" << '//E*O*F arcdel.c//' /* ARC - Archive utility - ARCDEL $define(tag,$$segment(@1,$$index(@1,=)+1))# $define(version,Version $tag( TED_VERSION DB =2.09), created on $tag( TED_DATE DB =02/03/86) at $tag( TED_TIME DB =22:53:27))# $undefine(tag)# $version (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED By: Thom Henderson Description: This file contains the routines used to delete entries in an archive. Language: Colputer Innovations Optimizing C86 * * changed abort(..) to exit(_errmsg(1,...)) */ #include <stdio.h> #define EXTERN extern #include "arc.h" delarc(num,arg) /* remove files from archive */ int num; /* number of arguments */ char *arg[]; /* pointers to arguments */ { struct heads hdr; /* header data */ int del; /* true to delete a file */ int did[MAXARG]; /* true when argument used */ int n; /* index */ if(!num) /* she must specify which */ exit (_errmsg(1,"You must tell me which files to delete!")); for(n=0; n<num; n++) /* for each argument */ did[n] = 0; /* reset usage flag */ rempath(num,arg); /* strip off paths */ openarc(1); /* open archive for changes */ while(readhdr(&hdr,arc)) /* while more entries in archive */ { del = 0; /* reset delete flag */ for(n=0; n<num; n++) /* for each template given */ { if(match(hdr.name,arg[n])) { del = 1; /* turn on delete flag */ did[n] = 1; /* turn on usage flag */ break; /* stop looking */ } } if(del) /* skip over unwanted files */ { fseek(arc,hdr.size,1); if(note) printf("Deleting file: %s\n",hdr.name); } else /* else copy over file data */ { writehdr(&hdr,new); /* write out header and file */ filecopy(arc,new,hdr.size); } } hdrver = 0; /* special end of archive type */ writehdr(&hdr,new); /* write out archive end marker */ closearc(1); /* close archive after changes */ if(note) { for(n=0; n<num; n++) /* report unused arguments */ { if(!did[n]) { printf("File not found: %s\n",arg[n]); nerrs++; } } } } //E*O*F arcdel.c// echo x - arcdir.c cat > "arcdir.c" << '//E*O*F arcdir.c//' /* ARC - Archive utility - ARCDIR (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED By: Thom Henderson Description: This file contains the dir() routine used when adding files to an archive. It is an adaptation of the CI-C86 library function filedir(). It differes in that it returns the file names one by one, instead of all at once. */ #include <stdio.h> #include <dir.h> #define EXTERN extern /* * the following main() is only here for testing purposes. */ #ifdef TRYMAIN main() { char *search; char *dir(), *found; char placeholder[80]; for (;;) { search = placeholder; printf ("search string: "); scanf ("%s",search); while (found = dir (search, 0)) { /* * make it a 'search for next' */ search = (char*)0; printf ("%s\n",found); } } } #endif char *dir(filename,mode) /* get files, one by one */ char *filename; /* template, or NULL */ int mode; /* search mode bits; irrelevant for OS-9 */ { /* * OS-9/68k version */ static DIR *dirptr; static struct direct *nextfile; static char matchfile[80]; /* local nonvolatile search string */ char is_it_dir[80]; /* local string to check whether a file is a directory */ static char dirname[80]; /* directory part of path name */ extern char *rindex(); /* need this to scan for '/' */ char tempname[80]; /* trial file name */ int temppath; /* temporary path number */ static int wildcards; /* flag: file name contains wild cards */ static int foundone; /* true if matching file found */ /* * if a file name has been given.. */ if (filename) { foundone = 0; /* * check if there are wildcards */ wildcards = ((rindex(filename,'?') || rindex(filename,'*')) ? 1:0); /* * check if there is a directory path */ if (rindex(filename,'/')) { /* * yes: strip off directory path */ int slash_index; slash_index = (int)(rindex(filename,'/') - filename); strncpy (dirname, filename, slash_index); dirname[slash_index] = '\0'; strcpy (tempname, rindex(filename,'/')+1); strcpy (filename, tempname); } else /* * no: use current directory */ { strcpy (dirname, "."); } /* * and open directory */ dirptr = opendir(dirname); /* * copy search template to nonvolatile string */ strcpy (matchfile, filename); } /* * scan the directory */ while ((nextfile = readdir (dirptr)) != (struct direct *)0) { #ifdef DEBUG printf ("name: %s search name: %s ",nextfile->d_name,matchfile); if (!filename) printf ("NULL search pattern\n"); else printf ("\n"); #endif /* * check if it is a directory name, if so, forget it */ sprintf (is_it_dir,"%s/%s",dirname, nextfile->d_name); /* * build file name, including path name; trying to open a directory file * will return -1... */ temppath = open (is_it_dir,1); if (temppath == -1) { #ifdef DEBUG printf ("%s: cannot open\n",is_it_dir); #endif continue; } close (temppath); /* * now use the _cmpnam() function to perform wild card matching */ if (!_cmpnam (nextfile->d_name, matchfile, strlen(matchfile))) { foundone = 1; /* * if file name did not contain wild cards, close directory before * leaving */ if (!wildcards) closedir (dirptr); return nextfile->d_name; } /* * this file not matching, but found one before, and it is no wild * card search: finish */ else if (foundone && (!wildcards)) { closedir (dirptr); return (char *)0; } else { #ifdef DEBUG puts ("NO MATCH"); foundone = 0; #endif } } /* * all done, but none found: return NULL pointer */ closedir (dirptr); return (char *)0; } //E*O*F arcdir.c// echo x - arcdos.c cat > "arcdos.c" << '//E*O*F arcdos.c//' /* ARC - Archive utility - ARCDOS By: Thom Henderson Description: This file contains certain DOS level routines that assist in doing fancy things with an archive, primarily reading and setting the date and time last modified. These are, by nature, system dependant functions. But they are also, by nature, very expendable. */ #include <stdio.h> #define EXTERN extern #include "arc.h" #ifdef OSK #include <direct.h> #endif getstamp(f,date,time) /* get a file's date/time stamp */ FILE *f; /* file to get stamp from */ unsigned short *date, *time; /* storage for the stamp */ { #ifdef OSK /* * this is the OS-9/68k version */ int path; struct fildes filbuf; char filedate[5]; /* * need to get the path number belonging to the file descriptor */ path = fileno (f); /* * get file descriptor */ _gs_gfd (path, &filbuf, sizeof (struct fildes)); /* * copy date to local array */ strncpy (filedate, filbuf.fd_date,5); /* * dissect date and build MSDOS compatible date entry * * below is the layout of the date and time words * * Byte 3 Byte 2: empty (CI86 int is 16 bits) * * Byte 1 Byte 0 * * year month day * |-----------| |-------| |-------| * 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 * |_______| |___________| |_______| * hours(24) minutes seconds/2 * * The 'year' storage format is funny: when decoding the year, the formula * is (yr+80) % 100 * */ #ifdef DEBUG puts ("getstamp"); printf ("file date: %d %d %d %d %d\n",filedate[0],filedate[1],filedate[2],filedate[3],filedate[4]); #endif *date = (unsigned short)((filedate[0]+20) & 0x7f); *date <<= 9; *date &= (unsigned short)0xfe00; *date += (unsigned short)((filedate[1] & 0x0f)<< 5); *date += (unsigned short)(filedate[2] & 0x1f); *time = (unsigned short)(filedate[3] & 0x1f); *time <<= 11; *time += (unsigned short)((filedate[4] & 0x3f) << 5); #ifdef DEBUG printf ("getstamp: date = %04.4x time = %04.4x\n",*date&0xffff,*time&0xffff); #endif #else fprintf (stderr, "getstamp routine not implemented\n"); *date = *time = 0; #endif } setstamp(f,date,time) /* set a file's date/time stamp */ FILE *f; /* file to set stamp on */ unsigned short date, time; /* desired date, time */ { /* * inverse of the above */ #ifdef OSK /* * this is the OS-9/68k version */ int path; struct fildes filbuf; char filedate[5]; int yr, mo, dy, hh, mm, ss; /* * need to get the path number belonging to the file descriptor */ path = fileno (f); /* * get file descriptor */ _gs_gfd (path, &filbuf, sizeof (struct fildes)); /* * dissect date from MSDOS format and insert into OS-9 file descriptor * * below is the layout of the date and time words * * Byte 3 Byte 2: empty (CI86 int is 16 bits) * * Byte 1 Byte 0 * * year month day * |-----------| |-------| |-------| * 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 * |_______| |___________| |_______| * hours(24) minutes seconds/2 * */ yr = (((date >> 9) & 0x7f)+80)%100; /* dissect the date */ mo = (date >> 5) & 0x0f; dy = date & 0x1f; hh = (time >> 11) & 0x1f; /* dissect the time */ mm = (time >> 5) & 0x3f; ss = (time & 0x1f) * 2; filedate[0] = yr; filedate[1] = mo; filedate[2] = dy; filedate[3] = hh; filedate[4] = mm; /* * no seconds in OS-9! */ strncpy (filbuf.fd_date, filedate, 5); _ss_pfd (path, &filbuf); #else fprintf (stderr, "setstamp routine not implemented\n"); #endif } //E*O*F arcdos.c// echo x - arcext.c cat > "arcext.c" << '//E*O*F arcext.c//' /******* arcext.mac $define(arc,$ifdef(xarc,off,on))# macro switch for ARC only code $define(xarc,$ifdef(xarc,on,off))# macro switch for XARC only code $emit($arc)# */ /* ARC - Archive utility - ARCEXT $define(tag,$$segment(@1,$$index(@1,=)+1))# $define(version,Version $tag( TED_VERSION DB =2.18), created on $tag( TED_DATE DB =02/03/86) at $tag( TED_TIME DB =22:55:19))# $undefine(tag)# $version (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED By: Thom Henderson Description: This file contains the routines used to extract files from an archive. Language: Computer Innovations Optimizing C86 */ #include <stdio.h> #define EXTERN extern #include "arc.h" #define ARC #ifdef ARC extarc(num,arg,prt) /* extract files from archive */ int num; /* number of arguments */ char *arg[]; /* pointers to arguments */ int prt; /* true if printing */ #else extarc() /* extract files from archive */ #endif { struct heads hdr; /* file header */ #ifdef ARC int save; /* true to save current file */ int did[MAXARG]; /* true when argument was used */ char *i, *rindex(); /* string index */ char **name, *malloc(); /* name pointer list, allocator */ int n; /* index */ #ifdef DEBUG printf ("extarc (%d,%s,%d)\n",num,arg[0],prt); #endif name = (char **)malloc(num*sizeof(char *)); /* get storage for name pointers */ for(n=0; n<num; n++) /* for each argument */ { did[n] = 0; /* reset usage flag */ if(!(i=rindex(arg[n],'\\'))) /* find start of name */ if(!(i=rindex(arg[n],'/'))) if(!(i=rindex(arg[n],':'))) i = arg[n]-1; name[n] = i+1; } #endif openarc(0); /* open archive for reading */ #ifdef ARC if(num) /* if files were named */ { #ifdef DEBUG printf ("before readhdr: n: %d num: %d\n",n,num); #endif while(readhdr(&hdr,arc)) /* while more files to check */ { save = 0; /* reset save flag */ #ifdef DEBUG printf ("n: %d num: %d\n",n,num); #endif for(n=0; n<num; n++) /* for each template given */ { # ifdef DEBUG printf ("header name: %s matchname: %s\n", hdr.name, name[n]); # endif if(match(hdr.name,name[n])) { save = 1; /* turn on save flag */ did[n] = 1; /* turn on usage flag */ break; /* stop looking */ } } if(save) /* extract if desired, else skip */ extfile(&hdr,arg[n],prt); else fseek(arc,hdr.size,1); } } else while(readhdr(&hdr,arc)) /* else extract all files */ extfile(&hdr,"",prt); #else while(readhdr(&hdr,arc)) /* extract all files */ extfile(&hdr); #endif closearc(0); /* close archive after reading */ #ifdef ARC if(note) { for(n=0; n<num; n++) /* report unused args */ { if(!did[n]) { printf("File not found: %s\n",arg[n]); nerrs++; } } } free(name); #endif } #ifdef ARC static extfile(hdr,path,prt) /* extract a file */ struct heads *hdr; /* pointer to header data */ char *path; /* pointer to path name */ int prt; /* true if printing */ #else static extfile(hdr) /* extract a file */ struct heads *hdr; #endif /**** $define(use,$ife($arc,on,fix,hdr->name))# *****/ { FILE *f, *fopen(); /* extracted file, opener */ char buf[STRLEN]; /* input buffer */ #ifdef ARC char fix[STRLEN]; /* fixed name buffer */ char *i, *rindex(); /* string index */ if(prt) /* printing is much easier */ { unpack(arc,stdout,hdr); /* unpack file from archive */ printf("\f"); /* eject the form */ return; /* see? I told you! */ } strcpy(fix,path); /* note path name template */ if(!(i=rindex(fix,'\\'))) /* find start of name */ if(!(i=rindex(fix,'/'))) if(!(i=rindex(fix,':'))) i = fix-1; strcpy(i+1,hdr->name); /* replace template with name */ #endif if(note) #ifdef ARC printf("Extracting file: %s\n",fix); #else printf("Extracting file: %s\n",hdr->name); #endif if(warn) { if(f=fopen( #ifdef ARC fix, #else hdr->name, #endif READBIN)) /* see if it exists */ { fclose(f); #ifdef ARC printf("WARNING: File %s already exists!",fix); #else printf("WARNING: File %s already exists!",hdr->name); #endif while(1) { printf(" Overwrite it (y/n)? "); fflush (stdin); fgets(buf,STRLEN,stdin); *buf = toupper(*buf); if(*buf=='Y' || *buf=='N') break; } if(*buf=='N') { #ifdef ARC printf("%s not extracted.\n",fix); #else printf("%s not extracted.\n",hdr->name); #endif fseek(arc,hdr->size,1); return; } } } if(!(f=fopen( #ifdef ARC fix, #else hdr->name, #endif WRITEBIN))) { if(warn) { printf("Cannot create %s\n", #ifdef ARC fix); #else hdr->name); #endif nerrs++; } fseek(arc,hdr->size,1); return; } /* now unpack the file */ unpack(arc,f,hdr); /* unpack file from archive */ setstamp(f,hdr->date,hdr->time); /* set the proper date/time stamp */ fclose(f); /* all done writing to file */ } //E*O*F arcext.c// echo x - arcio.c cat > "arcio.c" << '//E*O*F arcio.c//' /* ARC - Archive utility - ARCIO $define(tag,$$segment(@1,$$index(@1,=)+1))# $define(version,Version $tag( TED_VERSION DB =2.30), created on $tag( TED_DATE DB =02/03/86) at $tag( TED_TIME DB =22:56:00))# $undefine(tag)# $version (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED By: Thom Henderson Description: This file contains the file I/O routines used to manipulate an archive. Language: Computer Innovations Optimizing C86 * * changed abort(..) to exit(_errmsg(1,...)) */ #include <stdio.h> #define EXTERN extern #include "arc.h" int readhdr(hdr,f) /* read a header from an archive */ struct heads *hdr; /* storage for header */ FILE *f; /* archive to read header from */ { char name[FNLEN]; /* filename buffer */ int try = 0; /* retry counter */ static int first = 1; /* true only on first read */ #ifdef DEBUG puts ("readhdr"); #endif if(!f) /* if archive didn't open */ return 0; /* then pretend it's the end */ if(feof(f)) /* if no more data */ return 0; /* then signal end of archive */ if(fgetc(f)!=ARCMARK) /* check archive validity */ { if(warn) { printf("An entry in %s has a bad header.",arcname); nerrs++; } while(!feof(f)) { try++; if(fgetc(f)==ARCMARK) { ungetc(hdrver=fgetc(f),f); if(hdrver>=0 && hdrver<=ARCVER) break; } } if(feof(f) && first) exit (_errmsg(1,"%s is not an archive",arcname)); if(warn) printf(" %d bytes skipped.\n",try); if(feof(f)) return 0; } hdrver = fgetc(f); /* get header version */ #ifdef DEBUG printf ("header version %d\n",hdrver); #endif if(hdrver<0) exit (_errmsg(1,"Invalid header in archive %s",arcname)); if(hdrver==0) return 0; /* note our end of archive marker */ if(hdrver>ARCVER) { fread(name,sizeof(char),FNLEN,f); printf("I don't know how to handle file %s in archive %s\n", name,arcname); printf("I think you need a newer version of ARC.\n"); exit(1); } /* amount to read depends on header type */ if(hdrver==1) /* old style is shorter */ { fread(hdr,sizeof(struct heads)-sizeof(long int),1,f); hdrver = 2; /* convert header to new format */ hdr->length = hdr->size; /* size is same when not packed */ } #ifndef OSK else fread(hdr,sizeof(struct heads),1,f); #else /* * see comments below why we can read one less than sizeof(struct heads) */ else fread (hdr, sizeof(struct heads)-1, 1, f); #endif #ifdef DEBUG printf ("header read\n"); #endif #ifdef OSK /* * one heck of a hack for the 68000! Since the 68k always word-aligns, * the struct heads is actually one byte longer than in the file! (The * file name is 13 chars, expanded to 14 chars by 68k C). Thus, bytes * 13..end must be moved down one. Further, long and short ints must be * byte-swapped. */ { char *ptr; int i; ptr = (char *)hdr; for (i=sizeof(struct heads)-2; i>=13; i--) *(ptr+i+1) = *(ptr+i); hdr->length = longswap(hdr->length); hdr->size = longswap(hdr->size); hdr->date = (unsigned short)wordswap(hdr->date); hdr->time = (unsigned short)wordswap(hdr->time); hdr->crc = (short)(wordswap(hdr->crc) & 0xffff); } #endif first = 0; return 1; /* we read something */ } writehdr(hdr,f) /* write a header to an archive */ struct heads *hdr; /* header to write */ FILE *f; /* archive to write to */ { #ifdef OSK struct heads temphdr; #endif #ifdef DEBUG puts ("writehdr"); #endif fputc(ARCMARK,f); /* write out the mark of ARC */ fputc(hdrver,f); /* write out the header version */ if(!hdrver) /* if that's the end */ { #ifdef DEBUG puts ("writehdr: hdrver=0: returning"); return; /* then write no more */ #endif } #ifdef OSK { char *ptr; int i; /* * copy hdr to temphdr */ _strass (&temphdr, hdr, sizeof (struct heads)); temphdr.length = longswap(temphdr.length); temphdr.size = longswap(temphdr.size); temphdr.date = (unsigned short)wordswap(temphdr.date); temphdr.time = (unsigned short)wordswap(temphdr.time); temphdr.crc = (short)(wordswap(temphdr.crc) & 0xffff); ptr = (char *)&temphdr; for (i=13; i<sizeof(struct heads)-1; i++) { *(ptr+i) = *(ptr+i+1); } } fwrite(&temphdr,sizeof(struct heads)-1,1,f); #else fwrite(hdr,sizeof(struct heads),1,f); #endif /* note the newest file for updating the archive timestamp */ if(hdr->date>arcdate ||(hdr->date==arcdate && hdr->time>arctime)) { arcdate = hdr->date; arctime = hdr->time; } #ifdef DEBUG puts ("writehdr returning"); #endif } filecopy(f,t,size) /* bulk file copier */ FILE *f, *t; /* from, to */ long size; /* number of bytes */ { int len; /* length of a given copy */ #ifdef DEBUG printf("filecopy: size = %ld\n",size); #endif while(size--) /* while more bytes to move */ putc_tst(fgetc(f),t); } putc_tst(c,t) /* put a character, with tests */ char c; /* character to output */ FILE *t; /* file to write to */ { if(t) if(fputc(c,t)==EOF) { /* * next line added for OS-9 */ #ifdef OSK if (c != 0xff) #endif exit (_errmsg(1,"Write fail (disk full?)")); } } //E*O*F arcio.c// exit 0 ------------------------------------- The views expressed in OS-9 Discussions are those of the individual authors only. Copies of digests are available by mail request. ------ Moderator: John Daleske cbosgd!cbdkc1!daleske daleske@cbdkc1.ATT.COM Submissions should go to: cbosgd!os9 os9@cbosgd.ATT.COM Comments to the moderator cbosgd!os9-request os9-request@cbosgd.ATT.COM ********************* End of OS-9 Discussions *********************