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 >
Wrap
C/C++ Source or Header
|
1994-10-03
|
8KB
|
304 lines
/*
LABEL Create, modify or remove drive volume labels.
Compile using Borland or Turbo C++.
Copyright (C) 1994 Max Brante
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/***************************************************************************/
#include <conio.h>
#include <dos.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
/***************************************************************************/
/* Comment out the BETA define if not beta version */
// #define BETA
#define VERSION "1.1"
/***************************************************************************/
/* Process errors and exit */
void error(int errnum) {
switch (errnum&0xFF) {
case 0x00:
printf("Write protect error.\n");
break;
case 0x01:
printf("Unknown unit.\n");
break;
case 0x02:
printf("Drive not ready.\n");
break;
case 0x03:
printf("Unknown command.\n");
break;
case 0x04:
printf("Data error (bad CRC).\n");
break;
case 0x05:
printf("Bad request structure length.\n");
break;
case 0x06:
printf("Seek error.\n");
break;
case 0x07:
printf("Unknown media type.\n");
break;
case 0x08:
printf("Sector not found\n");
break;
case 0x0A:
printf("Write fault.\n");
break;
case 0x0B:
printf("Read fault.\n");
break;
case 0x0C:
printf("General failiure.\n");
break;
}
exit(1);
}
/***************************************************************************/
/* Show how to use LABEL */
void usage() {
printf("Creates, changes or deletes the volume label of a disk.\n\n");
printf("LABEL [drive:][label]\n");
}
/***************************************************************************/
/* Main function */
void main(int argc,char **argv) {
char label[12],oldlabel[12];
unsigned char buf[512],ch;
unsigned char *dirent;
unsigned nument;
int drive,haslabel=0,getlabel=1,savedlabel=0;
long dirstart,i,lsect;
unsigned serhi,serlo;
time_t timer;
struct tm tblock;
char far *mdbptr;
union REGS regs;
#ifdef BETA
printf("LABEL %s beta version\n",VERSION);
#endif
memcpy(label,0,sizeof(label));
/* Process the command line parameters */
switch(argc) {
case 1:
/* getdisk() returns the current drive number */
drive=getdisk();
break;
case 3:
strcpy(label,argv[2]);
getlabel=0;
case 2:
if (strcmp("/?",argv[1])==0) {
usage();
exit(0);
}
if (argv[1][1]==':' && strlen(argv[1])==2 && isalpha(argv[1][0]))
drive=toupper(argv[1][0])-'A';
else if (argc==2) {
memcpy(label,argv[1],11);
drive=getdisk();
getlabel=0;
}
break;
default:
usage();
exit(1);
}
/* Get time and date */
/* time() returns time of day in seconds, elapsed since 00:00:00 GMT,
January 1, 1970. */
timer = time(NULL);
/* localtime() converts date and time to a structure */
memcpy(&tblock,localtime(&timer),sizeof(struct tm));
/* Get drive info */
regs.h.ah=0x1c;
regs.h.dl=drive+1;
/* intdos() generates a dos interrupt*/
intdos(®s,®s);
/* If drive not valid */
if (regs.h.al==0xFF)
error(2);
/* Read boot record of logical disk */
/* absread() reads absolute disk sectors */
if (absread(drive,1,0,buf)==-1)
error(errno);
/* Get number of root directory entries */
nument=*(unsigned *)&buf[0x11];
/* Get the start block number of the root directory */
dirstart=buf[0x10]*(*(unsigned *)&(buf[0x16]))+1;
/* Get volume serial number */
serlo=*(unsigned *)&buf[0x27];
serhi=*(unsigned *)&buf[0x29];
/* Loop through the entries in the root directory */
for(i=0;i<nument*32;i+=32){
/* If we crossed a block boundary, read next one */
if ((i%512)==0) {
if (absread(drive,1,dirstart+i/512,buf)==-1)
error(errno);
drive=drive;
}
/* Point dirent at current entry in the root directory */
dirent=&buf[i%512];
/* If first byte in directory entry is 0 no more entries */
if (*dirent==0)
break;
/* If volume label attribute is set and the label isn't deleted
we have found the volume label */
if ((dirent[0x0B]&8)==8 && *dirent!=0xE5) {
/* Get volume the label and the number of the block in which the entry
containing the label is. */
memcpy(oldlabel,dirent,11);
oldlabel[11]=0;
lsect=dirstart+i/512;
haslabel=1;
break;
}
}
/* If the user didn't enter a label on the command line, get one*/
if (getlabel) {
if (haslabel)
printf("Volume in drive %c is %s\n",drive+'A',oldlabel);
else
printf("Volume in drive %c has no label\n",drive+'A');
printf("Volume Serial Number is %04X-%04X\n",serhi,serlo);
printf("Volume label (11 characters, ENTER for none)? ");
fgets(label,11,stdin);
if(label[strlen(label)-1]=='\n')
label[strlen(label)-1]=0;
}
if (strlen(label)!=0)
memset(&label[strlen(label)],32,11-strlen(label));
strupr(label);
/* If we didn't get a new label */
if (getlabel && strlen(label)==0) {
if(haslabel) {
printf("\nDelete current volume label (y/N)? ");
/* getche() returns the next keypress and echos to screen */
ch=tolower(getche());
if (ch=='y') {
/* Delete the old label */
*dirent=0xE5;
/* abswrite() writes absolute disk sectors */
if (abswrite(drive,1,lsect,buf)==-1)
error(errno);
if (absread(drive,1,0,buf)==-1)
error(errno);
/* Change the label field in the boot block */
memcpy(&buf[43],"NO NAME ",11);
if (abswrite(drive,1,0,buf)==-1)
error(errno);
}
}
}
/* If we did get a new label */
else {
/* If the volume had a old label, change it */
if (haslabel) {
memcpy(dirent,label,11);
savedlabel=1;
}
/* The volume had no label so find a unused directory entry
and save the label */
else {
/* Loop through the entries in the root directory */
for(i=0;i<nument*32;i+=32){
/* If we crossed a block boundary, read next one */
if ((i%512)==0) {
if (absread(drive,1,dirstart+i/512,buf)==-1)
error(errno);
drive=drive;
}
/* Point dirent at current entry in the root directory */
dirent=&buf[i%512];
/* If the directory entry deleted or isn't used, save label there */
if (*dirent==0xE5 || *dirent==0) {
memset(dirent,0,32);
memcpy(dirent,label,11);
dirent[0x0B]=0x28;
lsect=dirstart+i/512;
savedlabel=1;
break;
}
}
}
if (savedlabel) {
/* Save the time and date of the change in the directory entry */
*(unsigned*)&dirent[0x16]=(tblock.tm_hour&31)<<11 |
(tblock.tm_min&63)<<5 |
(tblock.tm_sec&31);
*(unsigned*)&dirent[0x18]=((80-tblock.tm_year)&127)<<9 |
((1+tblock.tm_mon)&15)<<5 |
(tblock.tm_mday&31);
/* Write the dirictory entry to the volume */
if (abswrite(drive,1,lsect,buf)==-1)
error(errno);
/* Update the label field in the boot record */
if (absread(drive,1,0,buf)==-1)
error(errno);
memcpy(&buf[43],label,11);
if (abswrite(drive,1,0,buf)==-1)
error(errno);
}
}
}