home *** CD-ROM | disk | FTP | other *** search
- /*
- * Initialize a MSDOS diskette. Read the boot block for disk layout
- * and switch to the proper floppy disk device to match the format
- * of the disk. Sets a bunch of global variables. Returns 0 on success,
- * or 1 on failure.
- */
-
- #include <stdio.h>
- #include <ctype.h>
- #include <signal.h>
- #include "devices.h"
- #include "msdos.h"
-
- /* #undef DUP_FAT */
-
- extern int fd, dir_len, dir_start, clus_size, fat_len, num_clus;
- extern unsigned char *fatbuf;
- extern char *mcwd;
-
- /* The available drivers */
- extern struct device fd_devices[];
-
- /* The bootblock */
- union bootblock bb ;
-
- int
- init(mode)
- int mode;
- {
- int code, buflen, intr();
- void perror(), exit(), move(), reset_dir();
- char *getenv(), *fixmcwd(), *malloc(), *dummy;
- long lseek();
- struct device *try;
- int ncyl = 0, nsect = 0, ntrack =0 ;
- char *floppy = getenv("FLOPPY");
-
- /*
- * Let the user set the geometry in the environment
- * It is possible for this to be the only way out of the catch-22
- * wherein the geometry needs to be read from the first block
- * which cannot be read until the geometry is set!
- */
-
- if ( dummy = getenv("NCYL") )
- ncyl = strtol(dummy,0,0) ;
- if ( dummy = getenv("NTRACK") )
- ntrack = strtol(dummy,0,0) ;
- if ( dummy = getenv("NSECT") )
- nsect = strtol(dummy,0,0) ;
-
- fd = -1 ;
-
- for ( try = fd_devices ; try->drv_dev ; ++try )
- if ( !floppy ||
- strncmp(try->drv_dev, floppy, strlen(floppy)) == 0 ) {
- (void) fprintf(stderr,"\nTrying %s ... ",try->drv_dev) ;
- fflush(stderr);
- if ( (fd = open(try->drv_dev, mode|try->drv_mode)) > 0 ) {
- if ( try->drv_ifunc && (*(try->drv_ifunc))(fd,ncyl,ntrack,nsect) ) {
- close(fd) ;
- fd = -1;
- continue ;
- }
- if( read_boot() ) {
- close(fd) ;
- fd = -1;
- continue ;
- }
- (void) fprintf(stderr,"ok\n") ;
- fflush(stderr) ;
- break ;
- }
- perror("open") ;
- }
-
- if ( fd < 0 ) {
- (void) fprintf(stderr,"All known devices failed.\nSorry.\n") ;
- exit(1) ;
- }
-
- dir_start = DIROFF(bb.sb) ;
- dir_len = DIRLEN(bb.sb);
- clus_size = CLSIZ(bb.sb);
- fat_len = FATLEN(bb.sb);
- num_clus = NCLUST(bb.sb);
-
- /* Set the parameters if needed */
- if ( try->drv_ifunc )
- if( (*(try->drv_ifunc))(fd,NCYL(bb.sb),NTRACK(bb.sb),NSECT(bb.sb)) )
- exit(1) ;
-
- buflen = fat_len * MSECSIZ;
- fatbuf = (unsigned char *) malloc((unsigned int) buflen);
-
- /* read the FAT sectors */
- move(FATOFF(bb.sb));
- if (read(fd, fatbuf, buflen) != buflen) {
- (void) fprintf(stderr,"Could not read the FAT table\n");
- perror("init: read");
- exit(1) ;
- }
-
- /* set dir_chain to root directory */
- reset_dir();
- /* get Current Working Directory */
- mcwd = fixmcwd(getenv("MCWD"));
- /* test it out.. */
- if (subdir("")) {
- (void) fprintf(stderr, "Environment variable MCWD needs updating\n");
- exit(1);
- }
- return(0);
- }
-
- /*
- * Set the logical sector. Non brain-dead drivers don't move the
- * head until we ask for data, so computing relative seeks is overkill.
- */
-
- void
- move(sector)
- int sector;
- {
- long lseek();
- void exit(), perror();
-
- if (lseek(fd, (long)sector*MSECSIZ, 0) < 0) {
- perror("move: lseek");
- exit(1);
- }
- }
-
- /*
- * Fix MCWD to be a proper directory name. Always has a leading separator.
- * Never has a trailing separator (unless it is the path itself).
- */
-
- char *
- fixmcwd(dirname)
- char *dirname;
- {
- char *s, *ans, *malloc(), *strcpy(), *strcat();
-
- if (dirname == NULL)
- return("/");
-
- ans = malloc((unsigned int) strlen(dirname)+2);
- /* add a leading separator */
- if (*dirname != '/' && *dirname != '\\') {
- strcpy(ans, "/");
- strcat(ans, dirname);
- }
- else
- strcpy(ans, dirname);
- /* translate to upper case */
- for (s = ans; *s; ++s) {
- if (islower(*s))
- *s = toupper(*s);
- }
- /* if separator alone */
- if (strlen(ans) == 1)
- return(ans);
- /* zap the trailing separator */
- s--;
- if (*s == '/' || *s == '\\')
- *s = '\0';
- return(ans);
- }
-
- /*
- * Do a graceful exit if the program is interupted. This will reduce
- * (but not eliminate) the risk of generating a corrupted disk on
- * a user abort.
- */
-
- int
- intr()
- {
- void writefat();
-
- writefat();
- close(fd);
- exit(1);
- }
-
- /*
- * Write the FAT table to the disk. Up to now the FAT manipulation has
- * been done in memory. All errors are fatal. (Might not be too smart
- * to wait till the end of the program to write the table. Oh well...)
- */
-
- void
- writefat()
- {
- int buflen;
- void move();
-
- move(FATOFF(bb.sb)) ;
- buflen = fat_len * MSECSIZ;
- if (write(fd, (char *) fatbuf, buflen) != buflen) {
- perror("writefat: write");
- exit(1);
- }
- #ifdef DUP_FAT
- /* the duplicate FAT table */
- if (write(fd, (char *) fatbuf, buflen) != buflen) {
- perror("writefat: write");
- exit(1);
- }
- #endif /* DUP_FAT */
- return;
- }
-
- read_boot()
- {
- unsigned char buf[MSECSIZ];
- static unsigned char ans;
-
- move(0) ;
-
- if (read(fd, &bb, MSECSIZ) != MSECSIZ ) {
- return(1) ;
- }
-
- /* Do not know how to deal with non 512 byte blocks! */
- if ( SECSIZ(bb.sb) != MSECSIZ ) {
- fprintf(stderr,"File system block size of %d bytes is not valid\n",
- SECSIZ(bb.sb));
- exit(1) ;
- }
-
- return(0) ;
- }
-