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 void label_name(doscp_t *cp, const char *filename, int verbose,
31 int *mangled, dos_name_t *ans)
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]))
53 wbuffer[i] = towupper(wbuffer[i]);
56 wcschr(L"^+=/[]:,?*\\<>|\".", wbuffer[i])
58 strchr("^+=/[]:,?*\\<>|\".", wbuffer[i])
65 if (have_lower && have_upper)
67 wchar_to_dos(cp, wbuffer, ans->base, len, mangled);
70 int labelit(struct dos_name_t *dosname,
77 /* find out current time */
79 mk_entry(dosname, 0x8, 0, 0, now, &entry->dir);
83 static void usage(int ret) NORETURN;
84 static void usage(int ret)
86 fprintf(stderr, "Mtools version %s, dated %s\n",
88 fprintf(stderr, "Usage: %s [-vscVn] [-N serial] drive:\n", progname);
93 void mlabel(int argc, char **argv, int type)
97 int verbose, clear, interactive, show;
100 char longname[VBUFSIZE];
103 struct MainParam_t mp;
107 enum { SER_NONE, SER_RANDOM, SER_SET } set_serial = SER_NONE;
109 int need_write_boot = 0;
112 union bootsector boot;
115 struct label_blk_t *labelBlock;
119 init_clash_handling(&ch);
120 ch.name_converter = label_name;
121 ch.ignore_entry = -2;
127 if(helpFlag(argc, argv))
129 while ((c = getopt(argc, argv, "i:vcsnN:h")) != EOF) {
132 set_cmd_line_image(optarg, 0);
144 set_serial = SER_RANDOM;
145 srandom((long)time (0));
149 set_serial = SER_SET;
150 serial = strtol(optarg, &eptr, 16);
153 "%s not a valid serial number\n",
165 if (argc - optind != 1 || !argv[optind][0] || argv[optind][1] != ':')
169 newLabel = argv[optind]+2;
170 if(strlen(newLabel) > VBUFSIZE) {
171 fprintf(stderr, "Label too long\n");
176 interactive = !show && !clear &&!newLabel[0] &&
177 (set_serial == SER_NONE);
178 if(!clear && !newLabel[0]) {
181 RootDir = open_root_dir(argv[optind][0], isRop ? 0 : O_RDWR, isRop);
187 fprintf(stderr, "%s: Cannot initialize drive\n", argv[0]);
191 initializeDirentry(&entry, RootDir);
192 r=vfat_lookup(&entry, 0, 0, ACCEPT_LABEL | MATCH_ANY,
193 shortname, longname);
199 if(show || interactive){
200 if(isNotFound(&entry))
201 printf(" Volume has no label\n");
203 printf(" Volume label is %s (abbr=%s)\n",
204 longname, shortname);
206 printf(" Volume label is %s\n", shortname);
210 /* ask for new label */
213 fprintf(stderr,"Enter the new volume label : ");
214 if(fgets(newLabel, VBUFSIZE, stdin) == NULL) {
216 fprintf(stderr, "\n");
219 newLabel[strlen(newLabel)-1] = '\0';
222 if((!show || newLabel[0]) && !isNotFound(&entry)){
223 /* if we have a label, wipe it out before putting new one */
224 if(interactive && newLabel[0] == '\0')
225 if(ask_confirmation("Delete volume label (y/n): ")){
229 entry.dir.attr = 0; /* for old mlabel */
233 if (newLabel[0] != '\0') {
235 result = mwrite_one(RootDir,newLabel,0,labelit,NULL,&ch) ?
240 if( (!show || newLabel[0]) || set_serial != SER_NONE) {
242 have_boot = (force_read(Fs,boot.characters,0,sizeof(boot)) ==
247 labelBlock = &boot.boot.ext.old.labelBlock;
249 labelBlock = &boot.boot.ext.fat32.labelBlock;
252 if(!show || newLabel[0]){
254 const char *shrtLabel;
257 shrtLabel = "NO NAME ";
259 shrtLabel = newLabel;
260 cp = GET_DOSCONVERT(Fs);
261 label_name(cp, shrtLabel, verbose, &mangled, &dosname);
263 if(have_boot && boot.boot.descr >= 0xf0 &&
264 labelBlock->dos4 == 0x29) {
265 strncpy(labelBlock->label, dosname.base, 11);
271 if((set_serial != SER_NONE) & have_boot) {
272 if(have_boot && boot.boot.descr >= 0xf0 &&
273 labelBlock->dos4 == 0x29) {
274 set_dword(labelBlock->serial, serial);
279 if(need_write_boot) {
280 force_write(Fs, (char *)&boot, 0, sizeof(boot));