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

📄 fs_fat.c

📁 keil arm flash fs 最新版 在Keil arm下使用
💻 C
📖 第 1 页 / 共 5 页
字号:
   /* Check for "." and ".." name */
   ch0 = *fn;
   ch1 = *(fn + 1);
   ch2 = *(fn + 2);
   if (ch0 == '.') {
      if (ch1 == 0) {
         en[0] = '.';
         return (__TRUE);
      }
      else if (ch1 == '.' && ch2 == 0) {
         en[0] = '.';
         en[1] = '.';
         return (__TRUE);
      }
   }

   /* Copy name part (maximum 8 characters) */
   for (i = 0; i < 8; ) {
      if (!(*fn))     {          return (__TRUE); }
      if (*fn == '.') { dot = 1; fn++; break;     }
      if (*fn == ' ') {          fn++; continue;  }
      en[i] = val_char(*fn);
      if (en[i] >= 'a' && en[i] <= 'z')
         en[i] = en[i] & (~0x20);
      i  ++;
      fn ++;
   }

   /* Copy extension part (maximum 3 characters) */
   for (i = 8; i < 11; ) {
      if (!(*fn))     {         return (__TRUE); }
      if (*fn == '.') { dot = 1; fn++; continue; }
      if (*fn == ' ') {          fn++; continue; }
      if (dot)        {
         en[i] = val_char(*fn);
         if (en[i] >= 'a' && en[i] <= 'z')
            en[i] = en[i] & (~0x20);
         i  ++;
      }
      fn ++;
   }
   return (__TRUE);
}


/*--------------------------- check_lfn -------------------------------------*/

static BOOL check_lfn (const char *fn) {
   /* Check if "fn" is a long name. */
   BOOL dot = 0;
   U8   ch, prev_ch = 0;
   U32  i = 0, j = 0;

   while (*fn) {
      if (val_char_sn (*fn) == __FALSE) {
         goto lfn;
      }
      
      /* If 'space' exists in name then it is a long name. */
      if (*fn == ' ') goto lfn;

      /* If '.' exists in name more then once or if there are more then 3 
         valid characters after '.' then it is a long name. */
      if (*fn == '.') {
         if (dot) goto lfn;
         fn ++;
         j   = 0;
         dot = 1;
         continue;
      }

      /* If cases (upper or lower) of letter are different then it is a 
         long name. */
      ch = *fn;
      if ((ch >= 'a' && ch <= 'z') ||
          (ch >= 'A' && ch <= 'Z')) {
         if (i > 0 && ((prev_ch ^ ch) & 0x20)) {
            goto lfn;
         }
         prev_ch = ch;
      }

      if (dot) {
         if (j++ > 2) 
            goto lfn;
      }
      i  ++;
      fn ++;
   }

   if (i > 12) {
      /* This is a long name. */
lfn:  return (__TRUE);
   }

   /* This is a short name. */
   return (__FALSE);
}


/*--------------------------- val_char --------------------------------------*/

static U8 val_char (U8 ch) {
   /* Validate character 'ch' to be a valid character if not convert it 
      to 'X'. */

   if (val_char_sn (ch) == __FALSE) {
      return ('X');
   }

   return (ch);
}


/*--------------------------- val_char_sn -----------------------------------*/

static BOOL val_char_sn (U8 ch) {
   /* Validate character 'ch' to be a valid short name character. */

   if ((ch >= ' ' && ch <= '!') ||
       (ch >= '#' && ch <= ')') ||
       (ch == '-')              ||
       (ch == '.')              ||
       (ch >= '0' && ch <= '9') ||
       (ch == '@')              ||
       (ch >= 'A' && ch <= 'Z') ||
       (ch >= '^' && ch <= '{') ||
       (ch == '}')              ||
       (ch == '~')               ) {

       /* This is a valid short name character. */
       return (__TRUE);
   }

   /* This is not a valid short name character. */
   return (__FALSE);
}


/*--------------------------- val_char_ln -----------------------------------*/
#if 0
static BOOL val_char_ln (U8 ch) {
   /* Validate character 'ch' to be a valid long name character. */

   if (val_char_sn (ch) == __TRUE) {
      /* If character is a valid short name character then it is also a valid 
         long name character. */
      return (__TRUE);
   }

   if (ch == '+' || 
       ch == ',' || 
       ch == ';' || 
       ch == '=' || 
       ch == '[' || 
       ch == ']' ||
       ch >  127) {

       /* This is a valid long name character. */
       return (__TRUE);
   }

   /* This is not a valid long name character. */
   return (__FALSE);
}
#endif

/*--------------------------- val_char_lab ----------------------------------*/

static U8 val_char_lab (U8 ch) {
   /* Validate character 'ch' to be a valid disk label character. */

   if ((ch >= '0' && ch <= '9') ||
       (ch >= 'A' && ch <= 'Z') ||
       (ch == '_') || (ch == ' ')) {
      return (ch);
   }
   if (ch >= 'a' && ch <= 'z') {
      /* Convert to uppercase. */
      return (ch & ~0x20);
   }
   /* This is not a valid disk label character. */
   return (0);
}


/*--------------------------- get_dir_name ----------------------------------*/

static BOOL get_dir_name (const char *fn, char *dn, unsigned int *sz) {
   /* Return first name (dir or file) if "fn" given as path + file name, and 
      also calculates number of characters until the end of name (sz).
      It returns __TRUE if directory name else it returns __FALSE.           */
   /* Example: *fn  = "Some Folder\Test\Some file.txt"
               *dn  = "Some Folder"                                    
                sz  = 12                                                     */
   U8  ch;
   U32 i, j;

   for (i = 0, j = 0; ; i++) {
      ch = *(fn + i);
      if (ch == '\\' || ch == '\"') {
         dn[j] = 0;
         *sz   = i + 1;
         return (__TRUE);
      }
      if (ch == 0) {
         dn[j] = 0;
         return (__FALSE);
      }
      dn[j++] = ch;
   }
}


/*--------------------------- get_nt_name -----------------------------------*/

static BOOL get_nt_name (const char *fn, char *sn, int num) {
   /* Create a short name in "sn" with numeric tail (with value num) 
      of a long name given in "fn".
      It returns __TRUE if successfull else it returns __FALSE.              */
   /* Example: *fn   = "Some file.txt"
               *sn   = "SOMEFI~3.TXT
                num  = 3                                                     */
   U8  ch, num_sz;
   U32 dot_pos  = 0xFFFF;
   U32 val, i, j;

   /* Calculate how many digits requested number has (maximum 6). */
   if      (num > 99999) num_sz = 6;
   else if (num >  9999) num_sz = 5;
   else if (num >   999) num_sz = 4;
   else if (num >    99) num_sz = 3;
   else if (num >     9) num_sz = 2;
   else                  num_sz = 1;

   /* Find position of last dot (.) in long name. */
   for (i = 0; *(fn + i); i++) {
      if (*(fn + i) == '.') dot_pos = i;
   }

   /* Copy first part of the name. */
   for (i = 0, j = 0; (i < dot_pos) && (j < (7 - num_sz)); i++) {
      ch = *(fn + i);
      if ((ch == ' ') || (ch == '.')) {
         continue;
      }
      else {
         sn[j++] = val_char (ch);
      }
   }

   sn[j++] = '~';

   switch (num_sz) {
      case 6: 
         val            = num / 100000;
         num           -= val * 100000;
         if (val > 9) val = 9;
         sn[j++]  = '0' + val;
      case 5: 
         val            = num /  10000;
         num           -= val *  10000;
         sn[j++]  = '0' + val;
      case 4: 
         val            = num /   1000;
         num           -= val *   1000;
         sn[j++]  = '0' + val;
      case 3: 
         val            = num /    100;
         num           -= val *    100;
         sn[j++]  = '0' + val;
      case 2: 
         val            = num /     10;
         num           -= val *     10;
         sn[j++]  = '0' + val;
      case 1: 
         sn[j++]  = '0' + num;
         break;
   }

   sn[j++] = '.';

   if (dot_pos != 0xFFFF) {
      for (i = dot_pos + 1; (i < dot_pos + 4); i++) {
         ch = *(fn + i);
         if (!ch) {
            break;
         }
         sn[j++] = val_char (ch);
      }
   }

   sn[j] = 0;                           /* Terminate name string */

   return (__TRUE);
}


/*--------------------------- get_dir_sect ---------------------------------*/

static U32 get_dir_sect (U32 clus) {
   /* Calculate sector address of the cluster, and update in_root_1x flag. */
   U32 sect;

   in_root_1x = 0;
   if (clus == 0) {
      startDirClus = 0;

      /* This is a ROOT folder. */
      if (mmc.FatType == FS_FAT32) {
         /* This is a ROOT folder on FAT32. */
         sect = clus_to_sect (mmc.FAT32_RootClus);
      }
      else {
         /* This is a ROOT folder on FAT12 or FAT16. */
         sect = mmc.BootRecSec + mmc.RootDirAddr;
         in_root_1x = 1;
      }
   }
   else {
      /* This is a subfolder. */
      sect = clus_to_sect (clus);
   }
   return (sect);
}


/*--------------------------- search_for_name -------------------------------*/

static BOOL search_for_name (const char *name, IOB *fcb, U8 type, U8 keep_fcb) {
   /* Search for entries with requested name and of requested type 
      (file or dir).                                                         */

   char         sen[13];
   FILEREC     *frec;
   U8           lfn_f         = 0;
   U8           dir_f         = (type == ENT_DIR);
   U8           same_f        = 1;
   U8           type_f        = 0;
   U8           sfn_name_f    = __FALSE;
   U8           chksum        = 0;
   U8           ents          = 0;
   U8           name_ents     = 1;
   U32          clus          = fcb->_firstClus;
   U32          idx;
   U32          first_clus    = 0;
   U32          first_offs    = 0;
   U32          sect;
   U32          i;

   startDirClus = fcb->_firstClus;

   /* Calculate number of requested entries needed for name. */
   if (check_lfn(name) == __TRUE) {
      /* Add number of LFN entries. */
      name_ents += ((strlen(name) + 12) / 13);
   }

   /* Convert name to short entry type (8.3) */
   sfn_name_f = cvt_fatname (name, sen);

   /* Calculate current sector address for folder. */
   sect = get_dir_sect (clus);

   /* Search through name entries. */
   for (idx = 0;  ; idx++) {
      if (in_root_1x) {
         if (idx == 512) {
            return (__FALSE);
         }
      }
      else {
         /* Check if step to next cluster is needed. */
         if (idx == mmc.EntsPerClus) {
            idx = 0;
            if (clus < mmc.FAT32_RootClus) {
               clus = mmc.FAT32_RootClus;
            }
            set_next_clus (&clus);
            if (is_EOC (clus)) {
               /* No more entries, end of current directory. */
               goto not_found;
            }
            sect = clus_to_sect (clus);
         }
      }

      read_sector (sect + (idx >> 4));
      frec = (FILEREC *)ca.buf + (idx & 0x0F);

      if (frec->FileName[0] == 0x00) {
         /* There are no allocated entries after this one. */
         goto not_found;
      }

      if (frec->FileName[0] == 0xE5) {
         /* Erased file, first character is 0xE5. */
         continue;
      }

      if (frec->Attr == ATTR_VOLUME_ID) {
         /* Skip Volume ID entry. */
         continue;
      }

      if ((frec->Attr == ATTR_LONG_NAME) && (LFN_REC(frec)->Ordinal & ORD_LONG_NAME_LAST)) {
         /* Long name last entry found. */
         lfn_f           = 1;
         same_f          = 1;
         if (((LFN_REC(frec)->Ordinal & ~ORD_LONG_NAME_LAST) + 1) != name_ents) {
            same_f       = 0;
         }
         first_clus      = clus;
         first_offs      = idx;
         ents            = 0;
         chksum          = LFN_REC(frec)->Checksum;
      }

      /* type_f == 1 if type of entry we are searching for is the same 
         one we are checking now. */
      type_f = !(dir_f ^ ((frec->Attr & ATTR_DIRECTORY) == ATTR_DIRECTORY));

      if (lfn_f) {
         /* Long name entry found. */
         ents ++;

         if (frec->Attr != ATTR_LONG_NAME) {
            /* If this is long name's accompanying short entry. */
            lfn_f = 0;

            /* Calculate short name's checksum. */
            if ((same_f) && (chksum == lfn_calc_chksum(frec->FileName))) {
               if (type_f) {
                  /* If this is the file or directory we searched for. */
                  if (keep_fcb) {
                     goto found_keep_fcb;
                  }
                  goto found;
               }
            }
            else {
               /* Check also if name is same as only short name (for checking 
                  if short name already exists). */
               goto chk_short;
            }
         }

         if (!same_f) {
            /* If this is not the entry we are searching for. */
            continue;
         }

         if (chksum != LFN_REC(frec)->Checksum) {
            /* If any of long entries does not have the same checksum 
               as previous ones then this name is invalid. */
            same_f = 0;
            continue;
         }

         /* Long name checking in progress. */
         i = ((LFN_REC(frec)->Ordinal & 0x1F) - 1) * 13;

         /* Compare 13 chars of name with 13 chars of entry name, ignore case. */
         same_f = lfn_cmp_name ((U8 *)frec, (S8 *)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -