251 lines
5.1 KiB
C
Executable file
251 lines
5.1 KiB
C
Executable file
/*
|
|
* mlabel.c
|
|
* Make an MSDOS volume label
|
|
*/
|
|
|
|
#include "sysincludes.h"
|
|
#include "msdos.h"
|
|
#include "mainloop.h"
|
|
#include "vfat.h"
|
|
#include "mtools.h"
|
|
#include "nameclash.h"
|
|
|
|
char *label_name(char *filename, int verbose,
|
|
int *mangled, char *ans)
|
|
{
|
|
int len;
|
|
int i;
|
|
int have_lower, have_upper;
|
|
|
|
strcpy(ans," ");
|
|
len = strlen(filename);
|
|
if(len > 11){
|
|
*mangled = 1;
|
|
len = 11;
|
|
} else
|
|
*mangled = 0;
|
|
strncpy(ans, filename, len);
|
|
have_lower = have_upper = 0;
|
|
for(i=0; i<11; i++){
|
|
if(islower((unsigned char)ans[i]))
|
|
have_lower = 1;
|
|
if(isupper(ans[i]))
|
|
have_upper = 1;
|
|
ans[i] = toupper((unsigned char)ans[i]);
|
|
|
|
if(strchr("^+=/[]:,?*\\<>|\".", ans[i])){
|
|
*mangled = 1;
|
|
ans[i] = '~';
|
|
}
|
|
}
|
|
if (have_lower && have_upper)
|
|
*mangled = 1;
|
|
return ans;
|
|
}
|
|
|
|
int labelit(char *dosname,
|
|
char *longname,
|
|
void *arg0,
|
|
direntry_t *entry)
|
|
{
|
|
time_t now;
|
|
|
|
/* find out current time */
|
|
getTimeNow(&now);
|
|
mk_entry(dosname, 0x8, 0, 0, now, &entry->dir);
|
|
return 0;
|
|
}
|
|
|
|
static void usage(void)
|
|
{
|
|
fprintf(stderr, "Mtools version %s, dated %s\n",
|
|
mversion, mdate);
|
|
fprintf(stderr, "Usage: %s [-vscn] [-N serial] drive:[label]\n"
|
|
"\t-v Verbose\n"
|
|
"\t-s Show label\n"
|
|
"\t-c Clear label\n"
|
|
"\t-n New random serial number\n"
|
|
"\t-N New given serial number\n", progname);
|
|
exit(1);
|
|
}
|
|
|
|
|
|
void mlabel(int argc, char **argv, int type)
|
|
{
|
|
|
|
char *drive, *newLabel;
|
|
int verbose, clear, interactive, show, open_mode;
|
|
direntry_t entry;
|
|
int result=0;
|
|
char longname[VBUFSIZE];
|
|
char shortname[13];
|
|
ClashHandling_t ch;
|
|
struct MainParam_t mp;
|
|
Stream_t *RootDir;
|
|
int c;
|
|
int mangled;
|
|
enum { SER_NONE, SER_RANDOM, SER_SET } set_serial = SER_NONE;
|
|
long serial = 0;
|
|
int need_write_boot = 0;
|
|
int have_boot = 0;
|
|
char *eptr = "";
|
|
struct bootsector boot;
|
|
Stream_t *Fs=0;
|
|
int r;
|
|
struct label_blk_t *labelBlock;
|
|
|
|
init_clash_handling(&ch);
|
|
ch.name_converter = label_name;
|
|
ch.ignore_entry = -2;
|
|
|
|
verbose = 0;
|
|
clear = 0;
|
|
show = 0;
|
|
|
|
while ((c = getopt(argc, argv, "vcsnN:")) != EOF) {
|
|
switch (c) {
|
|
case 'v':
|
|
verbose = 1;
|
|
break;
|
|
case 'c':
|
|
clear = 1;
|
|
break;
|
|
case 's':
|
|
show = 1;
|
|
break;
|
|
case 'n':
|
|
set_serial = SER_RANDOM;
|
|
srandom((long)time (0));
|
|
serial=random();
|
|
break;
|
|
case 'N':
|
|
set_serial = SER_SET;
|
|
serial = strtol(optarg, &eptr, 16);
|
|
if(*eptr) {
|
|
fprintf(stderr,
|
|
"%s not a valid serial number\n",
|
|
optarg);
|
|
exit(1);
|
|
}
|
|
break;
|
|
default:
|
|
usage();
|
|
}
|
|
}
|
|
|
|
if (argc - optind != 1 || skip_drive(argv[optind]) == argv[optind])
|
|
usage();
|
|
|
|
init_mp(&mp);
|
|
newLabel = skip_drive(argv[optind]);
|
|
interactive = !show && !clear &&!newLabel[0] &&
|
|
(set_serial == SER_NONE);
|
|
open_mode = O_RDWR;
|
|
drive = get_drive(argv[optind], NULL);
|
|
RootDir = open_root_dir(drive, open_mode);
|
|
if(strlen(newLabel) > VBUFSIZE) {
|
|
fprintf(stderr, "Label too long\n");
|
|
FREE(&RootDir);
|
|
exit(1);
|
|
}
|
|
|
|
if(!RootDir && open_mode == O_RDWR && !clear && !newLabel[0] &&
|
|
( errno == EACCES || errno == EPERM) ) {
|
|
show = 1;
|
|
interactive = 0;
|
|
RootDir = open_root_dir(drive, O_RDONLY);
|
|
}
|
|
if(!RootDir) {
|
|
fprintf(stderr, "%s: Cannot initialize drive\n", argv[0]);
|
|
exit(1);
|
|
}
|
|
|
|
initializeDirentry(&entry, RootDir);
|
|
r=vfat_lookup(&entry, 0, 0, ACCEPT_LABEL | MATCH_ANY,
|
|
shortname, longname);
|
|
if (r == -2) {
|
|
FREE(&RootDir);
|
|
exit(1);
|
|
}
|
|
|
|
if(show || interactive){
|
|
if(isNotFound(&entry))
|
|
printf(" Volume has no label\n");
|
|
else if (*longname)
|
|
printf(" Volume label is %s (abbr=%s)\n",
|
|
longname, shortname);
|
|
else
|
|
printf(" Volume label is %s\n", shortname);
|
|
|
|
}
|
|
|
|
/* ask for new label */
|
|
if(interactive){
|
|
newLabel = longname;
|
|
fprintf(stderr,"Enter the new volume label : ");
|
|
fgets(newLabel, VBUFSIZE, stdin);
|
|
if(newLabel[0])
|
|
newLabel[strlen(newLabel)-1] = '\0';
|
|
}
|
|
|
|
if((!show || newLabel[0]) && !isNotFound(&entry)){
|
|
/* if we have a label, wipe it out before putting new one */
|
|
if(interactive && newLabel[0] == '\0')
|
|
if(ask_confirmation("Delete volume label (y/n): ",0,0)){
|
|
FREE(&RootDir);
|
|
exit(0);
|
|
}
|
|
entry.dir.name[0] = DELMARK;
|
|
entry.dir.attr = 0; /* for old mlabel */
|
|
dir_write(&entry);
|
|
}
|
|
|
|
if (newLabel[0] != '\0') {
|
|
ch.ignore_entry = 1;
|
|
result = mwrite_one(RootDir,newLabel,0,labelit,NULL,&ch) ?
|
|
0 : 1;
|
|
}
|
|
|
|
have_boot = 0;
|
|
if( (!show || newLabel[0]) || set_serial != SER_NONE) {
|
|
Fs = GetFs(RootDir);
|
|
have_boot = (force_read(Fs,(char *)&boot,0,sizeof(boot)) ==
|
|
sizeof(boot));
|
|
}
|
|
|
|
if(_WORD(boot.fatlen)) {
|
|
labelBlock = &boot.ext.old.labelBlock;
|
|
} else {
|
|
labelBlock = &boot.ext.fat32.labelBlock;
|
|
}
|
|
|
|
if(!show || newLabel[0]){
|
|
|
|
if(!newLabel[0])
|
|
strncpy(shortname, "NO NAME ",11);
|
|
else
|
|
label_name(newLabel, verbose, &mangled, shortname);
|
|
|
|
if(have_boot && boot.descr >= 0xf0 &&
|
|
labelBlock->dos4 == 0x29) {
|
|
strncpy(labelBlock->label, shortname, 11);
|
|
need_write_boot = 1;
|
|
|
|
}
|
|
}
|
|
|
|
if((set_serial != SER_NONE) & have_boot) {
|
|
if(have_boot && boot.descr >= 0xf0 &&
|
|
labelBlock->dos4 == 0x29) {
|
|
set_dword(labelBlock->serial, serial);
|
|
need_write_boot = 1;
|
|
}
|
|
}
|
|
|
|
if(need_write_boot) {
|
|
force_write(Fs, (char *)&boot, 0, sizeof(boot));
|
|
}
|
|
|
|
FREE(&RootDir);
|
|
exit(result);
|
|
}
|