~vojtech-horky/helenos/helenos-qemu

« back to all changes in this revision

Viewing changes to uspace/srv/fs/cdfs/cdfs_ops.c

  • Committer: Vojtech Horky
  • Date: 2017-06-14 06:22:31 UTC
  • mfrom: (2103.1.569 HelenOS.mainline)
  • Revision ID: vojtechhorky@users.sourceforge.net-20170614062231-q4ui9pyxp0gs2hrl
MergeĀ mainlineĀ changes

Show diffs side-by-side

added added

removed removed

Lines of Context:
207
207
        link_t link;              /**< Link to list of all instances */
208
208
        service_id_t service_id;  /**< Service ID of block device */
209
209
        cdfs_enc_t enc;           /**< Filesystem string encoding */
 
210
        char *vol_ident;          /**< Volume identifier */
210
211
} cdfs_t;
211
212
 
212
213
typedef struct {
482
483
 *
483
484
 * @param data  File name buffer
484
485
 * @param dsize Fine name buffer size
 
486
 * @param enc   Encoding
485
487
 * @param dtype Directory entry type
486
488
 * @return      Decoded file name (allocated string)
487
489
 */
516
518
        return name;
517
519
}
518
520
 
 
521
/** Decode volume identifier.
 
522
 *
 
523
 * @param data  Volume identifier buffer
 
524
 * @param dsize Volume identifier buffer size
 
525
 * @param enc   Encoding
 
526
 * @return      Decoded volume identifier (allocated string)
 
527
 */
 
528
static char *cdfs_decode_vol_ident(void *data, size_t dsize, cdfs_enc_t enc)
 
529
{
 
530
        char *ident;
 
531
        size_t i;
 
532
        
 
533
        ident = cdfs_decode_str(data, dsize, enc);
 
534
        if (ident == NULL)
 
535
                return NULL;
 
536
        
 
537
        /* Trim trailing spaces */
 
538
        i = str_size(ident);
 
539
        while (i > 0 && ident[i - 1] == ' ')
 
540
                --i;
 
541
        ident[i] = '\0';
 
542
        
 
543
        return ident;
 
544
}
 
545
 
519
546
static bool cdfs_readdir(cdfs_t *fs, fs_node_t *fs_node)
520
547
{
521
548
        cdfs_node_t *node = CDFS_NODE(fs_node);
840
867
 * @param altroot       First filesystem block
841
868
 * @param rlba          Place to store LBA of root dir
842
869
 * @param rsize         Place to store size of root dir
 
870
 * @param vol_ident     Place to store pointer to volume identifier
843
871
 * @return              EOK if found, ENOENT if not
844
872
 */
845
873
static int cdfs_find_joliet_svd(service_id_t sid, cdfs_lba_t altroot,
846
 
    uint32_t *rlba, uint32_t *rsize)
 
874
    uint32_t *rlba, uint32_t *rsize, char **vol_ident)
847
875
{
848
876
        cdfs_lba_t bi;
849
877
 
898
926
                        continue;
899
927
                *rlba = uint32_lb(vol_desc->data.prisec.root_dir.lba);
900
928
                *rsize = uint32_lb(vol_desc->data.prisec.root_dir.size);
 
929
 
 
930
                *vol_ident = cdfs_decode_vol_ident(vol_desc->data.prisec.ident,
 
931
                    32, enc_ucs2);
 
932
 
901
933
                block_put(block);
902
934
                return EOK;
903
935
        }
905
937
        return ENOENT;
906
938
}
907
939
 
908
 
static bool iso_readfs(cdfs_t *fs, fs_node_t *rfn,
909
 
    cdfs_lba_t altroot)
 
940
/** Read the volume descriptors. */
 
941
static bool iso_read_vol_desc(service_id_t sid, cdfs_lba_t altroot,
 
942
    uint32_t *rlba, uint32_t *rsize, cdfs_enc_t *enc, char **vol_ident)
910
943
{
911
944
        /* First 16 blocks of isofs are empty */
912
945
        block_t *block;
913
 
        int rc = block_get(&block, fs->service_id, altroot + 16, BLOCK_FLAGS_NONE);
 
946
        int rc = block_get(&block, sid, altroot + 16, BLOCK_FLAGS_NONE);
914
947
        if (rc != EOK)
915
948
                return false;
916
949
        
955
988
        
956
989
        // TODO: implement path table support
957
990
        
958
 
        cdfs_node_t *node = CDFS_NODE(rfn);
959
 
        
960
991
        /* Search for Joliet SVD */
961
992
        
962
993
        uint32_t jrlba;
963
994
        uint32_t jrsize;
964
995
        
965
 
        rc = cdfs_find_joliet_svd(fs->service_id, altroot, &jrlba, &jrsize);
 
996
        rc = cdfs_find_joliet_svd(sid, altroot, &jrlba, &jrsize, vol_ident);
966
997
        if (rc == EOK) {
967
998
                /* Found */
968
 
                node->lba = jrlba;
969
 
                node->size = jrsize;
970
 
                fs->enc = enc_ucs2;
 
999
                *rlba = jrlba;
 
1000
                *rsize = jrsize;
 
1001
                *enc = enc_ucs2;
971
1002
        } else {
972
 
                node->lba = uint32_lb(vol_desc->data.prisec.root_dir.lba);
973
 
                node->size = uint32_lb(vol_desc->data.prisec.root_dir.size);
974
 
                fs->enc = enc_ascii;
975
 
        }
976
 
        
977
 
        if (!cdfs_readdir(fs, rfn)) {
978
 
                block_put(block);
979
 
                return false;
 
1003
                *rlba = uint32_lb(vol_desc->data.prisec.root_dir.lba);
 
1004
                *rsize = uint32_lb(vol_desc->data.prisec.root_dir.size);
 
1005
                *enc = enc_ascii;
 
1006
                *vol_ident = cdfs_decode_vol_ident(vol_desc->data.prisec.ident,
 
1007
                    32, enc_ascii);
980
1008
        }
981
1009
        
982
1010
        block_put(block);
983
1011
        return true;
984
1012
}
985
1013
 
 
1014
static bool iso_readfs(cdfs_t *fs, fs_node_t *rfn,
 
1015
    cdfs_lba_t altroot)
 
1016
{
 
1017
        cdfs_node_t *node = CDFS_NODE(rfn);
 
1018
        
 
1019
        if (!iso_read_vol_desc(fs->service_id, altroot, &node->lba,
 
1020
            &node->size, &fs->enc, &fs->vol_ident))
 
1021
                return false;
 
1022
        
 
1023
        return cdfs_readdir(fs, rfn);
 
1024
}
 
1025
 
986
1026
/* Mount a session with session start offset
987
1027
 *
988
1028
 */
1020
1060
        return NULL;
1021
1061
}
1022
1062
 
 
1063
static int cdfs_fsprobe(service_id_t service_id, vfs_fs_probe_info_t *info)
 
1064
{
 
1065
        char *vol_ident;
 
1066
 
 
1067
        /* Initialize the block layer */
 
1068
        int rc = block_init(service_id, BLOCK_SIZE);
 
1069
        if (rc != EOK)
 
1070
                return rc;
 
1071
        
 
1072
        cdfs_lba_t altroot = 0;
 
1073
        
 
1074
        /*
 
1075
         * Read TOC multisession information and get the start address
 
1076
         * of the first track in the last session
 
1077
         */
 
1078
        scsi_toc_multisess_data_t toc;
 
1079
 
 
1080
        rc = block_read_toc(service_id, 1, &toc, sizeof(toc));
 
1081
        if (rc == EOK && (uint16_t_be2host(toc.toc_len) == 10))
 
1082
                altroot = uint32_t_be2host(toc.ftrack_lsess.start_addr);
 
1083
        
 
1084
        /* Initialize the block cache */
 
1085
        rc = block_cache_init(service_id, BLOCK_SIZE, 0, CACHE_MODE_WT);
 
1086
        if (rc != EOK) {
 
1087
                block_fini(service_id);
 
1088
                return rc;
 
1089
        }
 
1090
        
 
1091
        /* Check if this device is not already mounted */
 
1092
        fs_node_t *rootfn;
 
1093
        rc = cdfs_root_get(&rootfn, service_id);
 
1094
        if ((rc == EOK) && (rootfn)) {
 
1095
                cdfs_node_put(rootfn);
 
1096
                block_cache_fini(service_id);
 
1097
                block_fini(service_id);
 
1098
                return EOK;
 
1099
        }
 
1100
        
 
1101
        /* Read volume descriptors */
 
1102
        uint32_t rlba;
 
1103
        uint32_t rsize;
 
1104
        cdfs_enc_t enc;
 
1105
        if (!iso_read_vol_desc(service_id, altroot, &rlba, &rsize, &enc,
 
1106
            &vol_ident)) {
 
1107
                block_cache_fini(service_id);
 
1108
                block_fini(service_id);
 
1109
                return EIO;
 
1110
        }
 
1111
        
 
1112
        str_cpy(info->label, FS_LABEL_MAXLEN + 1, vol_ident);
 
1113
        free(vol_ident);
 
1114
        
 
1115
        block_cache_fini(service_id);
 
1116
        block_fini(service_id);
 
1117
        return EOK;
 
1118
}
 
1119
 
1023
1120
static int cdfs_mounted(service_id_t service_id, const char *opts,
1024
 
    fs_index_t *index, aoff64_t *size, unsigned int *lnkcnt)
 
1121
    fs_index_t *index, aoff64_t *size)
1025
1122
{
1026
1123
        /* Initialize the block layer */
1027
1124
        int rc = block_init(service_id, BLOCK_SIZE);
1078
1175
        cdfs_node_t *root = CDFS_NODE(rootfn);
1079
1176
        *index = root->index;
1080
1177
        *size = root->size;
1081
 
        *lnkcnt = root->lnkcnt;
1082
1178
        
1083
1179
        return EOK;
1084
1180
}
1101
1197
        hash_table_apply(&nodes, rm_service_id_nodes, &fs->service_id);
1102
1198
        block_cache_fini(fs->service_id);
1103
1199
        block_fini(fs->service_id);
 
1200
        free(fs->vol_ident);
1104
1201
        free(fs);
1105
1202
}
1106
1203
 
1296
1393
}
1297
1394
 
1298
1395
vfs_out_ops_t cdfs_ops = {
 
1396
        .fsprobe = cdfs_fsprobe,
1299
1397
        .mounted = cdfs_mounted,
1300
1398
        .unmounted = cdfs_unmounted,
1301
1399
        .read = cdfs_read,