static int do_mkdir(int argc, char **argv) { sc_path_t path; sc_file_t *file; unsigned int size; int r, op; if (argc != 2) return usage(do_mkdir); if (arg_to_path(argv[0], &path, 1) != 0) return usage(do_mkdir); if (sscanf(argv[1], "%u", &size) != 1) return usage(do_mkdir); file = sc_file_new(); file->id = (path.value[0] << 8) | path.value[1]; file->type = SC_FILE_TYPE_DF; file->size = size; file->status = SC_FILE_STATUS_ACTIVATED; for (op = 0; op < SC_MAX_AC_OPS; op++) sc_file_add_acl_entry(file, op, SC_AC_NONE, 0); r = create_file(file); sc_file_free(file); return r; }
static int do_put(int argc, char **argv) { u8 buf[256]; int r, err = 1; size_t count = 0; unsigned int idx = 0; sc_path_t path; sc_file_t *file = NULL; const char *filename; FILE *outf = NULL; if (argc < 1 || argc > 2) return usage(do_put); if (arg_to_path(argv[0], &path, 0) != 0) return usage(do_put); filename = (argc == 2) ? argv[1] : path_to_filename(&path, '_'); outf = fopen(filename, "rb"); if (outf == NULL) { perror(filename); goto err; } r = sc_select_file(card, &path, &file); if (r) { check_ret(r, SC_AC_OP_SELECT, "unable to select file", current_file); goto err; } count = file->size; while (count) { int c = count > sizeof(buf) ? sizeof(buf) : count; r = fread(buf, 1, c, outf); if (r < 0) { perror("fread"); goto err; } if (r != c) count = c = r; r = sc_update_binary(card, idx, buf, c, 0); if (r < 0) { check_ret(r, SC_AC_OP_READ, "update failed", file); goto err; } if (r != c) { printf("expecting %d, wrote only %d bytes.\n", c, r); goto err; } idx += c; count -= c; } printf("Total of %d bytes written.\n", idx); err = 0; err: sc_file_free(file); if (outf) fclose(outf); select_current_path_or_die(); return -err; }
static int do_create(int argc, char **argv) { sc_path_t path; sc_file_t *file; unsigned int size; int r, op; if (argc != 2) return usage(do_create); if (arg_to_path(argv[0], &path, 1) != 0) return usage(do_create); /* %z isn't supported everywhere */ if (sscanf(argv[1], "%u", &size) != 1) return usage(do_create); file = sc_file_new(); file->id = (path.value[0] << 8) | path.value[1]; file->type = SC_FILE_TYPE_WORKING_EF; file->ef_structure = SC_FILE_EF_TRANSPARENT; file->size = (size_t) size; file->status = SC_FILE_STATUS_ACTIVATED; for (op = 0; op < SC_MAX_AC_OPS; op++) sc_file_add_acl_entry(file, op, SC_AC_NONE, 0); r = create_file(file); sc_file_free(file); return r; }
static int do_update_record(int argc, char **argv) { u8 buf[240]; size_t buflen; int r, i, err = 1; int rec, offs; sc_path_t path; sc_file_t *file; if (argc != 4) return usage(do_update_record); if (arg_to_path(argv[0], &path, 0) != 0) return usage(do_update_record); rec = strtol(argv[1],NULL,10); offs = strtol(argv[2],NULL,10); printf("in: %i; %i; %s\n", rec, offs, argv[3]); r = sc_select_file(card, &path, &file); if (r) { check_ret(r, SC_AC_OP_SELECT, "unable to select file", current_file); return -1; } if (file->ef_structure != SC_FILE_EF_LINEAR_VARIABLE) { printf("EF structure should be SC_FILE_EF_LINEAR_VARIABLE\n"); goto err; } else if (rec < 1 || rec > file->record_count) { printf("Invalid record number %i\n", rec); goto err; } r = sc_read_record(card, rec, buf, sizeof(buf), SC_RECORD_BY_REC_NR); if (r<0) { printf("Cannot read record %i; return %i\n", rec, r); goto err;; } buflen = sizeof(buf) - offs; i = parse_string_or_hexdata(argv[3], buf + offs, &buflen); if (!i) { printf("unable to parse data\n"); goto err; } r = sc_update_record(card, rec, buf, r, SC_RECORD_BY_REC_NR); if (r<0) { printf("Cannot update record %i; return %i\n", rec, r); goto err; } printf("Total of %d bytes written to record %i at %i offset.\n", i, rec, offs); err = 0; err: sc_file_free(file); select_current_path_or_die(); return -err; }
static int do_update_binary(int argc, char **argv) { u8 buf[240]; int r, err = 1, in_len; int offs; sc_path_t path; sc_file_t *file; char *in_str; if (argc < 2 || argc > 3) goto usage; if (arg_to_path(argv[0], &path, 0) != 0) goto usage; offs = strtol(argv[1],NULL,10); in_str = argv[2]; printf("in: %i; %s\n", offs, in_str); if (*in_str=='\"') { in_len = strlen(in_str)-2 >= sizeof(buf) ? sizeof(buf)-1 : strlen(in_str)-2; strncpy((char *) buf, in_str+1, in_len); } else { in_len = hex2binary(buf, sizeof(buf), in_str); if (!in_len) { printf("unable to parse hex value\n"); return -1; } } r = sc_select_file(card, &path, &file); if (r) { check_ret(r, SC_AC_OP_SELECT, "unable to select file", current_file); return -1; } if (file->ef_structure != SC_FILE_EF_TRANSPARENT) { printf("EF structure should be SC_FILE_EF_TRANSPARENT\n"); goto err; } r = sc_update_binary(card, offs, buf, in_len, 0); if (r < 0) { printf("Cannot update %04X; return %i\n", file->id, r); goto err; } printf("Total of %d bytes written to %04X at %i offset.\n", r, file->id, offs); err = 0; err: sc_file_free(file); select_current_path_or_die(); return -err; usage: printf("Usage: update <file id> offs <hex value> | <'\"' enclosed string>\n"); return -1; }
static int do_cd(int argc, char **argv) { sc_path_t path; sc_file_t *file; int r; if (argc != 1) goto usage; if (strcmp(argv[0], "..") == 0) { path = current_path; if (path.len < 4) { printf("unable to go up, already in MF.\n"); return -1; } if (path.type == SC_PATH_TYPE_DF_NAME) { sc_format_path("3F00", &path); } else { path.len -= 2; } r = sc_select_file(card, &path, &file); if (r) { printf("unable to go up: %s\n", sc_strerror(r)); return -1; } if (current_file) sc_file_free(current_file); current_file = file; current_path = path; return 0; } if (arg_to_path(argv[0], &path, 0) != 0) goto usage; r = sc_select_file(card, &path, &file); if (r) { check_ret(r, SC_AC_OP_SELECT, "unable to select DF", current_file); return -1; } if ((file->type != SC_FILE_TYPE_DF) && (card->type != SC_CARD_TYPE_BELPIC_EID)) { printf("Error: file is not a DF.\n"); sc_file_free(file); select_current_path_or_die(); return -1; } current_path = path; if (current_file) sc_file_free(current_file); current_file = file; return 0; usage: puts("Usage: cd <file_id>|aid:<DF name>"); return -1; }
static int do_cd(int argc, char **argv) { sc_path_t path; sc_file_t *file; int r; if (argc != 1) goto usage; if (strcmp(argv[0], "..") == 0) { if (current_path.len < 4) { printf("unable to go up, already in MF.\n"); return -1; } path = current_path; path.len -= 2; r = sc_select_file(card, &path, &file); if (r) { printf("unable to go up: %s\n", sc_strerror(r)); return -1; } sc_file_free(current_file); current_file = file; current_path = path; return 0; } if (arg_to_path(argv[0], &path, 0) != 0) goto usage; r = sc_select_file(card, &path, &file); if (r) { check_ret(r, SC_AC_OP_SELECT, "unable to select DF", current_file); return -1; } if ((file->type != SC_FILE_TYPE_DF) && !(card->caps & SC_CARD_CAP_NO_FCI)) { printf("Error: file is not a DF.\n"); sc_file_free(file); r = sc_select_file(card, ¤t_path, NULL); if (r) { printf("unable to select parent file: %s\n", sc_strerror(r)); die(1); } return -1; } current_path = path; sc_file_free(current_file); current_file = file; return 0; usage: puts("Usage: cd <file_id>|aid:<DF name>"); return -1; }
static int do_update_binary(int argc, char **argv) { u8 buf[240]; size_t buflen = sizeof(buf); int r, err = 1; int offs; sc_path_t path; sc_file_t *file; if (argc != 3) return usage(do_update_binary); if (arg_to_path(argv[0], &path, 0) != 0) return usage(do_update_binary); offs = strtol(argv[1],NULL,10); printf("in: %i; %s\n", offs, argv[2]); r = parse_string_or_hexdata(argv[2], buf, &buflen); if (r < 0) { printf("unable to parse data\n"); return -1; } r = sc_select_file(card, &path, &file); if (r) { check_ret(r, SC_AC_OP_SELECT, "unable to select file", current_file); return -1; } if (file->ef_structure != SC_FILE_EF_TRANSPARENT) { printf("EF structure should be SC_FILE_EF_TRANSPARENT\n"); goto err; } r = sc_update_binary(card, offs, buf, buflen, 0); if (r < 0) { printf("Cannot update %04X; return %i\n", file->id, r); goto err; } printf("Total of %d bytes written to %04X at %i offset.\n", r, file->id, offs); err = 0; err: sc_file_free(file); select_current_path_or_die(); return -err; }
static int do_cat(int argc, char **argv) { int r, err = 0; sc_path_t path; sc_file_t *file; int not_current = 1; if (argc > 1) goto usage; if (!argc) { path = current_path; file = current_file; not_current = 0; } else { if (arg_to_path(argv[0], &path, 1) != 0) goto usage; r = sc_select_file(card, &path, &file); if (r) { check_ret(r, SC_AC_OP_SELECT, "unable to select file", current_file); return -1; } } if (file->type != SC_FILE_TYPE_WORKING_EF) { printf("only working EFs may be read\n"); sc_file_free(file); return -1; } if (file->ef_structure == SC_FILE_EF_TRANSPARENT) read_and_print_binary_file(file); else read_and_print_record_file(file); if (not_current) { sc_file_free(file); r = sc_select_file(card, ¤t_path, NULL); if (r) { printf("unable to select parent file: %s\n", sc_strerror(r)); die(1); } } return -err; usage: puts("Usage: cat [file_id]"); return -1; }
static int do_delete(int argc, char **argv) { sc_path_t path; int r; if (argc != 1) return usage(do_delete); if (arg_to_path(argv[0], &path, 1) != 0) return usage(do_delete); if (path.len != 2) return usage(do_delete); path.type = SC_PATH_TYPE_FILE_ID; r = sc_delete_file(card, &path); if (r) { check_ret(r, SC_AC_OP_DELETE, "DELETE FILE failed", current_file); return -1; } return 0; }
static int do_info(int argc, char **argv) { sc_file_t *file; sc_path_t path; size_t i; const char *st; int r, not_current = 1; const id2str_t *ac_ops = NULL; if (!argc) { path = current_path; file = current_file; not_current = 0; } else if (argc == 1) { if (arg_to_path(argv[0], &path, 0) != 0) return usage(do_info); r = sc_select_file(card, &path, &file); if (r) { printf("unable to select file: %s\n", sc_strerror(r)); return -1; } } else return usage(do_info); switch (file->type) { case SC_FILE_TYPE_WORKING_EF: case SC_FILE_TYPE_INTERNAL_EF: st = "Elementary File"; break; case SC_FILE_TYPE_DF: st = "Dedicated File"; break; default: st = "Unknown File"; break; } printf("\n%s ID %04X\n\n", st, file->id); printf("%-15s%s\n", "File path:", path_to_filename(&path, '/')); printf("%-15s%lu bytes\n", "File size:", (unsigned long) file->size); if (file->type == SC_FILE_TYPE_DF) { static const id2str_t ac_ops_df[] = { { SC_AC_OP_SELECT, "SELECT" }, { SC_AC_OP_LOCK, "LOCK" }, { SC_AC_OP_DELETE, "DELETE" }, { SC_AC_OP_CREATE, "CREATE" }, { SC_AC_OP_REHABILITATE, "REHABILITATE" }, { SC_AC_OP_INVALIDATE, "INVALIDATE" }, { SC_AC_OP_LIST_FILES, "LIST FILES" }, { SC_AC_OP_CRYPTO, "CRYPTO" }, { SC_AC_OP_DELETE_SELF, "DELETE SELF" }, { 0, NULL } }; if (file->namelen) { printf("%-15s", "DF name:"); util_print_binary(stdout, file->name, file->namelen); printf("\n"); } ac_ops = ac_ops_df; } else { static const id2str_t ac_ops_ef[] = { { SC_AC_OP_READ, "READ" }, { SC_AC_OP_UPDATE, "UPDATE" }, { SC_AC_OP_DELETE, "DELETE" }, { SC_AC_OP_WRITE, "WRITE" }, { SC_AC_OP_REHABILITATE, "REHABILITATE" }, { SC_AC_OP_INVALIDATE, "INVALIDATE" }, { SC_AC_OP_LIST_FILES, "LIST FILES" }, { SC_AC_OP_CRYPTO, "CRYPTO" }, { 0, NULL } }; const id2str_t ef_type_name[] = { { SC_FILE_EF_TRANSPARENT, "Transparent" }, { SC_FILE_EF_LINEAR_FIXED, "Linear fixed" }, { SC_FILE_EF_LINEAR_FIXED_TLV, "Linear fixed, SIMPLE-TLV" }, { SC_FILE_EF_LINEAR_VARIABLE, "Linear variable" }, { SC_FILE_EF_LINEAR_VARIABLE_TLV, "Linear variable, SIMPLE-TLV" }, { SC_FILE_EF_CYCLIC, "Cyclic" }, { SC_FILE_EF_CYCLIC_TLV, "Cyclic, SIMPLE-TLV" }, { 0, NULL } }; const char *ef_type = "Unknown"; for (i = 0; ef_type_name[i].str != NULL; i++) if (file->ef_structure == ef_type_name[i].id) ef_type = ef_type_name[i].str; printf("%-15s%s\n", "EF structure:", ef_type); ac_ops = ac_ops_ef; } for (i = 0; ac_ops != NULL && ac_ops[i].str != NULL; i++) { int len = strlen(ac_ops[i].str); printf("ACL for %s:%*s %s\n", ac_ops[i].str, (12 > len) ? (12 - len) : 0, "", util_acl_to_str(sc_file_get_acl_entry(file, ac_ops[i].id))); } if (file->prop_attr_len) { printf("%-25s", "Proprietary attributes:"); util_hex_dump(stdout, file->prop_attr, file->prop_attr_len, " "); printf("\n"); } if (file->sec_attr_len) { printf("%-25s", "Security attributes:"); util_hex_dump(stdout, file->sec_attr, file->sec_attr_len, " "); printf("\n"); } printf("\n"); if (not_current) { sc_file_free(file); select_current_path_or_die(); } return 0; }
static int do_cat(int argc, char **argv) { int r, err = 1; sc_path_t path; sc_file_t *file = NULL; int not_current = 1; int sfi = 0; if (argc > 1) return usage(do_cat); if (!argc) { path = current_path; file = current_file; not_current = 0; } else { const char sfi_prefix[] = "sfi:"; if (strncasecmp(argv[0], sfi_prefix, strlen(sfi_prefix)) == 0) { const char *sfi_n = argv[0] + strlen(sfi_prefix); if(!current_file) { printf("A DF must be selected to read by SFI\n"); goto err; } path = current_path; file = current_file; not_current = 0; sfi = atoi(sfi_n); if ((sfi < 1) || (sfi > 30)) { printf("Invalid SFI: %s\n", sfi_n); return usage(do_cat); } } else { if (arg_to_path(argv[0], &path, 0) != 0) return usage(do_cat); r = sc_select_file(card, &path, &file); if (r) { check_ret(r, SC_AC_OP_SELECT, "unable to select file", current_file); goto err; } } } if (file->type != SC_FILE_TYPE_WORKING_EF && !(file->type == SC_FILE_TYPE_DF && sfi)) { printf("only working EFs may be read\n"); goto err; } if (file->ef_structure == SC_FILE_EF_TRANSPARENT && !sfi) read_and_util_print_binary_file(file); else read_and_print_record_file(file, sfi); err = 0; err: if (not_current) { if (file != NULL) sc_file_free(file); select_current_path_or_die(); } return -err; }
static int do_asn1(int argc, char **argv) { int r, err = 1; sc_path_t path; sc_file_t *file = NULL; int not_current = 1; size_t len; unsigned char *buf = NULL; if (argc > 1) return usage(do_asn1); /* select file */ if (argc) { if (arg_to_path(argv[0], &path, 0) != 0) { puts("Invalid file path"); return -1; } r = sc_select_file(card, &path, &file); if (r) { check_ret(r, SC_AC_OP_SELECT, "unable to select file", current_file); goto err; } } else { path = current_path; file = current_file; not_current = 0; } if (file->type != SC_FILE_TYPE_WORKING_EF) { printf("only working EFs may be read\n"); goto err; } /* read */ if (file->ef_structure != SC_FILE_EF_TRANSPARENT) { printf("only transparent file type is supported at the moment\n"); goto err; } len = file->size; buf = calloc(1, len); if (!buf) { goto err; } r = sc_read_binary(card, 0, buf, len, 0); if (r < 0) { check_ret(r, SC_AC_OP_READ, "read failed", file); goto err; } if ((size_t)r != len) { printf("expecting %lu, got only %d bytes.\n", (unsigned long) len, r); goto err; } /* asn1 dump */ sc_asn1_print_tags(buf, len); err = 0; err: if (buf) free(buf); if (not_current) { if (file) sc_file_free(file); select_current_path_or_die(); } return -err; }
static int do_info(int argc, char **argv) { sc_file_t *file; sc_path_t path; size_t i; const char *st; int r, not_current = 1; if (!argc) { path = current_path; file = current_file; not_current = 0; } else if (argc == 1) { if (arg_to_path(argv[0], &path, 0) != 0) goto usage; r = sc_select_file(card, &path, &file); if (r) { printf("unable to select file: %s\n", sc_strerror(r)); return -1; } } else goto usage; switch (file->type) { case SC_FILE_TYPE_WORKING_EF: case SC_FILE_TYPE_INTERNAL_EF: st = "Elementary File"; break; case SC_FILE_TYPE_DF: st = "Dedicated File"; break; default: st = "Unknown File"; break; } printf("\n%s ID %04X\n\n", st, file->id); printf("%-15s", "File path:"); for (i = 0; i < path.len; i++) { for (i = 0; i < path.len; i++) { if ((i & 1) == 0 && i) printf("/"); printf("%02X", path.value[i]); } } printf("\n%-15s%lu bytes\n", "File size:", (unsigned long) file->size); if (file->type == SC_FILE_TYPE_DF) { const char *ops[] = { "SELECT", "LOCK", "DELETE", "CREATE", "REHABILITATE", "INVALIDATE", "LIST FILES", "CRYPTO", "DELETE SELF" }; if (file->namelen) { printf("%-15s", "DF name:"); util_print_binary(stdout, file->name, file->namelen); printf("\n"); } for (i = 0; i < sizeof(ops)/sizeof(ops[0]); i++) { char buf[80]; sprintf(buf, "ACL for %s:", ops[i]); printf("%-25s%s\n", buf, util_acl_to_str(sc_file_get_acl_entry(file, i))); } } else { const char *structs[] = { "Unknown", "Transparent", "Linear fixed", "Linear fixed, SIMPLE-TLV", "Linear variable", "Linear variable TLV", "Cyclic, SIMPLE-TLV", }; const struct { const char * label; int op; } ops[] = { { "READ", SC_AC_OP_READ }, { "UPDATE", SC_AC_OP_UPDATE }, { "DELETE", SC_AC_OP_DELETE }, { "WRITE", SC_AC_OP_WRITE }, { "REHABILITATE", SC_AC_OP_REHABILITATE }, { "INVALIDATE", SC_AC_OP_INVALIDATE }, { "LIST_FILES", SC_AC_OP_LIST_FILES }, { "CRYPTO", SC_AC_OP_CRYPTO }, }; printf("%-15s%s\n", "EF structure:", structs[file->ef_structure]); for (i = 0; i < sizeof(ops)/sizeof(ops[0]); i++) { char buf[80]; sprintf(buf, "ACL for %s:", ops[i].label); printf("%-25s%s\n", buf, util_acl_to_str(sc_file_get_acl_entry(file, ops[i].op))); } } if (file->prop_attr_len) { printf("%-25s", "Proprietary attributes:"); for (i = 0; i < file->prop_attr_len; i++) printf("%02X ", file->prop_attr[i]); printf("\n"); } if (file->sec_attr_len) { printf("%-25s", "Security attributes:"); for (i = 0; i < file->sec_attr_len; i++) printf("%02X ", file->sec_attr[i]); printf("\n"); } printf("\n"); if (not_current) { sc_file_free(file); select_current_path_or_die(); } return 0; usage: puts("Usage: info [file_id]"); return -1; }
static int do_update_record(int argc, char **argv) { u8 buf[240]; int r, i, err = 1; int rec, offs; sc_path_t path; sc_file_t *file; char *in_str; if (argc < 3 || argc > 4) goto usage; if (arg_to_path(argv[0], &path, 0) != 0) goto usage; rec = strtol(argv[1],NULL,10); offs = strtol(argv[2],NULL,10); in_str = argv[3]; printf("in: %i; %i; %s\n", rec, offs, in_str); r = sc_select_file(card, &path, &file); if (r) { check_ret(r, SC_AC_OP_SELECT, "unable to select file", current_file); return -1; } if (file->ef_structure != SC_FILE_EF_LINEAR_VARIABLE) { printf("EF structure should be SC_FILE_EF_LINEAR_VARIABLE\n"); goto err; } else if (rec < 1 || rec > file->record_count) { printf("Invalid record number %i\n", rec); goto err; } r = sc_read_record(card, rec, buf, sizeof(buf), SC_RECORD_BY_REC_NR); if (r<0) { printf("Cannot read record %i; return %i\n", rec, r); goto err;; } i = hex2binary(buf + offs, sizeof(buf) - offs, in_str); if (!i) { printf("unable to parse hex value\n"); goto err; } r = sc_update_record(card, rec, buf, r, SC_RECORD_BY_REC_NR); if (r<0) { printf("Cannot update record %i; return %i\n", rec, r); goto err; } printf("Total of %d bytes written to record %i at %i offset.\n", i, rec, offs); err = 0; err: sc_file_free(file); select_current_path_or_die(); return -err; usage: printf("Usage: update_record <file id> rec_nr rec_offs <hex value>\n"); return -1; }
static int do_get(int argc, char **argv) { u8 buf[256]; int r, err = 0; size_t count = 0; unsigned int idx = 0; sc_path_t path; sc_file_t *file; char fbuf[256], *filename; FILE *outf = NULL; if (argc < 1 || argc > 2) goto usage; if (arg_to_path(argv[0], &path, 0) != 0) goto usage; if (argc == 2) filename = argv[1]; else { size_t i = 0; while (2*i < path.len) { sprintf(&fbuf[5*i], "%02X%02X_", path.value[2*i], path.value[2*i+1]); i++; } fbuf[5*i-1] = 0; filename = fbuf; } outf = fopen(filename, "wb"); if (outf == NULL) { perror(filename); return -1; } r = sc_select_file(card, &path, &file); if (r) { fclose(outf); check_ret(r, SC_AC_OP_SELECT, "unable to select file", current_file); return -1; } if (file->type != SC_FILE_TYPE_WORKING_EF) { fclose(outf); printf("only working EFs may be read\n"); sc_file_free(file); return -1; } count = file->size; while (count) { int c = count > sizeof(buf) ? sizeof(buf) : count; r = sc_read_binary(card, idx, buf, c, 0); if (r < 0) { check_ret(r, SC_AC_OP_READ, "read failed", file); err = 1; goto err; } if ((r != c) && !(card->caps & SC_CARD_CAP_NO_FCI)) { printf("expecting %d, got only %d bytes.\n", c, r); err = 1; goto err; } if ((r == 0) && (card->caps & SC_CARD_CAP_NO_FCI)) break; fwrite(buf, r, 1, outf); idx += r; count -= r; } printf("Total of %d bytes read from %s and saved to %s.\n", idx, argv[0], filename); err: sc_file_free(file); r = sc_select_file(card, ¤t_path, NULL); if (r) { printf("unable to select parent file: %s\n", sc_strerror(r)); die(1); } if (outf) fclose(outf); return -err; usage: printf("Usage: get <file id> [output file]\n"); return -1; }
static int do_get(int argc, char **argv) { u8 buf[256]; int r, err = 1; size_t count = 0; unsigned int idx = 0; sc_path_t path; sc_file_t *file = NULL; char *filename; FILE *outf = NULL; if (argc < 1 || argc > 2) return usage(do_get); if (arg_to_path(argv[0], &path, 0) != 0) return usage(do_get); filename = (argc == 2) ? argv[1] : path_to_filename(&path, '_'); outf = (strcmp(filename, "-") == 0) ? stdout : fopen(filename, "wb"); if (outf == NULL) { perror(filename); goto err; } r = sc_select_file(card, &path, &file); if (r) { check_ret(r, SC_AC_OP_SELECT, "unable to select file", current_file); goto err; } if (file->type != SC_FILE_TYPE_WORKING_EF) { printf("only working EFs may be read\n"); goto err; } count = file->size; while (count) { int c = count > sizeof(buf) ? sizeof(buf) : count; r = sc_read_binary(card, idx, buf, c, 0); if (r < 0) { check_ret(r, SC_AC_OP_READ, "read failed", file); goto err; } if ((r != c) && (card->type != SC_CARD_TYPE_BELPIC_EID)) { printf("expecting %d, got only %d bytes.\n", c, r); goto err; } if ((r == 0) && (card->type == SC_CARD_TYPE_BELPIC_EID)) break; fwrite(buf, r, 1, outf); idx += r; count -= r; } if (outf == stdout) { fwrite("\n", 1, 1, outf); } else { printf("Total of %d bytes read from %s and saved to %s.\n", idx, argv[0], filename); } err = 0; err: if (file) sc_file_free(file); if (outf != NULL && outf != stdout) fclose(outf); select_current_path_or_die(); return -err; }
static int do_put(int argc, char **argv) { u8 buf[256]; int r, err = 0; size_t count = 0; unsigned int idx = 0; sc_path_t path; sc_file_t *file; const char *filename; FILE *outf = NULL; if (argc < 1 || argc > 2) goto usage; if (arg_to_path(argv[0], &path, 0) != 0) goto usage; if (argc == 2) filename = argv[1]; else { sprintf((char *) buf, "%02X%02X", path.value[0], path.value[1]); filename = (char *) buf; } outf = fopen(filename, "rb"); if (outf == NULL) { perror(filename); return -1; } r = sc_select_file(card, &path, &file); if (r) { check_ret(r, SC_AC_OP_SELECT, "unable to select file", current_file); fclose(outf); return -1; } count = file->size; while (count) { int c = count > sizeof(buf) ? sizeof(buf) : count; r = fread(buf, 1, c, outf); if (r < 0) { perror("fread"); err = 1; goto err; } if (r != c) count = c = r; r = sc_update_binary(card, idx, buf, c, 0); if (r < 0) { check_ret(r, SC_AC_OP_READ, "update failed", file); err = 1; goto err; } if (r != c) { printf("expecting %d, wrote only %d bytes.\n", c, r); err = 1; goto err; } idx += c; count -= c; } printf("Total of %d bytes written.\n", idx); err: sc_file_free(file); r = sc_select_file(card, ¤t_path, NULL); if (r) { printf("unable to select parent file: %s\n", sc_strerror(r)); die(1); } if (outf) fclose(outf); return -err; usage: printf("Usage: put <file id> [input file]\n"); return -1; }