in fs/fatfs/src/ff.c [4922:5037]
FRESULT f_setlabel (
const TCHAR* label /* Pointer to the volume label to set */
)
{
FRESULT res;
FATFS_DIR dj;
FATFS *fs;
BYTE dirvn[22];
UINT i, j, slen;
WCHAR w;
static const char badchr[] = "\"*+,.:;<=>\?[]|\x7F";
/* Get logical drive */
res = find_volume(&label, &fs, FA_WRITE);
if (res != FR_OK) LEAVE_FF(fs, res);
dj.obj.fs = fs;
/* Get length of given volume label */
for (slen = 0; (UINT)label[slen] >= ' '; slen++) ; /* Get name length */
#if _FS_EXFAT
if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */
for (i = j = 0; i < slen; ) { /* Create volume label in directory form */
w = label[i++];
#if !_LFN_UNICODE
if (IsDBCS1(w)) {
w = (i < slen && IsDBCS2(label[i])) ? w << 8 | (BYTE)label[i++] : 0;
}
w = ff_convert(w, 1);
#endif
if (w == 0 || chk_chr(badchr, w) || j == 22) { /* Check validity check validity of the volume label */
LEAVE_FF(fs, FR_INVALID_NAME);
}
st_word(dirvn + j, w); j += 2;
}
slen = j;
} else
#endif
{ /* On the FAT12/16/32 volume */
for ( ; slen && label[slen - 1] == ' '; slen--) ; /* Remove trailing spaces */
if (slen) { /* Is there a volume label to be set? */
dirvn[0] = 0; i = j = 0; /* Create volume label in directory form */
do {
#if _LFN_UNICODE
w = ff_convert(ff_wtoupper(label[i++]), 0);
#else
w = (BYTE)label[i++];
if (IsDBCS1(w)) {
w = (j < 10 && i < slen && IsDBCS2(label[i])) ? w << 8 | (BYTE)label[i++] : 0;
}
#if _USE_LFN != 0
w = ff_convert(ff_wtoupper(ff_convert(w, 1)), 0);
#else
if (IsLower(w)) w -= 0x20; /* To upper ASCII characters */
#ifdef _EXCVT
if (w >= 0x80) w = ExCvt[w - 0x80]; /* To upper extended characters (SBCS cfg) */
#else
if (!_DF1S && w >= 0x80) w = 0; /* Reject extended characters (ASCII cfg) */
#endif
#endif
#endif
if (w == 0 || chk_chr(badchr, w) || j >= (UINT)((w >= 0x100) ? 10 : 11)) { /* Reject invalid characters for volume label */
LEAVE_FF(fs, FR_INVALID_NAME);
}
if (w >= 0x100) dirvn[j++] = (BYTE)(w >> 8);
dirvn[j++] = (BYTE)w;
} while (i < slen);
while (j < 11) dirvn[j++] = ' '; /* Fill remaining name field */
if (dirvn[0] == DDEM) LEAVE_FF(fs, FR_INVALID_NAME); /* Reject illegal name (heading DDEM) */
}
}
/* Set volume label */
dj.obj.sclust = 0; /* Open root directory */
res = dir_sdi(&dj, 0);
if (res == FR_OK) {
res = dir_read(&dj, 1); /* Get volume label entry */
if (res == FR_OK) {
if (_FS_EXFAT && fs->fs_type == FS_EXFAT) {
dj.dir[XDIR_NumLabel] = (BYTE)(slen / 2); /* Change the volume label */
mem_cpy(dj.dir + XDIR_Label, dirvn, slen);
} else {
if (slen) {
mem_cpy(dj.dir, dirvn, 11); /* Change the volume label */
} else {
dj.dir[DIR_Name] = DDEM; /* Remove the volume label */
}
}
fs->wflag = 1;
res = sync_fs(fs);
} else { /* No volume label entry is found or error */
if (res == FR_NO_FILE) {
res = FR_OK;
if (slen) { /* Create a volume label entry */
res = dir_alloc(&dj, 1); /* Allocate an entry */
if (res == FR_OK) {
mem_set(dj.dir, 0, SZDIRE); /* Clear the entry */
if (_FS_EXFAT && fs->fs_type == FS_EXFAT) {
dj.dir[XDIR_Type] = 0x83; /* Create 83 entry */
dj.dir[XDIR_NumLabel] = (BYTE)(slen / 2);
mem_cpy(dj.dir + XDIR_Label, dirvn, slen);
} else {
dj.dir[DIR_Attr] = AM_VOL; /* Create volume label entry */
mem_cpy(dj.dir, dirvn, 11);
}
fs->wflag = 1;
res = sync_fs(fs);
}
}
}
}
}
LEAVE_FF(fs, res);
}