Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/fs/fat/fat_dentry.c

    r5d95f02 r19f857a  
    11/*
    22 * Copyright (c) 2008 Jakub Jermar
    3  * Copyright (c) 2011 Oleg Romanenko
    43 * All rights reserved.
    54 *
     
    4039#include <ctype.h>
    4140#include <str.h>
    42 #include <errno.h>
    43 #include <byteorder.h>
    44 #include <assert.h>
     41
     42static bool is_d_char(const char ch)
     43{
     44        if (isalnum(ch) || ch == '_')
     45                return true;
     46        else
     47                return false;
     48}
    4549
    4650/** Compare path component with the name read from the dentry.
     
    7680}
    7781
    78 void fat_dentry_name_get(const fat_dentry_t *d, char *buf)
    79 {
    80         unsigned int i;
    81        
    82         for (i = 0; i < FAT_NAME_LEN; i++) {
    83                 if (d->name[i] == FAT_PAD)
    84                         break;
    85                
    86                 if (d->name[i] == FAT_DENTRY_E5_ESC)
    87                         *buf++ = 0xe5;
    88                 else {
    89                         if (d->lcase & FAT_LCASE_LOWER_NAME)
    90                                 *buf++ = tolower(d->name[i]);
    91                         else
    92                                 *buf++ = d->name[i];
    93                 }
    94         }
    95        
    96         if (d->ext[0] != FAT_PAD)
    97                 *buf++ = '.';
    98        
    99         for (i = 0; i < FAT_EXT_LEN; i++) {
    100                 if (d->ext[i] == FAT_PAD) {
    101                         *buf = '\0';
    102                         return;
    103                 }
    104                
    105                 if (d->ext[i] == FAT_DENTRY_E5_ESC)
    106                         *buf++ = 0xe5;
    107                 else {
    108                         if (d->lcase & FAT_LCASE_LOWER_EXT)
    109                                 *buf++ = tolower(d->ext[i]);
    110                         else
    111                                 *buf++ = d->ext[i];
    112                 }
    113         }
    114        
    115         *buf = '\0';
    116 }
    117 
    118 void fat_dentry_name_set(fat_dentry_t *d, const char *name)
    119 {
    120         unsigned int i;
    121         const char fake_ext[] = "   ";
    122         bool lower_name = true;
    123         bool lower_ext = true;
    124        
    125         for (i = 0; i < FAT_NAME_LEN; i++) {
    126                 switch ((uint8_t) *name) {
    127                 case 0xe5:
    128                         d->name[i] = FAT_DENTRY_E5_ESC;
    129                         name++;
    130                         break;
    131                 case '\0':
    132                 case '.':
    133                         d->name[i] = FAT_PAD;
    134                         break;
    135                 default:
    136                         if (isalpha(*name)) {
    137                                 if (!islower(*name))
    138                                         lower_name = false;
    139                         }
    140                        
    141                         d->name[i] = toupper(*name++);
    142                         break;
    143                 }
    144         }
    145        
    146         if (*name++ != '.')
    147                 name = fake_ext;
    148        
    149         for (i = 0; i < FAT_EXT_LEN; i++) {
    150                 switch ((uint8_t) *name) {
    151                 case 0xe5:
    152                         d->ext[i] = FAT_DENTRY_E5_ESC;
    153                         name++;
    154                         break;
    155                 case '\0':
    156                         d->ext[i] = FAT_PAD;
    157                         break;
    158                 default:
    159                         if (isalpha(*name)) {
    160                                 if (!islower(*name))
    161                                         lower_ext = false;
    162                         }
    163                        
    164                         d->ext[i] = toupper(*name++);
    165                         break;
    166                 }
    167         }
    168        
    169         if (lower_name)
    170                 d->lcase |= FAT_LCASE_LOWER_NAME;
    171         else
    172                 d->lcase &= ~FAT_LCASE_LOWER_NAME;
    173        
    174         if (lower_ext)
    175                 d->lcase |= FAT_LCASE_LOWER_EXT;
    176         else
    177                 d->lcase &= ~FAT_LCASE_LOWER_EXT;
    178 }
    179 
    180 fat_dentry_clsf_t fat_classify_dentry(const fat_dentry_t *d)
    181 {
    182         if (d->attr == FAT_ATTR_LFN) {
    183                 /* long name entry */
    184                 if (FAT_LFN_ORDER(d) & FAT_LFN_ERASED)
    185                         return FAT_DENTRY_FREE;
    186                 else
    187                         return FAT_DENTRY_LFN;
    188         }
    189         if (d->attr & FAT_ATTR_VOLLABEL) {
    190                 /* volume label entry */
    191                 return FAT_DENTRY_SKIP;
    192         }
    193         if (d->name[0] == FAT_DENTRY_ERASED) {
    194                 /* not-currently-used entry */
    195                 return FAT_DENTRY_FREE;
    196         }
    197         if (d->name[0] == FAT_DENTRY_UNUSED) {
    198                 /* never used entry */
    199                 return FAT_DENTRY_LAST;
    200         }
    201         if (d->name[0] == FAT_DENTRY_DOT) {
    202                 /*
    203                  * Most likely '.' or '..'.
    204                  * It cannot occur in a regular file name.
    205                  */
    206                 return FAT_DENTRY_SKIP;
    207         }
    208         return FAT_DENTRY_VALID;
    209 }
    210 
    211 /** Compute checksum of Node name.
    212  *
    213  * Returns an unsigned byte checksum computed on an unsigned byte
    214  * array. The array must be 11 bytes long and is assumed to contain
    215  * a name stored in the format of a MS-DOS directory entry.
    216  *
    217  * @param name          Node name read from the dentry.
    218  *
    219  * @return              An 8-bit unsigned checksum of the name.
    220  */
    221 uint8_t fat_dentry_chksum(uint8_t *name)
    222 {
    223         uint8_t i, sum = 0;
    224 
    225         for (i = 0; i < (FAT_NAME_LEN + FAT_EXT_LEN); i++)
    226                 sum = ((sum & 1) ? 0x80 : 0) + (sum >> 1) + name[i];
    227 
    228         return sum;
    229 }
    230 
    231 /** Get number of bytes in a string with size limit.
    232  *
    233  * @param str  NULL-terminated (or not) string.
    234  * @param size Maximum number of bytes to consider.
    235  *
    236  * @return Number of bytes in string (without 0 and ff).
    237  *
    238  */
    239 size_t fat_lfn_str_nlength(const uint16_t *str, size_t size)
    240 {
    241         size_t offset = 0;
    242 
    243         while (offset < size) {
    244                 if (str[offset] == 0 || str[offset] == FAT_LFN_PAD)
    245                         break;
    246                 offset++;
    247         }
    248         return offset;
    249 }
    250 
    251 /** Get number of bytes in a FAT long entry occuped by characters.
    252  *
    253  * @param d FAT long entry.
    254  *
    255  * @return Number of bytes.
    256  *
    257  */
    258 size_t fat_lfn_size(const fat_dentry_t *d)
    259 {
    260         size_t size = 0;
    261        
    262         size += fat_lfn_str_nlength(FAT_LFN_PART1(d), FAT_LFN_PART1_SIZE);
    263         size += fat_lfn_str_nlength(FAT_LFN_PART2(d), FAT_LFN_PART2_SIZE);
    264         size += fat_lfn_str_nlength(FAT_LFN_PART3(d), FAT_LFN_PART3_SIZE);     
    265        
    266         return size;
    267 }
    268 
    269 size_t fat_lfn_get_entry(const fat_dentry_t *d, uint16_t *dst, size_t *offset)
    270 {
    271         int i;
    272         for (i = FAT_LFN_PART3_SIZE - 1; i >= 0 && *offset > 0; i--) {
    273                 if (d->lfn.part3[i] == 0 || d->lfn.part3[i] == FAT_LFN_PAD)
    274                         continue;
    275                 (*offset)--;
    276                 dst[(*offset)] = uint16_t_le2host(d->lfn.part3[i]);
    277         }
    278         for (i = FAT_LFN_PART2_SIZE - 1; i >= 0 && *offset > 0; i--) {
    279                 if (d->lfn.part2[i] == 0 || d->lfn.part2[i] == FAT_LFN_PAD)
    280                         continue;
    281                 (*offset)--;
    282                 dst[(*offset)] = uint16_t_le2host(d->lfn.part2[i]);
    283         }
    284         for (i = FAT_LFN_PART1_SIZE - 1; i >= 0 && *offset > 0; i--) {
    285                 if (d->lfn.part1[i] == 0 || d->lfn.part1[i] == FAT_LFN_PAD)
    286                         continue;
    287                 (*offset)--;
    288                 dst[(*offset)] = uint16_t_le2host(d->lfn.part1[i]);
    289         }
    290         return *offset;
    291 }
    292 
    293 size_t fat_lfn_set_entry(const uint16_t *src, size_t *offset, size_t size,
    294     fat_dentry_t *d)
    295 {
    296         size_t idx;
    297         for (idx = 0; idx < FAT_LFN_PART1_SIZE; idx++) {
    298                 if (*offset < size) {
    299                         d->lfn.part1[idx] = host2uint16_t_le(src[*offset]);
    300                         (*offset)++;
    301                 } else
    302                         d->lfn.part1[idx] = FAT_LFN_PAD;
    303         }
    304         for (idx = 0; idx < FAT_LFN_PART2_SIZE; idx++) {
    305                 if (*offset < size) {
    306                         d->lfn.part2[idx] = host2uint16_t_le(src[*offset]);
    307                         (*offset)++;
    308                 } else
    309                         d->lfn.part2[idx] = FAT_LFN_PAD;
    310         }
    311         for (idx = 0; idx < FAT_LFN_PART3_SIZE; idx++) {
    312                 if (*offset < size) {
    313                         d->lfn.part3[idx] = host2uint16_t_le(src[*offset]);
    314                         (*offset)++;
    315                 } else
    316                         d->lfn.part3[idx] = FAT_LFN_PAD;
    317         }
    318 
    319         if (src[*offset] == 0)
    320                 offset++;
    321         FAT_LFN_ATTR(d) = FAT_ATTR_LFN;
    322         d->lfn.type = 0;
    323         d->lfn.firstc_lo = 0;
    324        
    325         return *offset;
    326 }
    327 
    328 void str_to_ascii(char *dst, const char *src, size_t count, uint8_t pad)
    329 {
    330         wchar_t ch;
    331         size_t off = 0;
    332         size_t i = 0;
    333        
    334         while (i < count) {
    335                 if ((ch = str_decode(src, &off, STR_NO_LIMIT)) != 0) {
    336                         if (ascii_check(ch) & IS_D_CHAR(ch))
    337                                 *dst = toupper(ch);
    338                         else
    339                                 *dst = pad;
    340                 } else
    341                         break;
    342 
    343                 dst++;
    344                 i++;
    345         }
    346         *dst = '\0';
    347 }
    348 
    349 bool fat_valid_name(const char *name)
    350 {
    351         wchar_t ch;
    352         size_t offset=0;
    353         bool result = true;
    354        
    355         while ((ch = str_decode(name, &offset, STR_NO_LIMIT)) != 0) {
    356                 if (str_chr(FAT_STOP_CHARS, ch) != NULL) {
    357                         result = false;
    358                         break;
    359                 }
    360         }
    361         return result;
    362 }
    363 
    364 bool fat_valid_short_name(const char *name)
     82bool fat_dentry_name_verify(const char *name)
    36583{
    36684        unsigned int i;
    36785        unsigned int dot = 0;
    36886        bool dot_found = false;
     87       
    36988
    37089        for (i = 0; name[i]; i++) {
     
    37796                        }
    37897                } else {
    379                         if (!IS_D_CHAR(name[i]))
     98                        if (!is_d_char(name[i]))
    38099                                return false;
    381100                }
     
    395114}
    396115
    397 size_t utf16_length(const uint16_t *wstr)
    398 {
    399         size_t len = 0;
    400        
    401         while (*wstr++ != 0)
    402                 len++;
    403        
    404         return len;
     116void fat_dentry_name_get(const fat_dentry_t *d, char *buf)
     117{
     118        unsigned int i;
     119       
     120        for (i = 0; i < FAT_NAME_LEN; i++) {
     121                if (d->name[i] == FAT_PAD)
     122                        break;
     123               
     124                if (d->name[i] == FAT_DENTRY_E5_ESC)
     125                        *buf++ = 0xe5;
     126                else {
     127                        if (d->lcase & FAT_LCASE_LOWER_NAME)
     128                                *buf++ = tolower(d->name[i]);
     129                        else
     130                                *buf++ = d->name[i];
     131                }
     132        }
     133       
     134        if (d->ext[0] != FAT_PAD)
     135                *buf++ = '.';
     136       
     137        for (i = 0; i < FAT_EXT_LEN; i++) {
     138                if (d->ext[i] == FAT_PAD) {
     139                        *buf = '\0';
     140                        return;
     141                }
     142               
     143                if (d->ext[i] == FAT_DENTRY_E5_ESC)
     144                        *buf++ = 0xe5;
     145                else {
     146                        if (d->lcase & FAT_LCASE_LOWER_EXT)
     147                                *buf++ = tolower(d->ext[i]);
     148                        else
     149                                *buf++ = d->ext[i];
     150                }
     151        }
     152       
     153        *buf = '\0';
     154}
     155
     156void fat_dentry_name_set(fat_dentry_t *d, const char *name)
     157{
     158        unsigned int i;
     159        const char fake_ext[] = "   ";
     160        bool lower_name = true;
     161        bool lower_ext = true;
     162       
     163        for (i = 0; i < FAT_NAME_LEN; i++) {
     164                switch ((uint8_t) *name) {
     165                case 0xe5:
     166                        d->name[i] = FAT_DENTRY_E5_ESC;
     167                        name++;
     168                        break;
     169                case '\0':
     170                case '.':
     171                        d->name[i] = FAT_PAD;
     172                        break;
     173                default:
     174                        if (isalpha(*name)) {
     175                                if (!islower(*name))
     176                                        lower_name = false;
     177                        }
     178                       
     179                        d->name[i] = toupper(*name++);
     180                        break;
     181                }
     182        }
     183       
     184        if (*name++ != '.')
     185                name = fake_ext;
     186       
     187        for (i = 0; i < FAT_EXT_LEN; i++) {
     188                switch ((uint8_t) *name) {
     189                case 0xe5:
     190                        d->ext[i] = FAT_DENTRY_E5_ESC;
     191                        name++;
     192                        break;
     193                case '\0':
     194                        d->ext[i] = FAT_PAD;
     195                        break;
     196                default:
     197                        if (isalpha(*name)) {
     198                                if (!islower(*name))
     199                                        lower_ext = false;
     200                        }
     201                       
     202                        d->ext[i] = toupper(*name++);
     203                        break;
     204                }
     205        }
     206       
     207        if (lower_name)
     208                d->lcase |= FAT_LCASE_LOWER_NAME;
     209        else
     210                d->lcase &= ~FAT_LCASE_LOWER_NAME;
     211       
     212        if (lower_ext)
     213                d->lcase |= FAT_LCASE_LOWER_EXT;
     214        else
     215                d->lcase &= ~FAT_LCASE_LOWER_EXT;
     216}
     217
     218fat_dentry_clsf_t fat_classify_dentry(const fat_dentry_t *d)
     219{
     220        if (d->attr & FAT_ATTR_VOLLABEL) {
     221                /* volume label entry */
     222                return FAT_DENTRY_SKIP;
     223        }
     224        if (d->name[0] == FAT_DENTRY_ERASED) {
     225                /* not-currently-used entry */
     226                return FAT_DENTRY_FREE;
     227        }
     228        if (d->name[0] == FAT_DENTRY_UNUSED) {
     229                /* never used entry */
     230                return FAT_DENTRY_LAST;
     231        }
     232        if (d->name[0] == FAT_DENTRY_DOT) {
     233                /*
     234                 * Most likely '.' or '..'.
     235                 * It cannot occur in a regular file name.
     236                 */
     237                return FAT_DENTRY_SKIP;
     238        }
     239        return FAT_DENTRY_VALID;
    405240}
    406241
Note: See TracChangeset for help on using the changeset viewer.