📄 fs_fat32util.c
字号:
dir->fd_currcluster = cluster; dir->fd_currsector = fat_cluster2sector(fs, cluster); } } } /* Save the new index into dir->fd_currsector */ dir->fd_index = ndx; return OK;}/**************************************************************************** * Name: fat_finddirentry * * Desciption: Given a path to something that may or may not be in the file * system, return the directory entry of the item. * ****************************************************************************/int fat_finddirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo, const char *path){ size_t cluster; ubyte *direntry = NULL; char terminator; int ret; /* Initialize to traverse the chain. Set it to the cluster of * the root directory */ cluster = fs->fs_rootbase; if (fs->fs_type == FSTYPE_FAT32) { /* For FAT32, the root directory is variable sized and is a * cluster chain like any other directory. fs_rootbase holds * the first cluster of the root directory. */ dirinfo->dir.fd_startcluster = cluster; dirinfo->dir.fd_currcluster = cluster; dirinfo->dir.fd_currsector = fat_cluster2sector(fs, cluster); } else { /* For FAT12/16, the first sector of the root directory is a sector * relative to the first sector of the fat volume. */ dirinfo->dir.fd_startcluster = 0; dirinfo->dir.fd_currcluster = 0; dirinfo->dir.fd_currsector = cluster; } /* fd_index is the index into the current directory table */ dirinfo->dir.fd_index = 0; /* If no path was provided, then the root directory must be exactly * what the caller is looking for. */ if (*path == '\0') { dirinfo->fd_entry = NULL; return OK; } /* Otherwise, loop until the path is found */ for (;;) { /* Convert the next the path segment name into the kind of * name that we would see in the directory entry. */ ret = fat_path2dirname(&path, dirinfo, &terminator); if (ret < 0) { /* ERROR: The filename contains invalid characters or is * too long. */ return ret; } /* Now search the current directory entry for an entry with this * matching name. */ for (;;) { /* Read the next sector into memory */ ret = fat_fscacheread(fs, dirinfo->dir.fd_currsector); if (ret < 0) { return ret; } /* Get a pointer to the directory entry */ direntry = &fs->fs_buffer[DIRSEC_BYTENDX(fs, dirinfo->dir.fd_index)]; /* Check if we are at the end of the directory */ if (direntry[DIR_NAME] == DIR0_ALLEMPTY) { return -ENOENT; } /* Check if we have found the directory entry that we are looking for */ if (direntry[DIR_NAME] != DIR0_EMPTY && !(DIR_GETATTRIBUTES(direntry) & FATATTR_VOLUMEID) && !memcmp(&direntry[DIR_NAME], dirinfo->fd_name, 8+3) ) { /* Yes.. break out of the loop */ break; } /* No... get the next directory index and try again */ if (fat_nextdirentry(fs, &dirinfo->dir) != OK) { return -ENOENT; } } /* We get here only if we have found a directory entry that matches * the path element that we are looking for. * * If the terminator character in the path was the end of the string * then we have successfully found the directory entry that describes * the path. */ if (!terminator) { /* Return the pointer to the matching directory entry */ dirinfo->fd_entry = direntry; return OK; } /* No.. then we have found one of the intermediate directories on * the way to the final path target. In this case, make sure * the thing that we found is, indeed, a directory. */ if (!(DIR_GETATTRIBUTES(direntry) & FATATTR_DIRECTORY)) { /* Ooops.. we found something else */ return -ENOTDIR; } /* Get the cluster number of this directory */ cluster = ((uint32)DIR_GETFSTCLUSTHI(direntry) << 16) | DIR_GETFSTCLUSTLO(direntry); /* The restart scanning at the new directory */ dirinfo->dir.fd_currcluster = dirinfo->dir.fd_startcluster = cluster; dirinfo->dir.fd_currsector = fat_cluster2sector(fs, cluster); dirinfo->dir.fd_index = 2; }}/**************************************************************************** * Name: fat_allocatedirentry * * Desciption: Find a free directory entry * ****************************************************************************/int fat_allocatedirentry(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo){ sint32 cluster; size_t sector; ubyte *direntry; ubyte ch; int ret; int i; /* Re-initialize directory object */ cluster = dirinfo->dir.fd_startcluster; if (cluster) { /* Cluster chain can be extended */ dirinfo->dir.fd_currcluster = cluster; dirinfo->dir.fd_currsector = fat_cluster2sector(fs, cluster); } else { /* Fixed size FAT12/16 root directory is at fixxed offset/size */ dirinfo->dir.fd_currsector = fs->fs_rootbase; } dirinfo->dir.fd_index = 0; for (;;) { unsigned int dirindex; /* Read the directory sector into fs_buffer */ ret = fat_fscacheread(fs, dirinfo->dir.fd_currsector); if (ret < 0) { return ret; } /* Get a pointer to the entry at fd_index */ dirindex = (dirinfo->dir.fd_index & DIRSEC_NDXMASK(fs)) * 32; direntry = &fs->fs_buffer[dirindex]; /* Check if this directory entry is empty */ ch = direntry[DIR_NAME]; if (ch == DIR0_ALLEMPTY || ch == DIR0_EMPTY) { /* It is empty -- we have found a directory entry */ dirinfo->fd_entry = direntry; return OK; } ret = fat_nextdirentry(fs, &dirinfo->dir); if (ret < 0) { return ret; } } /* If we get here, then we have reached the end of the directory table * in this sector without finding a free directory enty. * * It this is a fixed size dirctory entry, then this is an error. * Otherwise, we can try to extend the directory cluster chain to * make space for the new directory entry. */ if (!cluster) { /* The size is fixed */ return -ENOSPC; } /* Try to extend the cluster chain for this directory */ cluster = fat_extendchain(fs, dirinfo->dir.fd_currcluster); if (cluster < 0) { return cluster; } /* Flush out any cached date in fs_buffer.. we are going to use * it to initialize the new directory cluster. */ ret = fat_fscacheflush(fs); if (ret < 0) { return ret; } /* Clear all sectors comprising the new directory cluster */ fs->fs_currentsector = fat_cluster2sector(fs, cluster); memset(fs->fs_buffer, 0, fs->fs_hwsectorsize); sector = sector; for (i = fs->fs_fatsecperclus; i; i--) { ret = fat_hwwrite(fs, fs->fs_buffer, sector, 1); if ( ret < 0) { return ret; } sector++; } dirinfo->fd_entry = fs->fs_buffer; return OK;}/**************************************************************************** * Name: fat_dirname2path * * Desciption: Convert a filename in a raw directory entry into a user * filename. This is essentially the inverse operation of that performed * by fat_path2dirname. See that function for more details. * ****************************************************************************/int fat_dirname2path(char *path, ubyte *direntry){#ifdef CONFIG_FAT_LCNAMES ubyte ntflags;#endif int ch; int ndx; /* Check if we will be doing upper to lower case conversions */#ifdef CONFIG_FAT_LCNAMES ntflags = DIR_GETNTRES(direntry);#endif /* Get the 8-byte filename */ for (ndx = 0; ndx < 8; ndx++) { /* Get the next filename character from the directory entry */ ch = direntry[ndx]; /* Any space (or ndx==8) terminates the filename */ if (ch == ' ') { break; } /* In this version, we never write 0xe5 in the directoryfilenames * (because we do not handle any character sets where 0xe5 is valid * in a filaname), but we could encounted this in a filesystem * written by some other system */ if (ndx == 0 && ch == DIR0_E5) { ch = 0xe5; } /* Check if we should perform upper to lower case conversion * of the (whole) filename. */#ifdef CONFIG_FAT_LCNAMES if (ntflags & FATNTRES_LCNAME && isupper(ch)) { ch = tolower(ch); }#endif /* Copy the next character into the filename */ *path++ = ch; } /* Check if there is an extension */ if (direntry[8] != ' ') { /* Yes, output the dot before the extension */ *path++ = '.'; /* Then output the (up to) 3 character extension */ for (ndx = 8; ndx < 11; ndx++) { /* Get the next extensions character from the directory entry */ ch = direntry[DIR_NAME + ndx]; /* Any space (or ndx==11) terminates the extension */ if (ch == ' ') { break; } /* Check if we should perform upper to lower case conversion * of the (whole) filename. */#ifdef CONFIG_FAT_LCNAMES if (ntflags & FATNTRES_LCEXT && isupper(ch)) { ch = tolower(ch); }#endif /* Copy the next character into the filename */ *path++ = ch; } } /* Put a null terminator at the end of the filename */ *path = '\0'; return OK;}/**************************************************************************** * Name: fat_dirtruncate * * Desciption: Truncate an existing file to zero length * * Assumptions: The caller holds mountpoint semaphore, fs_buffer holds * the directory entry, dirinfo refers to the current fs_buffer content. * ****************************************************************************/int fat_dirtruncate(struct fat_mountpt_s *fs, struct fat_dirinfo_s *dirinfo){ unsigned int startcluster; uint32 writetime; size_t savesector; int ret; /* Get start cluster of the file to truncate */ startcluster = ((uint32)DIR_GETFSTCLUSTHI(dirinfo->fd_entry) << 16) | DIR_GETFSTCLUSTLO(dirinfo->fd_entry); /* Clear the cluster start value in the directory and set the file size * to zero. This makes the file look empty but also have to dispose of * all of the clusters in the chain. */ DIR_PUTFSTCLUSTHI(dirinfo->fd_entry, 0); DIR_PUTFSTCLUSTLO(dirinfo->fd_entry, 0); DIR_PUTFILESIZE(dirinfo->fd_entry, 0); /* Set the ARCHIVE attribute and update the write time */ DIR_PUTATTRIBUTES(dirinfo->fd_entry, FATATTR_ARCHIVE); writetime = fat_systime2fattime(); DIR_PUTWRTTIME(dirinfo->fd_entry, writetime & 0xffff); DIR_PUTWRTDATE(dirinfo->fd_entry, writetime > 16); /* This sector needs to be written back to disk eventually */ fs->fs_dirty = TRUE; /* Now remove the entire cluster chain comprising the file */ savesector = fs->fs_currentsector; ret = fat_removechain(fs, startcluster); if (ret < 0) { return ret; } /* Setup FSINFO to resuse this cluster next */ fs->fs_fsinextfree = startcluster - 1; /* Make sure that the directory is still in the cache */ return fat_fscacheread(fs, savesector);}/**************************************************************************** * Name: fat_dircreate * * Desciption: Create a directory entry for a new file *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -