root/trunk/src/libopensc/muscle-filesystem.c

Revision 3177, 6.0 KB (checked in by aj, 18 months ago)

fix compiler/sparse warnings.

Line 
1/*
2 * muscle-filesystem.c: Support for MuscleCard Applet from musclecard.com
3 *
4 * Copyright (C) 2006, Identity Alliance, Thomas Harning <support@identityalliance.com>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 */
20
21#include "muscle-filesystem.h"
22#include <opensc/errors.h>
23#include <memory.h>
24#include <stdio.h>
25#include <assert.h>
26
27#define MSCFS_NO_MEMORY         SC_ERROR_OUT_OF_MEMORY
28#define MSCFS_INVALID_ARGS      SC_ERROR_INVALID_ARGUMENTS
29#define MSCFS_FILE_NOT_FOUND    SC_ERROR_FILE_NOT_FOUND
30#define MSCFS_CACHE_INCREMENT 128
31
32static msc_id rootId = { { 0x3F, 0x00, 0x3F, 0x00 } };
33
34static const u8* ignoredFiles[] = {
35        (const u8*)"l0\0\0",
36        (const u8*)"L0\0\0",
37        NULL
38};
39
40mscfs_t *mscfs_new(void) {
41        mscfs_t *fs = (mscfs_t*)malloc(sizeof(mscfs_t));
42        memset(fs, 0, sizeof(mscfs_t));
43        memcpy(fs->currentPath, "\x3F\x00", 2);
44        return fs;
45}
46
47void mscfs_free(mscfs_t *fs) {
48        mscfs_clear_cache(fs);
49}
50
51void mscfs_clear_cache(mscfs_t* fs) {
52        if(!fs->cache.array) {
53                return;
54        }
55        free(fs->cache.array);
56        fs->cache.array = NULL;
57        fs->cache.totalSize = 0;
58        fs->cache.size = 0;
59}
60
61static int mscfs_is_ignored(mscfs_t* fs, msc_id objectId)
62{
63        int ignored = 0;
64        const u8** ptr = ignoredFiles;
65        while(ptr && *ptr && !ignored) {
66                if(0 == memcmp(objectId.id, *ptr, 4))
67                        ignored = 1;
68                ptr++;
69        }
70        return ignored;
71}
72
73int mscfs_push_file(mscfs_t* fs, mscfs_file_t *file)
74{
75        mscfs_cache_t *cache = &fs->cache;
76        if(!cache->array || cache->size == cache->totalSize) {
77                int length = cache->totalSize + MSCFS_CACHE_INCREMENT;
78                mscfs_file_t *oldArray;
79                cache->totalSize = length;
80                oldArray = cache->array;
81                cache->array = malloc(sizeof(mscfs_file_t) * length);
82                if(!cache->array)
83                        return MSCFS_NO_MEMORY;
84                if(oldArray) {
85                        memcpy(cache->array, oldArray, sizeof(mscfs_file_t) * cache->size);
86                        free(oldArray);
87                }
88        }
89        cache->array[cache->size] = *file;
90        cache->size++;
91        return 0;
92}
93
94int mscfs_update_cache(mscfs_t* fs) {
95        mscfs_file_t file;
96        int r;
97        mscfs_clear_cache(fs);
98        r = fs->listFile(&file, 1, fs->udata);
99        if(r == 0)
100                return 0;
101        else if(r < 0)
102                return r;
103        while(1) {
104                if(!mscfs_is_ignored(fs, file.objectId)) {
105                        /* Check if its a directory in the root */
106                        u8* oid = file.objectId.id;
107                        if(oid[2] == 0 && oid[3] == 0) {
108                                oid[2] = oid[0];
109                                oid[3] = oid[1];
110                                oid[0] = 0x3F;
111                                oid[1] = 0x00;
112                                file.ef = 0;
113                        } else  {
114                                file.ef = 1; /* File is a working elementary file */
115                        }
116                       
117                        mscfs_push_file(fs, &file);
118                }
119                r = fs->listFile(&file, 0, fs->udata);
120                if(r == 0)
121                        break;
122                else if(r < 0)
123                        return r;
124        }
125        return fs->cache.size;
126}
127
128void mscfs_check_cache(mscfs_t* fs)
129{
130        if(!fs->cache.array) {
131                mscfs_update_cache(fs);
132        }
133}
134
135int mscfs_lookup_path(mscfs_t* fs, const u8 *path, int pathlen, msc_id* objectId, int isDirectory)
136{
137        u8* oid = objectId->id;
138        if ((pathlen & 1) != 0) /* not divisble by 2 */
139                return MSCFS_INVALID_ARGS;
140        if(isDirectory) {
141                /* Directory must be right next to root */
142                if((0 == memcmp(path, "\x3F\x00", 2) && pathlen == 4)
143                || (0 == memcmp(fs->currentPath, "\x3F\x00", 2) && pathlen == 2)) {
144                        oid[0] = path[pathlen - 2];
145                        oid[1] = path[pathlen - 1];
146                        oid[2] = oid[3] = 0;
147                } else {
148                        return MSCFS_INVALID_ARGS;
149                }
150        }
151        oid[0] = fs->currentPath[0];
152        oid[1] = fs->currentPath[1];
153        /* Chop off the root in the path */
154        if(pathlen > 2 && memcmp(path, "\x3F\x00", 2) == 0) {
155                path += 2;
156                pathlen -= 2;
157                oid[0] = 0x3F;
158                oid[1] = 0x00;
159        }
160        /* Limit to a single directory */
161        if(pathlen > 4)
162                return MSCFS_INVALID_ARGS;
163        /* Reset to root */
164        if(0 == memcmp(path, "\x3F\x00", 2) && pathlen == 2) {
165                oid[0] = oid[2] = path[0];
166                oid[1] = oid[3] = path[1];
167        } else if(pathlen == 2) { /* Path preserved for current-path */
168                oid[2] = path[0];
169                oid[3] = path[1];
170        } else if(pathlen == 4) {
171                oid[0] = path[0];
172                oid[1] = path[1];
173                oid[2] = path[2];
174                oid[3] = path[3];
175        }
176       
177        return 0;
178}
179
180int mscfs_lookup_local(mscfs_t* fs, const int id, msc_id* objectId)
181{
182        u8* oid = objectId->id;
183        oid[0] = fs->currentPath[0];
184        oid[1] = fs->currentPath[1];
185        oid[2] = (id >> 8) & 0xFF;
186        oid[3] = id & 0xFF;
187        return 0;
188}
189
190/* -1 any, 0 DF, 1 EF */
191int mscfs_check_selection(mscfs_t *fs, int requiredItem)
192{
193        if(fs->currentPath[0] == 0 && fs->currentPath[1] == 0)
194                return MSCFS_INVALID_ARGS;
195        if(requiredItem == 1 && fs->currentFile[0] == 0 && fs->currentFile[1] == 0)
196                return MSCFS_INVALID_ARGS;
197        return 0;
198}
199
200int mscfs_loadFileInfo(mscfs_t* fs, const u8 *path, int pathlen, mscfs_file_t **file_data, int* idx)
201{
202        msc_id fullPath;
203        int x;
204        assert(fs != NULL && path != NULL && file_data != NULL);
205        mscfs_lookup_path(fs, path, pathlen, &fullPath, 0);
206       
207        /* Obtain file information while checking if it exists */
208        mscfs_check_cache(fs);
209        if(idx) *idx = -1;
210        for(x = 0; x < fs->cache.size; x++) {
211                msc_id objectId;
212                *file_data = &fs->cache.array[x];
213                objectId = (*file_data)->objectId;
214                if(0 == memcmp(objectId.id, fullPath.id, 4)) {
215                        if(idx) *idx = x;
216                        break;
217                }
218                *file_data = NULL;
219        }
220        if(*file_data == NULL && (0 == memcmp("\x3F\x00\x00\x00", fullPath.id, 4) || 0 == memcmp("\x3F\x00\x3F\x00", fullPath.id, 4 ))) {
221                static mscfs_file_t ROOT_FILE;
222                ROOT_FILE.ef = 0;
223                ROOT_FILE.size = 0;
224                /* Faked Root ID */
225                ROOT_FILE.objectId = rootId;
226               
227                ROOT_FILE.read = 0;
228                ROOT_FILE.write = 0x02; /* User Pin access */
229                ROOT_FILE.delete = 0x02;
230               
231                *file_data = &ROOT_FILE;
232                if(idx) *idx = -2;
233        } else if(*file_data == NULL) {
234                return MSCFS_FILE_NOT_FOUND;
235        }
236       
237        return 0;
238}
Note: See TracBrowser for help on using the browser.