home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
rtsi.com
/
2014.01.www.rtsi.com.tar
/
www.rtsi.com
/
OS9
/
OSK
/
SRC
/
msdos_diskaccess.lzh
/
MS_DISK_ACCESS
/
mread.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-08-04
|
7KB
|
316 lines
/*
* Read (copy) a MSDOS file to Unix
*
* Emmet P. Gray US Army, HQ III Corps & Fort Hood
* ...!uunet!uiucuxc!fthood!egray Attn: AFZF-DE-ENV
* Directorate of Engineering & Housing
* Environmental Management Office
* Fort Hood, TX 76544-5057
*/
#include <stdio.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "msdos.h"
#define LOWERCASE
int fd; /* the file descriptor for the floppy */
int dir_start; /* starting sector for directory */
int dir_len; /* length of directory (in sectors) */
int dir_entries; /* number of directory entries */
int dir_chain[25]; /* chain of sectors in directory */
int clus_size; /* cluster size (in sectors) */
int fat_len; /* length of FAT table (in sectors) */
int num_clus; /* number of available clusters */
unsigned char *fatbuf; /* the File Allocation Table */
char *buf; /* The input buffer */
long bufsiz; /* It's size */
int maxcontig; /* In clusters */
char *mcwd; /* the Current Working Directory */
extern union bootblock bb;
long size;
long current;
int textmode = 0;
int nowarn = 0;
main(argc, argv)
int argc;
char *argv[];
{
extern int optind;
extern char *optarg;
int fat, i, ismatch, entry, single, c, oops, mod_time;
long mod_date, convstamp();
char *filename, *newfile, text[4], tname[9], *getname(), *unixname();
char *strncpy(), *pathname, *getpath(), *target, tmp[MAX_PATH];
char *strcat(), *strcpy();
void perror(), exit(), free();
struct directory *dir, *search();
struct stat stbuf;
if (init(0)) {
fprintf(stderr, "mread: Cannot initialize diskette\n");
exit(1);
}
/* get command line options */
oops = 0;
mod_time = 0;
while ((c = getopt(argc, argv, "tnm")) != EOF) {
switch(c) {
case 't':
textmode = 1;
break;
case 'n':
nowarn = 1;
break;
case 'm':
mod_time = 1;
break;
default:
oops = 1;
break;
}
}
if (oops || (argc - optind) < 2) {
fprintf(stderr, "Usage: mread [-tn] msdosfile unixfile\n");
fprintf(stderr, " or mread [-tn] msdosfile [msdosfiles...] unixdirectory\n");
exit(1);
}
/* only 1 file to copy... */
single = 1;
target = argv[argc-1];
/* ...unless last arg is a directory */
if (!stat(target, &stbuf)) {
if ((stbuf.st_mode & S_IFMT) == S_IFDIR)
single = 0;
}
/* too many arguments */
if (single && (argc - optind) != 2) {
fprintf(stderr,
"mread: too many arguments or target dir omitted\n");
exit(1);
}
bufsiz = NSECT(bb.sb) * NTRACK(bb.sb) ;
maxcontig = (bufsiz += clus_size - (--bufsiz) % clus_size)/clus_size;
if ( (buf = (char *)malloc(bufsiz *= MSECSIZ)) == NULL ) {
fprintf(stderr,"Could not allocate input buffer\n");
exit(1) ;
}
for (i=optind; i<argc-1; i++) {
filename = getname(argv[i]);
pathname = getpath(argv[i]);
if (subdir(pathname)) {
free(filename);
free(pathname);
continue;
}
ismatch = 0;
for (entry=0; entry<dir_entries; entry++) {
dir = search(entry);
/* if empty */
if (dir->name[0] == 0x0)
break;
/* if erased */
if (dir->name[0] == 0xe5)
continue;
/* if dir or volume lable */
if ((dir->attr & 0x10) || (dir->attr & 0x08))
continue;
strncpy(tname, (char *) dir->name, 8);
strncpy(text, (char *) dir->ext, 3);
tname[8] = '\0';
text[3] = '\0';
newfile = unixname(tname, text);
fat = dir->start[1]*0x100 + dir->start[0];
size = dir->size[2]*0x10000L + dir->size[1]*0x100 + dir->size[0];
if (mod_time)
mod_date = convstamp(dir->time, dir->date);
else
mod_date = 0L;
/* if single file */
if (single) {
if (!strcmp(newfile, filename)) {
readit(fat, target, mod_date);
ismatch = 1;
break;
}
}
/* if multiple files */
else {
if (match(newfile, filename)) {
printf("Copying %s\n", newfile);
strcpy(tmp, target);
strcat(tmp, "/");
strcat(tmp, newfile);
readit(fat, tmp, mod_date);
ismatch = 1;
}
}
free(newfile);
}
if (!ismatch)
fprintf(stderr, "mread: File \"%s\" not found\n", filename);
free(filename);
free(pathname);
}
close(fd);
exit(0);
}
/*
* Decode the FAT chain given the begining FAT entry, open the named Unix
* file for write.
*/
static int readpos;
int
readit(fat, target, mod_date)
int fat;
char *target;
long mod_date;
{
void getclusters() ;
char ans[10];
void exit();
int curfat;
FILE *fp;
struct stat stbuf;
struct utimbuf {
time_t actime;
time_t modtime;
} utbuf;
#ifdef LOWERCASE
char *c;
c = target;
while(*c) {
if (isupper(*c))
*c = tolower(*c);
c++;
}
#endif /* LOWERCASE */
if (!nowarn) {
if (!access(target, 0)) {
while (1) {
printf("File \"%s\" exists, overwrite (y/n) ? ", target);
gets(ans);
if (ans[0] == 'n' || ans[0] == 'N')
return;
if (ans[0] == 'y' || ans[0] == 'Y')
break;
}
/* sanity checking */
if (!stat(target, &stbuf)) {
if ((stbuf.st_mode & S_IFREG) != S_IFREG) {
fprintf(stderr, "mread: \"%s\" is not a regular file\n", target);
return;
}
}
}
}
if (!(fp = fopen(target, "w"))) {
fprintf(stderr, "mread: Can't open \"%s\" for write\n", target);
return;
}
#ifdef OSK
fp->_bufsiz = 20480;
#endif
current = 0L;
readpos = -1;
for(;;) {
/*
* Find chain of contiguous clusters
* curfat -> last in chain + 1
*/
for(curfat=fat;
++curfat < fat + maxcontig &&
getfat(curfat-1)==curfat;) ;
getclusters(fat, curfat, fp);
/* get next cluster number */
fat = getfat(--curfat);
if (fat == -1) {
fprintf(stderr, "mread: FAT problem\n");
exit(1);
}
/* end of cluster chain */
if (fat >= 0xff8)
break;
}
if (fclose(fp)) {
fprintf(stderr,"Error closing %s\n",target) ;
perror("close?") ;
exit(1) ;
}
/* preserve mod times ? */
if (mod_date != 0L) {
utbuf.actime = mod_date;
utbuf.modtime = mod_date;
utime(target, &utbuf);
}
return;
}
/*
* Read the named cluster, write to the Unix file descriptor.
*/
void
getclusters(start, end, fp)
FILE *fp;
{
register int i;
int buflen, blk;
void exit(), perror(), move();
blk = (start - 2)*clus_size + dir_start + dir_len;
if (blk != readpos)
move(blk);
buflen = (end-start) * clus_size * MSECSIZ;
if (read(fd, (char *) buf, buflen) != buflen) {
perror("getcluster: read");
exit(1);
}
readpos = blk + (end-start)*clus_size;
/* stop at size not EOF marker */
if (textmode) {
for (i=0; i<buflen; i++) {
current++;
if (current > size)
break;
if ( buf[i] == '\l')
continue;
if ( current == size && buf[i] == 0x1a)
continue;
putc((char) buf[i], fp);
}
}
else {
buflen = (size > buflen) ? buflen : size;
if (fwrite(buf,buflen,1,fp)!=1) {
perror("getclusters: fwrite") ;
exit(1) ;
}
size -= buflen ;
}
return;
}