int sc_pkcs15_cache_file(struct sc_pkcs15_card *p15card, const sc_path_t *path, const u8 *buf, size_t bufsize) { char fname[PATH_MAX]; int r; FILE *f; size_t c; r = generate_cache_filename(p15card, path, fname, sizeof(fname)); if (r != 0) return r; f = fopen(fname, "wb"); /* If the open failed because the cache directory does * not exist, create it and a re-try the fopen() call. */ if (f == NULL && errno == ENOENT) { if ((r = sc_make_cache_dir(p15card->card->ctx)) < 0) return r; f = fopen(fname, "wb"); } if (f == NULL) return 0; c = fwrite(buf, 1, bufsize, f); fclose(f); if (c != bufsize) { sc_debug(p15card->card->ctx, SC_LOG_DEBUG_NORMAL, "fwrite() wrote only %d bytes", c); unlink(fname); return SC_ERROR_INTERNAL; } return 0; }
int sc_pkcs15_read_cached_file(struct sc_pkcs15_card *p15card, const sc_path_t *path, u8 **buf, size_t *bufsize) { char fname[PATH_MAX]; int r; FILE *f; size_t count, offset, got; struct stat stbuf; u8 *data = NULL; r = generate_cache_filename(p15card, path, fname, sizeof(fname)); if (r != 0) return r; r = stat(fname, &stbuf); if (r) return SC_ERROR_FILE_NOT_FOUND; if (path->count < 0) { count = stbuf.st_size; offset = 0; } else { count = path->count; offset = path->index; if (offset + count > (size_t)stbuf.st_size) return SC_ERROR_FILE_NOT_FOUND; /* cache file bad? */ } if (*buf == NULL) { data = malloc((size_t)stbuf.st_size); if (data == NULL) return SC_ERROR_OUT_OF_MEMORY; } else if (count > *bufsize) return SC_ERROR_BUFFER_TOO_SMALL; f = fopen(fname, "rb"); if (f == NULL) { if (data) free(data); return SC_ERROR_FILE_NOT_FOUND; } if (offset) { if (0 != fseek(f, (long)offset, SEEK_SET)) { fclose(f); free(data); return SC_ERROR_FILE_NOT_FOUND; } } if (data) *buf = data; got = fread(*buf, 1, count, f); fclose(f); if (got != count) { if (data) free(data); return SC_ERROR_BUFFER_TOO_SMALL; } *bufsize = count; if (data) *buf = data; return 0; }
int sc_pkcs15_read_cached_file(struct sc_pkcs15_card *p15card, const sc_path_t *path, u8 **buf, size_t *bufsize) { char fname[PATH_MAX]; int rv; FILE *f; size_t count; struct stat stbuf; u8 *data = NULL; if (path->len < 2) return SC_ERROR_INVALID_ARGUMENTS; /* Accept full path or FILE-ID path with AID */ if ((path->type != SC_PATH_TYPE_PATH) && (path->type != SC_PATH_TYPE_FILE_ID || path->aid.len == 0)) return SC_ERROR_INVALID_ARGUMENTS; sc_log(p15card->card->ctx, "try to read cache for %s", sc_print_path(path)); rv = generate_cache_filename(p15card, path, fname, sizeof(fname)); if (rv != SC_SUCCESS) return rv; sc_log(p15card->card->ctx, "read cached file %s", fname); f = fopen(fname, "rb"); if (!f) return SC_ERROR_FILE_NOT_FOUND; if (fstat(fileno(f), &stbuf)) { fclose(f); return SC_ERROR_FILE_NOT_FOUND; } if (path->count < 0) { count = stbuf.st_size; } else { count = path->count; if (path->index + count > (size_t)stbuf.st_size) { rv = SC_ERROR_FILE_NOT_FOUND; /* cache file bad? */ goto err; } if (0 != fseek(f, (long)path->index, SEEK_SET)) { rv = SC_ERROR_FILE_NOT_FOUND; goto err; } } if (*buf == NULL) { data = malloc((size_t)stbuf.st_size); if (data == NULL) { rv = SC_ERROR_OUT_OF_MEMORY; goto err; } } else if (count > *bufsize) { rv = SC_ERROR_BUFFER_TOO_SMALL; goto err; } if (data) *buf = data; if (count != fread(*buf, 1, count, f)) { rv = SC_ERROR_BUFFER_TOO_SMALL; goto err; } *bufsize = count; rv = SC_SUCCESS; err: if (rv != SC_SUCCESS) if (data) free(data); fclose(f); return rv; }