home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 21 / CD_ASCQ_21_040595.iso / dos / prg / c / freedos3 / source / label / label.c < prev    next >
C/C++ Source or Header  |  1994-10-03  |  8KB  |  304 lines

  1. /*
  2.         LABEL Create, modify or remove drive volume labels.
  3.         Compile using Borland or Turbo C++.
  4.         Copyright (C) 1994 Max Brante
  5.         
  6.  
  7.         This program is free software; you can redistribute it and/or modify
  8.         it under the terms of the GNU General Public License as published by
  9.         the Free Software Foundation; either version 2 of the License, or
  10.         (at your option) any later version.
  11.  
  12.         This program is distributed in the hope that it will be useful,
  13.         but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.         GNU General Public License for more details.
  16.  
  17.         You should have received a copy of the GNU General Public License
  18.         along with this program; if not, write to the Free Software
  19.         Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20. */
  21.  
  22. /***************************************************************************/
  23.  
  24. #include <conio.h>
  25. #include <dos.h>
  26. #include <stdio.h>
  27. #include <string.h>
  28. #include <time.h>
  29.  
  30. /***************************************************************************/
  31. /* Comment out the BETA define if not beta version */
  32.  
  33. // #define BETA
  34. #define VERSION "1.1"
  35.  
  36. /***************************************************************************/
  37. /* Process errors and exit */
  38.  
  39. void error(int errnum) {
  40.     switch (errnum&0xFF) {
  41.         case 0x00:
  42.             printf("Write protect error.\n");
  43.             break;
  44.         case 0x01:
  45.             printf("Unknown unit.\n");
  46.             break;
  47.         case 0x02:
  48.             printf("Drive not ready.\n");
  49.             break;
  50.         case 0x03:
  51.             printf("Unknown command.\n");
  52.             break;
  53.         case 0x04:
  54.             printf("Data error (bad CRC).\n");
  55.             break;
  56.         case 0x05:
  57.             printf("Bad request structure length.\n");
  58.             break;
  59.         case 0x06:
  60.             printf("Seek error.\n");
  61.             break;
  62.         case 0x07:
  63.             printf("Unknown media type.\n");
  64.             break;
  65.         case 0x08:
  66.             printf("Sector not found\n");
  67.             break;
  68.         case 0x0A:
  69.             printf("Write fault.\n");
  70.             break;
  71.         case 0x0B:
  72.             printf("Read fault.\n");
  73.             break;
  74.         case 0x0C:
  75.             printf("General failiure.\n");
  76.             break;
  77.     }
  78.     exit(1);
  79. }
  80.  
  81. /***************************************************************************/
  82. /* Show how to use LABEL */
  83.  
  84. void usage() {
  85.     printf("Creates, changes or deletes the volume label of a disk.\n\n");
  86.     printf("LABEL [drive:][label]\n");
  87. }
  88.  
  89. /***************************************************************************/
  90. /* Main function */
  91.  
  92. void main(int argc,char **argv) {
  93.     char          label[12],oldlabel[12];
  94.     unsigned char buf[512],ch;
  95.     unsigned char *dirent;
  96.     unsigned      nument;
  97.     int           drive,haslabel=0,getlabel=1,savedlabel=0;
  98.     long          dirstart,i,lsect;
  99.     unsigned      serhi,serlo;
  100.     time_t        timer;
  101.     struct tm     tblock;
  102.     char far      *mdbptr;
  103.     union REGS    regs;
  104.  
  105. #ifdef BETA
  106. printf("LABEL %s beta version\n",VERSION);
  107. #endif
  108.  
  109.     memcpy(label,0,sizeof(label));
  110.  
  111.     /* Process the command line parameters */
  112.     switch(argc) {
  113.         case 1:
  114.  
  115.             /* getdisk() returns the current drive number */
  116.             drive=getdisk();
  117.             break;
  118.         case 3:
  119.             strcpy(label,argv[2]);
  120.             getlabel=0;
  121.         case 2:
  122.             if (strcmp("/?",argv[1])==0) {
  123.                 usage();
  124.                 exit(0);
  125.             }
  126.             if (argv[1][1]==':' && strlen(argv[1])==2 && isalpha(argv[1][0]))
  127.                 drive=toupper(argv[1][0])-'A';
  128.             else if (argc==2) {
  129.                 memcpy(label,argv[1],11);
  130.                 drive=getdisk();
  131.                 getlabel=0;
  132.             }
  133.             break;
  134.         default:
  135.             usage();
  136.             exit(1);
  137.     }
  138.  
  139.     /* Get time and date */
  140.     /* time() returns time of day in seconds, elapsed since 00:00:00 GMT,
  141.          January 1, 1970. */
  142.     timer = time(NULL);
  143.  
  144.     /* localtime() converts date and time to a structure */
  145.     memcpy(&tblock,localtime(&timer),sizeof(struct tm));
  146.  
  147.     /* Get drive info */
  148.     regs.h.ah=0x1c;
  149.     regs.h.dl=drive+1;
  150.     /* intdos() generates a dos interrupt*/
  151.     intdos(®s,®s);
  152.     /* If drive not valid */
  153.     if (regs.h.al==0xFF)
  154.         error(2);
  155.  
  156.  
  157.     /* Read boot record of logical disk */
  158.     /* absread() reads absolute disk sectors */
  159.     if (absread(drive,1,0,buf)==-1)
  160.         error(errno);
  161.  
  162.     /* Get number of root directory entries */
  163.     nument=*(unsigned *)&buf[0x11];
  164.  
  165.     /* Get the start block number of the root directory */
  166.     dirstart=buf[0x10]*(*(unsigned *)&(buf[0x16]))+1;
  167.  
  168.     /* Get volume serial number */
  169.     serlo=*(unsigned *)&buf[0x27];
  170.     serhi=*(unsigned *)&buf[0x29];
  171.  
  172.     /* Loop through the entries in the root directory */
  173.     for(i=0;i<nument*32;i+=32){
  174.  
  175.         /* If we crossed a block boundary, read next one */
  176.         if ((i%512)==0) {
  177.             if (absread(drive,1,dirstart+i/512,buf)==-1)
  178.                 error(errno);
  179.             drive=drive;
  180.         }
  181.  
  182.         /* Point dirent at current entry in the root directory */
  183.         dirent=&buf[i%512];
  184.  
  185.         /* If first byte in directory entry is 0 no more entries */
  186.         if (*dirent==0)
  187.             break;
  188.  
  189.         /* If volume label attribute is set and the label isn't deleted
  190.              we have found the volume label */
  191.         if ((dirent[0x0B]&8)==8 && *dirent!=0xE5) {
  192.  
  193.             /* Get volume the label and the number of the block in which the entry
  194.                  containing the label is. */
  195.             memcpy(oldlabel,dirent,11);
  196.             oldlabel[11]=0;
  197.             lsect=dirstart+i/512;
  198.             haslabel=1;
  199.             break;
  200.         }
  201.     }
  202.  
  203.     /* If the user didn't enter a label on the command line, get one*/
  204.     if (getlabel) {
  205.         if (haslabel)
  206.             printf("Volume in drive %c is %s\n",drive+'A',oldlabel);
  207.         else
  208.             printf("Volume in drive %c has no label\n",drive+'A');
  209.         printf("Volume Serial Number is %04X-%04X\n",serhi,serlo);
  210.         printf("Volume label (11 characters, ENTER for none)? ");
  211.         fgets(label,11,stdin);
  212.         if(label[strlen(label)-1]=='\n')
  213.             label[strlen(label)-1]=0;
  214.     }
  215.     if (strlen(label)!=0)
  216.         memset(&label[strlen(label)],32,11-strlen(label));
  217.     strupr(label);
  218.  
  219.     /* If we didn't get a new label */
  220.     if (getlabel && strlen(label)==0) {
  221.         if(haslabel) {
  222.             printf("\nDelete current volume label (y/N)? ");
  223.             /* getche() returns the next keypress and echos to screen */
  224.             ch=tolower(getche());
  225.             if (ch=='y') {
  226.  
  227.                 /* Delete the old label */
  228.                 *dirent=0xE5;
  229.  
  230.                 /* abswrite() writes absolute disk sectors */
  231.                 if (abswrite(drive,1,lsect,buf)==-1)
  232.                     error(errno);
  233.                 if (absread(drive,1,0,buf)==-1)
  234.                     error(errno);
  235.  
  236.                 /* Change the label field in the boot block */
  237.                 memcpy(&buf[43],"NO NAME    ",11);
  238.                 if (abswrite(drive,1,0,buf)==-1)
  239.                     error(errno);
  240.             }
  241.         }
  242.     }
  243.  
  244.     /* If we did get a new label */
  245.     else {
  246.  
  247.         /* If the volume had a old label, change it */
  248.         if (haslabel) {
  249.             memcpy(dirent,label,11);
  250.             savedlabel=1;
  251.         }
  252.  
  253.         /* The volume had no label so find a unused directory entry
  254.              and save the label */
  255.         else {
  256.  
  257.             /* Loop through the entries in the root directory */
  258.             for(i=0;i<nument*32;i+=32){
  259.  
  260.                     /* If we crossed a block boundary, read next one */
  261.                 if ((i%512)==0) {
  262.                     if (absread(drive,1,dirstart+i/512,buf)==-1)
  263.                         error(errno);
  264.                     drive=drive;
  265.                 }
  266.  
  267.                 /* Point dirent at current entry in the root directory */
  268.                 dirent=&buf[i%512];
  269.  
  270.                 /* If the directory entry deleted or isn't used, save label there */
  271.                 if (*dirent==0xE5 || *dirent==0) {
  272.                     memset(dirent,0,32);
  273.                     memcpy(dirent,label,11);
  274.                     dirent[0x0B]=0x28;
  275.                     lsect=dirstart+i/512;
  276.                     savedlabel=1;
  277.                     break;
  278.                 }
  279.             }
  280.         }
  281.  
  282.         if (savedlabel) {
  283.             /* Save the time and date of the change in the directory entry */
  284.             *(unsigned*)&dirent[0x16]=(tblock.tm_hour&31)<<11 |
  285.                                                             (tblock.tm_min&63)<<5 |
  286.                                                             (tblock.tm_sec&31);
  287.             *(unsigned*)&dirent[0x18]=((80-tblock.tm_year)&127)<<9 |
  288.                                                             ((1+tblock.tm_mon)&15)<<5 |
  289.                                                             (tblock.tm_mday&31);
  290.  
  291.             /* Write the dirictory entry to the volume */
  292.             if (abswrite(drive,1,lsect,buf)==-1)
  293.                 error(errno);
  294.  
  295.             /* Update the label field in the boot record */
  296.             if (absread(drive,1,0,buf)==-1)
  297.                 error(errno);
  298.             memcpy(&buf[43],label,11);
  299.             if (abswrite(drive,1,0,buf)==-1)
  300.                 error(errno);
  301.         }
  302.     }
  303. }
  304.