home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / UTILITY / RAMDISK / SRDSK141.ZIP / FORMAT.C < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-06  |  14.7 KB  |  536 lines

  1. /* ReSizeable RAMDisk - disk formatting
  2. ** Copyright (c) 1992 Marko Kohtala
  3. */
  4.  
  5. #include "srdisk.h"
  6. #include <stdio.h>
  7. #include <string.h>
  8. #include <dos.h>
  9.  
  10. /*
  11. **  Format printing
  12. */
  13.  
  14. char *stringisize_flags(int flags)
  15. {
  16.   static char _string[60];
  17.   _string[0] = 0;
  18.   if (!flags) {
  19.     return " NONE";
  20.   } else {
  21.     if (flags & C_APPENDED) strcat(_string, " APPENDED");
  22.     if (flags & C_MULTIPLE) strcat(_string, " MULTIPLE");
  23.     if (flags & C_32BITSEC) strcat(_string, " 32BITSEC");
  24.     if (flags & C_NOALLOC) strcat(_string, " NOALLOC");
  25.     if (flags & C_UNKNOWN) strcat(_string, " unknown");
  26.   }
  27.   return _string;
  28. }
  29.  
  30. void print_format(struct format_s *f)
  31. {
  32.   printf("\n"
  33.          "Drive %c:\n"
  34.          "  Disk size: %luK\n"
  35.          "  Cluster size: %d bytes\n"
  36.          "  Sector size: %d bytes\n"
  37.          "  Directory entries: %d\n"
  38.          "  FAT copies: %d\n"
  39.          "  Bytes available: %ld\n"
  40.          "  Write protection: %s\n"
  41.          ,drive
  42.          ,f->size
  43.          ,f->cluster_size
  44.          ,f->bps
  45.          ,f->dir_entries
  46.          ,f->FATs
  47.          ,f->clusters*f->cluster_size
  48.          ,((f->RW_access & WRITE_ACCESS) ? "OFF" : "ON")
  49.          );
  50.   if (verbose > 3)
  51.     printf("  Sectors: %lu\n"
  52.            "  Reserved sectors: %d\n"
  53.            "  FAT sectors: %d\n"
  54.            "  Directory sectors: %d\n"
  55.            "  Sectors per cluster: %d\n"
  56.            "  Clusters: %lu\n"
  57.            "  FAT type: %u bit\n"
  58.            "  Max size: %luK\n"
  59.            ,f->sectors
  60.            ,f->reserved
  61.            ,f->FAT_sectors
  62.            ,f->dir_sectors
  63.            ,f->spc
  64.            ,f->clusters
  65.            ,f->FAT_type
  66.            ,f->max_size
  67.            );
  68. }
  69.  
  70. /*
  71. **  Count the files in root directory
  72. */
  73.  
  74. static int count_root(void)
  75. {
  76.   byte *sp;
  77.   int si;
  78.   dword sector = f.dir_start;
  79.   int entries = f.dir_entries;
  80.   int files = 0;
  81.  
  82.   sp = xalloc(f.bps);
  83.  
  84.   while(entries) {
  85.     read_sector(1, sector, sp);
  86.     for(si = 0; si < f.bps && entries; si += 32) {
  87.       if (sp[si] == 0) goto end;    /* Unused, end of directory */
  88.       if (sp[si] != 0xE5            /* Not deleted */
  89.       && !(sp[si+11] & 8))          /* and not label */
  90.         files++;                    /* so it is a file (or directory) */
  91.       entries--;
  92.     }
  93.     sector++;
  94.   }
  95.  
  96.  end:
  97.   free(sp);
  98.   return files;
  99. }
  100.  
  101. /*
  102. **  PERMISSION TO DELETE DATA
  103. */
  104.  
  105. int licence_to_kill(void)
  106. {
  107.   if (!force_f && count_root() > 0) {
  108.     printf("\n\aAbout to destroy all files on drive %c!\n\a"
  109.            "Continue (Y/N) ? ", drive);
  110.     if (!getYN()) {
  111.       printf("\nOperation aborted\n");
  112.       return 0;
  113.     }
  114.   }
  115.   return 1;
  116. }
  117.  
  118. /*
  119. **  COUNT MAX KBYTES FOR DRIVERS IN CHAIN
  120. */
  121.  
  122. static void count_maxK(void)
  123. {
  124.   int i;
  125.   int changed = 0;
  126.  
  127.   for (i = MAX_CHAINED_DRIVERS; i >= f.chain_len; i--)
  128.     if (newf.subconf[i].userdef) {
  129.       error("Too many /M values");
  130.       return;
  131.     }
  132.  
  133.   newf.max_size = 0;
  134.   for (i = 0; i < MAX_CHAINED_DRIVERS; i++)
  135.   {
  136.     if (!newf.subconf[i].userdef)
  137.       newf.subconf[i].maxK = f.subconf[i].maxK;
  138.     else if (newf.subconf[i].maxK != f.subconf[i].maxK)
  139.       changed++;
  140.     newf.max_size += newf.subconf[i].maxK;
  141.   }
  142.   if (!changed) changed_format &= ~MAX_PART_SIZES;
  143. }
  144.  
  145. /*
  146. **  FILL AND ADJUST THE newf
  147. **
  148. **  Fills newf fields with the user specified data
  149. */
  150.  
  151. static void make_newf(void)
  152. {
  153.   int suggest_bps, suggest_bpc, suggest_dir, suggest_FATs;
  154.  
  155.   newf.chain_len = f.chain_len;
  156.   newf.reserved = 1;
  157.  
  158.   #define dochange(change,new,old,default)  \
  159.     if (!(changed_format & (change)))       \
  160.       (new) = (default);                    \
  161.     else if ((new) == (old))                \
  162.       changed_format &= ~(change);
  163.  
  164.   /* Make values for the fields the user did not supply */
  165.   if (!(changed_format & DISK_SIZE))
  166.     newf.size = f.size;
  167.   if (!(changed_format & MEDIA))
  168.     newf.media = 0xFA;
  169.   if (!(changed_format & SEC_PER_TRACK))
  170.     newf.sec_per_track = 1;
  171.   if (!(changed_format & SIDES))
  172.     newf.sides = 1;
  173.   if (!(changed_format & WRITE_PROTECTION))
  174.     newf.RW_access = WRITE_ACCESS;
  175.  
  176.   count_maxK();
  177.  
  178.   if (use_old_format_f) {
  179.     suggest_bps = f.bps;
  180.     suggest_bpc = f.cluster_size;
  181.     suggest_dir = f.dir_entries;
  182.     suggest_FATs = f.FATs;
  183.   }
  184.   else {
  185.     if (!(changed_format & SECTOR_SIZE)) {
  186.       if (changed_format & CLUSTER_SIZE && newf.cluster_size < max_bps)
  187.         suggest_bps = newf.cluster_size;
  188.       else
  189.         suggest_bps = max_bps;
  190.     }
  191.     else
  192.         suggest_bps = newf.bps;
  193.     if (!(changed_format & CLUSTER_SIZE)) {
  194.       /* !!!! Make better estimate */
  195.       suggest_bpc = newf.size <= 1536L   ? 512  :
  196.                     newf.size <= 30000L  ? 1024 : 2048;
  197.     }
  198.     if (!(changed_format & DIR_ENTRIES)) {
  199.       if (newf.size > 16*512)
  200.         suggest_dir = 512;
  201.       else {
  202.         int entries_per_sec;
  203.         suggest_dir = (int)(newf.size / 16);
  204.         entries_per_sec = suggest_bps / 32;
  205.         suggest_dir += entries_per_sec - suggest_dir % entries_per_sec;
  206.       }
  207.     }
  208.     if (!(changed_format & NO_OF_FATS))
  209.       suggest_FATs = 1;
  210.   }
  211.  
  212.   dochange(SECTOR_SIZE, newf.bps, f.bps, suggest_bps)
  213.   dochange(CLUSTER_SIZE, newf.cluster_size, f.cluster_size, suggest_bpc)
  214.   dochange(DIR_ENTRIES, newf.dir_entries, f.dir_entries, suggest_dir)
  215.   dochange(NO_OF_FATS, newf.FATs, f.FATs, suggest_FATs)
  216.   #undef dochange
  217. }
  218.  
  219. static int count_new_format(void)
  220. {
  221.   newf.FAT_type = 12;        /* By default try to use 12 bit FAT */
  222.  
  223.   /* Make sure sectors are big enough for the disk */
  224.   while((newf.sectors = newf.size * 1024 / newf.bps) >
  225.       ((conf->flags & C_32BITSEC) ? 0x7FFFFFL : 0xFFFFL) )
  226.     newf.bps <<= 1;
  227.   if (newf.bps > 512)
  228.     warning("Sector size larger than 512 bytes, may crash DOS");
  229.  
  230.   if (newf.cluster_size < newf.bps)
  231.     newf.cluster_size = newf.bps;
  232.  
  233.   { div_t divr;
  234.     divr = div(newf.dir_entries * 32, newf.bps);
  235.     newf.dir_sectors = divr.quot + (divr.rem ? 1 : 0);
  236.   }
  237.  
  238.  count_clusters:
  239.   newf.system_sectors = newf.reserved + newf.dir_sectors;
  240.   newf.data_sectors = max(newf.sectors - newf.system_sectors, 0);
  241.  
  242.   newf.spc = newf.cluster_size / newf.bps;
  243.  
  244.   { ldiv_t divr;
  245.     long spFAT;
  246.     divr = ldiv(((long)newf.data_sectors + 2 * newf.spc) * newf.FAT_type,
  247.                 (long)8 * newf.cluster_size + newf.FATs * newf.FAT_type);
  248.     spFAT = divr.quot + (divr.rem ? 1 : 0);
  249.     if (spFAT > 0xFFFF) {
  250.       if (newf.bps < 512) {
  251.         newf.bps <<= 1;
  252.         if (newf.cluster_size < newf.bps)
  253.           newf.cluster_size = newf.bps;
  254.       }
  255.       else
  256.         newf.cluster_size <<= 1;
  257.       goto count_clusters;
  258.     }
  259.     newf.spFAT = (word)spFAT;
  260.   }
  261.  
  262.   newf.FAT_sectors = newf.spFAT * newf.FATs;
  263.   newf.system_sectors += newf.FAT_sectors;
  264.   newf.data_sectors = max(newf.data_sectors - newf.FAT_sectors, 0);
  265.  
  266.   newf.clusters = newf.data_sectors / newf.spc;
  267.  
  268.   /* Make sure we use the right FAT type */
  269.   if (newf.FAT_type < 16 && newf.clusters > 4077) {
  270.     newf.FAT_type = 16;
  271.     goto count_clusters;
  272.   }
  273.   if (newf.FAT_type > 12 && newf.clusters < 4088 || newf.clusters > 65518L) {
  274.     newf.FAT_type = 12;
  275.     newf.cluster_size <<= 1;
  276.     goto count_clusters;
  277.   }
  278.  
  279.   newf.dir_start = newf.reserved + newf.FAT_sectors;
  280.  
  281.   /* If Disk will be disabled */
  282.   if (!newf.size) {
  283.     newf.data_sectors = 0;
  284.     newf.clusters = 0;
  285.     return 1;
  286.   }
  287.  
  288.   if (newf.sectors <= newf.system_sectors || !newf.clusters)
  289.     return 0;
  290.  
  291.   return 1;
  292. }
  293.  
  294. /*
  295. **  CONFIGURE DRIVE FOR FORMAT newf
  296. **
  297. **  Disable drive and configure it. RW_access must be set by caller.
  298. **
  299. **  Return 0 if format is impossible
  300. */
  301.  
  302. int configure_drive(void)
  303. {
  304.   long Kleft = newf.size;
  305.   struct config_s far *subconf;
  306.   dword alloc, lastalloc;
  307.   int err = 0;
  308.   int i;
  309.  
  310.   conf->RW_access = 0;  /* Disable DOS access to drive */
  311.  
  312.   if (changed_format & MAX_PART_SIZES) {
  313.     for (subconf = conf, i = 0; subconf; subconf = conf_ptr(subconf->next), i++)
  314.       subconf->maxK = newf.subconf[i].maxK;
  315.     if (verbose > 1) {
  316.       printf("\nAdjusted max allocation sizes");
  317.       if (!format_f) printf(" - reformat disk to enable change");
  318.       puts("");
  319.     }
  320.   }
  321.  
  322.   if (newf.size != f.current_size || changed_format & MAX_PART_SIZES) {
  323.     for(subconf = conf; subconf; subconf = conf_ptr(subconf->next)) {
  324.       alloc = max(min(subconf->maxK, Kleft), 0);
  325.       lastalloc = disk_alloc(subconf, alloc);
  326.       if (lastalloc != alloc && (err = !lastalloc) != 0) break;
  327.       subconf->size = lastalloc;
  328.  
  329.       Kleft -= lastalloc;
  330.     }
  331.  
  332.     if (Kleft > 0) {    /* If not enough memory could be allocated */
  333.       err = 1;
  334.       if (!conf->next) {   /* If single drive, try to preserve it */
  335.         if (disk_alloc(conf, f.current_size) == f.current_size) {
  336.           conf->size = f.current_size;      /* Fix back what was changed */
  337.           conf->sectors = (long)f.current_size * 1024 / f.bps;
  338.           conf->RW_access = f.RW_access;    /* Enable the disk */
  339.           error("Failed to allocate memory");
  340.           return 0;                         /* Return failure */
  341.         }
  342.       }
  343.       /* Free all memory */
  344.       for (subconf = conf; subconf; subconf = conf_ptr(subconf->next)) {
  345.         if (!disk_alloc(subconf, 0)) {
  346.           subconf->size = 0;
  347.           subconf->sectors = 0;
  348.         }
  349.       }
  350.       newf.size = 0;
  351.       newf.sectors = 0;
  352.       error("Failed to allocate memory - disk disabled");
  353.     }
  354.  
  355.     if (Kleft < 0 && verbose > 1)
  356.       printf("\n%ldKbytes extra allocated,\n"
  357.              "Perhaps you should make your disk that much larger.\n"
  358.              ,-Kleft);
  359.   }
  360.  
  361.   for(subconf = conf; subconf; subconf = conf_ptr(subconf->next)) {
  362.     subconf->sectors = subconf->size * 1024 / newf.bps;
  363.     subconf->BPB_bps = newf.bps;
  364.   }
  365.  
  366.   conf->BPB_spc = newf.spc;
  367.   conf->BPB_reserved = newf.reserved;
  368.   conf->BPB_FATs = newf.FATs;
  369.   conf->BPB_dir = newf.dir_entries;
  370.   conf->BPB_sectors = (conf->flags & C_32BITSEC && newf.sectors > 0xFFFEL) ?
  371.                       0 : newf.sectors;
  372.   conf->BPB_media = newf.media;
  373.   conf->BPB_FATsectors = newf.spFAT;
  374.   conf->BPB_spt = newf.sec_per_track;
  375.   conf->BPB_heads = newf.sides;
  376.   conf->BPB_hidden = 0L;
  377.   conf->BPB_tsectors = newf.sectors;
  378.   conf->tsize = newf.size;
  379.   conf->open_files = 0;
  380.   if (format_f) conf->media_change = -1;
  381.  
  382.   return !err;
  383. }
  384.  
  385. void format_disk(void)
  386. {
  387.   int Fsec;
  388.   int i;
  389.   byte *sector;
  390.  
  391.   make_newf();
  392.  
  393.   if (!format_f) {
  394.     warning("No change in format - disk remains untouched");
  395.     return;
  396.   }
  397.  
  398.   if (newf.size > newf.max_size) {
  399.     error("Not enough memory for disk available");
  400.     return;
  401.   }
  402.  
  403.   if (!force_f && conf->open_files) {
  404.     error("Files open on drive");
  405.     return;
  406.   }
  407.  
  408.   if (!count_new_format())
  409.   {
  410.     error("Impossible format for disk");
  411.     return;
  412.   }
  413.  
  414.   root_files = f.size ? count_root() : 0;
  415.  
  416.   /* If Disk will be disabled */
  417.   if (!newf.size) {
  418.     if (!f.size) {
  419.       /* If was disabled also before */
  420.       configure_drive();
  421.       if (verbose > 1) printf("\nNew configuration saved for later use\n");
  422.     } else {
  423.       /* If disk now get's disabled */
  424.       if (!licence_to_kill()) return;
  425.       configure_drive();
  426.       if (verbose > 1) printf("\nRAMDisk disabled\n");
  427.     }
  428.     return;
  429.   }
  430.   if (verbose > 1) {
  431.     printf("\nNew disk configuration:\n");
  432.     print_format(&newf);
  433.   }
  434.  
  435.   if (f.size && !licence_to_kill()) return;
  436.  
  437.   /* Request the new disk space and configure the driver(s) */
  438.   if (!configure_drive()) return;
  439.  
  440.   sector = xalloc(newf.bps);
  441.  
  442.   /* Write the new disk */
  443.  
  444.   /* Make the boot sector */
  445.   memset(sector, 0, newf.bps);
  446.   { struct boot_s {
  447.       word jump;
  448.       byte nop;
  449.       char oem[8];
  450.       word bps;
  451.       byte spc;
  452.       word reserved;
  453.       byte FATs;
  454.       word dir_entries;
  455.       word sectors;
  456.       byte media;
  457.       word spFAT;
  458.       word spt;
  459.       word sides;
  460.       dword hidden;
  461.       dword sectors32;
  462.       byte physical;
  463.       byte :8;
  464.       byte signature;
  465.       dword serial;
  466.       char label[11];
  467.       char filesystem[8];
  468.       word bootcode;
  469.     } *b = (struct boot_s*)sector;
  470.  
  471.     b->jump = 0x3CEB;                     /* Boot record JMP instruction */
  472.     b->nop = 0x90;                        /* NOP instruction */
  473.     memcpy(&b->oem, "SRD "VERSION, 8);    /* OEM code and version */
  474.     b->bps = newf.bps;
  475.     b->spc = newf.spc;
  476.     b->reserved = newf.reserved;
  477.     b->FATs = newf.FATs;
  478.     b->dir_entries = newf.dir_entries;
  479.     b->sectors = (conf->flags & C_32BITSEC && newf.sectors > 0xFFFEL) ?
  480.                  0 : newf.sectors;
  481.     b->media = newf.media;                /* Media */
  482.     b->spFAT = newf.spFAT;
  483.     b->spt = newf.sec_per_track;          /* Sectors per track */
  484.     b->sides = newf.sides;                /* Sides */
  485.     b->hidden = 0;                        /* Hidden sectors */
  486.     b->sectors32 = newf.sectors;          /* Total number of sectors */
  487.     b->physical = -1;                     /* Physical drive number */
  488.     b->signature = 0x29;                  /* Signature byte */
  489.     b->serial = time(NULL);               /* Serial number */
  490.     _fmemcpy(&b->label,
  491.              ((struct dev_hdr far *)MK_FP(FP_SEG(conf), 0))->u.volume,
  492.              11);                         /* Volume label */
  493.     memcpy(&b->filesystem, newf.FAT_type == 12 ? "FAT12   " :
  494.                            newf.FAT_type == 16 ? "FAT16   " : "        "
  495.                            ,8);
  496.     b->bootcode = 0xFEEB;           /* Boot code (JMP $) */
  497.   }
  498.   *(word  *)(sector+newf.bps-2) = 0xAA55;      /* Validity code */
  499.   write_sector(1, 0, sector);           /* Write boot sector */
  500.  
  501.   for (i = 0; i < newf.FATs; i++) {
  502.     word sector_n =
  503.         newf.reserved + newf.spFAT * i;
  504.     /* Write 1st FAT sector */
  505.     memset(sector, 0, newf.bps);  /* Make 1st FAT sector */
  506.     ((word *)sector)[0] = newf.media | 0xFF00;
  507.     ((word *)sector)[1] = newf.FAT_type == 12 ? 0xFF : 0xFFFF;
  508.     write_sector(1, sector_n++, sector);
  509.  
  510.     /* Write FAT sectors from 2nd to last */
  511.     *(dword *)sector = 0L;
  512.     for (Fsec = 1; Fsec < newf.spFAT; Fsec++)
  513.         write_sector(1, sector_n++, sector);
  514.   }
  515.  
  516.   /* Write 1st directory sector */
  517.   newf.dir_start = newf.reserved + newf.FAT_sectors;
  518.   _fmemcpy(sector, ((struct dev_hdr far *)MK_FP(FP_SEG(conf), 0))->u.volume, 11);
  519.   sector[11] = FA_LABEL;
  520.   *(dword *)(sector+22) = DOS_time(time(NULL));
  521.   write_sector(1, newf.dir_start, sector);
  522.  
  523.   /* Write directory sectors from 2nd to last */
  524.   memset(sector, 0, 32);
  525.   for (Fsec = 1; Fsec < newf.dir_sectors; Fsec++)
  526.       write_sector(1, newf.dir_start+Fsec, sector);
  527.  
  528.   conf->RW_access = READ_ACCESS | newf.RW_access;
  529.  
  530.   free(sector);
  531.  
  532.   if (verbose > 1) printf("\nDisk formatted\n");
  533. }
  534.  
  535.  
  536.