Changeset 375ab5e in mainline for uspace/srv/fs/fat/fat_dentry.c


Ignore:
Timestamp:
2011-08-24T20:10:43Z (13 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
eb660787
Parents:
7fadb65 (diff), 842a2d2 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge from lp:~romanenko-oleg/helenos/fat.

File:
1 edited

Legend:

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

    r7fadb65 r375ab5e  
    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 == '_')
    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        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 */
     238size_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 */
     257size_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
     268size_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
     292size_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
     329void 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
     351bool 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
     366bool fat_valid_short_name(const char *name)
    83367{
    84368        unsigned int i;
    85369        unsigned int dot = 0;
    86370        bool dot_found = false;
    87        
    88371
    89372        for (i = 0; name[i]; i++) {
     
    96379                        }
    97380                } else {
    98                         if (!is_d_char(name[i]))
     381                        if (!IS_D_CHAR(name[i]))
    99382                                return false;
    100383                }
     
    114397}
    115398
    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;
     399size_t utf16_length(const uint16_t *wstr)
     400{
     401        size_t len = 0;
     402       
     403        while (*wstr++ != 0)
     404                len++;
     405       
     406        return len;
    240407}
    241408
Note: See TracChangeset for help on using the changeset viewer.