/* ** SETVOL.C - set, change, or kill a disk volume label ** ** public domain demo by Bob Stout ** DOS 5 enhancements suggested by Keith Beedle */ #include #include #include #include #include #include #include "portable.h" /* Also in SNIPPETS */ #define NUL '\0' #if defined(__TURBOC__) #pragma option -a- #include #include #define _A_VOLID FA_LABEL #define _far far #else #include #if defined(__ZTC__) #pragma ZTC align 1 #else /* MSC/QC/WATCOM/METAWARE */ #pragma pack(1) #endif struct fcb { char fcb_drive; char fcb_name[8]; char fcb_ext[3]; short fcb_curblk; short fcb_recsize; long fcb_filsize; short fcb_date; char fcb_resv[10]; char fcb_currec; long fcb_random; }; struct xfcb { char xfcb_flag; char xfcb_resv[5]; char xfcb_attr; struct fcb xfcb_fcb; }; #endif #include "dos5boot.h" /* SNIPPETS file with DOS 5 boot record structure */ /* ** NOTE: The following use functions in four other SNIPPETS files, ** ABSDISK.ASM, ABSDISKC.C, DRVALID.C, and PUSHDIR.C */ int AbsDiskRead(unsigned short, size_t, size_t, void *); int AbsDiskWrite(unsigned short, size_t, size_t, void *); int getdrv(void); int PushDir(char *); int PopDir(void); /* ** Erase an existing volume label */ void vol_kill(char *fname) { union REGS regs; struct SREGS sregs; struct xfcb buf; /* Parse the filename into an FCB */ segread(&sregs); regs.h.ah = 0x29; regs.h.al = 0; regs.x.si = (unsigned)fname; regs.x.di = (unsigned)&buf.xfcb_fcb; sregs.es = sregs.ds; intdosx(®s, ®s, &sregs); /* Volume labels require extended FCB's */ buf.xfcb_flag = 0xff; buf.xfcb_attr = _A_VOLID; /* Delete the old label */ regs.h.ah = 0x13; regs.x.dx = (unsigned)&buf; intdos(®s, ®s); } /* ** Create a new volume label */ void setvol(char *label) { char new_label[13]; /* name + ext + '.' + NUL */ struct xfcb buf; union REGS regs; struct SREGS sregs; const char pattern[] = "????????"; char _far *dta; /* ** Change to root directory. */ PushDir("\\"); /* If drive is already labeled, remove it */ segread(&sregs); regs.h.ah = 0x2f; intdosx(®s, ®s, &sregs); dta = MK_FP(sregs.es, regs.x.bx); buf.xfcb_flag = 0xff; buf.xfcb_attr = _A_VOLID; buf.xfcb_fcb.fcb_drive = 0; memcpy(buf.xfcb_fcb.fcb_name, pattern, 8); memcpy(buf.xfcb_fcb.fcb_ext, pattern, 3); regs.h.ah = 0x11; regs.x.dx = (unsigned)&buf; intdos(®s, ®s); if (0 == regs.h.al) { int i; char oldlabel[13], _far *p, *q; for (i = 0, p = dta + 8, q =oldlabel; i < 8; ++i, ++p, ++q) { *q = *p; } *q++ = '.'; for (i = 0, p = dta + 16; i < 3; ++i, ++p, ++q) { *q = *p; } vol_kill(oldlabel); } strcpy(new_label, label); if (8 < strlen(label)) { new_label[8] = '.'; strcpy(&new_label[9], &label[8]); } /* Parse the filename into an FCB */ segread(&sregs); regs.h.ah = 0x29; regs.h.al = 0; regs.x.si = (unsigned)new_label; regs.x.di = (unsigned)&buf.xfcb_fcb; sregs.es = sregs.ds; intdosx(®s, ®s, &sregs); /* Volume labels require extended FCB's */ buf.xfcb_flag = 0xff; buf.xfcb_attr = _A_VOLID; /* Create the new label */ regs.h.ah = 0x16; regs.x.dx = (unsigned)&buf; intdos(®s, ®s); /* Close the new label */ regs.h.ah = 0x10; regs.x.dx = (unsigned)&buf; intdos(®s, ®s); /* ** For DOS 5.0 replace the boot record too. */ if(_osmajor > 3) { int index, drive = getdrv(); B_REC boot_record; AbsDiskRead(drive, 1, 0, &boot_record); if(0 == strcmp(boot_record.bsOemName, "MSDOS5.0")) { index = 0; while (NUL != label[index]) { boot_record.bsVolumeLabel[index] = label[index]; index++; } for(index; index < 11; index++) boot_record.bsVolumeLabel[index] = 0x20; AbsDiskWrite(drive, 1, 0, &boot_record); } } PopDir(); } #ifdef TEST void main(int argc, char *argv[]) { if (2 > argc) { puts("\aUsage: SETVOL new_name"); abort(); } setvol(argv[1]); } #endif