minix/commands/i386/mtools-3.9.7/mlabel.c
2005-04-21 14:53:53 +00:00

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);
}