1 /* Copyright 1986-1992 Emmet P. Gray.
2 * Copyright 1996-1998,2000-2002,2005,2007-2009 Alain Knaff.
3 * This file is part of mtools.
5 * Mtools is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * Mtools is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with Mtools. If not, see <http://www.gnu.org/licenses/>.
19 * Make an MSDOS volume label
22 #include "sysincludes.h"
27 #include "nameclash.h"
28 #include "file_name.h"
30 static void _label_name(doscp_t *cp, const char *filename, int verbose,
31 int *mangled, dos_name_t *ans, int preserve_case)
35 int have_lower, have_upper;
38 memset(ans, ' ', sizeof(*ans)-1);
40 len = native_to_wchar(filename, wbuffer, 11, 0, 0);
47 have_lower = have_upper = 0;
49 if(islower(wbuffer[i]))
51 if(isupper(wbuffer[i]))
54 wbuffer[i] = towupper(wbuffer[i]);
57 wcschr(L"^+=/[]:,?*\\<>|\".", wbuffer[i])
59 strchr("^+=/[]:,?*\\<>|\".", wbuffer[i])
66 if (have_lower && have_upper)
68 wchar_to_dos(cp, wbuffer, ans->base, len, mangled);
71 void label_name_uc(doscp_t *cp, const char *filename, int verbose,
72 int *mangled, dos_name_t *ans)
74 _label_name(cp, filename, verbose, mangled, ans, 0);
77 void label_name_pc(doscp_t *cp, const char *filename, int verbose,
78 int *mangled, dos_name_t *ans)
80 _label_name(cp, filename, verbose, mangled, ans, 1);
83 int labelit(struct dos_name_t *dosname,
90 /* find out current time */
92 mk_entry(dosname, 0x8, 0, 0, now, &entry->dir);
96 static void usage(int ret) NORETURN;
97 static void usage(int ret)
99 fprintf(stderr, "Mtools version %s, dated %s\n",
101 fprintf(stderr, "Usage: %s [-vscVn] [-N serial] drive:\n", progname);
106 void mlabel(int argc, char **argv, int type)
109 const char *newLabel="";
110 int verbose, clear, interactive, show;
113 char longname[VBUFSIZE];
116 struct MainParam_t mp;
120 enum { SER_NONE, SER_RANDOM, SER_SET } set_serial = SER_NONE;
122 int need_write_boot = 0;
125 union bootsector boot;
128 struct label_blk_t *labelBlock;
133 init_clash_handling(&ch);
134 ch.name_converter = label_name_uc;
135 ch.ignore_entry = -2;
141 if(helpFlag(argc, argv))
143 while ((c = getopt(argc, argv, "i:vcsnN:h")) != EOF) {
146 set_cmd_line_image(optarg);
158 set_serial = SER_RANDOM;
159 srandom((long)time (0));
163 set_serial = SER_SET;
164 serial = strtoul(optarg, &eptr, 16);
167 "%s not a valid serial number\n",
179 if (argc - optind > 1)
181 if(argc - optind == 1) {
182 if(!argv[optind][0] || argv[optind][1] != ':')
184 drive = toupper(argv[argc -1][0]);
185 newLabel = argv[optind]+2;
187 drive = get_default_drive();
191 if(strlen(newLabel) > VBUFSIZE) {
192 fprintf(stderr, "Label too long\n");
197 interactive = !show && !clear &&!newLabel[0] &&
198 (set_serial == SER_NONE);
199 if(!clear && !newLabel[0]) {
202 if(clear && newLabel[0]) {
203 /* Clear and new label specified both */
204 fprintf(stderr, "Both clear and new label specified\n");
208 RootDir = open_root_dir(drive, isRop ? 0 : O_RDWR, isRop);
214 fprintf(stderr, "%s: Cannot initialize drive\n", argv[0]);
218 initializeDirentry(&entry, RootDir);
219 r=vfat_lookup(&entry, 0, 0, ACCEPT_LABEL | MATCH_ANY,
220 shortname, longname);
226 if(show || interactive){
227 if(isNotFound(&entry))
228 printf(" Volume has no label\n");
230 printf(" Volume label is %s (abbr=%s)\n",
231 longname, shortname);
233 printf(" Volume label is %s\n", shortname);
237 /* ask for new label */
241 allow_interrupts(&ss);
242 fprintf(stderr,"Enter the new volume label : ");
243 if(fgets(longname, VBUFSIZE, stdin) == NULL) {
244 fprintf(stderr, "\n");
252 longname[strlen(newLabel)-1] = '\0';
255 if(strlen(newLabel) > 11) {
256 fprintf(stderr,"New label too long\n");
261 if((!show || newLabel[0]) && !isNotFound(&entry)){
262 /* if we have a label, wipe it out before putting new one */
263 if(interactive && newLabel[0] == '\0')
264 if(ask_confirmation("Delete volume label (y/n): ")){
268 entry.dir.attr = 0; /* for old mlabel */
272 if (newLabel[0] != '\0') {
274 result = mwrite_one(RootDir,newLabel,0,labelit,NULL,&ch) ?
279 if( (!show || newLabel[0]) || set_serial != SER_NONE) {
281 have_boot = (force_read(Fs,boot.characters,0,sizeof(boot)) ==
286 labelBlock = &boot.boot.ext.old.labelBlock;
288 labelBlock = &boot.boot.ext.fat32.labelBlock;
291 if(!show || newLabel[0]){
293 const char *shrtLabel;
296 shrtLabel = "NO NAME ";
298 shrtLabel = newLabel;
299 cp = GET_DOSCONVERT(Fs);
300 label_name_pc(cp, shrtLabel, verbose, &mangled, &dosname);
302 if(have_boot && boot.boot.descr >= 0xf0 &&
303 labelBlock->dos4 == 0x29) {
304 strncpy(labelBlock->label, dosname.base, 11);
310 if((set_serial != SER_NONE) & have_boot) {
311 if(have_boot && boot.boot.descr >= 0xf0 &&
312 labelBlock->dos4 == 0x29) {
313 set_dword(labelBlock->serial, serial);
318 if(need_write_boot) {
319 force_write(Fs, (char *)&boot, 0, sizeof(boot));
320 /* If this is fat 32, write backup boot sector too */
321 if(!WORD_S(fatlen)) {
322 int backupBoot = WORD_S(ext.fat32.backupBoot);
323 force_write(Fs, (char *)&boot,
324 backupBoot * WORD_S(secsiz),