home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-01-10 | 40.8 KB | 1,615 lines |
- Newsgroups: comp.sources.unix
- From: fthood!egray@uxc.cso.uiuc.edu (Emmet P. Gray)
- Subject: v25i099: mtools2 - tools to manipulate MSDOS filesystems, V2.0, Part03/03
- Sender: sources-moderator@pa.dec.com
- Approved: vixie@pa.dec.com
-
- Submitted-By: fthood!egray@uxc.cso.uiuc.edu (Emmet P. Gray)
- Posting-Number: Volume 25, Issue 99
- Archive-Name: mtools2/part03
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 3 (of 3)."
- # Contents: mtools/Makefile mtools/init.c mtools/mdir.c mtools/mread.c
- # mtools/mwrite.c
- # Wrapped by lai@risotto on Sat Jan 11 12:03:35 1992
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'mtools/Makefile' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'mtools/Makefile'\"
- else
- echo shar: Extracting \"'mtools/Makefile'\" \(6713 characters\)
- sed "s/^X//" >'mtools/Makefile' <<'END_OF_FILE'
- X#
- X# Makefile for Mtools
- X#
- X# check the Configure file for some examples of device-specific setups
- X# Berkeley flavors of Unix should include -DBSD in the CFLAGS
- X
- XCFLAGS = -O
- XLDFLAGS = -s
- XLD = cc
- XLINT = lint
- XSHLIB =
- XSHAR = shar -a
- XBINDIR = /usr/local/bin
- XMANSECT = 1
- XMANDIR = /usr/man/man$(MANSECT)
- X#
- X# for AT&T Unix PC 7300/3b1 style shared libraries.
- X#SHOBJ = /lib/crt0s.o /lib/shlib.ifile
- X#LD = ld
- X
- XPROGS = mattrib mcd mcopy mdel mdir mformat mlabel mmd mrd mread mren \
- X mtype mwrite mkmanifest
- X
- XMATTRIB = mattrib.o buf_read.o buf_write.o devices.o dir_read.o \
- X dir_write.o expand.o fat_read.o init.o match.o parse.o subdir.o
- XMCD = mcd.o buf_read.o devices.o dir_read.o expand.o fat_read.o \
- X init.o is_dir.o match.o parse.o subdir.o
- XMCOPY = mcopy.o
- XMDEL = mdel.o buf_read.o buf_write.o devices.o dir_read.o dir_write.o \
- X expand.o fat_free.o fat_read.o fat_write.o init.o match.o parse.o \
- X subdir.o
- XMDIR = mdir.o buf_read.o devices.o dir_read.o expand.o fat_read.o \
- X init.o is_dir.o match.o parse.o subdir.o
- XMFORMAT = mformat.o devices.o dir_write.o expand.o
- XMLABEL = mlabel.o buf_read.o buf_write.o devices.o dir_read.o \
- X dir_write.o expand.o fat_read.o init.o
- XMMD = mmd.o buf_read.o buf_write.o devices.o dir_make.o dir_read.o \
- X dir_write.o expand.o fat_read.o fat_write.o init.o match.o parse.o \
- X subdir.o
- XMRD = mrd.o buf_read.o buf_write.o devices.o dir_read.o dir_write.o \
- X expand.o fat_free.o fat_read.o fat_write.o init.o match.o parse.o \
- X subdir.o
- XMREAD = mread.o buf_read.o devices.o dir_read.o expand.o fat_read.o \
- X file_read.o init.o match.o parse.o subdir.o
- XMREN = mren.o buf_read.o buf_write.o devices.o dir_read.o dir_write.o \
- X expand.o fat_read.o init.o match.o parse.o subdir.o
- XMTYPE = mtype.o buf_read.o devices.o dir_read.o expand.o fat_read.o \
- X file_read.o init.o match.o parse.o subdir.o
- XMWRITE = mwrite.o buf_read.o buf_write.o devices.o dir_make.o \
- X dir_read.o dir_write.o expand.o fat_free.o fat_read.o fat_write.o \
- X file_write.o init.o is_dir.o match.o parse.o subdir.o
- XMKMANIFEST = mkmanifest.o
- X
- Xall: $(PROGS)
- X
- Xmattrib: $(MATTRIB)
- X $(LD) $(LDFLAGS) $(MATTRIB) $(SHOBJ) -o mattrib $(SHLIB)
- X
- Xmcd: $(MCD)
- X $(LD) $(LDFLAGS) $(MCD) $(SHOBJ) -o mcd $(SHLIB)
- X
- Xmcopy: $(MCOPY)
- X $(LD) $(LDFLAGS) $(MCOPY) $(SHOBJ) -o mcopy $(SHLIB)
- X
- Xmdel: $(MDEL)
- X $(LD) $(LDFLAGS) $(MDEL) $(SHOBJ) -o mdel $(SHLIB)
- X
- Xmdir: $(MDIR)
- X $(LD) $(LDFLAGS) $(MDIR) $(SHOBJ) -o mdir $(SHLIB)
- X
- Xmformat: $(MFORMAT)
- X $(LD) $(LDFLAGS) $(MFORMAT) $(SHOBJ) -o mformat $(SHLIB)
- X
- Xmlabel: $(MLABEL)
- X $(LD) $(LDFLAGS) $(MLABEL) $(SHOBJ) -o mlabel $(SHLIB)
- X
- Xmmd: $(MMD)
- X $(LD) $(LDFLAGS) $(MMD) $(SHOBJ) -o mmd $(SHLIB)
- X
- Xmrd: $(MRD)
- X $(LD) $(LDFLAGS) $(MRD) $(SHOBJ) -o mrd $(SHLIB)
- X
- Xmread: $(MREAD)
- X $(LD) $(LDFLAGS) $(MREAD) $(SHOBJ) -o mread $(SHLIB)
- X
- Xmren: $(MREN)
- X $(LD) $(LDFLAGS) $(MREN) $(SHOBJ) -o mren $(SHLIB)
- X
- Xmtype: $(MTYPE)
- X $(LD) $(LDFLAGS) $(MTYPE) $(SHOBJ) -o mtype $(SHLIB)
- X
- Xmwrite: $(MWRITE)
- X $(LD) $(LDFLAGS) $(MWRITE) $(SHOBJ) -o mwrite $(SHLIB)
- X
- Xmkmanifest: $(MKMANIFEST)
- X $(LD) $(LDFLAGS) $(MKMANIFEST) $(SHOBJ) -o mkmanifest $(SHLIB)
- X
- Xinstall:
- X cp $(PROGS) $(BINDIR)
- X
- Xinstall_man:
- X cp Mattrib.1 $(MANDIR)/mattrib.$(MANSECT)
- X cp Mcd.1 $(MANDIR)/mcd.$(MANSECT)
- X cp Mcopy.1 $(MANDIR)/mcopy.$(MANSECT)
- X cp Mdel.1 $(MANDIR)/mdel.$(MANSECT)
- X cp Mdir.1 $(MANDIR)/mdir.$(MANSECT)
- X cp Mformat.1 $(MANDIR)/mformat.$(MANSECT)
- X cp Mlabel.1 $(MANDIR)/mlabel.$(MANSECT)
- X cp Mmd.1 $(MANDIR)/mmd.$(MANSECT)
- X cp Mrd.1 $(MANDIR)/mrd.$(MANSECT)
- X cp Mread.1 $(MANDIR)/mread.$(MANSECT)
- X cp Mren.1 $(MANDIR)/mren.$(MANSECT)
- X cp Mtools.1 $(MANDIR)/mtools.$(MANSECT)
- X cp Mtype.1 $(MANDIR)/mtype.$(MANSECT)
- X cp Mwrite.1 $(MANDIR)/mwrite.$(MANSECT)
- X cp Mkmanifest.1 $(MANDIR)/mkmanifest.$(MANSECT)
- X
- Xclean:
- X rm $(PROGS)
- X
- Xlint:
- X $(LINT) mattrib.c buf_read.c buf_write.c devices.c dir_read.c \
- X dir_write.c expand.c fat_read.c init.c match.c parse.c subdir.c
- X $(LINT) mcd.c buf_read.c devices.c dir_read.c expand.c fat_read.c \
- X init.c is_dir.c match.c parse.c subdir.c
- X $(LINT) mcopy.c
- X $(LINT) mdel.c buf_read.c buf_write.c devices.c dir_read.c dir_write.c \
- X expand.c fat_free.c fat_read.c fat_write.c init.c match.c parse.c \
- X subdir.c
- X $(LINT) mdir.c buf_read.c devices.c dir_read.c expand.c fat_read.c \
- X init.c is_dir.c match.c parse.c subdir.c
- X $(LINT) mformat.c devices.c dir_write.c expand.c
- X $(LINT) mlabel.c buf_read.c buf_write.c devices.c dir_read.c \
- X dir_write.c expand.c fat_read.c init.c
- X $(LINT) mmd.c buf_read.c buf_write.c devices.c dir_make.c dir_read.c \
- X dir_write.c expand.c fat_read.c fat_write.c init.c match.c parse.c \
- X subdir.c
- X $(LINT) mrd.c buf_read.c buf_write.c devices.c dir_read.c dir_write.c \
- X expand.c fat_free.c fat_read.c fat_write.c init.c match.c parse.c \
- X subdir.c
- X $(LINT) mread.c buf_read.c devices.c dir_read.c expand.c fat_read.c \
- X file_read.c init.c match.c parse.c subdir.c
- X $(LINT) mren.c buf_read.c buf_write.c devices.c dir_read.c dir_write.c \
- X expand.c fat_read.c init.c match.c parse.c subdir.c
- X $(LINT) mtype.c buf_read.c devices.c dir_read.c expand.c fat_read.c \
- X file_read.c init.c match.c parse.c subdir.c
- X $(LINT) mwrite.c buf_read.c buf_write.c devices.c dir_make.c \
- X dir_read.c dir_write.c expand.c fat_free.c fat_read.c fat_write.c \
- X file_write.c init.c is_dir.c match.c parse.c subdir.c
- X $(LINT) mkmanifest.c
- X
- Xshar:
- X $(SHAR) Configure Makefile Mattrib.1 Mcd.1 Mcopy.1 Mdel.1 Mdir.1 \
- X Mformat.1 Mkmanifest.1 Mlabel.1 Mmd.1 Mrd.1 Mread.1 Mren.1 \
- X Mtools.1 Mtype.1 Mwrite.1 Readme Release.notes buf_read.c \
- X buf_write.c devices.c dir_make.c dir_read.c dir_write.c expand.c \
- X fat_free.c > mtools_sh.1
- X $(SHAR) fat_read.c fat_write.c file_read.c file_write.c init.c \
- X is_dir.c match.c mattrib.c mcd.c mcopy.c mdel.c mdir.c mformat.c \
- X mkmanifest.c mlabel.c mmd.c > mtools_sh.2
- X $(SHAR) mrd.c mread.c mren.c msdos.h mtype.c mwrite.c parse.c \
- X patchlevel.h subdir.c > mtools_sh.3
- X $(SHAR) Mattrib.out Mcd.out Mcopy.out Mdel.out Mdir.out Mformat.out \
- X Mkmanifest.out Mlabel.out Mmd.out Mrd.out Mread.out Mren.out \
- X Mtools.out Mtype.out Mwrite.out > mtools_sh.4
- X
- Xbuf_read.o: msdos.h
- Xbuf_write.o: msdos.h
- Xdevices.o: msdos.h
- Xdir_make.o: msdos.h
- Xdir_read.o: msdos.h
- Xdir_write.o: msdos.h
- Xfat_free.o: msdos.h
- Xfat_read.o: msdos.h
- Xfat_write.o: msdos.h
- Xfile_read.o: msdos.h
- Xfile_write.o: msdos.h
- Xinit.o: msdos.h
- Xis_dir.o: msdos.h
- Xmattrib.o: msdos.h patchlevel.h
- Xmcd.o: msdos.h patchlevel.h
- Xmcopy.o: patchlevel.h
- Xmdel.o: msdos.h patchlevel.h
- Xmdir.o: msdos.h patchlevel.h
- Xmformat.o: msdos.h patchlevel.h
- Xmlabel.o: msdos.h patchlevel.h
- Xmmd.o: msdos.h patchlevel.h
- Xmrd.o: msdos.h patchlevel.h
- Xmread.o: msdos.h patchlevel.h
- Xmren.o: msdos.h patchlevel.h
- Xmtype.o: msdos.h patchlevel.h
- Xmwrite.o: msdos.h patchlevel.h
- Xparse.o: msdos.h
- Xsubdir.o: msdos.h
- END_OF_FILE
- if test 6713 -ne `wc -c <'mtools/Makefile'`; then
- echo shar: \"'mtools/Makefile'\" unpacked with wrong size!
- fi
- # end of 'mtools/Makefile'
- fi
- if test -f 'mtools/init.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'mtools/init.c'\"
- else
- echo shar: Extracting \"'mtools/init.c'\" \(7669 characters\)
- sed "s/^X//" >'mtools/init.c' <<'END_OF_FILE'
- X/*
- X * Initialize an MSDOS diskette. Read the boot sector, and switch to the
- X * proper floppy disk device to match the format on the disk. Sets a bunch
- X * of global variables. Returns 0 on success, or 1 on failure.
- X */
- X
- X#include <stdio.h>
- X#include <ctype.h>
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#include "msdos.h"
- X
- X#define FULL_CYL
- X#define WORD(x) ((boot->x)[0] + ((boot->x)[1] << 8))
- X#define DWORD(x) ((boot->x)[0] + ((boot->x)[1] << 8) + ((boot->x)[2] << 16) + ((boot->x)[3] << 24))
- X
- Xunsigned int num_clus; /* total number of cluster */
- Xint num_fat; /* the number of FAT tables */
- Xlong disk_offset; /* skip this many bytes */
- Xint fat_bits; /* the FAT encoding scheme */
- X
- Xextern int fd, fat_len, dir_len, dir_start, clus_size, dir_dirty, disk_dirty;
- Xextern int fat_error, disk_size;
- Xextern long disk_current;
- Xextern char *mcwd;
- Xextern unsigned char *fat_buf, *disk_buf, *dir_buf;
- Xextern struct device devices[];
- Xstatic struct bootsector *read_boot();
- X
- Xint
- Xinit(drive, mode)
- Xchar drive;
- Xint mode;
- X{
- X int fat_start, tracks, heads, sectors, old_dos;
- X char *malloc(), *name, *expand();
- X void perror(), exit(), reset_chain(), free(), fat_read();
- X struct bootsector *boot;
- X struct device *dev;
- X
- X if (fd != -1) {
- X close(fd);
- X free((char *) fat_buf);
- X free((char *) disk_buf);
- X free((char *) dir_buf);
- X }
- X /* check out the drive letter */
- X dev = devices;
- X while (dev->drive) {
- X if (dev->drive == drive)
- X break;
- X dev++;
- X }
- X if (!dev->drive) {
- X fprintf(stderr, "Drive '%c:' not supported\n", drive);
- X return(1);
- X }
- X /* open the device */
- X while (dev->name) {
- X if (dev->drive != drive)
- X break;
- X
- X name = expand(dev->name);
- X if ((fd = open(name, mode | dev->mode)) < 0) {
- X perror("init: open");
- X exit(1);
- X }
- X /* set default parameters, if needed */
- X if (dev->gioctl) {
- X if ((*(dev->gioctl)) (fd, dev->tracks, dev->heads, dev->sectors))
- X goto try_again;
- X }
- X /* read the boot sector */
- X disk_offset = dev->offset;
- X if ((boot = read_boot()) == NULL)
- X goto try_again;
- X
- X heads = WORD(nheads);
- X sectors = WORD(nsect);
- X if (heads && sectors)
- X tracks = WORD(psect) / (unsigned) (heads * sectors);
- X
- X /* sanity checking */
- X old_dos = 0;
- X if (!heads || heads > 100 || !sectors || sectors > 500 || tracks > 5000 || !boot->clsiz) {
- X /*
- X * The above technique will fail on diskettes that
- X * have been formatted with very old MSDOS, so we
- X * resort to the old table-driven method using the
- X * media signature (first byte in FAT).
- X */
- X unsigned char temp[MSECTOR_SIZE];
- X if (read(fd, (char *) temp, MSECTOR_SIZE) != MSECTOR_SIZE)
- X temp[0] = '0';
- X
- X switch (temp[0]) {
- X case 0xfe: /* 160k */
- X tracks = 40;
- X sectors = 8;
- X heads = 1;
- X dir_start = 3;
- X dir_len = 4;
- X clus_size = 1;
- X fat_len = 1;
- X num_clus = 313;
- X break;
- X case 0xfc: /* 180k */
- X tracks = 40;
- X sectors = 9;
- X heads = 1;
- X dir_start = 5;
- X dir_len = 4;
- X clus_size = 1;
- X fat_len = 2;
- X num_clus = 351;
- X break;
- X case 0xff: /* 320k */
- X tracks = 40;
- X sectors = 8;
- X heads = 2;
- X dir_start = 3;
- X dir_len = 7;
- X clus_size = 2;
- X fat_len = 1;
- X num_clus = 315;
- X break;
- X case 0xfd: /* 360k */
- X tracks = 40;
- X sectors = 9;
- X heads = 2;
- X dir_start = 5;
- X dir_len = 7;
- X clus_size = 2;
- X fat_len = 2;
- X num_clus = 354;
- X break;
- X default:
- X fprintf(stderr, "Probable non-MSDOS disk\n");
- X close(fd);
- X fd = -1;
- X return(1);
- X }
- X fat_start = 1;
- X num_fat = 2;
- X old_dos = 1;
- X }
- X /* check the parameters */
- X if (dev->tracks && !dev->gioctl) {
- X if (dev->tracks == tracks && dev->heads == heads && dev->sectors == sectors)
- X break;
- X }
- X else
- X break;
- X
- Xtry_again: close(fd);
- X fd = -1;
- X dev++;
- X }
- X if (fd == -1) {
- X if (boot != NULL && dev->tracks)
- X fprintf(stderr, "No support for %d tracks, %d heads, %d sector diskettes\n", tracks, heads, sectors);
- X return(1);
- X }
- X /* set new parameters, if needed */
- X if (dev->gioctl) {
- X if ((*(dev->gioctl)) (fd, tracks, heads, sectors)) {
- X fprintf(stderr, "Can't set disk parameters\n");
- X close(fd);
- X fd = -1;
- X return(1);
- X }
- X }
- X
- X /*
- X * all numbers are in sectors, except num_clus (which is in clusters)
- X */
- X if (!old_dos) {
- X clus_size = boot->clsiz;
- X fat_start = WORD(nrsvsect);
- X fat_len = WORD(fatlen);
- X dir_start = fat_start + (boot->nfat * fat_len);
- X dir_len = WORD(dirents) * MDIR_SIZE / (unsigned) MSECTOR_SIZE;
- X /*
- X * For DOS partitions > 32M
- X */
- X if (WORD(psect) == 0)
- X num_clus = (unsigned int) (DWORD(bigsect) - dir_start - dir_len) / clus_size;
- X else
- X num_clus = (unsigned int) (WORD(psect) - dir_start - dir_len) / clus_size;
- X num_fat = boot->nfat;
- X }
- X /* more sanity checking */
- X if (clus_size * MSECTOR_SIZE > MAX_CLUSTER) {
- X fprintf(stderr, "Cluster size of %d is larger than max of %d\n", clus_size * MSECTOR_SIZE, MAX_CLUSTER);
- X close(fd);
- X fd = -1;
- X return(1);
- X }
- X if (!old_dos && WORD(secsiz) != MSECTOR_SIZE) {
- X fprintf(stderr, "Sector size of %d is not supported\n", WORD(secsiz));
- X close(fd);
- X fd = -1;
- X return(1);
- X }
- X /* full cylinder buffering */
- X#ifdef FULL_CYL
- X disk_size = (dev->tracks) ? (sectors * heads) : 1;
- X#else /* FULL_CYL */
- X disk_size = (dev->tracks) ? sectors : 1;
- X#endif /* FULL_CYL */
- X
- X/*
- X * The driver in Dell's SVR4 v2.01 is unreliable with large writes.
- X */
- X#ifdef DELL
- X disk_size = 1;
- X#endif /* DELL */
- X
- X disk_buf = (unsigned char *) malloc((unsigned int) disk_size * MSECTOR_SIZE);
- X if (disk_buf == NULL) {
- X perror("init: malloc");
- X exit(1);
- X }
- X /* read the FAT sectors */
- X disk_current = -1000L;
- X disk_dirty = 0;
- X fat_error = 0;
- X fat_bits = dev->fat_bits;
- X fat_read(fat_start);
- X /* set dir_chain[] to root directory */
- X dir_dirty = 0;
- X reset_chain(NEW);
- X return(0);
- X}
- X
- X/*
- X * Fix the info in the MCWD file to be a proper directory name. Always
- X * has a leading separator. Never has a trailing separator (unless it is
- X * the path itself).
- X */
- X
- Xchar *
- Xfix_mcwd()
- X{
- X FILE *fp;
- X struct stat sbuf;
- X char *s, *strcpy(), *strcat(), *mcwd_path, *getenv(), *strncpy();
- X char buf[BUFSIZ], *file, *expand();
- X static char ans[MAX_PATH];
- X long now, time();
- X
- X mcwd_path = getenv("MCWD");
- X if (mcwd_path == NULL || *mcwd_path == '\0')
- X mcwd_path = "$HOME/.mcwd";
- X
- X file = expand(mcwd_path);
- X if (stat(file, &sbuf) < 0)
- X return("A:/");
- X /*
- X * Ignore the info, if the file is more than 6 hours old
- X */
- X time(&now);
- X if (now - sbuf.st_mtime > 6 * 60 * 60) {
- X fprintf(stderr, "Warning: \"%s\" is out of date, contents ignored\n", file);
- X return("A:/");
- X }
- X
- X if (!(fp = fopen(file, "r")))
- X return("A:/");
- X
- X if (!fgets(buf, BUFSIZ, fp))
- X return("A:/");
- X
- X buf[strlen(buf) -1] = '\0';
- X fclose(fp);
- X /* drive letter present? */
- X s = buf;
- X if (buf[0] && buf[1] == ':') {
- X strncpy(ans, buf, 2);
- X ans[2] = '\0';
- X s = &buf[2];
- X }
- X else
- X strcpy(ans, "A:");
- X /* add a leading separator */
- X if (*s != '/' && *s != '\\') {
- X strcat(ans, "/");
- X strcat(ans, s);
- X }
- X else
- X strcat(ans, s);
- X /* translate to upper case */
- X for (s = ans; *s; ++s) {
- X if (islower(*s))
- X *s = toupper(*s);
- X if (*s == '\\')
- X *s = '/';
- X }
- X /* if only drive, colon, & separator */
- X if (strlen(ans) == 3)
- X return(ans);
- X /* zap the trailing separator */
- X if (*--s == '/')
- X *s = '\0';
- X return(ans);
- X}
- X
- X/*
- X * Read the boot sector. We glean the disk parameters from this sector.
- X */
- X
- Xstatic struct bootsector *
- Xread_boot()
- X{
- X long lseek();
- X static struct bootsector boot;
- X
- X if (lseek(fd, disk_offset, 0) < 0)
- X return(NULL);
- X /* read the first sector */
- X if (read(fd, (char *) &boot, MSECTOR_SIZE) != MSECTOR_SIZE)
- X return(NULL);
- X
- X return(&boot);
- X}
- END_OF_FILE
- if test 7669 -ne `wc -c <'mtools/init.c'`; then
- echo shar: \"'mtools/init.c'\" unpacked with wrong size!
- fi
- # end of 'mtools/init.c'
- fi
- if test -f 'mtools/mdir.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'mtools/mdir.c'\"
- else
- echo shar: Extracting \"'mtools/mdir.c'\" \(7059 characters\)
- sed "s/^X//" >'mtools/mdir.c' <<'END_OF_FILE'
- X/*
- X * Display an MSDOS directory
- X *
- X * Emmet P. Gray US Army, HQ III Corps & Fort Hood
- X * ...!uunet!uiucuxc!fthood!egray Attn: AFZF-DE-ENV
- X * fthood!egray@uxc.cso.uiuc.edu 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#include "patchlevel.h"
- X
- Xint fd = -1; /* the file descriptor for the device */
- Xint dir_start; /* starting sector for directory */
- Xint dir_len; /* length of directory (in sectors) */
- Xint dir_entries; /* number of directory entries */
- Xint clus_size; /* cluster size (in sectors) */
- Xchar *mcwd; /* the Current Working Directory */
- Xint fat_error; /* FAT error detected? */
- X
- Xstatic long getfree();
- Xstatic char *conv_date(), *conv_time();
- X
- Xmain(argc, argv)
- Xint argc;
- Xchar *argv[];
- X{
- X int i, entry, files, fargn, wide, faked;
- X long size, blocks;
- X char *date, *time, last_drive, *fix_mcwd();
- X char *strncpy(), newpath[MAX_PATH], *get_name(), *get_path(), *pathname;
- X char *newfile, *filename, *unix_name(), volume[12], drive, *strpbrk();
- X char *strcpy(), *strcat(), newname[13], *strncat(), get_drive();
- X void exit();
- X struct directory *dir, *dir_read();
- X
- X fargn = 1;
- X wide = 0;
- X files = 0;
- X /* first argument */
- X if (argc > 1) {
- X if (!strcmp(argv[1], "-w")) {
- X wide = 1;
- X fargn = 2;
- X }
- X if (argv[1][0] == '-' && !wide) {
- X fprintf(stderr, "%s: illegal option -- %c\n", argv[0], argv[1][1]);
- X fprintf(stderr, "Mtools version %s, dated %s\n", VERSION, DATE);
- X fprintf(stderr, "Usage: %s: [-w] msdosdirectory\n", argv[0]);
- X fprintf(stderr, " %s: [-w] msdosfile [msdosfiles...]\n", argv[0]);
- X exit(1);
- X }
- X }
- X /* fake an argument */
- X faked = 0;
- X if (argc == fargn) {
- X faked++;
- X argc++;
- X }
- X last_drive = 'x';
- X mcwd = fix_mcwd();
- X
- X for (i = fargn; i < argc; i++) {
- X if (faked) {
- X drive = get_drive("");
- X filename = get_name("");
- X pathname = get_path("");
- X }
- X else {
- X drive = get_drive(argv[i]);
- X filename = get_name(argv[i]);
- X pathname = get_path(argv[i]);
- X }
- X /* is this a new device? */
- X if (drive != last_drive) {
- X if (last_drive != 'x') {
- X blocks = getfree() * MSECTOR_SIZE;
- X if (!files)
- X printf("File \"%s\" not found\n\n", newname);
- X else
- X printf(" %3d File(s) %6ld bytes free\n\n", files, blocks);
- X }
- X if (init(drive, 0)) {
- X fprintf(stderr, "%s: Cannot initialize '%c:'\n", argv[0], drive);
- X continue;
- X }
- X last_drive = drive;
- X files = 0;
- X /* find the volume label */
- X volume[0] = '\0';
- X for (entry = 0; entry < dir_entries; entry++) {
- X dir = dir_read(entry);
- X
- X /* if empty */
- X if (dir->name[0] == 0x0)
- X break;
- X
- X /* if erased */
- X if (dir->name[0] == 0xe5)
- X continue;
- X
- X /* if not volume label */
- X if (!(dir->attr & 0x08))
- X continue;
- X
- X strncpy(volume, (char *) dir->name, 8);
- X volume[8] = '\0';
- X strncat(volume, (char *) dir->ext, 3);
- X volume[11] = '\0';
- X break;
- X }
- X if (volume[0] == '\0')
- X printf(" Volume in drive %c has no label\n", drive);
- X else
- X printf(" Volume in drive %c is %s\n", drive, volume);
- X }
- X
- X /*
- X * Move to "first guess" subdirectory, so that is_dir() can
- X * search to see if filename is also a directory.
- X */
- X if (subdir(drive, pathname))
- X continue;
- X
- X /*
- X * Under MSDOS, wildcards that match directories don't
- X * display the contents of that directory. So I guess I'll
- X * do that too.
- X */
- X if ((strpbrk(filename, "*[?") == NULL) && is_dir(filename)) {
- X strcpy(newpath, pathname);
- X if (newpath[strlen(newpath) -1] != '/')
- X strcat(newpath, "/");
- X strcat(newpath, filename);
- X
- X /* move to real subdirectory */
- X if (subdir(drive, newpath))
- X continue;
- X
- X strcpy(newname, "*");
- X }
- X else {
- X strcpy(newpath, pathname);
- X strcpy(newname, filename);
- X }
- X /* if no files, assume '*' */
- X if (*filename == '\0')
- X strcpy(newname, "*");
- X
- X printf(" Directory for %c:%s\n\n", drive, newpath);
- X
- X for (entry = 0; entry < dir_entries; entry++) {
- X dir = dir_read(entry);
- X /* if empty */
- X if (dir->name[0] == 0x0)
- X break;
- X /* if erased */
- X if (dir->name[0] == 0xe5)
- X continue;
- X /* if a volume label */
- X if (dir->attr & 0x08)
- X continue;
- X
- X newfile = unix_name(dir->name, dir->ext);
- X if (!match(newfile, newname))
- X continue;
- X
- X files++;
- X if (wide && files != 1) {
- X if (!((files - 1) % 5))
- X putchar('\n');
- X }
- X date = conv_date(dir->date[1], dir->date[0]);
- X time = conv_time(dir->time[1], dir->time[0]);
- X size = dir->size[3] * 0x1000000L + dir->size[2] * 0x10000L + dir->size[1] * 0x100 + dir->size[0];
- X /* is a subdirectory */
- X if (dir->attr & 0x10) {
- X if (wide)
- X printf("%-8.8s %-3.3s ", dir->name, dir->ext);
- X else
- X printf("%-8.8s %-3.3s <DIR> %s %s\n", dir->name, dir->ext, date, time);
- X continue;
- X }
- X if (wide)
- X printf("%-8.8s %-3.3s ", dir->name, dir->ext);
- X else
- X printf("%-8.8s %-3.3s %8ld %s %s\n", dir->name, dir->ext, size, date, time);
- X }
- X if (argc > 2)
- X putchar('\n');
- X }
- X if (fd < 0)
- X exit(1);
- X
- X blocks = getfree() * MSECTOR_SIZE;
- X if (!files)
- X printf("File \"%s\" not found\n", newname);
- X else
- X printf(" %3d File(s) %6ld bytes free\n", files, blocks);
- X close(fd);
- X exit(0);
- X}
- X
- X/*
- X * Get the amount of free space on the diskette
- X */
- X
- Xstatic long
- Xgetfree()
- X{
- X register unsigned int i;
- X long total;
- X extern unsigned int num_clus;
- X unsigned int fat_decode();
- X
- X total = 0L;
- X for (i = 2; i < num_clus + 2; i++) {
- X /* if fat_decode returns zero */
- X if (!fat_decode(i))
- X total += clus_size;
- X }
- X return(total);
- X}
- X
- X/*
- X * Convert an MSDOS directory date stamp to ASCII
- X */
- X
- Xstatic char *
- Xconv_date(date_high, date_low)
- Xunsigned date_high, date_low;
- X{
- X/*
- X * hi byte | low byte
- X * |7|6|5|4|3|2|1|0|7|6|5|4|3|2|1|0|
- X * | | | | | | | | | | | | | | | | |
- X * \ 7 bits /\4 bits/\ 5 bits /
- X * year +80 month day
- X */
- X static char ans[9];
- X unsigned char year, month_hi, month_low, day;
- X
- X year = (date_high >> 1) + 80;
- X month_hi = (date_high & 0x1) << 3;
- X month_low = date_low >> 5;
- X day = date_low & 0x1f;
- X sprintf(ans, "%2d-%02d-%02d", month_hi + month_low, day, year);
- X return(ans);
- X}
- X
- X/*
- X * Convert an MSDOS directory time stamp to ASCII.
- X */
- X
- Xstatic char *
- Xconv_time(time_high, time_low)
- Xunsigned time_high, time_low;
- X{
- X/*
- X * hi byte | low byte
- X * |7|6|5|4|3|2|1|0|7|6|5|4|3|2|1|0|
- X * | | | | | | | | | | | | | | | | |
- X * \ 5 bits /\ 6 bits /\ 5 bits /
- X * hour minutes sec*2
- X */
- X static char ans[7];
- X char am_pm;
- X unsigned char hour, min_hi, min_low;
- X
- X hour = time_high >> 3;
- X am_pm = (hour >= 12) ? 'p' : 'a';
- X if (hour > 12)
- X hour = hour - 12;
- X if (hour == 0)
- X hour = 12;
- X min_hi = (time_high & 0x7) << 3;
- X min_low = time_low >> 5;
- X sprintf(ans, "%2d:%02d%c", hour, min_hi + min_low, am_pm);
- X return(ans);
- X}
- X
- X/*
- X * stubs for read-only programs
- X */
- X
- Xvoid
- Xdisk_flush()
- X{
- X extern int disk_dirty;
- X
- X disk_dirty = 0;
- X return;
- X}
- X
- Xvoid
- Xdir_flush()
- X{
- X extern int dir_dirty;
- X
- X dir_dirty = 0;
- X return;
- X}
- END_OF_FILE
- if test 7059 -ne `wc -c <'mtools/mdir.c'`; then
- echo shar: \"'mtools/mdir.c'\" unpacked with wrong size!
- fi
- # end of 'mtools/mdir.c'
- fi
- if test -f 'mtools/mread.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'mtools/mread.c'\"
- else
- echo shar: Extracting \"'mtools/mread.c'\" \(7810 characters\)
- sed "s/^X//" >'mtools/mread.c' <<'END_OF_FILE'
- X/*
- X * Read (copy) an MSDOS file to Unix
- X *
- X * Emmet P. Gray US Army, HQ III Corps & Fort Hood
- X * ...!uunet!uiucuxc!fthood!egray Attn: AFZF-DE-ENV
- X * fthood!egray@uxc.cso.uiuc.edu Directorate of Engineering & Housing
- X * Environmental Management Office
- X * Fort Hood, TX 76544-5057
- X */
- X
- X#define LOWERCASE
- X
- X#include <stdio.h>
- X#include <ctype.h>
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#ifdef BSD
- X#include <sys/time.h>
- X#else /* BSD */
- X#include <time.h>
- X#endif /* BSD */
- X#include "msdos.h"
- X#include "patchlevel.h"
- X
- Xint fd = -1; /* the file descriptor for the device */
- Xint dir_start; /* starting sector for directory */
- Xint dir_len; /* length of directory (in sectors) */
- Xint dir_entries; /* number of directory entries */
- Xint clus_size; /* cluster size (in sectors) */
- Xchar *mcwd; /* the Current Working Directory */
- Xint fat_error; /* FAT error detected? */
- X
- Xstatic void set_mtime();
- Xstatic FILE *open_file();
- Xstatic long conv_stamp();
- X
- Xmain(argc, argv)
- Xint argc;
- Xchar *argv[];
- X{
- X FILE *fp;
- X extern int optind;
- X extern char *optarg;
- X int i, ismatch, entry, single, c, oops, preserve, nowarn, textmode;
- X unsigned int fat;
- X long size, mtime;
- X char *filename, *newfile, *get_name(), *unix_name(), *pathname;
- X char *get_path(), *target, tmp[MAX_PATH], *strcat(), *strcpy(), drive;
- X char get_drive(), last_drive, *fix_mcwd(), *s;
- X void exit();
- X struct directory *dir, *dir_read();
- X struct stat stbuf;
- X
- X /* get command line options */
- X oops = 0;
- X preserve = 0;
- X nowarn = 0;
- X textmode = 0;
- X while ((c = getopt(argc, argv, "tnmv")) != EOF) {
- X switch (c) {
- X case 't':
- X textmode = 1;
- X break;
- X case 'n':
- X nowarn = 1;
- X break;
- X case 'm':
- X preserve = 1;
- X break;
- X case 'v': /* dummy option for mcopy */
- X break;
- X default:
- X oops = 1;
- X break;
- X }
- X }
- X
- X if (oops || (argc - optind) < 2) {
- X fprintf(stderr, "Mtools version %s, dated %s\n", VERSION, DATE);
- X fprintf(stderr, "Usage: %s [-tnm] msdosfile unixfile\n", argv[0]);
- X fprintf(stderr, " %s [-tnm] msdosfile [msdosfiles...] unixdirectory\n", argv[0]);
- X exit(1);
- X }
- X last_drive = 'x';
- X mcwd = fix_mcwd();
- 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 & S_IFMT) == S_IFDIR)
- X single = 0;
- X }
- X /* too many arguments */
- X if (single && (argc - optind) != 2) {
- X fprintf(stderr, "%s: Too many arguments or destination directory omitted\n", argv[0]);
- X exit(1);
- X }
- X
- X for (i = optind; i < argc - 1; i++) {
- X drive = get_drive(argv[i]);
- X if (drive != last_drive) {
- X if (init(drive, 0)) {
- X fprintf(stderr, "%s: Cannot initialize '%c:'\n", argv[0], drive);
- X continue;
- X }
- X last_drive = drive;
- X }
- X filename = get_name(argv[i]);
- X pathname = get_path(argv[i]);
- X if (subdir(drive, pathname))
- X continue;
- X
- X ismatch = 0;
- X for (entry = 0; entry < dir_entries; entry++) {
- X dir = dir_read(entry);
- X /* if empty */
- X if (dir->name[0] == 0x0)
- X break;
- X /* if erased */
- X if (dir->name[0] == 0xe5)
- X continue;
- X /* if dir or volume label */
- X if ((dir->attr & 0x10) || (dir->attr & 0x08))
- X continue;
- X
- X newfile = unix_name(dir->name, dir->ext);
- X
- X /* if single file */
- X if (single) {
- X if (!strcmp(newfile, filename)) {
- X fat = dir->start[1] * 0x100 + dir->start[0];
- X size = dir->size[3] * 0x1000000L + dir->size[2] * 0x10000L + dir->size[1] * 0x100 + dir->size[0];
- X if (preserve)
- X mtime = conv_stamp(dir->time, dir->date);
- X else
- X mtime = 0L;
- X if ((fp = open_file(target, nowarn))) {
- X if (file_read(fp, fat, textmode, 0, size)) {
- X fclose(fp);
- X break;
- X }
- X fclose(fp);
- X set_mtime(target, mtime);
- X }
- X ismatch = 1;
- X break;
- X }
- X }
- X /* if multiple files */
- X else {
- X if (match(newfile, filename)) {
- X fat = dir->start[1] * 0x100 + dir->start[0];
- X size = dir->size[3] * 0x1000000L + dir->size[2] * 0x10000L + dir->size[1] * 0x100 + dir->size[0];
- X if (preserve)
- X mtime = conv_stamp(dir->time, dir->date);
- X else
- X mtime = 0L;
- X printf("Copying %s\n", newfile);
- X#ifdef LOWERCASE
- X s = newfile;
- X while (*s) {
- X if (isupper(*s))
- X *s = tolower(*s);
- X s++;
- X }
- X#endif /* LOWERCASE */
- X strcpy(tmp, target);
- X strcat(tmp, "/");
- X strcat(tmp, newfile);
- X if ((fp = open_file(tmp, nowarn))) {
- X if (file_read(fp, fat, textmode, 0, size)) {
- X fclose(fp);
- X break;
- X }
- X fclose(fp);
- X set_mtime(tmp, mtime);
- X }
- X ismatch = 1;
- X }
- X }
- X }
- X if (fat_error)
- X break;
- X
- X if (!ismatch)
- X fprintf(stderr, "%s: File \"%s\" not found\n", argv[0], filename);
- X }
- X close(fd);
- X exit(0);
- X}
- X
- X/*
- X * Open the named Unix file for write.
- X */
- X
- Xstatic FILE *
- Xopen_file(target, nowarn)
- Xchar *target;
- Xint nowarn;
- X{
- X static FILE *fp;
- X char ans[10];
- X struct stat stbuf;
- X
- X if (!nowarn) {
- X if (!access(target, 0)) {
- X /* CONSTCOND */
- 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(NULL);
- X if (ans[0] == 'y' || ans[0] == 'Y')
- X break;
- X }
- X /* sanity checking */
- X if (!stat(target, &stbuf)) {
- X if ((stbuf.st_mode & S_IFREG) != S_IFREG) {
- X fprintf(stderr, "\"%s\" is not a regular file\n", target);
- X return(NULL);
- X }
- X }
- X }
- X }
- X
- X if (!(fp = fopen(target, "w"))) {
- X fprintf(stderr, "Can't open \"%s\" for write\n", target);
- X return(NULL);
- X }
- X return(fp);
- X}
- X
- X/*
- X * Convert an MSDOS time & date stamp to the Unix time() format
- X */
- X
- Xstatic long
- Xconv_stamp(time_field, date_field)
- Xunsigned char *time_field, *date_field;
- X{
- X#ifdef BSD
- X struct timeval tv;
- X struct timezone tz;
- X#else /* BSD */
- X extern long timezone;
- X void tzset();
- X#endif /* BSD */
- X struct tm *tmbuf, *localtime();
- X int year, mon, mday, hour, min, sec, old_leaps;
- X long answer, sec_year, sec_mon, sec_mday, sec_hour, sec_min, sec_leap;
- X long tzone, dst;
- X static int month[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304,
- X 334};
- X /* dissect the parts */
- X year = (date_field[1] >> 1) + 1980;
- X mon = (((date_field[1] & 0x1) << 3) + (date_field[0] >> 5));
- X mday = date_field[0] & 0x1f;
- X hour = time_field[1] >> 3;
- X min = (((time_field[1] & 0x7) << 3) + (time_field[0] >> 5));
- X sec = (time_field[0] & 0x1f) * 2;
- X /* how many previous leap years */
- X old_leaps = (year - 1972) / 4L;
- X sec_leap = old_leaps * 24L * 60L * 60L;
- X /* back off 1 day if before 29 Feb */
- X if (!(year % 4) && mon < 3)
- X sec_leap -= 24L * 60L * 60L;
- X sec_year = (year - 1970) * 365L * 24L * 60L * 60L;
- X sec_mon = month[mon - 1] * 24L * 60L * 60L;
- X sec_mday = mday * 24L * 60L * 60L;
- X sec_hour = hour * 60L * 60L;
- X sec_min = min * 60L;
- X /* correct for Time Zone */
- X#ifdef BSD
- X gettimeofday(&tv, &tz);
- X tzone = tz.tz_minuteswest * 60L;
- X#else /* BSD */
- X tzset();
- X tzone = timezone;
- X#endif /* BSD */
- X
- X answer = sec_leap + sec_year + sec_mon + sec_mday + sec_hour + sec_min + sec + tzone;
- X /* correct for Daylight Saving Time */
- X tmbuf = localtime(&answer);
- X dst = (tmbuf->tm_isdst) ? (-60L * 60L) : 0L;
- X answer += dst;
- X
- X return(answer);
- X}
- X
- X/*
- X * Preserve the file modification times after the fclose()
- X */
- X
- Xstatic void
- Xset_mtime(target, mtime)
- Xchar *target;
- Xlong mtime;
- X{
- X#ifdef BSD
- X struct timeval tv[2];
- X
- X if (mtime != 0L) {
- X tv[0].tv_sec = mtime;
- X tv[0].tv_usec = 0;
- X tv[1].tv_sec = mtime;
- X tv[1].tv_usec = 0;
- X utimes(target, tv);
- X }
- X#else /* BSD */
- X struct {
- X time_t actime;
- X time_t modtime;
- X } utbuf;
- X
- X if (mtime != 0L) {
- X utbuf.actime = mtime;
- X utbuf.modtime = mtime;
- X utime(target, &utbuf);
- X }
- X#endif /* BSD */
- X return;
- X}
- X
- X/*
- X * stubs for read-only programs
- X */
- X
- Xvoid
- Xdisk_flush()
- X{
- X extern int disk_dirty;
- X
- X disk_dirty = 0;
- X return;
- X}
- X
- Xvoid
- Xdir_flush()
- X{
- X extern int dir_dirty;
- X
- X dir_dirty = 0;
- X return;
- X}
- END_OF_FILE
- if test 7810 -ne `wc -c <'mtools/mread.c'`; then
- echo shar: \"'mtools/mread.c'\" unpacked with wrong size!
- fi
- # end of 'mtools/mread.c'
- fi
- if test -f 'mtools/mwrite.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'mtools/mwrite.c'\"
- else
- echo shar: Extracting \"'mtools/mwrite.c'\" \(7770 characters\)
- sed "s/^X//" >'mtools/mwrite.c' <<'END_OF_FILE'
- X/*
- X * Write (copy) a Unix file to MSDOS
- X *
- X * Emmet P. Gray US Army, HQ III Corps & Fort Hood
- X * ...!uunet!uiucuxc!fthood!egray Attn: AFZF-DE-ENV
- X * fthood!egray@uxc.cso.uiuc.edu Directorate of Engineering & Housing
- X * Environmental Management Office
- X * Fort Hood, TX 76544-5057
- X */
- X
- X#include <stdio.h>
- X#include <signal.h>
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#include "msdos.h"
- X#include "patchlevel.h"
- X
- Xint fd = -1; /* the file descriptor for the device */
- Xint dir_start; /* starting sector for directory */
- Xint dir_len; /* length of directory (in sectors) */
- Xint dir_entries; /* number of directory entries */
- Xint clus_size; /* cluster size (in sectors) */
- Xchar *mcwd; /* the Current Working Directory */
- Xint fat_error; /* FAT error detected? */
- X
- Xint full = 0;
- Xint textmode = 0;
- Xint nowarn = 0;
- Xstatic int got_signal();
- Xstatic struct directory *writeit();
- Xstatic long free_space();
- X
- Xmain(argc, argv)
- Xint argc;
- Xchar *argv[];
- X{
- X extern int optind;
- X extern char *optarg;
- X int i, entry, ismatch, nogo, slot, single;
- X int c, oops, verbose, first, mod_time;
- X unsigned int dot, start;
- X char *filename, *newfile, *get_name(), get_drive();
- X char *unix_name(), ans[10], *pathname, *get_path(), *fix_mcwd();
- X char tmp[MAX_PATH], target[13], *strcat(), *strcpy(), drive;
- X unsigned char *fixed, *dos_name();
- X void exit(), fat_write(), dir_write(), disk_flush(), dir_flush();
- X struct directory *dir, *dir_read();
- X /* catch signals */
- X signal(SIGINT, (SIG_TYPE(*) ()) got_signal);
- X signal(SIGTERM, (SIG_TYPE(*) ()) got_signal);
- X signal(SIGQUIT, (SIG_TYPE(*) ()) got_signal);
- X /* get command line options */
- X oops = 0;
- X verbose = 0;
- X mod_time = 0;
- X while ((c = getopt(argc, argv, "tnvm")) != EOF) {
- X switch (c) {
- X case 't':
- X textmode = 1;
- X break;
- X case 'n':
- X nowarn = 1;
- X break;
- X case 'v':
- X verbose = 1;
- X break;
- X case 'm':
- X mod_time = 1;
- X break;
- X default:
- X oops = 1;
- X break;
- X }
- X }
- X
- X if (oops || (argc - optind) < 2) {
- X fprintf(stderr, "Mtools version %s, dated %s\n", VERSION, DATE);
- X fprintf(stderr, "Usage: %s [-tnvm] unixfile msdosfile\n", argv[0]);
- X fprintf(stderr, " %s [-tnvm] unixfile [unixfiles...] msdosdirectory\n", argv[0]);
- X exit(1);
- X }
- X mcwd = fix_mcwd();
- X
- X drive = get_drive(argv[argc - 1]);
- X if (init(drive, 2)) {
- X fprintf(stderr, "%s: Cannot initialize '%c:'\n", argv[0], drive);
- X exit(1);
- X }
- X
- X filename = get_name(argv[argc - 1]);
- X pathname = get_path(argv[argc - 1]);
- X
- X /*
- X * Move to "first guess" directory so we can see if filename is also
- X * a directory.
- X */
- X if (subdir(drive, pathname))
- X exit(1);
- X /* test if last argv is a dir */
- X if (is_dir(filename) || *filename == '\0') {
- X if (*filename) {
- X strcpy(tmp, pathname);
- X if (tmp[strlen(tmp) -1] != '/')
- X strcat(tmp, "/");
- X strcat(tmp, filename);
- X
- X if (subdir(drive, tmp))
- X exit(1);
- X }
- X single = 0;
- X }
- X else {
- X single = 1;
- X /* too many arguments */
- X if ((argc - optind) != 2) {
- X fprintf(stderr, "%s: Too many arguments or destination directory omitted\n", argv[0]);
- X exit(1);
- X }
- X }
- X
- X for (i = optind; i < argc - 1; i++) {
- X if (single)
- X fixed = dos_name(argv[argc - 1], verbose);
- X else
- X fixed = dos_name(argv[i], verbose);
- X
- X strcpy(target, unix_name(fixed, fixed + 8));
- X /* see if exists and get slot */
- X ismatch = 0;
- X slot = -1;
- X dot = 0;
- X nogo = 0;
- X first = 1;
- X for (entry = 0; entry < dir_entries; entry++) {
- X dir = dir_read(entry);
- X /* save the '.' entry info */
- X if (first) {
- X first = 0;
- X if ((dir->attr & 0x10) && dir->name[0] == '.') {
- X dot = dir->start[1] * 0x100 + dir->start[0];
- X continue;
- X }
- X }
- X /* is empty */
- X if (dir->name[0] == 0x0) {
- 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 /* is dir or volume label */
- X if ((dir->attr & 0x10) || (dir->attr & 0x08))
- X continue;
- X
- X newfile = unix_name(dir->name, dir->ext);
- X
- X /* if file exists, delete it first */
- X if (!strcmp(target, newfile)) {
- X ismatch = 1;
- X start = dir->start[1] * 0x100 + dir->start[0];
- X if (nowarn) {
- X if (fat_free(start))
- X break;
- X dir->name[0] = 0xe5;
- X dir_write(entry, dir);
- X if (slot < 0)
- X slot = entry;
- X }
- X else {
- X /* CONSTCOND */
- X while (1) {
- X printf("File \"%s\" exists, overwrite (y/n) ? ", target);
- 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 if (fat_free(start))
- X break;
- X dir->name[0] = 0xe5;
- X dir_write(entry, dir);
- X if (slot < 0)
- X slot = entry;
- X break;
- X }
- X }
- X }
- X }
- X if (ismatch)
- X break;
- X }
- X if (fat_error)
- X break;
- X
- X if (nogo) /* chickened out... */
- X continue;
- X /* no '.' entry means root directory */
- X if (dot == 0 && slot < 0) {
- X fprintf(stderr, "%s: No directory slots\n", argv[0]);
- X break;
- X }
- X /* make the directory grow */
- X if (dot && slot < 0) {
- X if (dir_grow(dot)) {
- X fprintf(stderr, "%s: Disk full\n", argv[0]);
- X break;
- X }
- X /* first entry in 'new' directory */
- X slot = entry;
- X }
- X /* write the file */
- X if (dir = writeit(fixed, argv[i], verbose, mod_time, single, target))
- X dir_write(slot, dir);
- X
- X if (full) {
- X fprintf(stderr, "%s: Disk full\n", argv[0]);
- X break;
- X }
- X if (single)
- X break;
- X }
- X /* write the FAT, flush the buffers */
- X fat_write();
- X dir_flush();
- X disk_flush();
- X close(fd);
- X exit(0);
- X}
- X
- X/*
- X * Open the named file for read, create the cluster chain, return the
- X * directory structure or NULL on error.
- X */
- X
- Xstatic struct directory *
- Xwriteit(fixed, path, verbose, mod_time, single, target)
- Xunsigned char *fixed;
- Xchar *path;
- Xint verbose, mod_time, single;
- Xchar *target;
- X{
- X FILE *fp;
- X unsigned int fat, next_fat();
- X long filesize, file_write(), size, time(), now;
- X struct directory *dir, *mk_entry();
- X struct stat stbuf;
- X
- X if (stat(path, &stbuf) < 0) {
- X fprintf(stderr, "Can't stat \"%s\"\n", path);
- X return(NULL);
- X }
- X
- X if ((stbuf.st_mode & S_IFMT) == S_IFDIR) {
- X if (verbose)
- X fprintf(stderr, "\"%s\" is a directory\n", path);
- X return(NULL);
- X }
- X
- X if ((stbuf.st_mode & S_IFREG) != S_IFREG) {
- X if (verbose)
- X fprintf(stderr, "\"%s\" is not a regular file\n", path);
- X return(NULL);
- X }
- X
- X if (!(fp = fopen(path, "r"))) {
- X fprintf(stderr, "Can't open \"%s\" for read\n", path);
- X return(NULL);
- X }
- X
- X if (!single)
- X printf("Copying %s\n", target);
- X
- X /* will it fit? */
- X filesize = stbuf.st_size;
- X if (filesize > free_space()) {
- X full = 1;
- X return(NULL);
- X }
- X /* preserve mod time? */
- X if (mod_time)
- X now = stbuf.st_mtime;
- X else
- X time(&now);
- X
- X /* if a zero length file */
- X if (filesize == 0L) {
- X dir = mk_entry(fixed, 0x20, 0, 0L, now);
- X return(dir);
- X }
- X
- X if ((fat = next_fat(0)) == 1) {
- X full = 1;
- X fclose(fp);
- X return(NULL);
- X }
- X if ((size = file_write(fp, fat, filesize, textmode)) < 0) {
- X fclose(fp);
- X return(NULL);
- X }
- X fclose(fp);
- X
- X dir = mk_entry(fixed, 0x20, fat, size, now);
- X return(dir);
- X}
- X
- X/*
- X * Do a graceful exit if the program is interrupted. This will reduce
- X * (but not eliminate) the risk of generating a corrupted disk on
- X * a user abort.
- X */
- X
- Xstatic int
- Xgot_signal()
- X{
- X void exit(), disk_flush(), fat_write(), dir_flush();
- X
- X if (fd < 0)
- X exit(1);
- X fat_write();
- X dir_flush();
- X disk_flush();
- X close(fd);
- X exit(1);
- X}
- X
- X
- X/*
- X * Get the amount of remaining free space
- X */
- X
- Xstatic long
- Xfree_space()
- X{
- X register unsigned int i;
- X long total;
- X extern unsigned int num_clus;
- X unsigned int fat_decode();
- X
- X total = 0L;
- X for (i = 2; i < num_clus + 2; i++) {
- X /* if fat_decode returns zero */
- X if (!fat_decode(i))
- X total += clus_size;
- X }
- X total *= MSECTOR_SIZE;
- X return(total);
- X}
- END_OF_FILE
- if test 7770 -ne `wc -c <'mtools/mwrite.c'`; then
- echo shar: \"'mtools/mwrite.c'\" unpacked with wrong size!
- fi
- # end of 'mtools/mwrite.c'
- fi
- echo shar: End of archive 3 \(of 3\).
- cp /dev/null ark3isdone
- MISSING=""
- for I in 1 2 3 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 3 archives.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-