// sha1_check(data) // to return the sha1 of the data (given in the format returned by // read_file). // // sha1_check(data, sha1_hex, [sha1_hex, ...]) // returns the sha1 of the file if it matches any of the hex // strings passed, or "" if it does not equal any of them. // Value* Sha1CheckFn(const char* name, State* state, int argc, Expr* argv[]) { if (argc < 1) { return ErrorAbort(state, "%s() expects at least 1 arg", name); } Value** args = ReadValueVarArgs(state, argc, argv); if (args == NULL) { return NULL; } if (args[0]->size < 0) { fprintf(stderr, "%s(): no file contents received", name); return StringValue(strdup("")); } uint8_t digest[SHA_DIGEST_SIZE]; SHA(args[0]->data, args[0]->size, digest); FreeValue(args[0]); if (argc == 1) { return StringValue(PrintSha1(digest)); } int i; uint8_t* arg_digest = malloc(SHA_DIGEST_SIZE); for (i = 1; i < argc; ++i) { if (args[i]->type != VAL_STRING) { fprintf(stderr, "%s(): arg %d is not a string; skipping", name, i); } else if (ParseSha1(args[i]->data, arg_digest) != 0) { // Warn about bad args and skip them. fprintf(stderr, "%s(): error parsing \"%s\" as sha-1; skipping", name, args[i]->data); } else if (memcmp(digest, arg_digest, SHA_DIGEST_SIZE) == 0) { break; } FreeValue(args[i]); } if (i >= argc) { // Didn't match any of the hex strings; return false. return StringValue(strdup("")); } // Found a match; free all the remaining arguments and return the // matched one. int j; for (j = i+1; j < argc; ++j) { FreeValue(args[j]); } return args[i]; }
Value* RangeSha1Fn(const char* name, State* state, int argc, Expr* argv[]) { Value* blockdev_filename; Value* ranges; const uint8_t* digest = NULL; if (ReadValueArgs(state, argv, 2, &blockdev_filename, &ranges) < 0) { return NULL; } if (blockdev_filename->type != VAL_STRING) { ErrorAbort(state, "blockdev_filename argument to %s must be string", name); goto done; } if (ranges->type != VAL_STRING) { ErrorAbort(state, "ranges argument to %s must be string", name); goto done; } int fd = open(blockdev_filename->data, O_RDWR); if (fd < 0) { ErrorAbort(state, "failed to open %s: %s", blockdev_filename->data, strerror(errno)); goto done; } RangeSet* rs = parse_range(ranges->data); uint8_t buffer[BLOCKSIZE]; SHA_CTX ctx; SHA_init(&ctx); int i, j; for (i = 0; i < rs->count; ++i) { check_lseek(fd, (off64_t)rs->pos[i*2] * BLOCKSIZE, SEEK_SET); for (j = rs->pos[i*2]; j < rs->pos[i*2+1]; ++j) { readblock(fd, buffer, BLOCKSIZE); SHA_update(&ctx, buffer, BLOCKSIZE); } } digest = SHA_final(&ctx); close(fd); done: FreeValue(blockdev_filename); FreeValue(ranges); if (digest == NULL) { return StringValue(strdup("")); } else { return StringValue(PrintSha1(digest)); } }