root/trunk/src/libopensc/pkcs15-cache.c

Revision 3084, 4.1 kB (checked in by aj, 2 years ago)

convert to utf-8.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2 * pkcs15-cache.c: PKCS #15 file caching functions
3 *
4 * Copyright (C) 2001, 2002  Juha YrjölÀ <juha.yrjola@iki.fi>
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 "internal.h"
22#include "pkcs15.h"
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#ifdef HAVE_UNISTD_H
27#include <unistd.h>
28#endif
29#include <sys/stat.h>
30#include <limits.h>
31#include <errno.h>
32#include <assert.h>
33
34static int generate_cache_filename(struct sc_pkcs15_card *p15card,
35                                   const sc_path_t *path,
36                                   char *buf, size_t bufsize)
37{
38        char dir[PATH_MAX];
39        char pathname[SC_MAX_PATH_SIZE*2+1];
40        int  r;
41        const u8 *pathptr;
42        size_t i, pathlen;
43
44        if (path->type != SC_PATH_TYPE_PATH)
45                return SC_ERROR_INVALID_ARGUMENTS;
46        assert(path->len <= SC_MAX_PATH_SIZE);
47        r = sc_get_cache_dir(p15card->card->ctx, dir, sizeof(dir));
48        if (r)
49                return r;
50        pathptr = path->value;
51        pathlen = path->len;
52        if (pathlen > 2 && memcmp(pathptr, "\x3F\x00", 2) == 0) {
53                pathptr += 2;
54                pathlen -= 2;
55        }
56        for (i = 0; i < pathlen; i++)
57                sprintf(pathname + 2*i, "%02X", pathptr[i]);
58        if (p15card->serial_number != NULL) {
59                if (p15card->last_update != NULL)
60                        r = snprintf(buf, bufsize, "%s/%s_%s_%s", dir,
61                             p15card->serial_number, p15card->last_update,
62                             pathname);
63                else
64                        r = snprintf(buf, bufsize, "%s/%s_DATE_%s", dir,
65                             p15card->serial_number, pathname);
66                if (r < 0)
67                        return SC_ERROR_BUFFER_TOO_SMALL;
68        } else
69                return SC_ERROR_INVALID_ARGUMENTS;
70        return SC_SUCCESS;
71}
72
73int sc_pkcs15_read_cached_file(struct sc_pkcs15_card *p15card,
74                               const sc_path_t *path,
75                               u8 **buf, size_t *bufsize)
76{
77        char fname[PATH_MAX];
78        int r;
79        FILE *f;
80        size_t count, offset, got;
81        struct stat stbuf;
82        u8 *data = NULL;
83
84        r = generate_cache_filename(p15card, path, fname, sizeof(fname));
85        if (r != 0)
86                return r;
87        r = stat(fname, &stbuf);
88        if (r)
89                return SC_ERROR_FILE_NOT_FOUND;
90        if (path->count < 0) {
91                count = stbuf.st_size;
92                offset = 0;
93        } else {
94                count = path->count;
95                offset = path->index;
96                if (offset + count > (size_t)stbuf.st_size)
97                        return SC_ERROR_FILE_NOT_FOUND; /* cache file bad? */
98        }
99        if (*buf == NULL) {
100                data = (u8 *) malloc((size_t)stbuf.st_size);
101                if (data == NULL)
102                        return SC_ERROR_OUT_OF_MEMORY;
103        } else
104                if (count > *bufsize)
105                        return SC_ERROR_BUFFER_TOO_SMALL;
106        f = fopen(fname, "rb");
107        if (f == NULL) {
108                if (data)
109                        free(data);
110                return SC_ERROR_FILE_NOT_FOUND;
111        }
112        if (offset)
113                fseek(f, (long)offset, SEEK_SET);
114        if (data)
115                *buf = data;
116        got = fread(*buf, 1, count, f);
117        fclose(f);
118        if (got != count) {
119                if (data)
120                        free(data);
121                return SC_ERROR_BUFFER_TOO_SMALL;
122        }
123        *bufsize = count;
124        if (data)
125                *buf = data;
126        return 0;
127}
128
129int sc_pkcs15_cache_file(struct sc_pkcs15_card *p15card,
130                         const sc_path_t *path,
131                         const u8 *buf, size_t bufsize)
132{
133        char fname[PATH_MAX];
134        int r;
135        FILE *f;
136        size_t c;
137
138        r = generate_cache_filename(p15card, path, fname, sizeof(fname));
139        if (r != 0)
140                return r;
141
142        f = fopen(fname, "wb");
143        /* If the open failed because the cache directory does
144         * not exist, create it and a re-try the fopen() call.
145         */
146        if (f == NULL && errno == ENOENT) {
147                if ((r = sc_make_cache_dir(p15card->card->ctx)) < 0)
148                        return r;
149                f = fopen(fname, "wb");
150        }
151        if (f == NULL)
152                return 0;
153
154        c = fwrite(buf, 1, bufsize, f);
155        fclose(f);
156        if (c != bufsize) {
157                sc_error(p15card->card->ctx, "fwrite() wrote only %d bytes", c);
158                unlink(fname);
159                return SC_ERROR_INTERNAL;
160        }
161        return 0;
162}
Note: See TracBrowser for help on using the browser.