Changes in / [3fab770:a33f0a6] in mainline


Ignore:
Files:
26 added
12 edited

Legend:

Unmodified
Added
Removed
  • boot/Makefile.common

    r3fab770 ra33f0a6  
    102102        $(USPACE_PATH)/srv/fs/tmpfs/tmpfs \
    103103        $(USPACE_PATH)/srv/fs/fat/fat \
     104        $(USPACE_PATH)/srv/fs/exfat/exfat \
    104105        $(USPACE_PATH)/srv/fs/ext2fs/ext2fs \
    105106        $(USPACE_PATH)/srv/taskmon/taskmon \
     
    147148        $(USPACE_PATH)/app/dload/dload \
    148149        $(USPACE_PATH)/app/edit/edit \
     150        $(USPACE_PATH)/app/filecrc/filecrc \
     151        $(USPACE_PATH)/app/filegen/filegen \
    149152        $(USPACE_PATH)/app/ext2info/ext2info \
    150153        $(USPACE_PATH)/app/kill/kill \
  • uspace/Makefile

    r3fab770 ra33f0a6  
    3838        app/bnchmark \
    3939        app/edit \
     40        app/filecrc \
     41        app/filegen \
    4042        app/ext2info \
    4143        app/getterm \
     
    7779        srv/bd/part/guid_part \
    7880        srv/bd/part/mbr_part \
     81        srv/fs/exfat \
    7982        srv/fs/fat \
    8083        srv/fs/tmpfs \
  • uspace/lib/c/generic/str.c

    r3fab770 ra33f0a6  
    22 * Copyright (c) 2005 Martin Decky
    33 * Copyright (c) 2008 Jiri Svoboda
     4 * Copyright (c) 2011 Oleg Romanenko
    45 * All rights reserved.
    56 *
     
    366367}
    367368
     369/** Check whether wide string is plain ASCII.
     370 *
     371 * @return True if wide string is plain ASCII.
     372 *
     373 */
     374bool wstr_is_ascii(const wchar_t *wstr)
     375{
     376        while (*wstr && ascii_check(*wstr))
     377                wstr++;
     378        return *wstr == 0;
     379}
     380
    368381/** Check whether character is valid
    369382 *
     
    618631 * @param size  Size of the destination buffer.
    619632 * @param src   Source wide string.
    620  */
    621 void wstr_to_str(char *dest, size_t size, const wchar_t *src)
    622 {
     633 *
     634 * @return EOK, if success, negative otherwise.
     635 */
     636int wstr_to_str(char *dest, size_t size, const wchar_t *src)
     637{
     638        int rc;
    623639        wchar_t ch;
    624640        size_t src_idx;
     
    632648
    633649        while ((ch = src[src_idx++]) != 0) {
    634                 if (chr_encode(ch, dest, &dest_off, size - 1) != EOK)
     650                rc = chr_encode(ch, dest, &dest_off, size - 1);
     651                if (rc != EOK)
    635652                        break;
    636653        }
    637654
    638655        dest[dest_off] = '\0';
    639 }
     656        return rc;
     657}
     658
     659/** Convert UTF16 string to string.
     660 *
     661 * Convert utf16 string @a src to string. The output is written to the buffer
     662 * specified by @a dest and @a size. @a size must be non-zero and the string
     663 * written will always be well-formed. Surrogate pairs also supported.
     664 *
     665 * @param dest  Destination buffer.
     666 * @param size  Size of the destination buffer.
     667 * @param src   Source utf16 string.
     668 *
     669 * @return EOK, if success, negative otherwise.
     670 */
     671int utf16_to_str(char *dest, size_t size, const uint16_t *src)
     672{
     673        size_t idx=0, dest_off=0;
     674        wchar_t ch;
     675        int rc = EOK;
     676
     677        /* There must be space for a null terminator in the buffer. */
     678        assert(size > 0);
     679
     680        while (src[idx]) {
     681                if ((src[idx] & 0xfc00) == 0xd800) {
     682                        if (src[idx+1] && (src[idx+1] & 0xfc00) == 0xdc00) {
     683                                ch = 0x10000;
     684                                ch += (src[idx] & 0x03FF) << 10;
     685                                ch += (src[idx+1] & 0x03FF);
     686                                idx += 2;
     687                        }
     688                        else
     689                                break;
     690                } else {
     691                        ch = src[idx];
     692                        idx++;
     693                }
     694                rc = chr_encode(ch, dest, &dest_off, size-1);
     695                if (rc != EOK)
     696                        break;
     697        }
     698        dest[dest_off] = '\0';
     699        return rc;
     700}
     701
     702int str_to_utf16(uint16_t *dest, size_t size, const char *src)
     703{
     704        int rc=EOK;
     705        size_t offset=0;
     706        size_t idx=0;
     707        wchar_t c;
     708
     709        assert(size > 0);
     710       
     711        while ((c = str_decode(src, &offset, STR_NO_LIMIT)) != 0) {
     712                if (c > 0x10000) {
     713                        if (idx+2 >= size-1) {
     714                                rc=EOVERFLOW;
     715                                break;
     716                        }
     717                        c = (c - 0x10000);
     718                        dest[idx] = 0xD800 | (c >> 10);
     719                        dest[idx+1] = 0xDC00 | (c & 0x3FF);
     720                        idx++;
     721                } else {
     722                         dest[idx] = c;
     723                }
     724
     725                idx++;
     726                if (idx >= size-1) {
     727                        rc=EOVERFLOW;
     728                        break;
     729                }
     730        }
     731
     732        dest[idx] = '\0';
     733        return rc;
     734}
     735
    640736
    641737/** Convert wide string to new string.
     
    697793 * @param dlen  Length of destination buffer (number of wchars).
    698794 * @param src   Source string.
    699  */
    700 void str_to_wstr(wchar_t *dest, size_t dlen, const char *src)
    701 {
     795 *
     796 * @return EOK, if success, negative otherwise.
     797 */
     798int str_to_wstr(wchar_t *dest, size_t dlen, const char *src)
     799{
     800        int rc=EOK;
    702801        size_t offset;
    703802        size_t di;
     
    710809
    711810        do {
    712                 if (di >= dlen - 1)
     811                if (di >= dlen - 1) {
     812                        rc = EOVERFLOW;
    713813                        break;
     814                }
    714815
    715816                c = str_decode(src, &offset, STR_NO_LIMIT);
     
    718819
    719820        dest[dlen - 1] = '\0';
     821        return rc;
    720822}
    721823
     
    763865       
    764866        return (char *) res;
     867}
     868
     869/** Find first occurence of character in wide string.
     870 *
     871 * @param wstr String to search.
     872 * @param ch  Character to look for.
     873 *
     874 * @return Pointer to character in @a wstr or NULL if not found.
     875 */
     876wchar_t *wstr_chr(const wchar_t *wstr, wchar_t ch)
     877{
     878        while (*wstr && *wstr != ch)
     879                wstr++;
     880        if (*wstr)
     881                return (wchar_t *) wstr;
     882        else
     883                return NULL;
     884}
     885
     886/** Find last occurence of character in wide string.
     887 *
     888 * @param wstr String to search.
     889 * @param ch  Character to look for.
     890 *
     891 * @return Pointer to character in @a wstr or NULL if not found.
     892 */
     893wchar_t *wstr_rchr(const wchar_t *wstr, wchar_t ch)
     894{
     895        const wchar_t *res = NULL;
     896        while (*wstr) {
     897                if (*wstr == ch)
     898                        res = wstr;
     899                wstr++;
     900        }
     901        return (wchar_t *) res;
    765902}
    766903
     
    10171154}
    10181155
     1156void str_reverse(char* begin, char* end)
     1157{
     1158    char aux;
     1159    while(end>begin)
     1160        aux=*end, *end--=*begin, *begin++=aux;
     1161}
     1162
     1163int size_t_str(size_t value, int base, char* str, size_t size)
     1164{
     1165    static char num[] = "0123456789abcdefghijklmnopqrstuvwxyz";
     1166    char* wstr=str;
     1167       
     1168        if (size == 0)
     1169                return EINVAL;
     1170    if (base<2 || base>35) {
     1171        *str='\0';
     1172        return EINVAL;
     1173    }
     1174
     1175    do {
     1176        *wstr++ = num[value % base];
     1177                if (--size == 0)
     1178                        return EOVERFLOW;
     1179    } while(value /= base);
     1180    *wstr='\0';
     1181
     1182    // Reverse string
     1183    str_reverse(str,wstr-1);
     1184        return EOK;
     1185}
    10191186
    10201187/** Convert initial part of string to unsigned long according to given base.
  • uspace/lib/c/include/str.h

    r3fab770 ra33f0a6  
    11/*
    22 * Copyright (c) 2005 Martin Decky
     3 * Copyright (c) 2011 Oleg Romanenko
    34 * All rights reserved.
    45 *
     
    7172extern bool ascii_check(wchar_t ch);
    7273extern bool chr_check(wchar_t ch);
     74extern bool wstr_is_ascii(const wchar_t *wstr);
    7375
    7476extern int str_cmp(const char *s1, const char *s2);
     
    7981extern void str_append(char *dest, size_t size, const char *src);
    8082
     83extern int wstr_to_str(char *dest, size_t size, const wchar_t *src);
    8184extern int spascii_to_str(char *dest, size_t size, const uint8_t *src, size_t n);
    8285extern void wstr_to_str(char *dest, size_t size, const wchar_t *src);
    8386extern char *wstr_to_astr(const wchar_t *src);
    84 extern void str_to_wstr(wchar_t *dest, size_t dlen, const char *src);
     87extern int str_to_wstr(wchar_t *dest, size_t dlen, const char *src);
     88extern int utf16_to_str(char *dest, size_t size, const uint16_t *src);
     89extern int str_to_utf16(uint16_t *dest, size_t size, const char *src);
    8590
    8691extern char *str_chr(const char *str, wchar_t ch);
    8792extern char *str_rchr(const char *str, wchar_t ch);
     93extern wchar_t *wstr_chr(const wchar_t *wstr, wchar_t ch);
     94extern wchar_t *wstr_rchr(const wchar_t *wstr, wchar_t ch);
    8895
    8996extern bool wstr_linsert(wchar_t *str, wchar_t ch, size_t pos, size_t max_pos);
     
    9299extern char *str_dup(const char *);
    93100extern char *str_ndup(const char *, size_t max_size);
     101
     102extern void str_reverse(char* begin, char* end);
     103extern int size_t_str(size_t value, int base, char* str, size_t size);
    94104
    95105extern int str_uint64(const char *, char **, unsigned int, bool, uint64_t *);
  • uspace/srv/fs/fat/Makefile

    r3fab770 ra33f0a6  
    3939        fat_idx.c \
    4040        fat_dentry.c \
     41        fat_directory.c \
    4142        fat_fat.c
    4243
  • uspace/srv/fs/fat/fat.c

    r3fab770 ra33f0a6  
    22 * Copyright (c) 2006 Martin Decky
    33 * Copyright (c) 2008 Jakub Jermar
     4 * Copyright (c) 2011 Oleg Romanenko
    45 * All rights reserved.
    56 *
  • uspace/srv/fs/fat/fat.h

    r3fab770 ra33f0a6  
    11/*
    22 * Copyright (c) 2008 Jakub Jermar
     3 * Copyright (c) 2011 Oleg Romanenko
    34 * All rights reserved.
    45 *
     
    5556#define RSCNT(bs)       uint16_t_le2host((bs)->rscnt)
    5657#define FATCNT(bs)      (bs)->fatcnt
    57 #define SF(bs)          uint16_t_le2host((bs)->sec_per_fat)
     58#define SF(bs)          (uint16_t_le2host((bs)->sec_per_fat) !=0 ? \
     59    uint16_t_le2host((bs)->sec_per_fat) : \
     60    uint32_t_le2host(bs->fat32.sectors_per_fat))
    5861#define RDE(bs)         uint16_t_le2host((bs)->root_ent_max)
    5962#define TS(bs)          (uint16_t_le2host((bs)->totsec16) != 0 ? \
  • uspace/srv/fs/fat/fat_dentry.c

    r3fab770 ra33f0a6  
    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_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
     281size_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
     290size_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
     304size_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
     318void 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
     340bool 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
     355bool fat_valid_short_name(const char *name)
    83356{
    84357        unsigned int i;
    85358        unsigned int dot = 0;
    86359        bool dot_found = false;
    87        
    88360
    89361        for (i = 0; name[i]; i++) {
     
    96368                        }
    97369                } else {
    98                         if (!is_d_char(name[i]))
     370                        if (!IS_D_CHAR(name[i]))
    99371                                return false;
    100372                }
     
    114386}
    115387
    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;
     388size_t utf16_length(const uint16_t *wstr)
     389{
     390        size_t len = 0;
     391       
     392        while (*wstr++ != 0)
     393                len++;
     394       
     395        return len;
    240396}
    241397
  • uspace/srv/fs/fat/fat_dentry.h

    r3fab770 ra33f0a6  
    11/*
    22 * Copyright (c) 2008 Jakub Jermar
     3 * Copyright (c) 2011 Oleg Romanenko
    34 * All rights reserved.
    45 *
     
    3738#include <bool.h>
    3839
     40#define IS_D_CHAR(ch) (isalnum(ch) || ch == '_')
     41#define FAT_STOP_CHARS L"*?/\\\n\t|'"
     42
    3943#define FAT_NAME_LEN            8
    4044#define FAT_EXT_LEN             3
     
    4448#define FAT_EXT_PAD             "   "
    4549
    46 #define FAT_ATTR_RDONLY         (1 << 0)
    47 #define FAT_ATTR_VOLLABEL       (1 << 3)
    48 #define FAT_ATTR_SUBDIR         (1 << 4)
    49 
     50#define FAT_ATTR_RDONLY   0x01
     51#define FAT_ATTR_HIDDEN   0x02
     52#define FAT_ATTR_SYSTEM   0x04
     53#define FAT_ATTR_VOLLABEL 0x08
     54#define FAT_ATTR_SUBDIR   0x10
     55#define FAT_ATTR_ARCHIVE  0x20
     56#define FAT_ATTR_LFN \
     57    (FAT_ATTR_RDONLY | FAT_ATTR_HIDDEN | FAT_ATTR_SYSTEM | FAT_ATTR_VOLLABEL)
     58   
    5059#define FAT_LCASE_LOWER_NAME    0x08
    5160#define FAT_LCASE_LOWER_EXT     0x10
    5261
    53 #define FAT_PAD                 ' '
     62#define FAT_PAD                 ' '
     63#define FAT_LFN_PAD     0xffff
     64#define FAT_SFN_CHAR '_'
    5465
    5566#define FAT_DENTRY_UNUSED       0x00
     
    5768#define FAT_DENTRY_DOT          0x2e
    5869#define FAT_DENTRY_ERASED       0xe5
     70#define FAT_LFN_LAST            0x40
     71#define FAT_LFN_ERASED          0x80
     72
     73#define FAT_LFN_ORDER(d) (d->lfn.order)
     74#define FAT_IS_LFN(d) \
     75    ((FAT_LFN_ORDER(d) & FAT_LFN_LAST) == FAT_LFN_LAST)
     76#define FAT_LFN_COUNT(d) \
     77    (FAT_LFN_ORDER(d) ^ FAT_LFN_LAST)
     78#define FAT_LFN_PART1(d) (d->lfn.part1)
     79#define FAT_LFN_PART2(d) (d->lfn.part2)
     80#define FAT_LFN_PART3(d) (d->lfn.part3)
     81#define FAT_LFN_ATTR(d) (d->lfn.attr)
     82#define FAT_LFN_CHKSUM(d) (d->lfn.check_sum)
     83
     84#define FAT_LFN_NAME_SIZE   260
     85#define FAT_LFN_MAX_COUNT   20
     86#define FAT_LFN_PART1_SIZE  5
     87#define FAT_LFN_PART2_SIZE  6
     88#define FAT_LFN_PART3_SIZE  2
     89#define FAT_LFN_ENTRY_SIZE \
     90    (FAT_LFN_PART1_SIZE + FAT_LFN_PART2_SIZE + FAT_LFN_PART3_SIZE)
    5991
    6092typedef enum {
     
    6294        FAT_DENTRY_LAST,
    6395        FAT_DENTRY_FREE,
    64         FAT_DENTRY_VALID
     96        FAT_DENTRY_VALID,
     97        FAT_DENTRY_LFN
    6598} fat_dentry_clsf_t;
    6699
    67100typedef struct {
    68         uint8_t         name[8];
    69         uint8_t         ext[3];
    70         uint8_t         attr;
    71         uint8_t         lcase;
    72         uint8_t         ctime_fine;
    73         uint16_t        ctime;
    74         uint16_t        cdate;
    75         uint16_t        adate;
    76101        union {
    77                 uint16_t        eaidx;          /* FAT12/FAT16 */
    78                 uint16_t        firstc_hi;      /* FAT32 */
    79         } __attribute__ ((packed));
    80         uint16_t        mtime;
    81         uint16_t        mdate;
    82         union {
    83                 uint16_t        firstc;         /* FAT12/FAT16 */
    84                 uint16_t        firstc_lo;      /* FAT32 */
    85         } __attribute__ ((packed));
    86         uint32_t        size;
     102                struct {
     103                        uint8_t         name[8];
     104                        uint8_t         ext[3];
     105                        uint8_t         attr;
     106                        uint8_t         lcase;
     107                        uint8_t         ctime_fine;
     108                        uint16_t        ctime;
     109                        uint16_t        cdate;
     110                        uint16_t        adate;
     111                        union {
     112                                uint16_t        eaidx;          /* FAT12/FAT16 */
     113                                uint16_t        firstc_hi;      /* FAT32 */
     114                        } __attribute__ ((packed));
     115                        uint16_t        mtime;
     116                        uint16_t        mdate;
     117                        union {
     118                                uint16_t        firstc;         /* FAT12/FAT16 */
     119                                uint16_t        firstc_lo;      /* FAT32 */
     120                        } __attribute__ ((packed));
     121                        uint32_t        size;
     122                } __attribute__ ((packed));
     123                struct {
     124                        uint8_t         order;
     125                        uint16_t        part1[FAT_LFN_PART1_SIZE];
     126                        uint8_t         attr;
     127                        uint8_t         type;
     128                        uint8_t         check_sum;
     129                        uint16_t        part2[FAT_LFN_PART2_SIZE];
     130                        uint16_t        firstc_lo; /* MUST be 0 */
     131                        uint16_t        part3[FAT_LFN_PART3_SIZE];
     132                } __attribute__ ((packed)) lfn;
     133        };
    87134} __attribute__ ((packed)) fat_dentry_t;
    88135
     136
    89137extern int fat_dentry_namecmp(char *, const char *);
    90 extern bool fat_dentry_name_verify(const char *);
    91138extern void fat_dentry_name_get(const fat_dentry_t *, char *);
    92139extern void fat_dentry_name_set(fat_dentry_t *, const char *);
    93140extern fat_dentry_clsf_t fat_classify_dentry(const fat_dentry_t *);
     141extern uint8_t fat_dentry_chksum(uint8_t *);
     142
     143extern size_t fat_lfn_str_nlength(const uint16_t *, size_t);
     144extern size_t fat_lfn_size(const fat_dentry_t *);
     145extern size_t fat_lfn_get_part(const uint16_t *, size_t, uint16_t *, size_t *);
     146extern size_t fat_lfn_get_entry(const fat_dentry_t *, uint16_t *, size_t *);
     147extern size_t fat_lfn_set_part(const uint16_t *, size_t *, size_t, uint16_t *, size_t);
     148extern size_t fat_lfn_set_entry(const uint16_t *, size_t *, size_t, fat_dentry_t *);
     149
     150extern void str_to_ascii(char *dst, const char *src, size_t count, uint8_t pad);
     151extern size_t utf16_length(const uint16_t *wstr);
     152
     153extern bool fat_valid_name(const char *name);
     154extern bool fat_valid_short_name(const char *name);
     155
    94156
    95157#endif
  • uspace/srv/fs/fat/fat_fat.c

    r3fab770 ra33f0a6  
    11/*
    22 * Copyright (c) 2008 Jakub Jermar
     3 * Copyright (c) 2011 Oleg Romanenko
    34 * All rights reserved.
    45 *
     
    2930/** @addtogroup fs
    3031 * @{
    31  */ 
     32 */
    3233
    3334/**
     
    5455 * primitive boot sector members.
    5556 */
    56 #define RDS(bs)         ((sizeof(fat_dentry_t) * RDE((bs))) / BPS((bs))) + \
    57                         (((sizeof(fat_dentry_t) * RDE((bs))) % BPS((bs))) != 0)
    58 #define SSA(bs)         (RSCNT((bs)) + FATCNT((bs)) * SF((bs)) + RDS(bs))
    59 
    6057#define CLBN2PBN(bs, cl, bn) \
    6158        (SSA((bs)) + ((cl) - FAT_CLST_FIRST) * SPC((bs)) + (bn) % SPC((bs)))
     59
     60#define IS_ODD(number)  (number & 0x1)
    6261
    6362/**
     
    6564 * during allocation of clusters. The lock does not have to be held durring
    6665 * deallocation of clusters.
    67  */ 
     66 */
    6867static FIBRIL_MUTEX_INITIALIZE(fat_alloc_lock);
    6968
     
    7776 * @param numc          If non-NULL, output argument holding the number of
    7877 *                      clusters seen during the walk.
    79  * @param max_clusters  Maximum number of clusters to visit.   
     78 * @param max_clusters  Maximum number of clusters to visit.
    8079 *
    8180 * @return              EOK on success or a negative error code.
    8281 */
    83 int 
     82int
    8483fat_cluster_walk(fat_bs_t *bs, devmap_handle_t devmap_handle, fat_cluster_t firstc,
    85     fat_cluster_t *lastc, uint16_t *numc, uint16_t max_clusters)
    86 {
    87         block_t *b;
    88         uint16_t clusters = 0;
    89         fat_cluster_t clst = firstc;
     84    fat_cluster_t *lastc, uint32_t *numc, uint32_t max_clusters)
     85{
     86        uint32_t clusters = 0;
     87        fat_cluster_t clst = firstc, clst_last1 = FAT_CLST_LAST1(bs);
     88        fat_cluster_t clst_bad = FAT_CLST_BAD(bs);
    9089        int rc;
    9190
     
    9998        }
    10099
    101         while (clst < FAT_CLST_LAST1 && clusters < max_clusters) {
    102                 aoff64_t fsec;  /* sector offset relative to FAT1 */
    103                 unsigned fidx;  /* FAT1 entry index */
    104 
     100        while (clst < clst_last1 && clusters < max_clusters) {
    105101                assert(clst >= FAT_CLST_FIRST);
    106102                if (lastc)
    107103                        *lastc = clst;  /* remember the last cluster number */
    108                 fsec = (clst * sizeof(fat_cluster_t)) / BPS(bs);
    109                 fidx = clst % (BPS(bs) / sizeof(fat_cluster_t));
     104
    110105                /* read FAT1 */
    111                 rc = block_get(&b, devmap_handle, RSCNT(bs) + fsec,
    112                     BLOCK_FLAGS_NONE);
    113                 if (rc != EOK)
    114                         return rc;
    115                 clst = uint16_t_le2host(((fat_cluster_t *)b->data)[fidx]);
    116                 assert(clst != FAT_CLST_BAD);
    117                 rc = block_put(b);
    118                 if (rc != EOK)
    119                         return rc;
     106                rc = fat_get_cluster(bs, devmap_handle, FAT1, clst, &clst);
     107                if (rc != EOK)
     108                        return rc;
     109
     110                assert(clst != clst_bad);
    120111                clusters++;
    121112        }
    122113
    123         if (lastc && clst < FAT_CLST_LAST1)
     114        if (lastc && clst < clst_last1)
    124115                *lastc = clst;
    125116        if (numc)
     
    151142                return ELIMIT;
    152143
    153         if (nodep->firstc == FAT_CLST_ROOT)
     144        if (!FAT_IS_FAT32(bs) && nodep->firstc == FAT_CLST_ROOT)
    154145                goto fall_through;
    155146
     
    178169        if (rc != EOK)
    179170                return rc;
    180        
     171
    181172        /*
    182173         * Update the "current" cluster cache.
     
    198189 * @param clp           If not NULL, address where the cluster containing bn
    199190 *                      will be stored.
    200  *                      stored 
     191 *                      stored
    201192 * @param bn            Block number.
    202193 * @param flags         Flags passed to libblock.
     
    208199    fat_cluster_t fcl, fat_cluster_t *clp, aoff64_t bn, int flags)
    209200{
    210         uint16_t clusters;
    211         unsigned max_clusters;
     201        uint32_t clusters;
     202        uint32_t max_clusters;
    212203        fat_cluster_t c;
    213204        int rc;
     
    219210                return ELIMIT;
    220211
    221         if (fcl == FAT_CLST_ROOT) {
     212        if (!FAT_IS_FAT32(bs) && fcl == FAT_CLST_ROOT) {
    222213                /* root directory special case */
    223214                assert(bn < RDS(bs));
     
    275266                        return rc;
    276267        }
    277        
     268
    278269        if (o >= pos)
    279270                return EOK;
    280        
     271
    281272        /* zero out the initial part of the new cluster chain */
    282273        for (o = boundary; o < pos; o += BPS(bs)) {
     
    295286}
    296287
    297 /** Get cluster from the first FAT.
     288/** Get cluster from the first FAT. FAT12 version
    298289 *
    299290 * @param bs            Buffer holding the boot sector for the file system.
     
    305296 */
    306297int
     298fat_get_cluster_fat12(fat_bs_t *bs, devmap_handle_t devmap_handle, unsigned fatno,
     299    fat_cluster_t clst, fat_cluster_t *value)
     300{
     301        block_t *b, *b1;
     302        uint16_t byte1, byte2;
     303        aoff64_t offset;
     304        int rc;
     305
     306        offset = (clst + clst/2);
     307        if (offset / BPS(bs) >= SF(bs))
     308                return ERANGE;
     309
     310        rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno +
     311            offset / BPS(bs), BLOCK_FLAGS_NONE);
     312        if (rc != EOK)
     313                return rc;
     314
     315        byte1 = ((uint8_t*) b->data)[offset % BPS(bs)];
     316        /* This cluster access spans a sector boundary. Check only for FAT12 */
     317        if ((offset % BPS(bs)) + 1 == BPS(bs)) {
     318                /* Is it last sector of FAT? */
     319                if (offset / BPS(bs) < SF(bs)) {
     320                        /* No. Reading next sector */
     321                        rc = block_get(&b1, devmap_handle, 1 + RSCNT(bs) +
     322                                SF(bs)*fatno + offset / BPS(bs), BLOCK_FLAGS_NONE);
     323                        if (rc != EOK) {
     324                                block_put(b);
     325                                return rc;
     326                        }
     327                        /*
     328                        * Combining value with last byte of current sector and
     329                        * first byte of next sector
     330                        */
     331                        byte2 = ((uint8_t*) b1->data)[0];
     332
     333                        rc = block_put(b1);
     334                        if (rc != EOK) {
     335                                block_put(b);
     336                                return rc;
     337                        }
     338                }
     339                else {
     340                        /* Yes. It is last sector of FAT */
     341                        block_put(b);
     342                        return ERANGE;
     343                }
     344        }
     345        else
     346                byte2 = ((uint8_t*) b->data)[(offset % BPS(bs))+1];
     347
     348        *value = uint16_t_le2host(byte1 | (byte2 << 8));
     349        if (IS_ODD(clst))
     350                *value = (*value) >> 4;
     351        else
     352                *value = (*value) & FAT12_MASK;
     353       
     354        rc = block_put(b);
     355        return rc;
     356}
     357
     358/** Get cluster from the first FAT. FAT16 version
     359 *
     360 * @param bs            Buffer holding the boot sector for the file system.
     361 * @param devmap_handle Device handle for the file system.
     362 * @param clst          Cluster which to get.
     363 * @param value         Output argument holding the value of the cluster.
     364 *
     365 * @return              EOK or a negative error code.
     366 */
     367int
     368fat_get_cluster_fat16(fat_bs_t *bs, devmap_handle_t devmap_handle, unsigned fatno,
     369    fat_cluster_t clst, fat_cluster_t *value)
     370{
     371        block_t *b;
     372        aoff64_t offset;
     373        int rc;
     374
     375        offset = (clst * FAT16_CLST_SIZE);
     376
     377        rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno +
     378            offset / BPS(bs), BLOCK_FLAGS_NONE);
     379        if (rc != EOK)
     380                return rc;
     381
     382        *value = uint16_t_le2host(*(uint16_t *)(b->data + offset % BPS(bs)));
     383
     384        rc = block_put(b);
     385
     386        return rc;
     387}
     388
     389/** Get cluster from the first FAT. FAT32 version
     390 *
     391 * @param bs            Buffer holding the boot sector for the file system.
     392 * @param devmap_handle Device handle for the file system.
     393 * @param clst          Cluster which to get.
     394 * @param value         Output argument holding the value of the cluster.
     395 *
     396 * @return              EOK or a negative error code.
     397 */
     398int
     399fat_get_cluster_fat32(fat_bs_t *bs, devmap_handle_t devmap_handle, unsigned fatno,
     400    fat_cluster_t clst, fat_cluster_t *value)
     401{
     402        block_t *b;
     403        aoff64_t offset;
     404        int rc;
     405
     406        offset = (clst * FAT32_CLST_SIZE);
     407
     408        rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno +
     409            offset / BPS(bs), BLOCK_FLAGS_NONE);
     410        if (rc != EOK)
     411                return rc;
     412
     413        *value = uint32_t_le2host(*(uint32_t *)(b->data + offset % BPS(bs))) & FAT32_MASK;
     414
     415        rc = block_put(b);
     416
     417        return rc;
     418}
     419
     420
     421/** Get cluster from the first FAT.
     422 *
     423 * @param bs            Buffer holding the boot sector for the file system.
     424 * @param devmap_handle Device handle for the file system.
     425 * @param clst          Cluster which to get.
     426 * @param value         Output argument holding the value of the cluster.
     427 *
     428 * @return              EOK or a negative error code.
     429 */
     430int
    307431fat_get_cluster(fat_bs_t *bs, devmap_handle_t devmap_handle, unsigned fatno,
    308432    fat_cluster_t clst, fat_cluster_t *value)
    309433{
    310         block_t *b;
    311         fat_cluster_t *cp;
    312         int rc;
    313 
    314         rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno +
    315             (clst * sizeof(fat_cluster_t)) / BPS(bs), BLOCK_FLAGS_NONE);
    316         if (rc != EOK)
    317                 return rc;
    318         cp = (fat_cluster_t *)b->data +
    319             clst % (BPS(bs) / sizeof(fat_cluster_t));
    320         *value = uint16_t_le2host(*cp);
    321         rc = block_put(b);
    322        
     434        int rc;
     435
     436        assert(fatno < FATCNT(bs));
     437
     438        if (FAT_IS_FAT12(bs)) {
     439                rc = fat_get_cluster_fat12(bs, devmap_handle, fatno, clst, value);
     440        }
     441        else {
     442                if (FAT_IS_FAT32(bs))
     443                        rc = fat_get_cluster_fat32(bs, devmap_handle, fatno, clst, value);
     444                else
     445                        rc = fat_get_cluster_fat16(bs, devmap_handle, fatno, clst, value);
     446        }
     447
    323448        return rc;
    324449}
    325450
    326 /** Set cluster in one instance of FAT.
     451/** Set cluster in one instance of FAT. FAT12 version.
    327452 *
    328453 * @param bs            Buffer holding the boot sector for the file system.
     
    335460 */
    336461int
     462fat_set_cluster_fat12(fat_bs_t *bs, devmap_handle_t devmap_handle, unsigned fatno,
     463    fat_cluster_t clst, fat_cluster_t value)
     464{
     465        block_t *b, *b1=NULL;
     466        aoff64_t offset;
     467        uint16_t byte1, byte2;
     468        int rc;
     469
     470        offset = (clst + clst/2);
     471        if (offset / BPS(bs) >= SF(bs))
     472                return ERANGE;
     473       
     474        rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno +
     475            offset / BPS(bs), BLOCK_FLAGS_NONE);
     476        if (rc != EOK)
     477                return rc;
     478
     479        byte1 = ((uint8_t*) b->data)[offset % BPS(bs)];
     480        bool border = false;
     481        /* This cluster access spans a sector boundary. Check only for FAT12 */
     482        if ((offset % BPS(bs))+1 == BPS(bs)) {
     483                /* Is it last sector of FAT? */
     484                if (offset / BPS(bs) < SF(bs)) {
     485                        /* No. Reading next sector */
     486                        rc = block_get(&b1, devmap_handle, 1 + RSCNT(bs) +
     487                                SF(bs)*fatno + offset / BPS(bs), BLOCK_FLAGS_NONE);
     488                        if (rc != EOK) {
     489                                block_put(b);
     490                                return rc;
     491                        }
     492                        /*
     493                         * Combining value with last byte of current sector and
     494                         * first byte of next sector
     495                         */
     496                        byte2 = ((uint8_t*) b1->data)[0];
     497                        border = true;
     498                }
     499                else {
     500                        /* Yes. It is last sector of fat */
     501                        block_put(b);
     502                        return ERANGE;
     503                }
     504        }
     505        else
     506                byte2 = ((uint8_t*) b->data)[(offset % BPS(bs))+1];
     507
     508        if (IS_ODD(clst)) {
     509                byte1 &= 0x0f;
     510                byte2 = 0;
     511                value = (value << 4);
     512        } else {
     513                byte1 = 0;
     514                byte2 &= 0xf0;
     515                value &= FAT12_MASK;
     516        }
     517
     518        byte1 = byte1 | (value & 0xff);
     519        byte2 = byte2 | (value >> 8);
     520
     521        ((uint8_t*) b->data)[(offset % BPS(bs))] = byte1;
     522        if (border) {
     523                ((uint8_t*) b1->data)[0] = byte2;
     524
     525                b1->dirty = true;
     526                rc = block_put(b1);
     527                if (rc != EOK) {
     528                        block_put(b);
     529                        return rc;
     530                }
     531        } else
     532                ((uint8_t*) b->data)[(offset % BPS(bs))+1] = byte2;
     533
     534        b->dirty = true;        /* need to sync block */
     535        rc = block_put(b);
     536        return rc;
     537}
     538
     539/** Set cluster in one instance of FAT. FAT16 version.
     540 *
     541 * @param bs            Buffer holding the boot sector for the file system.
     542 * @param devmap_handle Device handle for the file system.
     543 * @param fatno         Number of the FAT instance where to make the change.
     544 * @param clst          Cluster which is to be set.
     545 * @param value         Value to set the cluster with.
     546 *
     547 * @return              EOK on success or a negative error code.
     548 */
     549int
     550fat_set_cluster_fat16(fat_bs_t *bs, devmap_handle_t devmap_handle, unsigned fatno,
     551    fat_cluster_t clst, fat_cluster_t value)
     552{
     553        block_t *b;
     554        aoff64_t offset;
     555        int rc;
     556
     557        offset = (clst * FAT16_CLST_SIZE);
     558
     559        rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno +
     560            offset / BPS(bs), BLOCK_FLAGS_NONE);
     561        if (rc != EOK)
     562                return rc;
     563
     564        *(uint16_t *)(b->data + offset % BPS(bs)) = host2uint16_t_le(value);
     565
     566        b->dirty = true;        /* need to sync block */
     567        rc = block_put(b);
     568        return rc;
     569}
     570
     571/** Set cluster in one instance of FAT. FAT32 version.
     572 *
     573 * @param bs            Buffer holding the boot sector for the file system.
     574 * @param devmap_handle Device handle for the file system.
     575 * @param fatno         Number of the FAT instance where to make the change.
     576 * @param clst          Cluster which is to be set.
     577 * @param value         Value to set the cluster with.
     578 *
     579 * @return              EOK on success or a negative error code.
     580 */
     581int
     582fat_set_cluster_fat32(fat_bs_t *bs, devmap_handle_t devmap_handle, unsigned fatno,
     583    fat_cluster_t clst, fat_cluster_t value)
     584{
     585        block_t *b;
     586        aoff64_t offset;
     587        int rc;
     588        fat_cluster_t temp;
     589
     590        offset = (clst * FAT32_CLST_SIZE);
     591
     592        rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno +
     593            offset / BPS(bs), BLOCK_FLAGS_NONE);
     594        if (rc != EOK)
     595                return rc;
     596
     597        temp = uint32_t_le2host(*(uint32_t *)(b->data + offset % BPS(bs)));
     598        temp &= 0xf0000000;
     599        temp |= (value & FAT32_MASK);
     600        *(uint32_t *)(b->data + offset % BPS(bs)) = host2uint32_t_le(temp);
     601
     602        b->dirty = true;        /* need to sync block */
     603        rc = block_put(b);
     604        return rc;
     605}
     606
     607/** Set cluster in one instance of FAT.
     608 *
     609 * @param bs            Buffer holding the boot sector for the file system.
     610 * @param devmap_handle Device handle for the file system.
     611 * @param fatno         Number of the FAT instance where to make the change.
     612 * @param clst          Cluster which is to be set.
     613 * @param value         Value to set the cluster with.
     614 *
     615 * @return              EOK on success or a negative error code.
     616 */
     617int
    337618fat_set_cluster(fat_bs_t *bs, devmap_handle_t devmap_handle, unsigned fatno,
    338619    fat_cluster_t clst, fat_cluster_t value)
    339620{
    340         block_t *b;
    341         fat_cluster_t *cp;
    342621        int rc;
    343622
    344623        assert(fatno < FATCNT(bs));
    345         rc = block_get(&b, devmap_handle, RSCNT(bs) + SF(bs) * fatno +
    346             (clst * sizeof(fat_cluster_t)) / BPS(bs), BLOCK_FLAGS_NONE);
    347         if (rc != EOK)
    348                 return rc;
    349         cp = (fat_cluster_t *)b->data +
    350             clst % (BPS(bs) / sizeof(fat_cluster_t));
    351         *cp = host2uint16_t_le(value);
    352         b->dirty = true;                /* need to sync block */
    353         rc = block_put(b);
     624
     625        if (FAT_IS_FAT12(bs))
     626                rc = fat_set_cluster_fat12(bs, devmap_handle, fatno, clst, value);
     627        else if (FAT_IS_FAT32(bs))
     628                rc = fat_set_cluster_fat32(bs, devmap_handle, fatno, clst, value);
     629        else
     630                rc = fat_set_cluster_fat16(bs, devmap_handle, fatno, clst, value);
     631
    354632        return rc;
    355633}
     
    369647        uint8_t fatno;
    370648        unsigned c;
    371         int rc;
    372 
    373         for (fatno = FAT1 + 1; fatno < bs->fatcnt; fatno++) {
     649        fat_cluster_t clst_last1 = FAT_CLST_LAST1(bs);
     650        int rc;
     651
     652        for (fatno = FAT1 + 1; fatno < FATCNT(bs); fatno++) {
    374653                for (c = 0; c < nclsts; c++) {
    375654                        rc = fat_set_cluster(bs, devmap_handle, fatno, lifo[c],
    376                             c == 0 ? FAT_CLST_LAST1 : lifo[c - 1]);
     655                            c == 0 ? clst_last1 : lifo[c - 1]);
    377656                        if (rc != EOK)
    378657                                return rc;
     
    404683    fat_cluster_t *mcl, fat_cluster_t *lcl)
    405684{
    406         block_t *blk;
    407         fat_cluster_t *lifo;    /* stack for storing free cluster numbers */
    408         unsigned found = 0;     /* top of the free cluster number stack */
    409         unsigned b, c, cl;
    410         int rc;
     685        fat_cluster_t *lifo;    /* stack for storing free cluster numbers */
     686        unsigned found = 0;     /* top of the free cluster number stack */
     687        fat_cluster_t clst, value, clst_last1 = FAT_CLST_LAST1(bs);
     688        int rc = EOK;
    411689
    412690        lifo = (fat_cluster_t *) malloc(nclsts * sizeof(fat_cluster_t));
    413691        if (!lifo)
    414692                return ENOMEM;
    415        
    416693        /*
    417694         * Search FAT1 for unused clusters.
    418695         */
    419696        fibril_mutex_lock(&fat_alloc_lock);
    420         for (b = 0, cl = 0; b < SF(bs); b++) {
    421                 rc = block_get(&blk, devmap_handle, RSCNT(bs) + b,
    422                     BLOCK_FLAGS_NONE);
    423                 if (rc != EOK)
    424                         goto error;
    425                 for (c = 0; c < BPS(bs) / sizeof(fat_cluster_t); c++, cl++) {
    426                         /*
    427                          * Check if the entire cluster is physically there.
    428                          * This check becomes necessary when the file system is
    429                          * created with fewer total sectors than how many is
    430                          * inferred from the size of the file allocation table
    431                          * or when the last cluster ends beyond the end of the
    432                          * device.
    433                          */
    434                         if ((cl >= FAT_CLST_FIRST) &&
    435                             CLBN2PBN(bs, cl, SPC(bs) - 1) >= TS(bs)) {
    436                                 rc = block_put(blk);
    437                                 if (rc != EOK)
    438                                         goto error;
    439                                 goto out;
    440                         }
    441 
    442                         fat_cluster_t *clst = (fat_cluster_t *)blk->data + c;
    443                         if (uint16_t_le2host(*clst) == FAT_CLST_RES0) {
    444                                 /*
    445                                  * The cluster is free. Put it into our stack
    446                                  * of found clusters and mark it as non-free.
    447                                  */
    448                                 lifo[found] = cl;
    449                                 *clst = (found == 0) ?
    450                                     host2uint16_t_le(FAT_CLST_LAST1) :
    451                                     host2uint16_t_le(lifo[found - 1]);
    452                                 blk->dirty = true;      /* need to sync block */
    453                                 if (++found == nclsts) {
    454                                         /* we are almost done */
    455                                         rc = block_put(blk);
    456                                         if (rc != EOK)
    457                                                 goto error;
    458                                         /* update the shadow copies of FAT */
    459                                         rc = fat_alloc_shadow_clusters(bs,
    460                                             devmap_handle, lifo, nclsts);
    461                                         if (rc != EOK)
    462                                                 goto error;
    463                                         *mcl = lifo[found - 1];
    464                                         *lcl = lifo[0];
    465                                         free(lifo);
    466                                         fibril_mutex_unlock(&fat_alloc_lock);
    467                                         return EOK;
    468                                 }
    469                         }
    470                 }
    471                 rc = block_put(blk);
    472                 if (rc != EOK) {
    473 error:
     697        for (clst=FAT_CLST_FIRST; clst < CC(bs)+2 && found < nclsts; clst++) {
     698                rc = fat_get_cluster(bs, devmap_handle, FAT1, clst, &value);
     699                if (rc != EOK)
     700                break;
     701
     702                if (value == FAT_CLST_RES0) {
     703                /*
     704                 * The cluster is free. Put it into our stack
     705                 * of found clusters and mark it as non-free.
     706                 */
     707                lifo[found] = clst;
     708                rc = fat_set_cluster(bs, devmap_handle, FAT1, clst,
     709                    (found == 0) ?  clst_last1 : lifo[found - 1]);
     710                if (rc != EOK)
     711                        break;
     712
     713                found++;
     714                }
     715        }
     716
     717        if (rc == EOK && found == nclsts) {
     718                rc = fat_alloc_shadow_clusters(bs, devmap_handle, lifo, nclsts);
     719                if (rc == EOK) {
     720                        *mcl = lifo[found - 1];
     721                        *lcl = lifo[0];
     722                        free(lifo);
    474723                        fibril_mutex_unlock(&fat_alloc_lock);
    475                         free(lifo);
    476                         return rc;
    477                 }
    478         }
    479 out:
    480         fibril_mutex_unlock(&fat_alloc_lock);
    481 
    482         /*
    483          * We could not find enough clusters. Now we need to free the clusters
    484          * we have allocated so far.
    485          */
    486         while (found--) {
     724                        return EOK;
     725                }
     726        }
     727
     728        /* If something wrong - free the clusters */
     729        if (found > 0) {
     730                while (found--) {
    487731                rc = fat_set_cluster(bs, devmap_handle, FAT1, lifo[found],
    488732                    FAT_CLST_RES0);
    489                 if (rc != EOK) {
    490                         free(lifo);
    491                         return rc;
    492                 }
    493         }
    494        
     733                }
     734        }
     735
    495736        free(lifo);
     737        fibril_mutex_unlock(&fat_alloc_lock);
    496738        return ENOSPC;
    497739}
     
    509751{
    510752        unsigned fatno;
    511         fat_cluster_t nextc;
     753        fat_cluster_t nextc, clst_bad = FAT_CLST_BAD(bs);
    512754        int rc;
    513755
    514756        /* Mark all clusters in the chain as free in all copies of FAT. */
    515         while (firstc < FAT_CLST_LAST1) {
    516                 assert(firstc >= FAT_CLST_FIRST && firstc < FAT_CLST_BAD);
     757        while (firstc < FAT_CLST_LAST1(bs)) {
     758                assert(firstc >= FAT_CLST_FIRST && firstc < clst_bad);
    517759                rc = fat_get_cluster(bs, devmap_handle, FAT1, firstc, &nextc);
    518760                if (rc != EOK)
    519761                        return rc;
    520                 for (fatno = FAT1; fatno < bs->fatcnt; fatno++) {
     762                for (fatno = FAT1; fatno < FATCNT(bs); fatno++) {
    521763                        rc = fat_set_cluster(bs, devmap_handle, fatno, firstc,
    522764                            FAT_CLST_RES0);
     
    564806                }
    565807
    566                 for (fatno = FAT1; fatno < bs->fatcnt; fatno++) {
    567                         rc = fat_set_cluster(bs, nodep->idx->devmap_handle, fatno,
    568                             lastc, mcl);
     808                for (fatno = FAT1; fatno < FATCNT(bs); fatno++) {
     809                        rc = fat_set_cluster(bs, nodep->idx->devmap_handle,
     810                            fatno, lastc, mcl);
    569811                        if (rc != EOK)
    570812                                return rc;
     
    590832int fat_chop_clusters(fat_bs_t *bs, fat_node_t *nodep, fat_cluster_t lcl)
    591833{
     834        fat_cluster_t clst_last1 = FAT_CLST_LAST1(bs);
    592835        int rc;
    593836        devmap_handle_t devmap_handle = nodep->idx->devmap_handle;
     
    616859
    617860                /* Terminate the cluster chain in all copies of FAT. */
    618                 for (fatno = FAT1; fatno < bs->fatcnt; fatno++) {
     861                for (fatno = FAT1; fatno < FATCNT(bs); fatno++) {
    619862                        rc = fat_set_cluster(bs, devmap_handle, fatno, lcl,
    620                             FAT_CLST_LAST1);
     863                            clst_last1);
    621864                        if (rc != EOK)
    622865                                return rc;
     
    673916
    674917        /* Check number of FATs. */
    675         if (bs->fatcnt == 0)
     918        if (FATCNT(bs) == 0)
    676919                return ENOTSUP;
    677920
    678921        /* Check total number of sectors. */
    679 
    680         if (bs->totsec16 == 0 && bs->totsec32 == 0)
     922        if (TS(bs) == 0)
    681923                return ENOTSUP;
    682924
    683925        if (bs->totsec16 != 0 && bs->totsec32 != 0 &&
    684             bs->totsec16 != bs->totsec32) 
     926            bs->totsec16 != bs->totsec32)
    685927                return ENOTSUP;
    686928
     
    690932
    691933        /* Check number of sectors per FAT. */
    692         if (bs->sec_per_fat == 0)
     934        if (SF(bs) == 0)
    693935                return ENOTSUP;
    694936
     
    700942         * sanitized to support file systems with this property.
    701943         */
    702         if ((uint16_t_le2host(bs->root_ent_max) * sizeof(fat_dentry_t)) %
    703             uint16_t_le2host(bs->bps) != 0)
     944        if (!FAT_IS_FAT32(bs) && (RDE(bs) * sizeof(fat_dentry_t)) % BPS(bs) != 0)
    704945                return ENOTSUP;
    705946
    706947        /* Check signature of each FAT. */
    707 
    708         for (fat_no = 0; fat_no < bs->fatcnt; fat_no++) {
     948        for (fat_no = 0; fat_no < FATCNT(bs); fat_no++) {
    709949                rc = fat_get_cluster(bs, devmap_handle, fat_no, 0, &e0);
    710950                if (rc != EOK)
     
    723963                 * set to one.
    724964                 */
    725                 if ((e0 >> 8) != 0xff || e1 != 0xffff)
     965                if (!FAT_IS_FAT12(bs) &&
     966                        ((e0 >> 8) != (FAT_MASK(bs) >> 8) || e1 != FAT_MASK(bs)))
    726967                        return ENOTSUP;
    727968        }
     
    732973/**
    733974 * @}
    734  */ 
     975 */
  • uspace/srv/fs/fat/fat_fat.h

    r3fab770 ra33f0a6  
    11/*
    22 * Copyright (c) 2008 Jakub Jermar
     3 * Copyright (c) 2011 Oleg Romanenko
    34 * All rights reserved.
    45 *
     
    2930/** @addtogroup fs
    3031 * @{
    31  */ 
     32 */
    3233
    3334#ifndef FAT_FAT_FAT_H_
     
    4041#define FAT1            0
    4142
    42 #define FAT_CLST_RES0   0x0000
    43 #define FAT_CLST_RES1   0x0001
    44 #define FAT_CLST_FIRST  0x0002
    45 #define FAT_CLST_BAD    0xfff7
    46 #define FAT_CLST_LAST1  0xfff8
    47 #define FAT_CLST_LAST8  0xffff
     43#define FAT_CLST_RES0     0
     44#define FAT_CLST_RES1     1
     45#define FAT_CLST_FIRST    2
     46
     47#define FAT32_CLST_BAD    0x0ffffff7
     48#define FAT32_CLST_LAST1  0x0ffffff8
     49#define FAT32_CLST_LAST8  0x0fffffff
     50
     51#define FAT12_MASK        0x0fff
     52#define FAT16_MASK        0xffff
     53#define FAT32_MASK        0x0fffffff
     54
     55#define FAT12_CLST_MAX    4085
     56#define FAT16_CLST_MAX    65525
     57
     58/* Size in bytes for cluster value of FAT */
     59#define FAT12_CLST_SIZE   2
     60#define FAT16_CLST_SIZE   2
     61#define FAT32_CLST_SIZE   4
    4862
    4963/* internally used to mark root directory's parent */
     
    5266#define FAT_CLST_ROOT           FAT_CLST_RES1
    5367
     68/*
     69 * Convenience macros for computing some frequently used values from the
     70 * primitive boot sector members.
     71 */
     72#define RDS(bs)   ((sizeof(fat_dentry_t) * RDE((bs))) / BPS((bs))) + \
     73                   (((sizeof(fat_dentry_t) * RDE((bs))) % BPS((bs))) != 0)
     74#define SSA(bs)   (RSCNT((bs)) + FATCNT((bs)) * SF((bs)) + RDS(bs))
     75#define DS(bs)    (TS(bs) - SSA(bs))
     76#define CC(bs)    (DS(bs) / SPC(bs))
     77
     78#define FAT_IS_FAT12(bs)        (CC(bs) < FAT12_CLST_MAX)
     79#define FAT_IS_FAT16(bs) \
     80    ((CC(bs) >= FAT12_CLST_MAX) && (CC(bs) < FAT16_CLST_MAX))
     81#define FAT_IS_FAT32(bs)        (CC(bs) >= FAT16_CLST_MAX)
     82
     83#define FAT_CLST_SIZE(bs) \
     84    (FAT_IS_FAT32(bs) ? FAT32_CLST_SIZE : FAT16_CLST_SIZE)
     85
     86#define FAT_MASK(bs) \
     87    (FAT_IS_FAT12(bs) ? FAT12_MASK : \
     88    (FAT_IS_FAT32(bs) ? FAT32_MASK : FAT16_MASK))
     89
     90#define FAT_CLST_LAST1(bs)      (FAT32_CLST_LAST1 & FAT_MASK((bs)))
     91#define FAT_CLST_LAST8(bs)      (FAT32_CLST_LAST8 & FAT_MASK((bs)))
     92#define FAT_CLST_BAD(bs)        (FAT32_CLST_BAD & FAT_MASK((bs)))
     93
     94#define FAT_ROOT_CLST(bs) \
     95    (FAT_IS_FAT32(bs) ? uint32_t_le2host(bs->fat32.root_cluster) : \
     96    FAT_CLST_ROOT)
     97
    5498/* forward declarations */
    5599struct block;
     
    57101struct fat_bs;
    58102
    59 typedef uint16_t fat_cluster_t;
     103typedef uint32_t fat_cluster_t;
    60104
    61105#define fat_clusters_get(numc, bs, dh, fc) \
    62     fat_cluster_walk((bs), (dh), (fc), NULL, (numc), (uint16_t) -1)
     106    fat_cluster_walk((bs), (dh), (fc), NULL, (numc), (uint32_t) -1)
    63107extern int fat_cluster_walk(struct fat_bs *, devmap_handle_t, fat_cluster_t,
    64     fat_cluster_t *, uint16_t *, uint16_t);
     108    fat_cluster_t *, uint32_t *, uint32_t);
    65109
    66110extern int fat_block_get(block_t **, struct fat_bs *, struct fat_node *,
     
    78122extern int fat_alloc_shadow_clusters(struct fat_bs *, devmap_handle_t,
    79123    fat_cluster_t *, unsigned);
     124extern int fat_get_cluster_fat12(struct fat_bs *, devmap_handle_t, unsigned,
     125    fat_cluster_t, fat_cluster_t *);
     126extern int fat_get_cluster_fat16(struct fat_bs *, devmap_handle_t, unsigned,
     127    fat_cluster_t, fat_cluster_t *);
     128extern int fat_get_cluster_fat32(struct fat_bs *, devmap_handle_t, unsigned,
     129    fat_cluster_t, fat_cluster_t *);
    80130extern int fat_get_cluster(struct fat_bs *, devmap_handle_t, unsigned,
    81131    fat_cluster_t, fat_cluster_t *);
     132extern int fat_set_cluster_fat12(struct fat_bs *, devmap_handle_t, unsigned,
     133    fat_cluster_t, fat_cluster_t);
     134extern int fat_set_cluster_fat16(struct fat_bs *, devmap_handle_t, unsigned,
     135    fat_cluster_t, fat_cluster_t);
     136extern int fat_set_cluster_fat32(struct fat_bs *, devmap_handle_t, unsigned,
     137    fat_cluster_t, fat_cluster_t);
    82138extern int fat_set_cluster(struct fat_bs *, devmap_handle_t, unsigned,
    83139    fat_cluster_t, fat_cluster_t);
  • uspace/srv/fs/fat/fat_ops.c

    r3fab770 ra33f0a6  
    11/*
    22 * Copyright (c) 2008 Jakub Jermar
     3 * Copyright (c) 2011 Oleg Romanenko
    34 * All rights reserved.
    45 *
     
    2930/** @addtogroup fs
    3031 * @{
    31  */ 
     32 */
    3233
    3334/**
     
    3940#include "fat_dentry.h"
    4041#include "fat_fat.h"
     42#include "fat_directory.h"
    4143#include "../../vfs/vfs.h"
    4244#include <libfs.h>
     
    5658#include <align.h>
    5759#include <malloc.h>
     60#include <str.h>
    5861
    5962#define FAT_NODE(node)  ((node) ? (fat_node_t *) (node)->data : NULL)
     
    104107        node->dirty = false;
    105108        node->lastc_cached_valid = false;
    106         node->lastc_cached_value = FAT_CLST_LAST1;
     109        node->lastc_cached_value = 0;
    107110        node->currc_cached_valid = false;
    108111        node->currc_cached_bn = 0;
    109         node->currc_cached_value = FAT_CLST_LAST1;
     112        node->currc_cached_value = 0;
    110113}
    111114
     
    116119        fat_dentry_t *d;
    117120        int rc;
    118        
     121
    119122        assert(node->dirty);
    120123
    121124        bs = block_bb_get(node->idx->devmap_handle);
    122        
     125
    123126        /* Read the block that contains the dentry of interest. */
    124127        rc = _fat_block_get(&b, bs, node->idx->devmap_handle, node->idx->pfc,
     
    136139                d->attr = FAT_ATTR_SUBDIR;
    137140        }
    138        
     141
    139142        /* TODO: update other fields? (e.g time fields) */
    140        
     143
    141144        b->dirty = true;                /* need to sync block */
    142145        rc = block_put(b);
     
    255258        fn->data = nodep;
    256259        nodep->bp = fn;
    257        
     260
    258261        *nodepp = nodep;
    259262        return EOK;
     
    291294         * We must instantiate the node from the file system.
    292295         */
    293        
     296
    294297        assert(idxp->pfc);
    295298
     
    309312
    310313        d = ((fat_dentry_t *)b->data) + (idxp->pdi % DPS(bs));
     314        if (FAT_IS_FAT32(bs)) {
     315                nodep->firstc = uint16_t_le2host(d->firstc_lo) |
     316                    (uint16_t_le2host(d->firstc_hi) << 16);
     317        }
     318        else
     319                nodep->firstc = uint16_t_le2host(d->firstc);
     320
    311321        if (d->attr & FAT_ATTR_SUBDIR) {
    312                 /* 
     322                /*
    313323                 * The only directory which does not have this bit set is the
    314324                 * root directory itself. The root directory node is handled
     
    316326                 */
    317327                nodep->type = FAT_DIRECTORY;
     328
    318329                /*
    319330                 * Unfortunately, the 'size' field of the FAT dentry is not
     
    321332                 * size of the directory by walking the FAT.
    322333                 */
    323                 uint16_t clusters;
    324                 rc = fat_clusters_get(&clusters, bs, idxp->devmap_handle,
    325                     uint16_t_le2host(d->firstc));
     334                uint32_t clusters;
     335                rc = fat_clusters_get(&clusters, bs, idxp->devmap_handle, nodep->firstc);
    326336                if (rc != EOK) {
    327337                        (void) block_put(b);
     
    334344                nodep->size = uint32_t_le2host(d->size);
    335345        }
    336         nodep->firstc = uint16_t_le2host(d->firstc);
     346
    337347        nodep->lnkcnt = 1;
    338348        nodep->refcnt = 1;
     
    363373int fat_match(fs_node_t **rfn, fs_node_t *pfn, const char *component)
    364374{
    365         fat_bs_t *bs;
    366375        fat_node_t *parentp = FAT_NODE(pfn);
    367         char name[FAT_NAME_LEN + 1 + FAT_EXT_LEN + 1];
    368         unsigned i, j;
    369         unsigned blocks;
     376        char name[FAT_LFN_NAME_SIZE];
    370377        fat_dentry_t *d;
    371378        devmap_handle_t devmap_handle;
    372         block_t *b;
    373379        int rc;
    374380
     
    376382        devmap_handle = parentp->idx->devmap_handle;
    377383        fibril_mutex_unlock(&parentp->idx->lock);
    378 
    379         bs = block_bb_get(devmap_handle);
    380         blocks = parentp->size / BPS(bs);
    381         for (i = 0; i < blocks; i++) {
    382                 rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE);
    383                 if (rc != EOK)
    384                         return rc;
    385                 for (j = 0; j < DPS(bs); j++) {
    386                         d = ((fat_dentry_t *)b->data) + j;
    387                         switch (fat_classify_dentry(d)) {
    388                         case FAT_DENTRY_SKIP:
    389                         case FAT_DENTRY_FREE:
    390                                 continue;
    391                         case FAT_DENTRY_LAST:
    392                                 /* miss */
    393                                 rc = block_put(b);
    394                                 *rfn = NULL;
    395                                 return rc;
    396                         default:
    397                         case FAT_DENTRY_VALID:
    398                                 fat_dentry_name_get(d, name);
    399                                 break;
     384       
     385        fat_directory_t di;
     386        rc = fat_directory_open(parentp, &di);
     387        if (rc != EOK)
     388                return rc;
     389
     390        while (fat_directory_read(&di, name, &d) == EOK) {
     391                if (fat_dentry_namecmp(name, component) == 0) {
     392                        /* hit */
     393                        fat_node_t *nodep;
     394                        aoff64_t o = di.pos % (BPS(di.bs) / sizeof(fat_dentry_t));
     395                        fat_idx_t *idx = fat_idx_get_by_pos(devmap_handle,
     396                                parentp->firstc, di.bnum * DPS(di.bs) + o);
     397                        if (!idx) {
     398                                /*
     399                                 * Can happen if memory is low or if we
     400                                 * run out of 32-bit indices.
     401                                 */
     402                                rc = fat_directory_close(&di);
     403                                return (rc == EOK) ? ENOMEM : rc;
    400404                        }
    401                         if (fat_dentry_namecmp(name, component) == 0) {
    402                                 /* hit */
    403                                 fat_node_t *nodep;
    404                                 fat_idx_t *idx = fat_idx_get_by_pos(devmap_handle,
    405                                     parentp->firstc, i * DPS(bs) + j);
    406                                 if (!idx) {
    407                                         /*
    408                                          * Can happen if memory is low or if we
    409                                          * run out of 32-bit indices.
    410                                          */
    411                                         rc = block_put(b);
    412                                         return (rc == EOK) ? ENOMEM : rc;
    413                                 }
    414                                 rc = fat_node_get_core(&nodep, idx);
    415                                 fibril_mutex_unlock(&idx->lock);
    416                                 if (rc != EOK) {
    417                                         (void) block_put(b);
    418                                         return rc;
    419                                 }
    420                                 *rfn = FS_NODE(nodep);
    421                                 rc = block_put(b);
    422                                 if (rc != EOK)
    423                                         (void) fat_node_put(*rfn);
     405                        rc = fat_node_get_core(&nodep, idx);
     406                        fibril_mutex_unlock(&idx->lock);
     407                        if (rc != EOK) {
     408                                (void) fat_directory_close(&di);
    424409                                return rc;
    425410                        }
    426                 }
    427                 rc = block_put(b);
    428                 if (rc != EOK)
     411                        *rfn = FS_NODE(nodep);
     412                        rc = fat_directory_close(&di);
     413                        if (rc != EOK)
     414                                (void) fat_node_put(*rfn);
    429415                        return rc;
    430         }
    431 
     416                } else {
     417                        rc = fat_directory_next(&di);
     418                        if (rc != EOK)
     419                                break;
     420                }
     421        }
     422        (void) fat_directory_close(&di);
    432423        *rfn = NULL;
    433424        return EOK;
     
    521512        rc = fat_idx_get_new(&idxp, devmap_handle);
    522513        if (rc != EOK) {
    523                 (void) fat_free_clusters(bs, devmap_handle, mcl);       
     514                (void) fat_free_clusters(bs, devmap_handle, mcl);
    524515                (void) fat_node_put(FS_NODE(nodep));
    525516                return rc;
     
    591582        fat_bs_t *bs;
    592583        block_t *b;
    593         unsigned i, j;
    594         unsigned blocks;
    595         fat_cluster_t mcl, lcl;
     584        fat_directory_t di;
     585        fat_dentry_t de;
    596586        int rc;
    597587
     
    607597        fibril_mutex_unlock(&childp->lock);
    608598
    609         if (!fat_dentry_name_verify(name)) {
    610                 /*
    611                  * Attempt to create unsupported name.
    612                  */
     599        if (!fat_valid_name(name))
    613600                return ENOTSUP;
    614         }
    615 
    616         /*
    617          * Get us an unused parent node's dentry or grow the parent and allocate
    618          * a new one.
    619          */
    620        
     601
    621602        fibril_mutex_lock(&parentp->idx->lock);
    622603        bs = block_bb_get(parentp->idx->devmap_handle);
    623 
    624         blocks = parentp->size / BPS(bs);
    625 
    626         for (i = 0; i < blocks; i++) {
    627                 rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE);
    628                 if (rc != EOK) {
    629                         fibril_mutex_unlock(&parentp->idx->lock);
    630                         return rc;
    631                 }
    632                 for (j = 0; j < DPS(bs); j++) {
    633                         d = ((fat_dentry_t *)b->data) + j;
    634                         switch (fat_classify_dentry(d)) {
    635                         case FAT_DENTRY_SKIP:
    636                         case FAT_DENTRY_VALID:
    637                                 /* skipping used and meta entries */
    638                                 continue;
    639                         case FAT_DENTRY_FREE:
    640                         case FAT_DENTRY_LAST:
    641                                 /* found an empty slot */
    642                                 goto hit;
    643                         }
    644                 }
    645                 rc = block_put(b);
    646                 if (rc != EOK) {
    647                         fibril_mutex_unlock(&parentp->idx->lock);
    648                         return rc;
    649                 }
    650         }
    651         j = 0;
    652        
    653         /*
    654          * We need to grow the parent in order to create a new unused dentry.
    655          */
    656         if (parentp->firstc == FAT_CLST_ROOT) {
    657                 /* Can't grow the root directory. */
    658                 fibril_mutex_unlock(&parentp->idx->lock);
    659                 return ENOSPC;
    660         }
    661         rc = fat_alloc_clusters(bs, parentp->idx->devmap_handle, 1, &mcl, &lcl);
    662         if (rc != EOK) {
    663                 fibril_mutex_unlock(&parentp->idx->lock);
    664                 return rc;
    665         }
    666         rc = fat_zero_cluster(bs, parentp->idx->devmap_handle, mcl);
    667         if (rc != EOK) {
    668                 (void) fat_free_clusters(bs, parentp->idx->devmap_handle, mcl);
    669                 fibril_mutex_unlock(&parentp->idx->lock);
    670                 return rc;
    671         }
    672         rc = fat_append_clusters(bs, parentp, mcl, lcl);
    673         if (rc != EOK) {
    674                 (void) fat_free_clusters(bs, parentp->idx->devmap_handle, mcl);
    675                 fibril_mutex_unlock(&parentp->idx->lock);
    676                 return rc;
    677         }
    678         parentp->size += BPS(bs) * SPC(bs);
    679         parentp->dirty = true;          /* need to sync node */
    680         rc = fat_block_get(&b, bs, parentp, i, BLOCK_FLAGS_NONE);
    681         if (rc != EOK) {
    682                 fibril_mutex_unlock(&parentp->idx->lock);
    683                 return rc;
    684         }
    685         d = (fat_dentry_t *)b->data;
    686 
    687 hit:
     604        rc = fat_directory_open(parentp, &di);
     605        if (rc != EOK)
     606                return rc;
     607
    688608        /*
    689609         * At this point we only establish the link between the parent and the
     
    692612         * dentry data is kept in the child node structure.
    693613         */
    694         memset(d, 0, sizeof(fat_dentry_t));
    695         fat_dentry_name_set(d, name);
    696         b->dirty = true;                /* need to sync block */
    697         rc = block_put(b);
     614        memset(&de, 0, sizeof(fat_dentry_t));
     615
     616        rc = fat_directory_write(&di, name, &de);
     617        if (rc!=EOK)
     618                return rc;
     619        rc = fat_directory_close(&di);
     620        if (rc!=EOK)
     621                return rc;
     622
    698623        fibril_mutex_unlock(&parentp->idx->lock);
    699         if (rc != EOK) 
     624        if (rc != EOK)
    700625                return rc;
    701626
    702627        fibril_mutex_lock(&childp->idx->lock);
    703        
     628
    704629        if (childp->type == FAT_DIRECTORY) {
    705630                /*
     
    720645                d = (fat_dentry_t *) b->data;
    721646                if ((fat_classify_dentry(d) == FAT_DENTRY_LAST) ||
    722                     (str_cmp((char *) d->name, FAT_NAME_DOT)) == 0) {
     647                    (bcmp(d->name, FAT_NAME_DOT, FAT_NAME_LEN)) == 0) {
    723648                        memset(d, 0, sizeof(fat_dentry_t));
    724649                        memcpy(d->name, FAT_NAME_DOT, FAT_NAME_LEN);
     
    730655                d++;
    731656                if ((fat_classify_dentry(d) == FAT_DENTRY_LAST) ||
    732                     (str_cmp((char *) d->name, FAT_NAME_DOT_DOT) == 0)) {
     657                    (bcmp(d->name, FAT_NAME_DOT_DOT, FAT_NAME_LEN) == 0)) {
    733658                        memset(d, 0, sizeof(fat_dentry_t));
    734659                        memcpy(d->name, FAT_NAME_DOT_DOT, FAT_NAME_LEN);
    735660                        memcpy(d->ext, FAT_EXT_PAD, FAT_EXT_LEN);
    736661                        d->attr = FAT_ATTR_SUBDIR;
    737                         d->firstc = (parentp->firstc == FAT_CLST_ROOT) ?
    738                             host2uint16_t_le(FAT_CLST_RES0) :
     662                        d->firstc = (parentp->firstc == FAT_ROOT_CLST(bs)) ?
     663                            host2uint16_t_le(FAT_CLST_ROOTPAR) :
    739664                            host2uint16_t_le(parentp->firstc);
    740665                        /* TODO: initialize also the date/time members. */
     
    750675
    751676        childp->idx->pfc = parentp->firstc;
    752         childp->idx->pdi = i * DPS(bs) + j;
     677        childp->idx->pdi = di.pos;      /* di.pos holds absolute position of SFN entry */
    753678        fibril_mutex_unlock(&childp->idx->lock);
    754679
     
    770695        fat_node_t *parentp = FAT_NODE(pfn);
    771696        fat_node_t *childp = FAT_NODE(cfn);
    772         fat_bs_t *bs;
    773         fat_dentry_t *d;
    774         block_t *b;
    775697        bool has_children;
    776698        int rc;
     
    778700        if (!parentp)
    779701                return EBUSY;
    780        
     702
    781703        rc = fat_has_children(&has_children, cfn);
    782704        if (rc != EOK)
     
    789711        assert(childp->lnkcnt == 1);
    790712        fibril_mutex_lock(&childp->idx->lock);
    791         bs = block_bb_get(childp->idx->devmap_handle);
    792 
    793         rc = _fat_block_get(&b, bs, childp->idx->devmap_handle, childp->idx->pfc,
    794             NULL, (childp->idx->pdi * sizeof(fat_dentry_t)) / BPS(bs),
    795             BLOCK_FLAGS_NONE);
    796         if (rc != EOK)
     713       
     714        fat_directory_t di;
     715        rc = fat_directory_open(parentp,&di);
     716        if (rc != EOK)
    797717                goto error;
    798         d = (fat_dentry_t *)b->data +
    799             (childp->idx->pdi % (BPS(bs) / sizeof(fat_dentry_t)));
    800         /* mark the dentry as not-currently-used */
    801         d->name[0] = FAT_DENTRY_ERASED;
    802         b->dirty = true;                /* need to sync block */
    803         rc = block_put(b);
     718        rc = fat_directory_seek(&di, childp->idx->pdi);
     719        if (rc != EOK)
     720                goto error;
     721        rc = fat_directory_erase(&di);
     722        if (rc != EOK)
     723                goto error;
     724        rc = fat_directory_close(&di);
    804725        if (rc != EOK)
    805726                goto error;
     
    820741
    821742error:
    822         fibril_mutex_unlock(&parentp->idx->lock);
     743        (void) fat_directory_close(&di);
     744        fibril_mutex_unlock(&childp->idx->lock);
    823745        fibril_mutex_unlock(&childp->lock);
    824         fibril_mutex_unlock(&childp->idx->lock);
     746        fibril_mutex_unlock(&parentp->lock);
    825747        return rc;
    826748}
     
    839761                return EOK;
    840762        }
    841        
     763
    842764        fibril_mutex_lock(&nodep->idx->lock);
    843765        bs = block_bb_get(nodep->idx->devmap_handle);
     
    847769        for (i = 0; i < blocks; i++) {
    848770                fat_dentry_t *d;
    849        
     771
    850772                rc = fat_block_get(&b, bs, nodep, i, BLOCK_FLAGS_NONE);
    851773                if (rc != EOK) {
     
    875797                if (rc != EOK) {
    876798                        fibril_mutex_unlock(&nodep->idx->lock);
    877                         return rc;     
     799                        return rc;
    878800                }
    879801        }
     
    946868        fat_bs_t *bs;
    947869        int rc;
    948        
     870
    949871        /* Check for option enabling write through. */
    950872        if (str_cmp(opts, "wtcache") == 0)
     
    967889        /* get the buffer with the boot sector */
    968890        bs = block_bb_get(devmap_handle);
    969        
     891
    970892        if (BPS(bs) != BS_SIZE) {
    971893                block_fini(devmap_handle);
     
    1003925                return ENOMEM;
    1004926        }
     927
    1005928        fs_node_initialize(rfn);
    1006929        fat_node_t *rootp = (fat_node_t *)malloc(sizeof(fat_node_t));
     
    1027950
    1028951        rootp->type = FAT_DIRECTORY;
    1029         rootp->firstc = FAT_CLST_ROOT;
     952        rootp->firstc = FAT_ROOT_CLST(bs);
    1030953        rootp->refcnt = 1;
    1031954        rootp->lnkcnt = 0;      /* FS root is not linked */
    1032         rootp->size = RDE(bs) * sizeof(fat_dentry_t);
     955
     956        if (FAT_IS_FAT32(bs)) {
     957                uint32_t clusters;
     958                rc = fat_clusters_get(&clusters, bs, devmap_handle, rootp->firstc);
     959                if (rc != EOK) {
     960                        free(rfn);
     961                        free(rootp);
     962                        free(ridxp); /* TODO: Is it right way to free ridxp? */
     963                        (void) block_cache_fini(devmap_handle);
     964                        block_fini(devmap_handle);
     965                        fat_idx_fini_by_devmap_handle(devmap_handle);
     966                        async_answer_0(rid, ENOTSUP);
     967                        return;
     968                }
     969                rootp->size = BPS(bs) * SPC(bs) * clusters;
     970        } else
     971                rootp->size = RDE(bs) * sizeof(fat_dentry_t);
     972
    1033973        rootp->idx = ridxp;
    1034974        ridxp->nodep = rootp;
    1035975        rootp->bp = rfn;
    1036976        rfn->data = rootp;
    1037        
     977
    1038978        fibril_mutex_unlock(&ridxp->lock);
    1039979
     
    10641004                return EBUSY;
    10651005        }
    1066        
     1006
    10671007        /*
    10681008         * Put the root node and force it to the FAT free node list.
     
    11411081                }
    11421082        } else {
    1143                 unsigned bnum;
    11441083                aoff64_t spos = pos;
    1145                 char name[FAT_NAME_LEN + 1 + FAT_EXT_LEN + 1];
     1084                char name[FAT_LFN_NAME_SIZE];
    11461085                fat_dentry_t *d;
    11471086
     
    11501089                assert(BPS(bs) % sizeof(fat_dentry_t) == 0);
    11511090
    1152                 /*
    1153                  * Our strategy for readdir() is to use the position pointer as
    1154                  * an index into the array of all dentries. On entry, it points
    1155                  * to the first unread dentry. If we skip any dentries, we bump
    1156                  * the position pointer accordingly.
    1157                  */
    1158                 bnum = (pos * sizeof(fat_dentry_t)) / BPS(bs);
    1159                 while (bnum < nodep->size / BPS(bs)) {
    1160                         aoff64_t o;
    1161 
    1162                         rc = fat_block_get(&b, bs, nodep, bnum,
    1163                             BLOCK_FLAGS_NONE);
    1164                         if (rc != EOK)
    1165                                 goto err;
    1166                         for (o = pos % (BPS(bs) / sizeof(fat_dentry_t));
    1167                             o < BPS(bs) / sizeof(fat_dentry_t);
    1168                             o++, pos++) {
    1169                                 d = ((fat_dentry_t *)b->data) + o;
    1170                                 switch (fat_classify_dentry(d)) {
    1171                                 case FAT_DENTRY_SKIP:
    1172                                 case FAT_DENTRY_FREE:
    1173                                         continue;
    1174                                 case FAT_DENTRY_LAST:
    1175                                         rc = block_put(b);
    1176                                         if (rc != EOK)
    1177                                                 goto err;
    1178                                         goto miss;
    1179                                 default:
    1180                                 case FAT_DENTRY_VALID:
    1181                                         fat_dentry_name_get(d, name);
    1182                                         rc = block_put(b);
    1183                                         if (rc != EOK)
    1184                                                 goto err;
    1185                                         goto hit;
    1186                                 }
    1187                         }
    1188                         rc = block_put(b);
    1189                         if (rc != EOK)
    1190                                 goto err;
    1191                         bnum++;
    1192                 }
     1091                fat_directory_t di;
     1092                rc = fat_directory_open(nodep, &di);
     1093                if (rc != EOK) goto err;
     1094                rc = fat_directory_seek(&di, pos);
     1095                if (rc != EOK) {
     1096                        (void) fat_directory_close(&di);
     1097                        goto err;
     1098                }
     1099
     1100                rc = fat_directory_read(&di, name, &d);
     1101                if (rc == EOK) goto hit;
     1102                if (rc == ENOENT) goto miss;
     1103
     1104err:
     1105                (void) fat_node_put(fn);
     1106                async_answer_0(callid, rc);
     1107                return rc;
     1108
    11931109miss:
     1110                rc = fat_directory_close(&di);
     1111                if (rc!=EOK)
     1112                        goto err;
    11941113                rc = fat_node_put(fn);
    11951114                async_answer_0(callid, rc != EOK ? rc : ENOENT);
     
    11971116                return rc != EOK ? rc : ENOENT;
    11981117
    1199 err:
    1200                 (void) fat_node_put(fn);
    1201                 async_answer_0(callid, rc);
    1202                 return rc;
    1203 
    12041118hit:
     1119                pos = di.pos;
     1120                rc = fat_directory_close(&di);
     1121                if (rc!=EOK)
     1122                        goto err;
    12051123                (void) async_data_read_finalize(callid, name, str_size(name) + 1);
    1206                 bytes = (pos - spos) + 1;
     1124                bytes = (pos - spos)+1;
    12071125        }
    12081126
     
    12241142        int flags = BLOCK_FLAGS_NONE;
    12251143        int rc;
    1226        
     1144
    12271145        rc = fat_node_get(&fn, devmap_handle, index);
    12281146        if (rc != EOK)
     
    12311149                return ENOENT;
    12321150        nodep = FAT_NODE(fn);
    1233        
     1151
    12341152        ipc_callid_t callid;
    12351153        size_t len;
     
    12471165         * but this one greatly simplifies fat_write(). Note that we can afford
    12481166         * to do this because the client must be ready to handle the return
    1249          * value signalizing a smaller number of bytes written. 
    1250          */ 
     1167         * value signalizing a smaller number of bytes written.
     1168         */
    12511169        bytes = min(len, BPS(bs) - pos % BPS(bs));
    12521170        if (bytes == BPS(bs))
    12531171                flags |= BLOCK_FLAGS_NOREAD;
    1254        
     1172
    12551173        boundary = ROUND_UP(nodep->size, BPC(bs));
    12561174        if (pos < boundary) {
     
    12951213                 */
    12961214                unsigned nclsts;
    1297                 fat_cluster_t mcl, lcl; 
    1298  
     1215                fat_cluster_t mcl, lcl;
     1216
    12991217                nclsts = (ROUND_UP(pos + bytes, BPC(bs)) - boundary) / BPC(bs);
    13001218                /* create an independent chain of nclsts clusters in all FATs */
     
    13801298                nodep->size = size;
    13811299                nodep->dirty = true;            /* need to sync node */
    1382                 rc = EOK;       
     1300                rc = EOK;
    13831301        } else {
    13841302                /*
     
    14011319                nodep->size = size;
    14021320                nodep->dirty = true;            /* need to sync node */
    1403                 rc = EOK;       
     1321                rc = EOK;
    14041322        }
    14051323out:
     
    14441362        if (!fn)
    14451363                return ENOENT;
    1446        
     1364
    14471365        fat_node_t *nodep = FAT_NODE(fn);
    1448        
     1366
    14491367        nodep->dirty = true;
    14501368        rc = fat_node_sync(nodep);
    1451        
     1369
    14521370        fat_node_put(fn);
    14531371        return rc;
Note: See TracChangeset for help on using the changeset viewer.