int main (int argc, char *argv[]) { uint8_t *data; int size; char *hashtype; char blobref[BLOBREF_MAX_STRING_SIZE]; if (argc != 2) { fprintf (stderr, "Usage: cat file | blobref hashtype\n"); exit (1); } hashtype = argv[1]; if ((size = read_all (STDIN_FILENO, (void **)&data)) < 0) log_err_exit ("read"); if (blobref_hash (hashtype, data, size, blobref, sizeof (blobref)) < 0) log_err_exit ("blobref_hash"); printf ("%s\n", blobref); return 0; }
void store_cb (flux_t *h, flux_msg_handler_t *mh, const flux_msg_t *msg, void *arg) { sqlite_ctx_t *ctx = arg; const void *data; int size, hash_len; uint8_t hash[BLOBREF_MAX_DIGEST_SIZE]; char blobref[BLOBREF_MAX_STRING_SIZE] = "-"; int uncompressed_size = -1; int rc = -1; int old_state; //delay cancellation to ensure lock-correctness in sqlite pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old_state); if (flux_request_decode_raw (msg, NULL, &data, &size) < 0) { flux_log_error (h, "store: request decode failed"); goto done; } if (size > ctx->blob_size_limit) { errno = EFBIG; goto done; } if (blobref_hash (ctx->hashfun, (uint8_t *)data, size, blobref, sizeof (blobref)) < 0) goto done; if ((hash_len = blobref_strtohash (blobref, hash, sizeof (hash))) < 0) goto done; if (size >= compression_threshold) { int r; int out_len = LZ4_compressBound(size); if (ctx->lzo_bufsize < out_len && grow_lzo_buf (ctx, out_len) < 0) goto done; r = LZ4_compress_default (data, ctx->lzo_buf, size, out_len); if (r == 0) { errno = EINVAL; goto done; } uncompressed_size = size; size = r; data = ctx->lzo_buf; } if (sqlite3_bind_text (ctx->store_stmt, 1, (char *)hash, hash_len, SQLITE_STATIC) != SQLITE_OK) { log_sqlite_error (ctx, "store: binding key"); set_errno_from_sqlite_error (ctx); goto done; } if (sqlite3_bind_int (ctx->store_stmt, 2, uncompressed_size) != SQLITE_OK) { log_sqlite_error (ctx, "store: binding size"); set_errno_from_sqlite_error (ctx); goto done; } if (sqlite3_bind_blob (ctx->store_stmt, 3, data, size, SQLITE_STATIC) != SQLITE_OK) { log_sqlite_error (ctx, "store: binding data"); set_errno_from_sqlite_error (ctx); goto done; } if (sqlite3_step (ctx->store_stmt) != SQLITE_DONE && sqlite3_errcode (ctx->db) != SQLITE_CONSTRAINT) { log_sqlite_error (ctx, "store: executing stmt"); set_errno_from_sqlite_error (ctx); goto done; } rc = 0; done: if (rc < 0) { if (flux_respond_error (h, msg, errno, NULL) < 0) flux_log_error (h, "store: flux_respond_error"); } else { if (flux_respond_raw (h, msg, blobref, strlen (blobref) + 1) < 0) flux_log_error (h, "store: flux_respond_raw"); } (void) sqlite3_reset (ctx->store_stmt); pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &old_state); }
int main(int argc, char** argv) { blobref_t ref; blobref_t ref2; uint8_t digest[BLOBREF_MAX_DIGEST_SIZE]; uint8_t data[1024]; plan (NO_PLAN); memset (data, 7, sizeof (data)); /* invalid args */ errno = 0; ok (blobref_hash ("nerf", data, sizeof (data), ref) < 0 && errno == EINVAL, "blobref_hash fails EINVAL with unknown hash name"); errno = 0; ok (blobref_strtohash (badref[0], digest, sizeof (digest)) < 0 && errno == EINVAL, "blobref_strtohash fails EINVAL with unknown hash prefix"); errno = 0; ok (blobref_strtohash (badref[1], digest, sizeof (digest)) < 0 && errno == EINVAL, "blobref_strtohash fails EINVAL with missing hash prefix separator"); errno = 0; ok (blobref_strtohash (badref[2], digest, sizeof (digest)) < 0 && errno == EINVAL, "blobref_strtohash fails EINVAL with wrong blobref length for prefix"); errno = 0; ok (blobref_strtohash (badref[3], digest, sizeof (digest)) < 0 && errno == EINVAL, "blobref_strtohash fails EINVAL with out of range blobref chars"); errno = 0; ok (blobref_strtohash (goodref[0], digest, 2) < 0 && errno == EINVAL, "blobref_strtohash fails EINVAL with runt digest size"); memset (digest, 6, sizeof (digest)); errno = 0; ok (blobref_hashtostr ("nerf", digest, SHA1_DIGEST_SIZE, ref) < 0 && errno == EINVAL, "blobref_hashtostr fails EINVAL with unknown hash"); errno = 0; ok (blobref_hashtostr ("sha1", digest, SHA256_BLOCK_SIZE, ref) < 0 && errno == EINVAL, "blobref_hashtostr fails EINVAL with wrong digest size for hash"); /* sha1 */ ok (blobref_hash ("sha1", NULL, 0, ref) == 0, "blobref_hash sha1 handles zero length data"); diag ("%s", ref); ok (blobref_hash ("sha1", data, sizeof (data), ref) == 0, "blobref_hash sha1 works"); diag ("%s", ref); ok (blobref_strtohash (ref, digest, sizeof (digest)) == SHA1_DIGEST_SIZE, "blobref_strtohash returns expected size hash"); ok (blobref_hashtostr ("sha1", digest, SHA1_DIGEST_SIZE, ref2) == 0, "blobref_hashtostr back again works"); diag ("%s", ref2); ok (strcmp (ref, ref2) == 0, "and blobrefs match"); /* sha256 */ ok (blobref_hash ("sha256", NULL, 0, ref) == 0, "blobref_hash sha256 handles zero length data"); diag ("%s", ref); ok (blobref_hash ("sha256", data, sizeof (data), ref) == 0, "blobref_hash sha256 works"); diag ("%s", ref); ok (blobref_strtohash (ref, digest, sizeof (digest)) == SHA256_BLOCK_SIZE, "blobref_strtohash returns expected size hash"); ok (blobref_hashtostr ("sha256", digest, SHA256_BLOCK_SIZE, ref2) == 0, "blobref_hashtostr back again works"); diag ("%s", ref2); ok (strcmp (ref, ref2) == 0, "and blobrefs match"); /* blobref_validate */ const char **pp; pp = &goodref[0]; while (*pp) { ok (blobref_validate (*pp) == 0, "blobref_validate: %s", *pp); pp++; } pp = &badref[0]; while (*pp) { errno = 0; ok (blobref_validate (*pp) < 0 && errno == EINVAL, "blobref_validate not: %s", *pp); pp++; } /* blobref_validate_hashtype */ ok (blobref_validate_hashtype ("sha1") == 0, "blobref_validate_hashtype sha1 is valid"); ok (blobref_validate_hashtype ("sha256") == 0, "blobref_validate_hashtype sha256 is valid"); ok (blobref_validate_hashtype ("nerf") == -1, "blobref_validate_hashtype nerf is invalid"); ok (blobref_validate_hashtype (NULL) == -1, "blobref_validate_hashtype NULL is invalid"); done_testing(); }