Ignore:
File:
1 edited

Legend:

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

    r842a2d2 r2c22f1f7  
    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 == '_' || 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         for (i=0; i<(FAT_NAME_LEN+FAT_EXT_LEN); i++) {
    225                 sum = ((sum & 1) ? 0x80 : 0) + (sum >> 1) + name[i];
    226         }
    227         return sum;
    228 }
    229 
    230 /** Get number of bytes in a string with size limit.
    231  *
    232  * @param str  NULL-terminated (or not) string.
    233  * @param size Maximum number of bytes to consider.
    234  *
    235  * @return Number of bytes in string (without 0 and ff).
    236  *
    237  */
    238 size_t fat_lfn_str_nlength(const uint16_t *str, size_t size)
    239 {
    240         size_t offset = 0;
    241 
    242         while (offset < size) {
    243                 if (str[offset] == 0 || str[offset] == FAT_LFN_PAD)
    244                         break;
    245                 offset++;
    246         }
    247         return offset;
    248 }
    249 
    250 /** Get number of bytes in a FAT long entry occuped by characters.
    251  *
    252  * @param d FAT long entry.
    253  *
    254  * @return Number of bytes.
    255  *
    256  */
    257 size_t fat_lfn_size(const fat_dentry_t *d)
    258 {
    259         size_t size = 0;
    260        
    261         size += fat_lfn_str_nlength(FAT_LFN_PART1(d), FAT_LFN_PART1_SIZE);
    262         size += fat_lfn_str_nlength(FAT_LFN_PART2(d), FAT_LFN_PART2_SIZE);
    263         size += fat_lfn_str_nlength(FAT_LFN_PART3(d), FAT_LFN_PART3_SIZE);     
    264        
    265         return size;
    266 }
    267 
    268 size_t fat_lfn_get_entry(const fat_dentry_t *d, uint16_t *dst, size_t *offset)
    269 {
    270         int i;
    271         for (i=FAT_LFN_PART3_SIZE-1; i>=0 && *offset>0; i--) {
    272                 if (d->lfn.part3[i] == 0 || d->lfn.part3[i] == FAT_LFN_PAD)
    273                         continue;
    274                 (*offset)--;
    275                 dst[(*offset)] = uint16_t_le2host(d->lfn.part3[i]);
    276         }
    277         for (i=FAT_LFN_PART2_SIZE-1; i>=0 && *offset>0; i--) {
    278                 if (d->lfn.part2[i] == 0 || d->lfn.part2[i] == FAT_LFN_PAD)
    279                         continue;
    280                 (*offset)--;
    281                 dst[(*offset)] = uint16_t_le2host(d->lfn.part2[i]);
    282         }
    283         for (i=FAT_LFN_PART1_SIZE-1; i>=0 && *offset>0; i--) {
    284                 if (d->lfn.part1[i] == 0 || d->lfn.part1[i] == FAT_LFN_PAD)
    285                         continue;
    286                 (*offset)--;
    287                 dst[(*offset)] = uint16_t_le2host(d->lfn.part1[i]);
    288         }
    289         return *offset;
    290 }
    291 
    292 size_t fat_lfn_set_entry(const uint16_t *src, size_t *offset, size_t size, fat_dentry_t *d)
    293 {
    294         size_t idx;
    295         for (idx=0; idx < FAT_LFN_PART1_SIZE; idx++) {
    296                 if (*offset < size) {
    297                         d->lfn.part1[idx] = host2uint16_t_le(src[*offset]);
    298                         (*offset)++;
    299                 }
    300                 else
    301                         d->lfn.part1[idx] = FAT_LFN_PAD;
    302         }
    303         for (idx=0; idx < FAT_LFN_PART2_SIZE; idx++) {
    304                 if (*offset < size) {
    305                         d->lfn.part2[idx] = host2uint16_t_le(src[*offset]);
    306                         (*offset)++;
    307                 }
    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                 }
    316                 else
    317                         d->lfn.part3[idx] = FAT_LFN_PAD;
    318         }
    319 
    320         if (src[*offset] == 0)
    321                 offset++;
    322         FAT_LFN_ATTR(d) = FAT_ATTR_LFN;
    323         d->lfn.type = 0;
    324         d->lfn.firstc_lo = 0;
    325        
    326         return *offset;
    327 }
    328 
    329 void str_to_ascii(char *dst, const char *src, size_t count, uint8_t pad)
    330 {
    331         wchar_t ch;
    332         size_t off = 0;
    333         size_t i = 0;
    334        
    335         while (i < count) {
    336                 if ((ch = str_decode(src, &off, STR_NO_LIMIT)) != 0) {
    337                         if (ascii_check(ch) & IS_D_CHAR(ch))
    338                                 *dst = toupper(ch);
    339                         else
    340                                 *dst = pad;
    341                 }
    342                 else
    343                         break;
    344 
    345                 dst++;
    346                 i++;
    347         }
    348         *dst = '\0';
    349 }
    350 
    351 bool fat_valid_name(const char *name)
    352 {
    353         wchar_t ch;
    354         size_t offset=0;
    355         bool result = true;
    356        
    357         while ((ch = str_decode(name, &offset, STR_NO_LIMIT)) != 0) {
    358                 if (wstr_chr(FAT_STOP_CHARS, ch) != NULL) {
    359                         result = false;
    360                         break;
    361                 }
    362         }
    363         return result;
    364 }
    365 
    366 bool fat_valid_short_name(const char *name)
     82bool fat_dentry_name_verify(const char *name)
    36783{
    36884        unsigned int i;
    36985        unsigned int dot = 0;
    37086        bool dot_found = false;
     87       
    37188
    37289        for (i = 0; name[i]; i++) {
     
    37996                        }
    38097                } else {
    381                         if (!IS_D_CHAR(name[i]))
     98                        if (!is_d_char(name[i]))
    38299                                return false;
    383100                }
     
    397114}
    398115
    399 size_t utf16_length(const uint16_t *wstr)
    400 {
    401         size_t len = 0;
    402        
    403         while (*wstr++ != 0)
    404                 len++;
    405        
    406         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;
    407240}
    408241
Note: See TracChangeset for help on using the changeset viewer.