1: /*
   2:  * Initialize an MSDOS diskette.  Read the boot sector, and switch to the
   3:  * proper floppy disk device to match the format on the disk.  Sets a bunch
   4:  * of global variables.  Returns 0 on success, or 1 on failure.
   5:  */
   6: 
   7: #include <stdio.h>
   8: #include <ctype.h>
   9: #include <sys/types.h>
  10: #include <sys/stat.h>
  11: #include "msdos.h"
  12: 
  13: #define FULL_CYL
  14: #define WORD(x) ((boot->x)[0] + ((boot->x)[1] << 8))
  15: #define DWORD(x) ((boot->x)[0] + ((boot->x)[1] << 8) + ((boot->x)[2] << 16) + ((boot->x)[3] << 24))
  16: 
  17: unsigned int num_clus;          /* total number of cluster */
  18: int num_fat;                /* the number of FAT tables */
  19: long disk_offset;           /* skip this many bytes */
  20: int fat_bits;               /* the FAT encoding scheme */
  21: 
  22: extern int fd, fat_len, dir_len, dir_start, clus_size, dir_dirty, disk_dirty;
  23: extern int fat_error, disk_size;
  24: extern long disk_current;
  25: extern char *mcwd;
  26: extern unsigned char *fat_buf, *disk_buf, *dir_buf;
  27: extern struct device devices[];
  28: static struct bootsector *read_boot();
  29: 
  30: int
  31: init(drive, mode)
  32: char drive;
  33: int mode;
  34: {
  35:     int fat_start, tracks, heads, sectors, old_dos;
  36:     char *malloc(), *name, *expand();
  37:     void perror(), exit(), reset_chain(), free(), fat_read();
  38:     struct bootsector *boot;
  39:     struct device *dev;
  40: 
  41:     if (fd != -1) {
  42:         close(fd);
  43:         free((char *) fat_buf);
  44:         free((char *) disk_buf);
  45:         free((char *) dir_buf);
  46:     }
  47:                     /* check out the drive letter */
  48:     dev = devices;
  49:     while (dev->drive) {
  50:         if (dev->drive == drive)
  51:             break;
  52:         dev++;
  53:     }
  54:     if (!dev->drive) {
  55:         fprintf(stderr, "Drive '%c:' not supported\n", drive);
  56:         return(1);
  57:     }
  58:                     /* open the device */
  59:     while (dev->name) {
  60:         if (dev->drive != drive)
  61:             break;
  62: 
  63:         name = expand(dev->name);
  64:         if ((fd = open(name, mode | dev->mode)) < 0) {
  65:             perror("init: open");
  66:             exit(1);
  67:         }
  68:                     /* set default parameters, if needed */
  69:         if (dev->gioctl) {
  70:             if ((*(dev->gioctl)) (fd, dev->tracks, dev->heads, dev->sectors))
  71:                 goto try_again;
  72:         }
  73:                     /* read the boot sector */
  74:         disk_offset = dev->offset;
  75:         if ((boot = read_boot()) == NULL)
  76:             goto try_again;
  77: 
  78:         heads = WORD(nheads);
  79:         sectors = WORD(nsect);
  80:         if (heads && sectors)
  81:             tracks = WORD(psect) / (unsigned) (heads * sectors);
  82: 
  83:                     /* sanity checking */
  84:         old_dos = 0;
  85:         if (!heads || heads > 100 || !sectors || sectors > 500 || tracks > 5000 || !boot->clsiz) {
  86:             /*
  87: 			 * The above technique will fail on diskettes that
  88: 			 * have been formatted with very old MSDOS, so we
  89: 			 * resort to the old table-driven method using the
  90: 			 * media signature (first byte in FAT).
  91: 			 */
  92:             unsigned char temp[MSECTOR_SIZE];
  93:             if (read(fd, (char *) temp, MSECTOR_SIZE) != MSECTOR_SIZE)
  94:                 temp[0] = '0';
  95: 
  96:             switch (temp[0]) {
  97:                 case 0xfe:  /* 160k */
  98:                     tracks = 40;
  99:                     sectors = 8;
 100:                     heads = 1;
 101:                     dir_start = 3;
 102:                     dir_len = 4;
 103:                     clus_size = 1;
 104:                     fat_len = 1;
 105:                     num_clus = 313;
 106:                     break;
 107:                 case 0xfc:  /* 180k */
 108:                     tracks = 40;
 109:                     sectors = 9;
 110:                     heads = 1;
 111:                     dir_start = 5;
 112:                     dir_len = 4;
 113:                     clus_size = 1;
 114:                     fat_len = 2;
 115:                     num_clus = 351;
 116:                     break;
 117:                 case 0xff:  /* 320k */
 118:                     tracks = 40;
 119:                     sectors = 8;
 120:                     heads = 2;
 121:                     dir_start = 3;
 122:                     dir_len = 7;
 123:                     clus_size = 2;
 124:                     fat_len = 1;
 125:                     num_clus = 315;
 126:                     break;
 127:                 case 0xfd:  /* 360k */
 128:                     tracks = 40;
 129:                     sectors = 9;
 130:                     heads = 2;
 131:                     dir_start = 5;
 132:                     dir_len = 7;
 133:                     clus_size = 2;
 134:                     fat_len = 2;
 135:                     num_clus = 354;
 136:                     break;
 137:                 default:
 138:                     fprintf(stderr, "Probable non-MSDOS disk\n");
 139:                     close(fd);
 140:                     fd = -1;
 141:                     return(1);
 142:             }
 143:             fat_start = 1;
 144:             num_fat = 2;
 145:             old_dos = 1;
 146:         }
 147:                     /* check the parameters */
 148:         if (dev->tracks && !dev->gioctl) {
 149:             if (dev->tracks == tracks && dev->heads == heads && dev->sectors == sectors)
 150:                 break;
 151:         }
 152:         else
 153:             break;
 154: 
 155: try_again:  close(fd);
 156:         fd = -1;
 157:         dev++;
 158:     }
 159:     if (fd == -1) {
 160:         if (boot != NULL && dev->tracks)
 161:             fprintf(stderr, "No support for %d tracks, %d heads, %d sector diskettes\n", tracks, heads, sectors);
 162:         return(1);
 163:     }
 164:                     /* set new parameters, if needed */
 165:     if (dev->gioctl) {
 166:         if ((*(dev->gioctl)) (fd, tracks, heads, sectors)) {
 167:             fprintf(stderr, "Can't set disk parameters\n");
 168:             close(fd);
 169:             fd = -1;
 170:             return(1);
 171:         }
 172:     }
 173: 
 174:     /*
 175: 	 * all numbers are in sectors, except num_clus (which is in clusters)
 176: 	 */
 177:     if (!old_dos) {
 178:         clus_size = boot->clsiz;
 179:         fat_start = WORD(nrsvsect);
 180:         fat_len = WORD(fatlen);
 181:         dir_start = fat_start + (boot->nfat * fat_len);
 182:         dir_len = WORD(dirents) * MDIR_SIZE / (unsigned) MSECTOR_SIZE;
 183:         /*
 184: 		 * For DOS partitions > 32M
 185: 		 */
 186:         if (WORD(psect) == 0)
 187:             num_clus = (unsigned int) (DWORD(bigsect) - dir_start - dir_len) / clus_size;
 188:         else
 189:             num_clus = (unsigned int) (WORD(psect) - dir_start - dir_len) / clus_size;
 190:         num_fat = boot->nfat;
 191:     }
 192:                     /* more sanity checking */
 193:     if (clus_size * MSECTOR_SIZE > MAX_CLUSTER) {
 194:         fprintf(stderr, "Cluster size of %d is larger than max of %d\n", clus_size * MSECTOR_SIZE, MAX_CLUSTER);
 195:         close(fd);
 196:         fd = -1;
 197:         return(1);
 198:     }
 199:     if (!old_dos && WORD(secsiz) != MSECTOR_SIZE) {
 200:         fprintf(stderr, "Sector size of %d is not supported\n", WORD(secsiz));
 201:         close(fd);
 202:         fd = -1;
 203:         return(1);
 204:     }
 205:                     /* full cylinder buffering */
 206: #ifdef FULL_CYL
 207:     disk_size = (dev->tracks) ? (sectors * heads) : 1;
 208: #else /* FULL_CYL */
 209:     disk_size = (dev->tracks) ? sectors : 1;
 210: #endif /* FULL_CYL */
 211: 
 212: /*
 213:  * The driver in Dell's SVR4 v2.01 is unreliable with large writes.
 214:  */
 215: #ifdef DELL
 216:     disk_size = 1;
 217: #endif /* DELL */
 218: 
 219:     disk_buf = (unsigned char *) malloc((unsigned int) disk_size * MSECTOR_SIZE);
 220:     if (disk_buf == NULL) {
 221:         perror("init: malloc");
 222:         exit(1);
 223:     }
 224:                     /* read the FAT sectors */
 225:     disk_current = -1000L;
 226:     disk_dirty = 0;
 227:     fat_error = 0;
 228:     fat_bits = dev->fat_bits;
 229:     fat_read(fat_start);
 230:                     /* set dir_chain[] to root directory */
 231:     dir_dirty = 0;
 232:     reset_chain(NEW);
 233:     return(0);
 234: }
 235: 
 236: /*
 237:  * Fix the info in the MCWD file to be a proper directory name.  Always
 238:  * has a leading separator.  Never has a trailing separator (unless it is
 239:  * the path itself).
 240:  */
 241: 
 242: char *
 243: fix_mcwd()
 244: {
 245:     FILE *fp;
 246:     struct stat sbuf;
 247:     char *s, *strcpy(), *strcat(), *mcwd_path, *getenv(), *strncpy();
 248:     char buf[BUFSIZ], *file, *expand();
 249:     static char ans[MAX_PATH];
 250:     long now, time();
 251: 
 252:     mcwd_path = getenv("MCWD");
 253:     if (mcwd_path == NULL || *mcwd_path == '\0')
 254:         mcwd_path = "$HOME/.mcwd";
 255: 
 256:     file = expand(mcwd_path);
 257:     if (stat(file, &sbuf) < 0)
 258:         return("A:/");
 259:     /*
 260: 	 * Ignore the info, if the file is more than 6 hours old
 261: 	 */
 262:     time(&now);
 263:     if (now - sbuf.st_mtime > 6 * 60 * 60) {
 264:         fprintf(stderr, "Warning: \"%s\" is out of date, contents ignored\n", file);
 265:         return("A:/");
 266:     }
 267: 
 268:     if (!(fp = fopen(file, "r")))
 269:         return("A:/");
 270: 
 271:     if (!fgets(buf, BUFSIZ, fp))
 272:         return("A:/");
 273: 
 274:     buf[strlen(buf) -1] = '\0';
 275:     fclose(fp);
 276:                     /* drive letter present? */
 277:     s = buf;
 278:     if (buf[0] && buf[1] == ':') {
 279:         strncpy(ans, buf, 2);
 280:         ans[2] = '\0';
 281:         s = &buf[2];
 282:     }
 283:     else
 284:         strcpy(ans, "A:");
 285:                     /* add a leading separator */
 286:     if (*s != '/' && *s != '\\') {
 287:         strcat(ans, "/");
 288:         strcat(ans, s);
 289:     }
 290:     else
 291:         strcat(ans, s);
 292:                     /* translate to upper case */
 293:     for (s = ans; *s; ++s) {
 294:         if (islower(*s))
 295:             *s = toupper(*s);
 296:         if (*s == '\\')
 297:             *s = '/';
 298:     }
 299:                     /* if only drive, colon, & separator */
 300:     if (strlen(ans) == 3)
 301:         return(ans);
 302:                     /* zap the trailing separator */
 303:     if (*--s == '/')
 304:         *s = '\0';
 305:     return(ans);
 306: }
 307: 
 308: /*
 309:  * Read the boot sector.  We glean the disk parameters from this sector.
 310:  */
 311: 
 312: static struct bootsector *
 313: read_boot()
 314: {
 315:     long lseek();
 316:     static struct bootsector boot;
 317: 
 318:     if (lseek(fd, disk_offset, 0) < 0)
 319:         return(NULL);
 320:                     /* read the first sector */
 321:     if (read(fd, (char *) &boot, MSECTOR_SIZE) != MSECTOR_SIZE)
 322:         return(NULL);
 323: 
 324:     return(&boot);
 325: }

Defined functions

read_boot defined in line 312; used 2 times

Defined variables

disk_offset defined in line 19; used 7 times
fat_bits defined in line 20; used 5 times
num_clus defined in line 17; used 7 times
num_fat defined in line 18; used 4 times

Defined macros

DWORD defined in line 15; used 1 times
FULL_CYL defined in line 13; used 1 times
WORD defined in line 14; used 10 times
Last modified: 1992-06-24
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1131
Valid CSS Valid XHTML 1.0 Strict