Ignore:
File:
1 edited

Legend:

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

    r411e9ca 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_part(const uint16_t *src, size_t src_size, uint16_t *dst, size_t *offset)
    269 {
    270         while (src_size!=0 && (*offset)!=0) {
    271                 src_size--;
    272                 if (src[src_size] == 0 || src[src_size] == FAT_LFN_PAD)
    273                         continue;
    274 
    275                 (*offset)--;
    276                 dst[(*offset)] = uint16_t_le2host(src[src_size]);
    277         }
    278         return (*offset);
    279 }
    280 
    281 size_t fat_lfn_get_entry(const fat_dentry_t *d, uint16_t *dst, size_t *offset)
    282 {
    283         fat_lfn_get_part(FAT_LFN_PART3(d), FAT_LFN_PART3_SIZE, dst, offset);
    284         fat_lfn_get_part(FAT_LFN_PART2(d), FAT_LFN_PART2_SIZE, dst, offset);
    285         fat_lfn_get_part(FAT_LFN_PART1(d), FAT_LFN_PART1_SIZE, dst, offset);
    286 
    287         return *offset;
    288 }
    289 
    290 size_t fat_lfn_set_part(const uint16_t *src, size_t *offset, size_t src_size, uint16_t *dst, size_t dst_size)
    291 {
    292         size_t idx;
    293         for (idx=0; idx < dst_size; idx++) {
    294                 if (*offset < src_size) {
    295                         dst[idx] = uint16_t_le2host(src[*offset]);
    296                         (*offset)++;
    297                 }
    298                 else
    299                         dst[idx] = FAT_LFN_PAD;
    300         }
    301         return *offset;
    302 }
    303 
    304 size_t fat_lfn_set_entry(const uint16_t *src, size_t *offset, size_t size, fat_dentry_t *d)
    305 {
    306         fat_lfn_set_part(src, offset, size, FAT_LFN_PART1(d), FAT_LFN_PART1_SIZE);
    307         fat_lfn_set_part(src, offset, size, FAT_LFN_PART2(d), FAT_LFN_PART2_SIZE);
    308         fat_lfn_set_part(src, offset, size, FAT_LFN_PART3(d), FAT_LFN_PART3_SIZE);
    309         if (src[*offset] == 0)
    310                 offset++;
    311         FAT_LFN_ATTR(d) = FAT_ATTR_LFN;
    312         d->lfn.type = 0;
    313         d->lfn.firstc_lo = 0;
    314        
    315         return *offset;
    316 }
    317 
    318 void str_to_ascii(char *dst, const char *src, size_t count, uint8_t pad)
    319 {
    320         wchar_t ch;
    321         size_t off = 0;
    322         size_t i = 0;
    323        
    324         while (i < count) {
    325                 if ((ch = str_decode(src, &off, STR_NO_LIMIT)) != 0) {
    326                         if (ascii_check(ch) & IS_D_CHAR(ch))
    327                                 *dst = toupper(ch);
    328                         else
    329                                 *dst = pad;
    330                 }
    331                 else
    332                         break;
    333 
    334                 dst++;
    335                 i++;
    336         }
    337         *dst = '\0';
    338 }
    339 
    340 bool fat_valid_name(const char *name)
    341 {
    342         wchar_t ch;
    343         size_t offset=0;
    344         bool result = true;
    345        
    346         while ((ch = str_decode(name, &offset, STR_NO_LIMIT)) != 0) {
    347                 if (wstr_chr(FAT_STOP_CHARS, ch) != NULL) {
    348                         result = false;
    349                         break;
    350                 }
    351         }
    352         return result;
    353 }
    354 
    355 bool fat_valid_short_name(const char *name)
     82bool fat_dentry_name_verify(const char *name)
    35683{
    35784        unsigned int i;
    35885        unsigned int dot = 0;
    35986        bool dot_found = false;
     87       
    36088
    36189        for (i = 0; name[i]; i++) {
     
    36896                        }
    36997                } else {
    370                         if (!IS_D_CHAR(name[i]))
     98                        if (!is_d_char(name[i]))
    37199                                return false;
    372100                }
     
    386114}
    387115
    388 size_t utf16_length(const uint16_t *wstr)
    389 {
    390         size_t len = 0;
    391        
    392         while (*wstr++ != 0)
    393                 len++;
    394        
    395         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;
    396240}
    397241
Note: See TracChangeset for help on using the changeset viewer.