Changeset 39b0a51 in mainline for uspace/srv/fs/fat/fat_ops.c


Ignore:
Timestamp:
2017-06-28T16:05:37Z (7 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
ee50130
Parents:
30eab78
Message:

FAT decoding of volume label.

File:
1 edited

Legend:

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

    r30eab78 r39b0a51  
    785785                        case FAT_DENTRY_SKIP:
    786786                        case FAT_DENTRY_FREE:
     787                        case FAT_DENTRY_VOLLABEL:
    787788                                continue;
    788789                        case FAT_DENTRY_LAST:
     
    909910};
    910911
    911 /*
    912  * FAT VFS_OUT operations.
    913  */
    914 
    915 static int fat_fsprobe(service_id_t service_id, vfs_fs_probe_info_t *info)
     912static int fat_fs_open(service_id_t service_id, enum cache_mode cmode,
     913    fs_node_t **rrfn, fat_idx_t **rridxp)
    916914{
    917915        fat_bs_t *bs;
     
    939937
    940938        /* Initialize the block cache */
    941         rc = block_cache_init(service_id, BPS(bs), 0 /* XXX */, CACHE_MODE_WB);
     939        rc = block_cache_init(service_id, BPS(bs), 0 /* XXX */, cmode);
    942940        if (rc != EOK) {
    943941                block_fini(service_id);
     
    947945        /* Do some simple sanity checks on the file system. */
    948946        rc = fat_sanity_check(bs, service_id);
    949 
     947        if (rc != EOK) {
     948                (void) block_cache_fini(service_id);
     949                block_fini(service_id);
     950                return rc;
     951        }
     952
     953        rc = fat_idx_init_by_service_id(service_id);
     954        if (rc != EOK) {
     955                (void) block_cache_fini(service_id);
     956                block_fini(service_id);
     957                return rc;
     958        }
     959
     960        /* Initialize the root node. */
     961        fs_node_t *rfn = (fs_node_t *)malloc(sizeof(fs_node_t));
     962        if (!rfn) {
     963                (void) block_cache_fini(service_id);
     964                block_fini(service_id);
     965                fat_idx_fini_by_service_id(service_id);
     966                return ENOMEM;
     967        }
     968
     969        fs_node_initialize(rfn);
     970        fat_node_t *rootp = (fat_node_t *)malloc(sizeof(fat_node_t));
     971        if (!rootp) {
     972                free(rfn);
     973                (void) block_cache_fini(service_id);
     974                block_fini(service_id);
     975                fat_idx_fini_by_service_id(service_id);
     976                return ENOMEM;
     977        }
     978        fat_node_initialize(rootp);
     979
     980        fat_idx_t *ridxp = fat_idx_get_by_pos(service_id, FAT_CLST_ROOTPAR, 0);
     981        if (!ridxp) {
     982                free(rfn);
     983                free(rootp);
     984                (void) block_cache_fini(service_id);
     985                block_fini(service_id);
     986                fat_idx_fini_by_service_id(service_id);
     987                return ENOMEM;
     988        }
     989        assert(ridxp->index == 0);
     990        /* ridxp->lock held */
     991
     992        rootp->type = FAT_DIRECTORY;
     993        rootp->firstc = FAT_ROOT_CLST(bs);
     994        rootp->refcnt = 1;
     995        rootp->lnkcnt = 0;      /* FS root is not linked */
     996
     997        if (FAT_IS_FAT32(bs)) {
     998                uint32_t clusters;
     999                rc = fat_clusters_get(&clusters, bs, service_id, rootp->firstc);
     1000                if (rc != EOK) {
     1001                        fibril_mutex_unlock(&ridxp->lock);
     1002                        free(rfn);
     1003                        free(rootp);
     1004                        (void) block_cache_fini(service_id);
     1005                        block_fini(service_id);
     1006                        fat_idx_fini_by_service_id(service_id);
     1007                        return ENOTSUP;
     1008                }
     1009                rootp->size = BPS(bs) * SPC(bs) * clusters;
     1010        } else
     1011                rootp->size = RDE(bs) * sizeof(fat_dentry_t);
     1012
     1013        rootp->idx = ridxp;
     1014        ridxp->nodep = rootp;
     1015        rootp->bp = rfn;
     1016        rfn->data = rootp;
     1017
     1018        fibril_mutex_unlock(&ridxp->lock);
     1019
     1020        *rrfn = rfn;
     1021        *rridxp = ridxp;
     1022
     1023        return EOK;
     1024}
     1025
     1026static void fat_fs_close(service_id_t service_id, fs_node_t *rfn)
     1027{
     1028        free(rfn->data);
     1029        free(rfn);
    9501030        (void) block_cache_fini(service_id);
    9511031        block_fini(service_id);
    952 
    953         return rc;
     1032        fat_idx_fini_by_service_id(service_id);
     1033}
     1034
     1035/*
     1036 * FAT VFS_OUT operations.
     1037 */
     1038
     1039static int fat_fsprobe(service_id_t service_id, vfs_fs_probe_info_t *info)
     1040{
     1041        fat_bs_t *bs;
     1042        fat_idx_t *ridxp;
     1043        fs_node_t *rfn;
     1044        fat_node_t *nodep;
     1045        fat_directory_t di;
     1046        char label[FAT_VOLLABEL_LEN + 1];
     1047        int i;
     1048        int rc;
     1049
     1050        rc = fat_fs_open(service_id, CACHE_MODE_WT, &rfn, &ridxp);
     1051        if (rc != EOK)
     1052                return rc;
     1053
     1054        nodep = FAT_NODE(rfn);
     1055
     1056        rc = fat_directory_open(nodep, &di);
     1057        if (rc != EOK)
     1058                return rc;
     1059
     1060        rc = fat_directory_vollabel_get(&di, label);
     1061        if (rc != EOK) {
     1062                /* No label in root directory. Read label from the BS */
     1063                bs = block_bb_get(service_id);
     1064                i = FAT_VOLLABEL_LEN;
     1065                while (i > 0 && bs->label[i - 1] == FAT_PAD)
     1066                        --i;
     1067
     1068                /* XXX Deal with non-ASCII characters */
     1069                memcpy(label, bs->label, i);
     1070                label[i] = '\0';
     1071        }
     1072
     1073        str_cpy(info->label, FS_LABEL_MAXLEN + 1, label);
     1074
     1075        fat_directory_close(&di);
     1076        fat_fs_close(service_id, rfn);
     1077
     1078        return EOK;
    9541079}
    9551080
     
    9591084{
    9601085        enum cache_mode cmode = CACHE_MODE_WB;
    961         fat_bs_t *bs;
    9621086        fat_instance_t *instance;
     1087        fat_idx_t *ridxp;
     1088        fs_node_t *rfn;
    9631089        int rc;
    9641090
     
    9781104        }
    9791105
    980         /* initialize libblock */
    981         rc = block_init(service_id, BS_SIZE);
     1106        rc = fat_fs_open(service_id, cmode, &rfn, &ridxp);
    9821107        if (rc != EOK) {
    9831108                free(instance);
     
    9851110        }
    9861111
    987         /* prepare the boot block */
    988         rc = block_bb_read(service_id, BS_BLOCK);
    989         if (rc != EOK) {
    990                 free(instance);
    991                 block_fini(service_id);
    992                 return rc;
    993         }
    994 
    995         /* get the buffer with the boot sector */
    996         bs = block_bb_get(service_id);
    997        
    998         if (BPS(bs) != BS_SIZE) {
    999                 free(instance);
    1000                 block_fini(service_id);
    1001                 return ENOTSUP;
    1002         }
    1003 
    1004         /* Initialize the block cache */
    1005         rc = block_cache_init(service_id, BPS(bs), 0 /* XXX */, cmode);
    1006         if (rc != EOK) {
    1007                 free(instance);
    1008                 block_fini(service_id);
    1009                 return rc;
    1010         }
    1011 
    1012         /* Do some simple sanity checks on the file system. */
    1013         rc = fat_sanity_check(bs, service_id);
    1014         if (rc != EOK) {
    1015                 free(instance);
    1016                 (void) block_cache_fini(service_id);
    1017                 block_fini(service_id);
    1018                 return rc;
    1019         }
    1020 
    1021         rc = fat_idx_init_by_service_id(service_id);
    1022         if (rc != EOK) {
    1023                 free(instance);
    1024                 (void) block_cache_fini(service_id);
    1025                 block_fini(service_id);
    1026                 return rc;
    1027         }
    1028 
    1029         /* Initialize the root node. */
    1030         fs_node_t *rfn = (fs_node_t *)malloc(sizeof(fs_node_t));
    1031         if (!rfn) {
    1032                 free(instance);
    1033                 (void) block_cache_fini(service_id);
    1034                 block_fini(service_id);
    1035                 fat_idx_fini_by_service_id(service_id);
    1036                 return ENOMEM;
    1037         }
    1038 
    1039         fs_node_initialize(rfn);
    1040         fat_node_t *rootp = (fat_node_t *)malloc(sizeof(fat_node_t));
    1041         if (!rootp) {
    1042                 free(instance);
    1043                 free(rfn);
    1044                 (void) block_cache_fini(service_id);
    1045                 block_fini(service_id);
    1046                 fat_idx_fini_by_service_id(service_id);
    1047                 return ENOMEM;
    1048         }
    1049         fat_node_initialize(rootp);
    1050 
    1051         fat_idx_t *ridxp = fat_idx_get_by_pos(service_id, FAT_CLST_ROOTPAR, 0);
    1052         if (!ridxp) {
    1053                 free(instance);
    1054                 free(rfn);
    1055                 free(rootp);
    1056                 (void) block_cache_fini(service_id);
    1057                 block_fini(service_id);
    1058                 fat_idx_fini_by_service_id(service_id);
    1059                 return ENOMEM;
    1060         }
    1061         assert(ridxp->index == 0);
    1062         /* ridxp->lock held */
    1063 
    1064         rootp->type = FAT_DIRECTORY;
    1065         rootp->firstc = FAT_ROOT_CLST(bs);
    1066         rootp->refcnt = 1;
    1067         rootp->lnkcnt = 0;      /* FS root is not linked */
    1068 
    1069         if (FAT_IS_FAT32(bs)) {
    1070                 uint32_t clusters;
    1071                 rc = fat_clusters_get(&clusters, bs, service_id, rootp->firstc);
    1072                 if (rc != EOK) {
    1073                         fibril_mutex_unlock(&ridxp->lock);
    1074                         free(instance);
    1075                         free(rfn);
    1076                         free(rootp);
    1077                         (void) block_cache_fini(service_id);
    1078                         block_fini(service_id);
    1079                         fat_idx_fini_by_service_id(service_id);
    1080                         return ENOTSUP;
    1081                 }
    1082                 rootp->size = BPS(bs) * SPC(bs) * clusters;
    1083         } else
    1084                 rootp->size = RDE(bs) * sizeof(fat_dentry_t);
     1112        fibril_mutex_lock(&ridxp->lock);
    10851113
    10861114        rc = fs_instance_create(service_id, instance);
    10871115        if (rc != EOK) {
    10881116                fibril_mutex_unlock(&ridxp->lock);
     1117                fat_fs_close(service_id, rfn);
    10891118                free(instance);
    1090                 free(rfn);
    1091                 free(rootp);
    1092                 (void) block_cache_fini(service_id);
    1093                 block_fini(service_id);
    1094                 fat_idx_fini_by_service_id(service_id);
    1095                 return rc;
    1096         }
    1097 
    1098         rootp->idx = ridxp;
    1099         ridxp->nodep = rootp;
    1100         rootp->bp = rfn;
    1101         rfn->data = rootp;
     1119                return rc;
     1120        }
    11021121
    11031122        fibril_mutex_unlock(&ridxp->lock);
    11041123
    11051124        *index = ridxp->index;
    1106         *size = rootp->size;
     1125        *size = FAT_NODE(rfn)->size;
    11071126
    11081127        return EOK;
     
    11741193         */
    11751194        (void) fat_node_put(fn);
    1176         (void) fat_node_put(fn);
    11771195
    11781196        /*
     
    11821200         */
    11831201        (void) fat_node_fini_by_service_id(service_id);
    1184         fat_idx_fini_by_service_id(service_id);
    1185         (void) block_cache_fini(service_id);
    1186         block_fini(service_id);
     1202        fat_fs_close(service_id, fn);
    11871203
    11881204        void *data;
Note: See TracChangeset for help on using the changeset viewer.