masscomp-request@soma.UUCP (07/20/87)
#! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # mkentry.c # mmd.c # mrd.c # mread.c # mren.c # mtype.c # mwrite.c # putfat.c # search.c # subdir.c # unixname.c # This archive created: Mon Jul 13 07:34:44 1987 export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 'mkentry.c'" '(2501 characters)' if test -f 'mkentry.c' then echo shar: "will not over-write existing file 'mkentry.c'" else sed 's/^X//' << \SHAR_EOF > 'mkentry.c' X/* X * mk_entry(), grow() X */ X X#include <stdio.h> X#include <time.h> X#include "msdos.h" X Xextern int fd, dir_start, dir_len, clus_size, dir_entries; Xextern int dir_chain[25]; X X/* X * Make a directory entry. Builds a directory entry based on the X * name, attribute, starting cluster number, and size. Returns a pointer X * to the directory structure. X */ X Xstruct directory * Xmk_entry(filename, attr, fat, size) Xchar *filename; Xunsigned char attr; Xint fat; Xint size; X{ X long clock, time(); X int i; X char *strncpy(); X static struct directory ndir; X struct tm *now, *localtime(); X unsigned char hour, min_hi, min_low, sec; X unsigned char year, month_hi, month_low, day; X X time(&clock); X now = localtime(&clock); X strncpy(ndir.name, filename, 8); X strncpy(ndir.ext, filename+8, 3); X ndir.attr = attr; X for (i=0; i<10; i++) X ndir.reserved[i] = NULL; X hour = now->tm_hour << 3; X min_hi = now->tm_min >> 3; X min_low = now->tm_min << 5; X sec = 0; X ndir.time[1] = hour + min_hi; X ndir.time[0] = min_low + sec; X year = (now->tm_year - 80) << 1; X month_hi = (now->tm_mon+1) >> 3; X month_low = (now->tm_mon+1) << 5; X day = now->tm_mday; X ndir.date[1] = year + month_hi; X ndir.date[0] = month_low + day; X ndir.start[1] = fat / 0x100; X ndir.start[0] = fat % 0x100; X ndir.size[3] = 0; /* can't be THAT large */ X ndir.size[2] = size / 0x10000; X ndir.size[1] = (size % 0x10000) / 0x100; X ndir.size[0] = (size % 0x10000) % 0x100; X return(&ndir); X} X X/* X * Make a subdirectory grow in length. Only subdirectories (not root) X * may grow. Returns a 0 on success or 1 on failure (disk full). X */ X Xint Xgrow(fat) Xint fat; X{ X int i, next, last, getfat(), nextfat(), num, sector, buflen; X char tbuf[CLSTRBUF]; X void perror(), exit(); X X last = nextfat(0); X if (last == -1) X return(1); X X while (1) { X next = getfat(fat); X if (next == -1) { X fprintf(stderr, "grow: FAT problem\n"); X exit(1); X } X /* end of cluster chain */ X if (next >= 0xff8) X break; X fat = next; X } X /* mark the end of the chain */ X putfat(fat, last); X putfat(last, 0xfff); X /* zero the buffer */ X buflen = clus_size * MSECSIZ; X for (i=0; i<buflen; i++) X tbuf[i] = NULL; X X /* write the cluster */ X sector = (last - 2) * clus_size + dir_start + dir_len; X move(sector); X if (write(fd, tbuf, buflen) != buflen) { X perror("grow: write"); X exit(1); X } X /* fix up the globals.... */ X num = dir_entries / 16; X dir_entries += clus_size * 16; X dir_chain[num] = sector; X if (clus_size == 2) X dir_chain[num+1] = sector +1; X return(0); X} SHAR_EOF if test 2501 -ne "`wc -c < 'mkentry.c'`" then echo shar: "error transmitting 'mkentry.c'" '(should have been 2501 characters)' fi fi echo shar: "extracting 'mmd.c'" '(3758 characters)' if test -f 'mmd.c' then echo shar: "will not over-write existing file 'mmd.c'" else sed 's/^X//' << \SHAR_EOF > 'mmd.c' X/* X * Make a MSDOS sub directory X * X * Emmet P. Gray US Army, HQ III Corps & Fort Hood X * ...!ihnp4!uiucuxc!fthood!egray Attn: AFZF-DE-ENV X * Directorate of Engineering & Housing X * Environmental Management Office X * Fort Hood, TX 76544-5057 X */ X X#include <stdio.h> X#include "msdos.h" X Xint fd; /* the file descriptor for the floppy */ Xint dir_start; /* starting sector for directory */ Xint dir_len; /* length of directory (in sectors) */ Xint dir_entries; /* number of directory entries */ Xint dir_chain[25]; /* chain of sectors in directory */ Xint clus_size; /* cluster size (in sectors) */ Xint fat_len; /* length of FAT table (in sectors) */ Xint num_clus; /* number of available clusters */ Xunsigned char *fatbuf; /* the File Allocation Table */ Xchar *mcwd; /* the Current Working Directory */ X Xmain(argc, argv) Xint argc; Xchar *argv[]; X{ X int entry, slot, fat, dot, subdir(); X char *filename, *newfile, *fixname(), *strncpy(), *unixname(); X char *getpath(), *pathname, tname[9], text[4], *fixed; X void exit(); X struct directory *dir, *search(), *mk_entry(); X X if (init(2)) { X fprintf(stderr, "mmd: Cannot initialize diskette\n"); X exit(1); X } X /* only 1 directory ! */ X if (argc != 2) { X fprintf(stderr, "Usage: mmd <MSDOS directory>\n"); X exit(1); X } X fixed = fixname(argv[1]); X filename = unixname(fixed, fixed+8); X pathname = getpath(argv[1]); X if (strcmp(fixed+8, " ")) { X fprintf(stderr, "mmd: Directory names cannot have extensions\n"); X exit(1); X } X if (subdir(pathname)) X exit(1); X /* see if exists and get slot */ X slot = -1; X dot = 0; X for (entry=0; entry<dir_entries; entry++) { X dir = search(entry); X /* if empty */ X if (dir->name[0] == NULL) { X if (slot < 0) X slot = entry; X break; X } X /* if erased */ X if (dir->name[0] == 0xe5) { X if (slot < 0) X slot = entry; X continue; X } X /* if not a directory */ X if (!(dir->attr & 0x10)) X continue; X strncpy(tname, dir->name, 8); X strncpy(text, dir->ext, 3); X newfile = unixname(tname, text); X /* save the 'dot' directory info */ X if (!strcmp(".", newfile)) X dot = dir->start[1]*0x100 + dir->start[0]; X X if (!strcmp(filename, newfile)) { X fprintf(stderr, "mmd: Directory '%s' already exists\n", filename); X exit(1); X } X } X /* no '.' entry means root directory */ X if (dot == 0 && slot < 0) { X printf(stderr, "mmd: No directory slots\n"); X exit(1); X } X /* make the directory grow */ X if (dot && slot < 0) { X if (grow(dot)) { X fprintf(stderr, "mmd: Disk full\n"); X exit(1); X } X /* first slot in 'new' directory */ X slot = entry; X } X fat = nextfat(0); X if (fat == -1) { X fprintf(stderr, "mmd: Disk full\n"); X exit(1); X } X /* make directory entry */ X dir = mk_entry(fixed, 0x10, fat, 0); X if (dir != NULL) { X writedir(slot, dir); X /* write the cluster */ X putfat(fat, 0xfff); X putcluster(fat, dot); X } X /* write FAT sectors */ X writefat(); X close(fd); X exit(0); X} X X/* X * Write a blank directory 'template' to the cluster starting at 'dot'. X */ X Xputcluster(dot, dot_dot) Xint dot; Xint dot_dot; X{ X long start; X void exit(), perror(); X int buflen; X static struct directory dirs[32]; X struct directory *mk_entry(); X X start = (dot - 2)*clus_size + dir_start + dir_len; X move(start); X X buflen = clus_size * MSECSIZ; X /* make the '.' and '..' entries */ X dirs[0] = *mk_entry(". ", 0x10, dot, 0); X dirs[1] = *mk_entry(".. ", 0x10, dot_dot, 0); X X if (write(fd, (char *) &dirs[0], buflen) != buflen) { X perror("putcluster: write"); X exit(1); X } X return; X} X X/* X * Returns next free cluster or -1 if none are available. X */ X Xint Xnextfat(last) Xint last; X{ X static int i; X X for (i=last+1; i<num_clus+2; i++) { X if (!getfat(i)) X return(i); X } X return(-1); X} SHAR_EOF if test 3758 -ne "`wc -c < 'mmd.c'`" then echo shar: "error transmitting 'mmd.c'" '(should have been 3758 characters)' fi fi echo shar: "extracting 'mrd.c'" '(3152 characters)' if test -f 'mrd.c' then echo shar: "will not over-write existing file 'mrd.c'" else sed 's/^X//' << \SHAR_EOF > 'mrd.c' X/* X * Delete a MSDOS sub directory X * X * Emmet P. Gray US Army, HQ III Corps & Fort Hood X * ...!ihnp4!uiucuxc!fthood!egray Attn: AFZF-DE-ENV X * Directorate of Engineering & Housing X * Environmental Management Office X * Fort Hood, TX 76544-5057 X */ X X#include <stdio.h> X#include "msdos.h" X Xint fd; /* the file descriptor for the floppy */ Xint dir_start; /* starting sector for directory */ Xint dir_len; /* length of directory (in sectors) */ Xint dir_entries; /* number of directory entries */ Xint dir_chain[25]; /* chain of sectors in directory */ Xint clus_size; /* cluster size (in sectors) */ Xint fat_len; /* length of FAT table (in sectors) */ Xint num_clus; /* number of available clusters */ Xunsigned char *fatbuf; /* the File Allocation Table */ Xchar *mcwd; /* the Current Working Directory */ X Xmain(argc, argv) Xint argc; Xchar *argv[]; X{ X int ismatch, entry, start, isempty(); X char *filename, *newfile, text[4], tname[9], *getname(); X char *strncpy(), *pathname, *getpath(), *unixname(); X void exit(); X struct directory *dir, *search(); X X if (init(2)) { X fprintf(stderr, "mrd: Cannot initialize diskette\n"); X exit(1); X } X /* only 1 directory ! */ X if (argc != 2) { X fprintf(stderr, "Usage: mrd <MSDOS directory>\n"); X exit(1); X } X X filename = getname(argv[1]); X pathname = getpath(argv[1]); X if (subdir(pathname)) X exit(1); X ismatch = 0; X for (entry=0; entry<dir_entries; entry++) { X dir = search(entry); X /* if empty */ X if (dir->name[0] == NULL) X break; X /* if erased */ X if (dir->name[0] == 0xe5) X continue; X /* if not dir */ X if (!(dir->attr & 0x10)) X continue; X strncpy(tname, dir->name, 8); X strncpy(text, dir->ext, 3); X newfile = unixname(tname, text); X if (!strcmp(newfile, filename)) { X start = dir->start[1]*0x100 + dir->start[0]; X if (!isempty(start)) { X fprintf(stderr, "mrd: Directory '%s' is not empty\n", filename); X exit(1); X } X if (!start) { X fprintf(stderr, "mrd: Can't remove root directory\n"); X exit(1); X } X zapit(start); X dir->name[0] = 0xe5; X writedir(entry, dir); X ismatch = 1; X } X } X if (!ismatch) { X fprintf(stderr, "mrd: Directory '%s' not found\n", filename); X exit(1); X } X /* update the FAT sectors */ X writefat(); X close(fd); X exit(0); X} X X/* X * See if directory is empty. Returns 1 if empty, 0 if not. Can't use X * subdir() and search() as it would clobber the globals. X */ X Xint Xisempty(fat) Xint fat; X{ X int i, next, buflen, sector, getfat(); X unsigned char tbuf[CLSTRBUF]; X void perror(), exit(); X X while (1) { X sector = (fat-2)*clus_size + dir_start + dir_len; X move(sector); X buflen = clus_size * MSECSIZ; X if (read(fd, tbuf, buflen) != buflen) { X perror("isempty: read"); X exit(1); X } X /* check first character of name */ X for (i=0; i<MSECSIZ; i+=MDIRSIZ) { X if (tbuf[i] == '.') X continue; X if (tbuf[i] != NULL && tbuf[i] != 0xe5) X return(0); X } X /* get next cluster number */ X next = getfat(fat); X if (next == -1) { X fprintf(stderr, "isempty: FAT problem\n"); X exit(1); X } X /* end of cluster chain */ X if (next >= 0xff8) X break; X fat = next; X } X return(1); X} SHAR_EOF if test 3152 -ne "`wc -c < 'mrd.c'`" then echo shar: "error transmitting 'mrd.c'" '(should have been 3152 characters)' fi fi echo shar: "extracting 'mread.c'" '(4675 characters)' if test -f 'mread.c' then echo shar: "will not over-write existing file 'mread.c'" else sed 's/^X//' << \SHAR_EOF > 'mread.c' X/* X * Read (copy) a MSDOS file to Unix X * X * Emmet P. Gray US Army, HQ III Corps & Fort Hood X * ...!ihnp4!uiucuxc!fthood!egray Attn: AFZF-DE-ENV X * Directorate of Engineering & Housing X * Environmental Management Office X * Fort Hood, TX 76544-5057 X */ X X#include <stdio.h> X#include <sys/types.h> X#include <sys/stat.h> X#include "msdos.h" X Xint fd; /* the file descriptor for the floppy */ Xint dir_start; /* starting sector for directory */ Xint dir_len; /* length of directory (in sectors) */ Xint dir_entries; /* number of directory entries */ Xint dir_chain[25]; /* chain of sectors in directory */ Xint clus_size; /* cluster size (in sectors) */ Xint fat_len; /* length of FAT table (in sectors) */ Xint num_clus; /* number of available clusters */ Xunsigned char *fatbuf; /* the File Allocation Table */ Xchar *mcwd; /* the Current Working Directory */ X Xlong size; Xlong current; Xint textmode = 0; Xint nowarn = 0; X Xmain(argc, argv) Xint argc; Xchar *argv[]; X{ X extern int optind; X extern char *optarg; X int fat, i, ismatch, entry, subdir(), single, c, oops; X char *filename, *newfile, text[4], tname[9], *getname(), *unixname(); X char *strncpy(), *pathname, *getpath(), *target, *tmp, *malloc(); X char *strcat(), *strcpy(); X void perror(), exit(); X struct directory *dir, *search(); X struct stat stbuf; X X if (init(0)) { X fprintf(stderr, "mread: Cannot initialize diskette\n"); X exit(1); X } X /* get command line options */ X oops = 0; X while ((c = getopt(argc, argv, "tn")) != EOF) { X switch(c) { X case 't': X textmode = 1; X break; X case 'n': X nowarn = 1; X break; X default: X oops = 1; X break; X } X } X X if (oops || (argc - optind) < 2) { X fprintf(stderr, "Usage: mread [-t|-n] <MSDOS file> <Unix file>\n"); X fprintf(stderr, " or mread [-t|-n] <MSDOS file> [<MSDOS files...>] <Unix directory>\n"); X exit(1); X } X /* only 1 file to copy... */ X single = 1; X target = argv[argc-1]; X /* ...unless last arg is a directory */ X if (!stat(target, &stbuf)) { X if (stbuf.st_mode & 040000) X single = 0; X } X X for (i=optind; i<argc-1; i++) { X filename = getname(argv[i]); X pathname = getpath(argv[i]); X if (subdir(pathname)) X continue; X ismatch = 0; X for (entry=0; entry<dir_entries; entry++) { X dir = search(entry); X /* if empty */ X if (dir->name[0] == NULL) X break; X /* if erased */ X if (dir->name[0] == 0xe5) X continue; X /* if dir or volume lable */ X if ((dir->attr & 0x10) || (dir->attr & 0x08)) X continue; X strncpy(tname, dir->name, 8); X strncpy(text, dir->ext, 3); X newfile = unixname(tname, text); X fat = dir->start[1]*0x100 + dir->start[0]; X size = dir->size[2]*0x10000 + dir->size[1]*0x100 + dir->size[0]; X /* if single file */ X if (single) { X if (!strcmp(newfile, filename)) { X readit(fat, target); X ismatch = 1; X break; X } X } X /* if multiple files */ X else { X if (match(newfile, filename)) { X printf("Copying %s\n", newfile); X tmp = malloc(strlen(target)+1+strlen(newfile)+1); X strcpy(tmp, target); X strcat(tmp, "/"); X strcat(tmp, newfile); X readit(fat, tmp); X ismatch = 1; X } X } X } X if (!ismatch) { X fprintf(stderr, "mread: File '%s' not found\n", filename); X continue; X } X } X close(fd); X exit(0); X} X X/* X * Decode the FAT chain given the begining FAT entry, open the named Unix X * file for write. X */ X Xreadit(fat, target) Xint fat; Xchar *target; X{ X char ans[10]; X void exit(); X FILE *fp; X X current = 0L; X if (!nowarn) { X if (!access(target, 0)) { X while (1) { X printf("File '%s' exists, overwrite (y/n) ? ", target); X gets(ans); X if (ans[0] == 'n' || ans[0] == 'N') X return; X if (ans[0] == 'y' || ans[0] == 'Y') X break; X } X } X } X X if (!(fp = fopen(target, "w"))) { X fprintf(stderr, "mread: Can't open '%s' for write\n", target); X return; X } X X while (1) { X getcluster(fat, fp); X /* get next cluster number */ X fat = getfat(fat); X if (fat == -1) { X fprintf(stderr, "mread: FAT problem\n"); X exit(1); X } X /* end of cluster chain */ X if (fat >= 0xff8) X break; X } X fclose(fp); X return; X} X X/* X * Read the named cluster, write to the Unix file descriptor. X */ X Xgetcluster(num, fp) Xint num; XFILE *fp; X{ X int i, buflen, start; X void exit(), perror(); X char buf[CLSTRBUF]; X X start = (num - 2)*clus_size + dir_start + dir_len; X move(start); X X buflen = clus_size * MSECSIZ; X if (read(fd, buf, buflen) != buflen) { X perror("getcluster: read"); X exit(1); X } X /* stop at size not EOF marker */ X for (i=0; i<buflen; i++) { X current++; X if (current > size) X break; X if (textmode && buf[i] == '\r') X continue; X fputc(buf[i], fp); X } X return; X} SHAR_EOF if test 4675 -ne "`wc -c < 'mread.c'`" then echo shar: "error transmitting 'mread.c'" '(should have been 4675 characters)' fi fi echo shar: "extracting 'mren.c'" '(2628 characters)' if test -f 'mren.c' then echo shar: "will not over-write existing file 'mren.c'" else sed 's/^X//' << \SHAR_EOF > 'mren.c' X/* X * Rename an existing MSDOS file X * X * Emmet P. Gray US Army, HQ III Corps & Fort Hood X * ...!ihnp4!uiucuxc!fthood!egray Attn: AFZF-DE-ENV X * Directorate of Engineering & Housing X * Environmental Management Office X * Fort Hood, TX 76544-5057 X */ X X#include <stdio.h> X#include "msdos.h" X Xint fd; /* the file descriptor for the floppy */ Xint dir_start; /* starting sector for directory */ Xint dir_len; /* length of directory (in sectors) */ Xint dir_entries; /* number of directory entries */ Xint dir_chain[25]; /* chain of sectors in directory */ Xint clus_size; /* cluster size (in sectors) */ Xint fat_len; /* length of FAT table (in sectors) */ Xint num_clus; /* number of available clusters */ Xunsigned char *fatbuf; /* the File Allocation Table */ Xchar *mcwd; /* the Current Working Directory */ X Xmain(argc, argv) Xint argc; Xchar *argv[]; X{ X int entry, ismatch, subdir(), nogo, isdir(); X char *filename, *newfile, *fixname(), *strncpy(), *unixname(); X char *getpath(), *pathname, tname[9], text[4], *getname(), *target; X char *new, ans[10], *temp, *strcpy(); X void exit(); X struct directory *dir, *search(); X X if (init(2)) { X fprintf(stderr, "mren: Cannot initialize diskette\n"); X exit(1); X } X if (argc != 3) { X fprintf(stderr, "Usage: mren <MSDOS source file> <MSDOS target file>\n"); X exit(1); X } X filename = getname(argv[1]); X pathname = getpath(argv[1]); X if (subdir(pathname)) X exit(1); X X temp = getname(argv[2]); X target = fixname(argv[2]); X if (isdir(filename) && strcmp(target+8, " ")) { X strcpy(target+8, " "); X fprintf(stderr, "mren: Directory names may not have extentions\n"); X } X new = unixname(target, target+8); X nogo = 0; X /* the name supplied may be altered */ X if (strcmp(temp, new)) { X while (!nogo) { X printf("Do you accept '%s' as the new file name (y/n) ? ", new); X gets(ans); X if (ans[0] == 'y' || ans[0] == 'Y') X break; X if (ans[0] == 'n' || ans[0] == 'N') X nogo = 1; X } X } X if (nogo) X exit(0); X /* see if exists and do it */ X ismatch = 0; X for (entry=0; entry<dir_entries; entry++) { X dir = search(entry); X /* if empty */ X if (dir->name[0] == NULL) X break; X /* if erased */ X if (dir->name[0] == 0xe5) X continue; X /* you may rename a directory */ X strncpy(tname, dir->name, 8); X strncpy(text, dir->ext, 3); X newfile = unixname(tname, text); X if (!strcmp(filename, newfile)) { X ismatch = 1; X strncpy(dir->name, target, 8); X strncpy(dir->ext, target+8, 3); X writedir(entry, dir); X } X } X if (!ismatch) { X fprintf(stderr, "mren: File '%s' not found\n", filename); X exit(1); X } X close(fd); X exit(0); X} SHAR_EOF if test 2628 -ne "`wc -c < 'mren.c'`" then echo shar: "error transmitting 'mren.c'" '(should have been 2628 characters)' fi fi echo shar: "extracting 'mtype.c'" '(3462 characters)' if test -f 'mtype.c' then echo shar: "will not over-write existing file 'mtype.c'" else sed 's/^X//' << \SHAR_EOF > 'mtype.c' X/* X * Display contents of a MSDOS file X * X * Emmet P. Gray US Army, HQ III Corps & Fort Hood X * ...!ihnp4!uiucuxc!fthood!egray Attn: AFZF-DE-ENV X * Directorate of Engineering & Housing X * Environmental Management Office X * Fort Hood, TX 76544-5057 X */ X X#include <stdio.h> X#include "msdos.h" X Xint fd; /* the file descriptor for the floppy */ Xint dir_start; /* starting sector for directory */ Xint dir_len; /* length of directory (in sectors) */ Xint dir_entries; /* number of directory entries */ Xint dir_chain[25]; /* chain of sectors in directory */ Xint clus_size; /* cluster size (in sectors) */ Xint fat_len; /* length of FAT table (in sectors) */ Xint num_clus; /* number of available clusters */ Xunsigned char *fatbuf; /* the File Allocation Table */ Xchar *mcwd; /* the Current Working Directory */ X Xlong size; Xlong current; Xstripmode = 0; Xtextmode = 0; X Xmain(argc, argv) Xint argc; Xchar *argv[]; X{ X extern int optind; X extern char *optarg; X int fat, i, ismatch, entry, subdir(), c, oops; X char *filename, *newfile, text[4], tname[9], *getname(), *unixname(); X char *strncpy(), *pathname, *getpath(); X void exit(); X struct directory *dir, *search(); X X if (init(0)) { X fprintf(stderr, "mtype: Cannot initialize diskette\n"); X exit(1); X } X /* get command line options */ X oops = 0; X while ((c = getopt(argc, argv, "st")) != EOF) { X switch(c) { X case 's': X stripmode = 1; X break; X case 't': X textmode = 1; X break; X default: X oops = 1; X break; X } X } X X if (oops || (argc - optind) < 1) { X fprintf(stderr, "Usage: mtype [-s|-t] <MSDOS file> [<MSDOS files...>]\n"); X exit(1); X } X X for (i=optind; i<argc; i++) { X filename = getname(argv[i]); X pathname = getpath(argv[i]); X if (subdir(pathname)) X continue; X ismatch = 0; X for (entry=0; entry<dir_entries; entry++) { X dir = search(entry); X /* if empty */ X if (dir->name[0] == NULL) X break; X /* if erased */ X if (dir->name[0] == 0xe5) X continue; X /* if dir or volume lable */ X if ((dir->attr & 0x10) || (dir->attr & 0x08)) X continue; X strncpy(tname, dir->name, 8); X strncpy(text, dir->ext, 3); X newfile = unixname(tname, text); X /* see it if matches the pattern */ X if (match(newfile, filename)) { X fat = dir->start[1]*0x100 + dir->start[0]; X size = dir->size[2]*0x10000 + dir->size[1]*0x100 + dir->size[0]; X readit(fat); X ismatch = 1; X } X } X if (!ismatch) { X fprintf(stderr, "mtype: File '%s' not found\n", filename); X continue; X } X } X close(fd); X exit(0); X} X X/* X * Decode the FAT chain given the begining FAT entry. X */ X Xreadit(fat) Xint fat; X{ X current = 0L; X X while (1) { X getcluster(fat); X /* get next cluster number */ X fat = getfat(fat); X if (fat == -1) { X fprintf(stderr, "mtype: FAT problem\n"); X exit(1); X } X /* end of cluster chain */ X if (fat >= 0xff8) X break; X } X return; X} X X/* X * Read the name cluster, output to the stdout. X */ X Xgetcluster(num) Xint num; X{ X int i, buflen, start; X void exit(), perror(); X char buf[CLSTRBUF]; X X start = (num - 2)*clus_size + dir_start + dir_len; X move(start); X X buflen = clus_size * MSECSIZ; X if (read(fd, buf, buflen) != buflen) { X perror("getcluster: read"); X exit(1); X } X /* stop at size not EOF marker */ X for (i=0; i<buflen; i++) { X current++; X if (current > size) X break; X if (textmode & buf[i] == '\r') X continue; X if (stripmode) X putchar(buf[i] & 0x7f); X else X putchar(buf[i]); X } X return; X} SHAR_EOF if test 3462 -ne "`wc -c < 'mtype.c'`" then echo shar: "error transmitting 'mtype.c'" '(should have been 3462 characters)' fi fi echo shar: "extracting 'mwrite.c'" '(7247 characters)' if test -f 'mwrite.c' then echo shar: "will not over-write existing file 'mwrite.c'" else sed 's/^X//' << \SHAR_EOF > 'mwrite.c' X/* X * Write (copy) a Unix file to MSDOS X * X * Emmet P. Gray US Army, HQ III Corps & Fort Hood X * ...!ihnp4!uiucuxc!fthood!egray Attn: AFZF-DE-ENV X * Directorate of Engineering & Housing X * Environmental Management Office X * Fort Hood, TX 76544-5057 X */ X X#include <stdio.h> X#include <sys/types.h> X#include <sys/stat.h> X#include "msdos.h" X Xint fd; /* the file descriptor for the floppy */ Xint dir_start; /* starting sector for directory */ Xint dir_len; /* length of directory (in sectors) */ Xint dir_entries; /* number of directory entries */ Xint dir_chain[25]; /* chain of sectors in directory */ Xint clus_size; /* cluster size (in sectors) */ Xint fat_len; /* length of FAT table (in sectors) */ Xint num_clus; /* number of available clusters */ Xunsigned char *fatbuf; /* the File Allocation Table */ Xchar *mcwd; /* the Current Working Directory */ X Xint full = 0; Xint textmode = 0; Xint nowarn = 0; Xint filesize; X Xmain(argc, argv) Xint argc; Xchar *argv[]; X{ X extern int optind; X extern char *optarg; X int i, entry, ismatch, nogo, slot, start, dot, subdir(), single; X int isdir(), root, c, oops; X char *filename, *newfile, tname[9], text[4], *fixname(), *getname(); X char *unixname(), ans[10], *strncpy(), *pathname, *getpath(), *fixed; X char *tmp, *malloc(), *strcat(), *strcpy(); X void exit(); X struct directory *dir, *search(), *writeit(); X X if (init(2)) { X fprintf(stderr, "mwrite: Cannot initialize diskette\n"); X exit(1); X } X /* get command line options */ X oops = 0; X while ((c = getopt(argc, argv, "tn")) != EOF) { X switch(c) { X case 't': X textmode = 1; X break; X case 'n': X nowarn = 1; X break; X default: X oops = 1; X break; X } X } X X if (oops || (argc - optind) < 2) { X fprintf(stderr, "Usage: mwrite [-t|-n] <Unix file> <MSDOS file>\n"); X fprintf(stderr, " or mwrite [-t|-n] <Unix file> [<Unix files...>] <MSDOS directory>\n"); X exit(1); X } X root = 0; X if (!strcmp(argv[argc-1], "/") || !strcmp(argv[argc-1], "\\")) X root = 1; X filename = getname(argv[argc-1]); X pathname = getpath(argv[argc-1]); X /* test if path is ok first */ X if (subdir(pathname)) X exit(1); X /* test if last argv is a dir */ X if (isdir(filename) || root) { X if (!strlen(pathname)) { X /* don't alter the presence or */ X /* absence of a leading separator */ X tmp = malloc(strlen(filename)+1); X strcpy(tmp, filename); X } X else { X tmp = malloc(strlen(pathname)+1+strlen(filename)+1); X strcpy(tmp, pathname); X strcat(tmp, "/"); X strcat(tmp, filename); X } X /* subdir is not recursive */ X subdir(tmp); X single = 0; X } X else X single = 1; X X for (i=optind; i<argc-1; i++) { X if (single) { X fixed = fixname(argv[argc-1]); X filename = unixname(fixed, fixed+8); X } X else { X fixed = fixname(argv[i]); X filename = unixname(fixed, fixed+8); X printf("Copying %s\n", filename); X } X /* see if exists and get slot */ X ismatch = 0; X slot = -1; X dot = 0; X nogo = 0; X for (entry=0; entry<dir_entries; entry++) { X dir = search(entry); X /* is empty */ X if (dir->name[0] == NULL) { X if (slot < 0) X slot = entry; X break; X } X /* is erased */ X if (dir->name[0] == 0xe5) { X if (slot < 0) X slot = entry; X continue; X } X strncpy(tname, dir->name, 8); X strncpy(text, dir->ext, 3); X newfile = unixname(tname, text); X /* save the '.' entry info */ X if ((dir->attr & 0x10) && !strcmp(".", newfile)) { X dot = dir->start[1]*0x100 + dir->start[0]; X continue; X } X /* is dir or volume lable */ X if ((dir->attr & 0x10) || (dir->attr & 0x08)) X continue; X /* if file exists, delete it first */ X if (!strcmp(filename, newfile)) { X ismatch = 1; X start = dir->start[1]*0x100 + dir->start[0]; X if (nowarn) { X zapit(start); X dir->name[0] = 0xe5; X writedir(entry, dir); X if (slot < 0) X slot = entry; X } else { X while (1) { X printf("File '%s' exists, overwrite (y/n) ? ", filename); X gets(ans); X if (ans[0] == 'n' || ans[0] == 'N') { X nogo = 1; X break; X } X if (ans[0] == 'y' || ans[0] == 'Y') { X zapit(start); X dir->name[0] = 0xe5; X writedir(entry, dir); X if (slot < 0) X slot = entry; X break; X } X } X } X } X if (ismatch) X break; X } X if (nogo) /* chickened out... */ X continue; X /* no '.' entry means root directory */ X if (dot == 0 && slot < 0) { X printf(stderr, "mwrite: No directory slots\n"); X exit(1); X } X /* make the directory grow */ X if (dot && slot < 0) { X if (grow(dot)) { X fprintf(stderr, "mwrite: Disk full\n"); X exit(1); X } X /* first entry in 'new' directory */ X slot = entry; X } X /* write the file */ X dir = writeit(fixed, argv[i]); X if (dir != NULL) X writedir(slot, dir); X X if (full) { X fprintf(stderr, "mwrite: Disk Full\n"); X break; X } X if (single) X break; X } X /* write FAT sectors */ X writefat(); X close(fd); X exit(0); X} X X/* X * Open the named file for write, create the cluster chain, return the X * directory structure. X */ X Xstruct directory * Xwriteit(fixed, path) Xchar *fixed; Xchar *path; X{ X FILE *fp; X int size, fat, firstfat, oldfat, nextfat(), putcluster(), putfat(); X struct directory *mk_entry(); X static struct directory *dir; X struct stat stbuf; X X if (stat(path, &stbuf) < 0) { X fprintf(stderr, "mwrite: Can't stat '%s'\n", path); X return(NULL); X } X filesize = stbuf.st_size; X if (!(fp = fopen(path, "r"))) { X fprintf(stderr, "mwrite: Can't open '%s' for read\n", path); X return(NULL); X } X size = 0; X firstfat = nextfat(0); X if (firstfat == -1) { X full = 1; X return(NULL); X } X fat = firstfat; X while (1) { X size += putcluster(fat, fp); X if (size >= filesize) { X putfat(fat, 0xfff); X break; X } X oldfat = fat; X /* get next free cluster */ X fat = nextfat(oldfat); X if (fat == -1) { X putfat(oldfat, 0xfff); X full = 1; X break; X } X putfat(oldfat, fat); X } X fclose(fp); X dir = mk_entry(fixed, 0, firstfat, size); X return(dir); X} X X/* X * Write to the cluster from the named Unix file descriptor. X */ X Xint Xputcluster(num, fp) Xint num; XFILE *fp; X{ X long start; X void exit(), perror(); X int buflen, c; X static int current; X char tbuf[CLSTRBUF]; X X start = (num - 2)*clus_size + dir_start + dir_len; X move(start); X X buflen = clus_size * MSECSIZ; X /* '\n' to '\r\n' translation */ X if (textmode) { X current = 0; X while (current < buflen) { X if ((c = fgetc(fp)) == EOF) { X /* put a file EOF marker */ X tbuf[current] = 0x1a; X break; X } X if (c == '\n') { X tbuf[current++] = '\r'; X if (current == buflen) X break; X tbuf[current++] = '\n'; X /* make the file appear larger */ X filesize++; X } X else X tbuf[current++] = c; X } X } X else { X if ((current = fread(tbuf, sizeof(char), buflen, fp)) < 0) { X perror("putcluster: fread"); X exit(1); X } X /* all files get an EOF marker */ X if (current != buflen) X tbuf[current+1] = 0x1a; X } X X if (write(fd, tbuf, buflen) != buflen) { X perror("putcluster: write"); X exit(1); X } X return(current); X} X X/* X * Returns next free cluster or -1 if none are available. X */ X Xint Xnextfat(last) Xint last; X{ X static int i; X X for (i=last+1; i<num_clus+2; i++) { X if (!getfat(i)) X return(i); X } X return(-1); X} SHAR_EOF if test 7247 -ne "`wc -c < 'mwrite.c'`" then echo shar: "error transmitting 'mwrite.c'" '(should have been 7247 characters)' fi fi echo shar: "extracting 'putfat.c'" '(3118 characters)' if test -f 'putfat.c' then echo shar: "will not over-write existing file 'putfat.c'" else sed 's/^X//' << \SHAR_EOF > 'putfat.c' X/* X * putfat(), writedir(), zapit(), writefat() X */ X X#include <stdio.h> X#include "msdos.h" X#undef DUP_FAT X Xextern int fd, fat_len, dir_chain[25]; Xextern unsigned char *fatbuf; X X/* X * Puts a code into the FAT table. Is the opposite of getfat(). No X * sanity checking is done on the code. Returns a 1 on error. X */ X Xint Xputfat(num, code) Xint num; Xunsigned int code; X{ X/* X * |0|1|2|3|4|5|6|7|0|1|2|3|4|5|6|7|0|1|2|3|4|5|6|7| X * | | | | | | | | | | | | | | | | | | | | | | | | | X * | n.0 | n.5 | n+1.0 | n+1.5 | n+2.0 | n+2.5 | X * \_____ \____ \______/________/_____ / X * ____\______\________/ _____/ ____\_/ X * / \ \ / / \ X * | n+1.5 | n.0 | n.5 | n+2.0 | n+2.5 | n+1.0 | X * | FAT entry k | FAT entry k+1 | X */ X int start; X /* which bytes contain the entry */ X start = num * 3 / 2; X if (start < 0 || start+1 > (fat_len * MSECSIZ)) X return(1); X /* (odd) not on byte boundary */ X if (num % 2) { X *(fatbuf+start) = (*(fatbuf+start) & 0x0f) + ((code << 4) & 0xf0); X *(fatbuf+start+1) = (code >> 4) & 0xff; X } X /* (even) on byte boundary */ X else { X *(fatbuf+start) = code & 0xff; X *(fatbuf+start+1) = (*(fatbuf+start+1) & 0xf0) + ((code >> 8) & 0x0f); X } X return(0); X} X X/* X * Write a directory entry. The first argument is the directory entry X * number to write to. The second is a pointer to the directory itself. X * All errors are fatal. X */ X Xwritedir(num, dir) Xint num; Xstruct directory *dir; X{ X int skip, entry; X void exit(), perror(); X static struct directory dirs[16]; X /* which sector */ X skip = dir_chain[num / 16]; X X move(skip); X /* read the sector */ X if (read(fd, (char *) &dirs[0], MSECSIZ) != MSECSIZ) { X perror("writedir: read"); X exit(1); X } X /* which entry in sector */ X entry = num % 16; X /* copy the structure */ X dirs[entry] = *dir; X move(skip); X /* write the sector */ X if (write(fd, (char *) &dirs[0], MSECSIZ) != MSECSIZ) { X perror("writedir: write"); X exit(1); X } X return; X} X X/* X * Remove a string of FAT entries (delete the file). The argument is X * the beginning of the string. Does not consider the file length, so X * if FAT is corrupted, watch out! All errors are fatal. X */ X Xzapit(fat) Xint fat; X{ X int next; X X while (1) { X /* get next cluster number */ X next = getfat(fat); X /* mark current cluster as empty */ X if (putfat(fat, 0) || next == -1) { X fprintf(stderr, "zapit: FAT problem\n"); X exit(1); X } X if (next >= 0xff8) X break; X fat = next; X } X return; X} X X/* X * Write the FAT table to the disk. Up to now the FAT manipulation has X * been done in memory. All errors are fatal. (Might not be too smart X * to wait till the end of the program to write the table. Oh well...) X */ X Xwritefat() X{ X int buflen; X X move(1); X buflen = fat_len * MSECSIZ; X if (write(fd, fatbuf, buflen) != buflen) { X perror("writefat: write"); X exit(1); X } X#ifdef DUP_FAT X /* the duplicate FAT table */ X if (write(fd, fatbuf, buflen) != buflen) { X perror("writefat: write"); X exit(1); X } X#endif DUP_FAT X return; X} SHAR_EOF if test 3118 -ne "`wc -c < 'putfat.c'`" then echo shar: "error transmitting 'putfat.c'" '(should have been 3118 characters)' fi fi echo shar: "extracting 'search.c'" '(1075 characters)' if test -f 'search.c' then echo shar: "will not over-write existing file 'search.c'" else sed 's/^X//' << \SHAR_EOF > 'search.c' X/* X * Search and extract a directory structure. The argument is the X * relative directory entry number (no sanity checking). It returns a X * pointer to the directory structure at that location. Attempts to X * optimize by trying to determine if the buffer needs to be re-read. X * A call to writedir() will scribble on the real buffer, so watch out! X */ X X#include <stdio.h> X#include "msdos.h" X /* dir_chain contains the list of sectors */ X /* that make up the current directory */ Xextern int fd, dir_chain[25]; X Xstruct directory * Xsearch(num) Xint num; X{ X int skip, entry; X void exit(), perror(); X static int last; X static struct directory dirs[16]; X X /* first call disables optimzation */ X if (num == 0) X last = 0; X /* which sector */ X skip = dir_chain[num / 16]; X /* don't read it if same sector */ X if (skip != last) { X move(skip); X /* read the sector */ X if (read(fd, (char *) &dirs[0], MSECSIZ) != MSECSIZ) { X perror("mread: read"); X exit(1); X } X } X last = skip; X /* which entry in sector */ X entry = num % 16; X return(&dirs[entry]); X} SHAR_EOF if test 1075 -ne "`wc -c < 'search.c'`" then echo shar: "error transmitting 'search.c'" '(should have been 1075 characters)' fi fi echo shar: "extracting 'subdir.c'" '(3843 characters)' if test -f 'subdir.c' then echo shar: "will not over-write existing file 'subdir.c'" else sed 's/^X//' << \SHAR_EOF > 'subdir.c' X/* X * subdir(), getdir(), get_chain(), reset_dir() X */ X X#include <stdio.h> X#include "msdos.h" X Xextern int dir_chain[25], dir_start, dir_len, dir_entries, clus_size; Xextern char *mcwd; Xstatic char *lastpath; X X/* X * Parse the path names of a sub directory. Both '/' and '\' are X * valid separators. However, the use of '\' will force the operator X * to use quotes in the command line to protect '\' from the shell. X * Returns 1 on error. Attempts to optimize by remembering the last X * path it parsed X */ X Xsubdir(name) Xchar *name; X{ X char *s, *tmp, *path, *malloc(), *strcpy(), *strcat(); X static int code; X int getdir(); X /* if full pathname */ X if (*name == '/' || *name == '\\') { X tmp = malloc(strlen(name)+1); X strcpy(tmp, name); X } X /* if relative to MCWD */ X else { X if (!strlen(name)) { X tmp = malloc(strlen(mcwd)+1); X strcpy(tmp, mcwd); X } X else { X tmp = malloc(strlen(mcwd)+1+strlen(name)+1); X strcpy(tmp, mcwd); X strcat(tmp, "/"); X strcat(tmp, name); X } X } X /* if paths are same, do nothing */ X if (!strcmp(tmp, lastpath)) X return(0); X /* not recursive, start at root */ X reset_dir(); X lastpath = malloc(strlen(tmp)+1); X strcpy(lastpath, tmp); X /* zap the leading separator */ X if (*tmp == '\\' || *tmp == '/') X tmp++; X for (s = tmp; *s; ++s) { X if (*s == '\\' || *s == '/') { X path = tmp; X *s = NULL; X if (getdir(path)) X return(1); X tmp = s+1; X } X } X code = getdir(tmp); X return(code); X} X X/* X * Find the directory and get the starting cluster. A null directory X * is ok. Returns a 1 on error. X */ X Xint Xgetdir(path) Xchar *path; X{ X int entry, start, get_chain(); X char *newname, *unixname(), *strncpy(), name[9], ext[4]; X struct directory *dir, *search(); X X /* nothing required */ X if (*path == NULL) X return(0); X X for (entry=0; entry<dir_entries; entry++) { X dir = search(entry); X /* if empty */ X if (dir->name[0] == NULL) X break; X /* if erased */ X if (dir->name[0] == 0xe5) X continue; X /* skip if not a directory */ X if (!(dir->attr & 0x10)) X continue; X strncpy(name, dir->name, 8); X name[8] = NULL; X strncpy(ext, dir->ext, 3); X ext[3] = NULL; X newname = unixname(name, ext); X if (!strcmp(newname, path)) { X start = dir->start[1]*0x100 + dir->start[0]; X /* if '..' pointing to root */ X if (!start && !strcmp(path, "..")) { X reset_dir(); X return(0); X } X /* fill in the directory chain */ X dir_entries = get_chain(start) * 16; X return(0); X } X } X /* if '.' or '..', must be root */ X if (!strcmp(path, ".") || !strcmp(path, "..")) { X reset_dir(); X return(0); X } X fprintf(stderr, "Path component '%s' is not a directory\n", path); X return(1); X} X X/* X * Fill in the global variable dir_chain. Argument is the starting X * cluster number. Info, in this variable is used by search() to X * scan a directory. An arbitrary limit of 25 sectors is placed, this X * equates to 400 entries. Returns the number of sectors in the chain. X */ X Xint Xget_chain(num) /* fill the directory chain */ Xint num; X{ X int next; X static int i; X void exit(); X X i = 0; X while (1) { X dir_chain[i] = (num - 2)*clus_size + dir_start + dir_len; X /* sectors, not clusters! */ X if (clus_size == 2) { X dir_chain[i+1] = dir_chain[i] + 1; X i++; X } X i++; X if (i >= 25) { X fprintf(stderr, "get_chain: directory too large\n"); X exit(1); X } X /* get next cluster number */ X next = getfat(num); X if (next == -1) { X fprintf(stderr, "get_chain: FAT problem\n"); X exit(1); X } X /* end of cluster chain */ X if (next >= 0xff8) { X break; X } X num = next; X } X return(i); X} X X/* X * Reset the global variable dir_chain to the root directory. X */ X Xreset_dir() X{ X int i; X X for (i=0; i<dir_len; i++) X dir_chain[i] = dir_start + i; X dir_entries = dir_len * 16; X /* disable subdir() optimization */ X lastpath = "\0"; X return; X} SHAR_EOF if test 3843 -ne "`wc -c < 'subdir.c'`" then echo shar: "error transmitting 'subdir.c'" '(should have been 3843 characters)' fi fi echo shar: "extracting 'unixname.c'" '(2293 characters)' if test -f 'unixname.c' then echo shar: "will not over-write existing file 'unixname.c'" else sed 's/^X//' << \SHAR_EOF > 'unixname.c' X/* X * unixname(), getname(), getpath() X */ X X#include <stdio.h> X#include <ctype.h> X X/* X * Get rid of spaces in a MSDOS 'raw' name (one that has come from the X * directory structure) so that it can be used for regular expression X * matching with a unix file name. Also used to 'unfix' a name that has X * been altered by fixname(). Returns a pointer to the unix style name. X */ X Xchar * Xunixname(name, ext) Xchar *name; Xchar *ext; X{ X static char *ans; X char *s, tname[9], text[4], *strcpy(), *strcat(), *malloc(); X char *strchr(), *strncpy(); X X strncpy(tname, name, 8); X s = strchr(tname, ' '); X if (s != NULL) X *s = NULL; X tname[8] = NULL; X X strncpy(text, ext, 3); X s = strchr(text, ' '); X if (s != NULL) X *s = NULL; X text[3] = NULL; X X if (*text != NULL) { X ans = malloc(strlen(tname)+1+strlen(text)+1); X strcpy(ans, tname); X strcat(ans, "."); X strcat(ans, text); X } X else { X ans = malloc(strlen(tname)+1); X strcpy(ans, tname); X } X return(ans); X} X X/* X * Get name component of filename. Translates name to upper case. Returns X * pointer to new name. Could be NULL. X */ X Xchar * Xgetname(name) Xchar *name; X{ X char *s, *malloc(), *strcpy(), *strrchr(); X static char *temp; X X if (*name == NULL) X return(NULL); X X temp = malloc(strlen(name)+1); X strcpy(temp, name); X X if (s = strrchr(temp, '/')) X temp = s+1; X if (s = strrchr(temp, '\\')) X temp = s+1; X X for (s = temp; *s; ++s) { X if (islower(*s)) X *s = toupper(*s); X } X return(temp); X} X X/* X * Get the path component of the filename. Translates to upper case. X * Returns pointer to path or NULL if no path exist. Doesn't alter X * leading separator, always strips trailing separator (unless it is the X * path itself). X */ X Xchar * Xgetpath(name) Xchar *name; X{ X char *s, *s1, *malloc(), *strcpy(), *strrchr(); X static char *temp; X X if (*name == NULL) X return(NULL); X X temp = malloc(strlen(name)+1); X strcpy(temp, name); X X s = strrchr(temp, '/'); X s1 = strrchr(temp, '\\'); X /* if both are NULL , no path */ X if (s1 == s) X return(NULL); X /* zap which ever is last separator */ X if (s1 > s) X *s1 = NULL; X if (s > s1) X *s = NULL; X /* translate to upper case */ X for (s = temp; *s; ++s) { X if (islower(*s)) X *s = toupper(*s); X } X /* if null, put separator back */ X if (!strlen(temp)) X temp = "/"; X return(temp); X} SHAR_EOF if test 2293 -ne "`wc -c < 'unixname.c'`" then echo shar: "error transmitting 'unixname.c'" '(should have been 2293 characters)' fi fi exit 0 # End of shell archive