⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tmfat32.c

📁 PNX1500上Fat32文件系统源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
            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 + -