Ignore:
File:
1 edited

Legend:

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

    r2c22f1f7 r5d95f02  
    11/*
    22 * Copyright (c) 2008 Jakub Jermar
     3 * Copyright (c) 2011 Oleg Romanenko
    34 * All rights reserved.
    45 *
     
    3940#include <ctype.h>
    4041#include <str.h>
    41 
    42 static bool is_d_char(const char ch)
    43 {
    44         if (isalnum(ch) || ch == '_' || ch == '-')
    45                 return true;
    46         else
    47                 return false;
    48 }
     42#include <errno.h>
     43#include <byteorder.h>
     44#include <assert.h>
    4945
    5046/** Compare path component with the name read from the dentry.
     
    8076}
    8177
    82 bool fat_dentry_name_verify(const char *name)
     78void 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
     118void 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
     180fat_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 */
     221uint8_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 */
     239size_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 */
     258size_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
     269size_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
     293size_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
     328void 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
     349bool 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
     364bool fat_valid_short_name(const char *name)
    83365{
    84366        unsigned int i;
    85367        unsigned int dot = 0;
    86368        bool dot_found = false;
    87        
    88369
    89370        for (i = 0; name[i]; i++) {
     
    96377                        }
    97378                } else {
    98                         if (!is_d_char(name[i]))
     379                        if (!IS_D_CHAR(name[i]))
    99380                                return false;
    100381                }
     
    114395}
    115396
    116 void 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 
    156 void 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 
    218 fat_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;
     397size_t utf16_length(const uint16_t *wstr)
     398{
     399        size_t len = 0;
     400       
     401        while (*wstr++ != 0)
     402                len++;
     403       
     404        return len;
    240405}
    241406
Note: See TracChangeset for help on using the changeset viewer.