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. 4 * 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. 9 * 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. 14 * 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/>. 17 * 18 * mlabel.c 19 * Make an MSDOS volume label 20 */ 21 22#include "sysincludes.h" 23#include "msdos.h" 24#include "mainloop.h" 25#include "vfat.h" 26#include "mtools.h" 27#include "nameclash.h" 28#include "file_name.h" 29 30#define USB_VOL_NAME_FILE "/tmp/usb_vol_name/%s" /* Foxconn added pling 05/06/2009 */ 31 32void label_name(doscp_t *cp, const char *filename, int verbose, 33 int *mangled, dos_name_t *ans) 34{ 35 int len; 36 int i; 37 int have_lower, have_upper; 38 wchar_t wbuffer[12]; 39 40 strcpy(ans->base," "); 41 len = native_to_wchar(filename, wbuffer, 11, 0, 0); 42 if(len > 11){ 43 *mangled = 1; 44 len = 11; 45 } else 46 *mangled = 0; 47 48 have_lower = have_upper = 0; 49 for(i=0; i<len; i++){ 50 if(islower(wbuffer[i])) 51 have_lower = 1; 52 if(isupper(wbuffer[i])) 53 have_upper = 1; 54 wbuffer[i] = towupper(wbuffer[i]); 55 if( 56#ifdef HAVE_WCHAR_H 57 wcschr(L"^+=/[]:,?*\\<>|\".", wbuffer[i]) 58#else 59 strchr("^+=/[]:,?*\\<>|\".", wbuffer[i]) 60#endif 61 ){ 62 *mangled = 1; 63 wbuffer[i] = '~'; 64 } 65 } 66 if (have_lower && have_upper) 67 *mangled = 1; 68 wchar_to_dos(cp, wbuffer, ans->base, len, mangled); 69} 70 71int labelit(struct dos_name_t *dosname, 72 char *longname, 73 void *arg0, 74 direntry_t *entry) 75{ 76 time_t now; 77 78 /* find out current time */ 79 getTimeNow(&now); 80 mk_entry(dosname, 0x8, 0, 0, now, &entry->dir); 81 return 0; 82} 83 84static void usage(int ret) NORETURN; 85static void usage(int ret) 86{ 87 fprintf(stderr, "Mtools version %s, dated %s\n", 88 mversion, mdate); 89 fprintf(stderr, "Usage: %s [-vscVn] [-N serial] drive:\n", progname); 90 exit(ret); 91} 92 93 94void mlabel(int argc, char **argv, int type) 95{ 96 97 char *newLabel; 98 int verbose, clear, interactive, show; 99 direntry_t entry; 100 int result=0; 101 char longname[VBUFSIZE]; 102 char shortname[45]; 103 ClashHandling_t ch; 104 struct MainParam_t mp; 105 Stream_t *RootDir; 106 int c; 107 int mangled; 108 enum { SER_NONE, SER_RANDOM, SER_SET } set_serial = SER_NONE; 109 long serial = 0; 110 int need_write_boot = 0; 111 int have_boot = 0; 112 char *eptr; 113 struct bootsector boot; 114 Stream_t *Fs=0; 115 int r; 116 struct label_blk_t *labelBlock; 117 int isRo=0; 118 int *isRop=NULL; 119 120 /* Foxconn added start pling 05/06/2009 */ 121 char sd_name[32]; 122 char vol_name[64]; 123 124 memset(sd_name, 0, sizeof(sd_name)); 125 memset(vol_name, 0, sizeof(vol_name)); 126 /* Foxconn added end pling 05/06/2009 */ 127 128 init_clash_handling(&ch); 129 ch.name_converter = label_name; 130 ch.ignore_entry = -2; 131 132 verbose = 0; 133 clear = 0; 134 show = 0; 135 136 if(helpFlag(argc, argv)) 137 usage(0); 138 while ((c = getopt(argc, argv, "i:vcsnN:h")) != EOF) { 139 switch (c) { 140 case 'i': 141 set_cmd_line_image(optarg, 0); 142 strcpy(sd_name, optarg); // Foxconn added pling 05/06/2009 143 break; 144 case 'v': 145 verbose = 1; 146 break; 147 case 'c': 148 clear = 1; 149 break; 150 case 's': 151 show = 1; 152 break; 153 case 'n': 154 set_serial = SER_RANDOM; 155 srandom((long)time (0)); 156 serial=random(); 157 break; 158 case 'N': 159 set_serial = SER_SET; 160 serial = strtol(optarg, &eptr, 16); 161 if(*eptr) { 162 fprintf(stderr, 163 "%s not a valid serial number\n", 164 optarg); 165 exit(1); 166 } 167 break; 168 case 'h': 169 usage(0); 170 default: 171 usage(1); 172 } 173 } 174 175 if (argc - optind != 1 || !argv[optind][0] || argv[optind][1] != ':') 176 usage(1); 177 178 init_mp(&mp); 179 newLabel = argv[optind]+2; 180 if(strlen(newLabel) > VBUFSIZE) { 181 fprintf(stderr, "Label too long\n"); 182 FREE(&RootDir); 183 exit(1); 184 } 185 186 interactive = !show && !clear &&!newLabel[0] && 187 (set_serial == SER_NONE); 188 if(!clear && !newLabel[0]) { 189 isRop = &isRo; 190 } 191 RootDir = open_root_dir(argv[optind][0], isRop ? 0 : O_RDWR, isRop); 192 if(isRo) { 193 show = 1; 194 interactive = 0; 195 } 196 if(!RootDir) { 197 fprintf(stderr, "%s: Cannot initialize drive\n", argv[0]); 198 exit(1); 199 } 200 201 initializeDirentry(&entry, RootDir); 202 r=vfat_lookup(&entry, 0, 0, ACCEPT_LABEL | MATCH_ANY, 203 shortname, longname); 204 if (r == -2) { 205 FREE(&RootDir); 206 exit(1); 207 } 208 209 if(show || interactive){ 210 if(isNotFound(&entry)) { 211 printf(" Volume has no label\n"); 212 strcpy(vol_name, ""); 213 } 214 else if (*longname) { 215 printf(" Volume label is %s (abbr=%s)\n", 216 longname, shortname); 217 strcpy(vol_name, longname); 218 } 219 else { 220 printf(" Volume label is %s\n", shortname); 221 strcpy(vol_name, shortname); 222 } 223 224 /* Foxconn added start pling 05/06/2009 */ 225 /* Store the volume label in a file under /tmp */ 226 FILE *fp = NULL; 227 char *devname; 228 char filename[64]; 229 230 if (strlen(sd_name)) { 231 devname = strstr(sd_name, "sd"); 232 if (devname) { 233 sprintf(filename, USB_VOL_NAME_FILE, devname); 234 fp = fopen(filename, "w"); 235 if (fp != NULL) { 236 fprintf(fp, "%s\n", vol_name); 237 fclose(fp); 238 } 239 } 240 } 241 /* Foxconn added end pling 05/06/2009 */ 242 } 243 244 /* ask for new label */ 245 if(interactive){ 246 newLabel = longname; 247 fprintf(stderr,"Enter the new volume label : "); 248 fgets(newLabel, VBUFSIZE, stdin); 249 if(newLabel[0]) 250 newLabel[strlen(newLabel)-1] = '\0'; 251 } 252 253 if((!show || newLabel[0]) && !isNotFound(&entry)){ 254 /* if we have a label, wipe it out before putting new one */ 255 if(interactive && newLabel[0] == '\0') 256 if(ask_confirmation("Delete volume label (y/n): ")){ 257 FREE(&RootDir); 258 exit(0); 259 } 260 entry.dir.attr = 0; /* for old mlabel */ 261 wipeEntry(&entry); 262 } 263 264 if (newLabel[0] != '\0') { 265 ch.ignore_entry = 1; 266 result = mwrite_one(RootDir,newLabel,0,labelit,NULL,&ch) ? 267 0 : 1; 268 } 269 270 have_boot = 0; 271 if( (!show || newLabel[0]) || set_serial != SER_NONE) { 272 Fs = GetFs(RootDir); 273 have_boot = (force_read(Fs,(char *)&boot,0,sizeof(boot)) == 274 sizeof(boot)); 275 } 276 277 if(_WORD(boot.fatlen)) { 278 labelBlock = &boot.ext.old.labelBlock; 279 } else { 280 labelBlock = &boot.ext.fat32.labelBlock; 281 } 282 283 if(!show || newLabel[0]){ 284 dos_name_t dosname; 285 const char *shrtLabel; 286 doscp_t *cp; 287 if(!newLabel[0]) 288 shrtLabel = "NO NAME "; 289 else 290 shrtLabel = newLabel; 291 cp = GET_DOSCONVERT(Fs); 292 label_name(cp, shrtLabel, verbose, &mangled, &dosname); 293 294 if(have_boot && boot.descr >= 0xf0 && 295 labelBlock->dos4 == 0x29) { 296 strncpy(labelBlock->label, dosname.base, 11); 297 need_write_boot = 1; 298 299 } 300 } 301 302 if((set_serial != SER_NONE) & have_boot) { 303 if(have_boot && boot.descr >= 0xf0 && 304 labelBlock->dos4 == 0x29) { 305 set_dword(labelBlock->serial, serial); 306 need_write_boot = 1; 307 } 308 } 309 310 if(need_write_boot) { 311 force_write(Fs, (char *)&boot, 0, sizeof(boot)); 312 } 313 314 FREE(&RootDir); 315 exit(result); 316} 317