📄 tmfat32.c
字号:
cluster &= FAT32_CLUSTER_MASK;
else if (p->fsType == tmFat32_FAT16)
cluster &= FAT16_CLUSTER_MASK;
else
cluster &= FAT12_CLUSTER_MASK;
while (cluster)
{
if (UTIL_fat_content(GET_FAT_ENTRY, cluster, 0, &next_cluster))
goto done;
if (UTIL_fat_content(SET_FAT_ENTRY, cluster, 0, Null))
goto done;
p->freeClusters++;
lastCluster = False;
if (p->fsType == tmFat32_FAT32)
{
next_cluster &= FAT32_CLUSTER_MASK;
if (next_cluster >= FAT32_EOC)
lastCluster = True;
}
else if (p->fsType == tmFat32_FAT16)
{
next_cluster &= FAT16_CLUSTER_MASK;
if (next_cluster >= FAT16_EOC)
lastCluster = True;
}
else
{
next_cluster &= FAT12_CLUSTER_MASK;
if (next_cluster >= FAT12_EOC)
lastCluster = True;
}
if (lastCluster)
cluster = 0;
else
cluster = next_cluster;
}
}
if (flags & DELETE_FILE_TRUNCATE)
{
// We're just truncating. Skip over all the longname entries, if any,
// and set the file size to zero. Update the appropriate time fields
// since the file was modified.
tmosalDateTime_t now; // Current time
offset = f->dir.short_offset;
cluster = f->dir.short_cluster;
if (UTIL_cluster_content(GET_CLUSTER_CONTENT, &cluster, &offset, mydir,
DIR_ENTRY_SIZE) != DIR_ENTRY_SIZE)
goto done;
SET32(&mydir[OFFSET_DIRFileSize], 0);
SET16(&mydir[OFFSET_DIRFstClusLO], 0);
SET16(&mydir[OFFSET_DIRFstClusHI], 0);
if ((tmosalGetDateTime(&now)) != TM_OK)
{
TMFAT_DEBUG0("tmosalGetDateTime failed!\n");
memset(&now, 0, sizeof(now));
}
UTIL_date_time(SET_TIME, TIME_ACCESS, mydir, Null, &now);
UTIL_date_time(SET_TIME, TIME_WRITE, mydir, Null, &now);
offset = f->dir.short_offset;
cluster = f->dir.short_cluster;
if (UTIL_cluster_content(SET_CLUSTER_CONTENT, &cluster, &offset, mydir,
DIR_ENTRY_SIZE) != DIR_ENTRY_SIZE)
goto done;
// The file is now empty
SET32(&f->dir.shortDir[OFFSET_DIRFileSize], 0);
SET16(&f->dir.shortDir[OFFSET_DIRFstClusLO], 0);
SET16(&f->dir.shortDir[OFFSET_DIRFstClusHI], 0);
f->size = 0;
f->curpos = 0;
f->seekpos = 0;
f->cur_cluster = 0;
f->cur_offset = 0;
f->base_cluster = 0;
}
else if (flags & DELETE_FILE_DIRECTORY)
{
// Free the directory entries in this file's parent directory. This could be
// one entry for a short name file or several for a long name file. We'll
// take the lazy approach and only mark them as free. We could check, for
// example, if these are the last entries in the parent directory and mark
// the new end of directory but we'll let the excellent Windows disk utilities
// clean up all the garbage instead.
mydir[0] = 0xE5;
nparts = f->dir.slots;
offset = f->dir.long_offset;
cluster = f->dir.long_cluster;
while (nparts--)
{
if (UTIL_cluster_content(SET_CLUSTER_CONTENT, &cluster, &offset, mydir, 1) != 1)
goto done;
if (offset == p->bytesPerCluster)
{
TMFAT_DEBUG2("offset == p->bytesPerCluster doing DELETE_FILE_DIRECTORY, offset=%u, cluster=%u\n",
offset, cluster);
goto done;
}
offset += DIR_ENTRY_SIZE - 1;
if ((nparts > 0) && (offset == p->bytesPerCluster))
{
// Ugh, the directory straddles a cluster
offset = 0;
if (UTIL_fat_content(GET_FAT_ENTRY, cluster, 0, &next_cluster))
goto done;
if (p->fsType == tmFat32_FAT32)
cluster = next_cluster & FAT32_CLUSTER_MASK;
else if (p->fsType == tmFat32_FAT16)
cluster = next_cluster & FAT16_CLUSTER_MASK;
else
cluster = next_cluster & FAT12_CLUSTER_MASK;
}
}
}
rval = 0;
done:
return rval;
}
// Create a short name from a long file name. Return 0 on success.
// This function is used to generate the famous "LETTER~1.DOC" file names.
static int UTIL_mangle_long_name (char *base, char *longname,
char *shortname, ptmFat32_File_t f)
{
Bool lossy = False;
Bool longname_fits = True;
char *s, *d;
int len, i;
int baselen;
int extlen;
int numlen;
int longlen;
char c;
char mylong[TM_FAT32_MAX_LONG_NAME+1]; // 255 + 1
char basis[8 + 1]; // Basis name
char ext[3 + 1]; // Extension, 1-3 chars
char numtail[7 + 1]; // Numeric tail can be from "~1" to "~999999"
len = strlen(base); // Remember the length of base pathname
strcpy(mylong, longname); // Work on a copy
// TMFAT_DEBUG2("+UTIL_mangle_long_name(base=%s,longname=%s)\n", base, longname);
// Convert to upper case and convert invalid short-name glyphs to
// underscores.
s = mylong;
while (*s)
{
c = *s;
if ((c == '+') || (c == ',') || (c == ';') || (c == '=') || (c == '[') || (c == ']'))
{
*s = '_';
lossy = True;
}
*s = toupper(*s);
s++;
}
// Strip all leading and embedded spaces from the long name.
s = d = mylong;
while (*s)
{
if (*s != 0x20)
*d++ = *s;
s++;
}
*d = 0;
// Strip all leading periods from the long name
s = d = mylong;
while (*s++ == '.')
{
}
s--;
while (*s)
*d++ = *s++;
*d = 0;
// Generate a candidate basis name
baselen = 0;
longlen = strlen(mylong);
d = basis;
for (i = 0; i < longlen; i++)
{
if (mylong[i] == '.')
continue;
*d++ = mylong[i];
baselen++;
if (baselen == 8)
break;
}
*d = 0;
if (longlen > baselen)
longname_fits = False;
// Get extension if it exists
s = strrchr(mylong, '.');
if (s)
{
extlen = strlen(&s[1]);
if (extlen < 4)
strcpy(ext, &s[1]);
else
extlen = 0;
}
else
extlen = 0;
// Generate the first candidate
i = 0;
if (!longname_fits || lossy)
{
sprintf(numtail, "~%d", ++i);
numlen = strlen(numtail);
strcpy(&basis[8-numlen],numtail);
}
// Test if it's unique
while (i <= 999999)
{
base[len] = 0;
strcat(base, "/");
strcat(base, basis);
if (extlen > 0)
{
strcat(base, ".");
strcat(base, ext);
}
// TMFAT_DEBUG1("Checking %s for uniqueness.\n", base);
if (UTIL_find_file(base, f))
{
// Fill in short name with spaces and then stuff with
// basis name and possible extension.
memset(shortname, 0x20, 11);
strncpy(shortname, basis, baselen);
if (extlen > 0)
strncpy(&shortname[8], ext, extlen);
strncpy(mylong, shortname, 11);
mylong[11] = 0;
// TMFAT_DEBUG1("-UTIL_mangle_long_name() ok with short name=%s.\n", mylong);
return 0; // Success
}
// Found a duplicate so try a new basis
sprintf(numtail, "~%d", ++i);
numlen = strlen(numtail);
strcpy(&basis[8-numlen],numtail);
}
return 1; // Failed to create a unique short name
}
// In preparation to create a new directory or file create the
// directory content in *dir given the full pathname. The
// function can return the following values. On error *dir
// *cluster, and *count may be modified but should not be
// used by the caller. *dir must be big enough to contain
// all the long directory entries (if applicable) and
// the final short directory entry.
//
// 0 Success. *dir contains the new directory content, *cluster
// is the starting cluster number of the directory where
// this content is to be written and *count is the number
// of DIR_ENTRY_SIZE entries created. *count will be 1
// for short names and >1 for long names.
//
// 1 Pathname is illegal. It may be too long or contain invalid
// characters.
//
// 2 The directory where this new entity is to be placed does
// not exist.
static int UTIL_fill_dir_content (const char *path, UInt8 *dir, UInt32 *cluster, int *count)
{
ptmFat32_FS_t p = GFS;
char *p1;
char *p2;
char *pc;
size_t len;
int i;
int j;
int k;
int n;
int nparts; // Number of long name parts
Bool short_name = False;
char my_path[PATH_MAX+1]; // 1024 + 1
tmFat32_File_t f;
tmosalDateTime_t now; // Current time
if (strlen(path) > PATH_MAX)
{
SET_ERRNO(ENAMETOOLONG);
TMFAT_DEBUG1("'%s' name length too long.\n", path);
return 1;
}
// The pathname is already normalized
strcpy(my_path, path); // Work with a copy
p1 = strrchr(my_path, '/');
if (!p1)
p1 = (char *) &my_path[p->prefixLen]; // Path is of the form "FOO:bar.txt"
else
p1++;
// p1 now points to the filename (last) portion of the path. Make sure the directory
// where this entity is to live exists before going any further. When time comes
// to write the generated directory data we'll start searching from the
// beginning of the cluster.
p1[-1] = 0; // Chop off the filename portion.
if (!UTIL_find_file(my_path, &f))
{
if (!f.isDir)
{
// TMFAT_DEBUG1("'%s' is not a directory.\n", my_path);
return 2;
}
*cluster = f.base_cluster;
}
else
{
// TMFAT_DEBUG1("Did not find '%s'.\n", my_path);
return 2;
}
len = strlen(p1);
if (len < 1 || len > TM_FAT32_MAX_LONG_NAME)
{
TMFAT_DEBUG2("Length (%d) of '%s' is too long.\n", len, p1);
return 1;
}
// p1 is the candidate file name. Determine if it's a short name.
if (len < 13)
{
p2 = strrchr(p1, '.');
if (p2)
{
// We have a dot
if (strlen(p2) < 5 && (p2 - p1) < 9 && (strchr(p1, '.') == p2))
{
// Have only dot and fits the 8.3 mold
short_name = True;
}
}
else if (len < 9)
{
// No dot and it fits
short_name = True;
}
}
if (short_name)
{
int thedot = 0;
// TMFAT_DEBUG2("We're short '%s', len = %d.\n", p1, len);
nparts = 0;
memset(dir, 0, DIR_ENTRY_SIZE);
// Some characters are not allowed in short names
// Do the MS n
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -