char *make_in_op_value(json_t *avu, baton_error_t *error) { json_t *op_value = NULL; init_baton_error(error); json_t *valarray = get_json_value(avu, "value", JSON_VALUE_KEY, JSON_VALUE_SHORT_KEY, error); if (error->code != 0) goto error; if (!json_is_array(valarray)) { set_baton_error(error, CAT_INVALID_ARGUMENT, "Invalid 'value' attribute: not a JSON array " "(required for `in` condition)"); goto error; } json_t *prev_value; // Open paren op_value = json_string("("); size_t index; json_t *value; json_array_foreach(valarray, index, value) { if (!json_is_string(value)) { set_baton_error(error, CAT_INVALID_ARGUMENT, "Invalid AVU value: not a JSON string " "in item %d of `in` array", index); goto error; } prev_value = op_value; json_t *tmp; if (index == 0) { tmp = json_pack("s+++", json_string_value(prev_value), "'", json_string_value(value), "'"); } else { tmp = json_pack("s+++", json_string_value(prev_value), ", '", json_string_value(value), "'"); } if (tmp) { op_value = tmp; json_decref(prev_value); } } // Close paren prev_value = op_value; json_t *tmp = json_pack("s+", json_string_value(op_value), ")"); if (tmp) { op_value = tmp; json_decref(prev_value); } logmsg(DEBUG, "Using IN value of %s", json_string_value(op_value)); char *copy = copy_str(json_string_value(op_value), MAX_STR_LEN); json_decref(op_value); return copy; error: if (op_value) json_decref(op_value); return NULL; }
static const char *get_opt_string_value(json_t *object, const char *name, const char *key, const char *short_key, baton_error_t *error) { const char *str = NULL; json_t *value; if (!json_is_object(object)) { set_baton_error(error, CAT_INVALID_ARGUMENT, "Invalid %s: not a JSON object", name); goto error; } value = json_object_get(object, key); if (!value && short_key) { value = json_object_get(object, short_key); } if (value && !json_is_string(value)) { set_baton_error(error, CAT_INVALID_ARGUMENT, "Invalid %s %s: not a JSON string", name, key); goto error; } if (value) { str = json_string_value(value); } return str; error: return NULL; }
static json_t *get_json_value(json_t *object, const char *name, const char *key, const char *short_key, baton_error_t *error) { json_t *value; if (!json_is_object(object)) { set_baton_error(error, CAT_INVALID_ARGUMENT, "Invalid %s: not a JSON object", name); goto error; } value = json_object_get(object, key); if (!value && short_key) { value = json_object_get(object, short_key); } if (!value) { set_baton_error(error, CAT_INVALID_ARGUMENT, "Invalid iRODS %s: %s property is missing", name, key); goto error; } return value; error: return NULL; }
static char *make_dir_path(const char *path, baton_error_t *error) { size_t slen = strnlen(path, MAX_STR_LEN); size_t dlen = slen + 1; // +1 for NUL // Only trim trailing '/' if the path is >1 character long if (slen > 1 && str_ends_with(path, "/", MAX_STR_LEN)) { dlen--; } if (dlen > MAX_STR_LEN) { set_baton_error(error, CAT_INVALID_ARGUMENT, "The path '%s' exceeded the maximum " "length of %d characters", path, MAX_STR_LEN); goto error; } char *dpath = NULL; dpath = calloc(dlen, sizeof (char)); if (!dpath) { set_baton_error(error, errno, "Failed to allocate memory: error %d %s", errno, strerror(errno)); goto error; } snprintf(dpath, dlen, "%s", path); return dpath; error: return NULL; }
static json_t *get_opt_array(json_t *object, const char *name, const char *key, const char *short_key, baton_error_t *error) { json_t *array; if (!json_is_object(object)) { set_baton_error(error, CAT_INVALID_ARGUMENT, "Invalid %s: not a JSON object", name); goto error; } array = json_object_get(object, key); if (!array && short_key) { array = json_object_get(object, short_key); } if (array && !json_is_array(array)) { set_baton_error(error, CAT_INVALID_ARGUMENT, "Invalid %s %s: not a JSON array", name, key); goto error; } if (!array) { array = json_array(); } else { json_incref(array); } return array; error: return NULL; }
json_t *data_object_path_to_json(const char *path, baton_error_t *error) { char path1[MAX_STR_LEN]; char path2[MAX_STR_LEN]; char *coll_name; char *data_name; init_baton_error(error); size_t term_len = strnlen(path, MAX_STR_LEN) + 1; if (term_len > MAX_STR_LEN) { set_baton_error(error, CAT_INVALID_ARGUMENT, "Failed to pack the data object path '%s' as JSON: " "it exceeded the maximum length of %d characters", path, MAX_STR_LEN); goto error; } snprintf(path1, sizeof path1, "%s", path); coll_name = dirname(path1); if (!coll_name) { set_baton_error(error, errno, "Failed to parse collection name of '%s': error %d %s", path1, errno, strerror(errno)); goto error; } snprintf(path2, sizeof path2, "%s", path); data_name = basename(path2); if (!data_name) { set_baton_error(error, errno, "Failed to parse data object name of '%s': error %d %s", path2, errno, strerror(errno)); goto error; } json_t *result = data_object_parts_to_json(coll_name, data_name, error); if (error->code != 0) goto error; return result; error: return NULL; }
int add_collection(json_t *object, const char *coll_name, baton_error_t *error) { init_baton_error(error); if (!json_is_object(object)) { set_baton_error(error, -1, "Failed to add collection data: " "target not a JSON object"); goto error; } json_t *coll = json_pack("s", coll_name); if (!coll) { set_baton_error(error, -1, "Failed to pack data object '%s' as JSON", coll_name); goto error; } return json_object_set_new(object, JSON_COLLECTION_KEY, coll); error: return error->code; }
static char *make_file_path(const char *path, const char *filename, baton_error_t *error) { size_t dlen = strnlen(path, MAX_STR_LEN); size_t flen = strnlen(filename, MAX_STR_LEN); size_t len = dlen + flen + 1; // +1 for NUL int includes_slash = str_ends_with(path, "/", MAX_STR_LEN); if (!includes_slash) len++; if (len > MAX_STR_LEN) { set_baton_error(error, CAT_INVALID_ARGUMENT, "The path components '%s' + '%s' " "combined exceeded the maximum length of %d " "characters", path, filename, MAX_STR_LEN); goto error; } char *fpath = NULL; fpath = calloc(len, sizeof (char)); if (!fpath) { set_baton_error(error, errno, "Failed to allocate memory: error %d %s", errno, strerror(errno)); goto error; } if (includes_slash) { snprintf(fpath, len, "%s%s", path, filename); } else { snprintf(fpath, len, "%s/%s", path, filename); } return fpath; error: return NULL; }
int add_replicates(json_t *object, json_t *replicates, baton_error_t *error) { init_baton_error(error); if (!json_is_object(object)) { set_baton_error(error, -1, "Failed to add replicates data: " "target not a JSON object"); goto error; } return json_object_set_new(object, JSON_REPLICATE_KEY, replicates); error: return error->code; }
int add_contents(json_t *object, json_t *contents, baton_error_t *error) { init_baton_error(error); if (!json_is_object(object)) { set_baton_error(error, -1, "Failed to add contents data: " "target not a JSON object"); goto error; } return json_object_set_new(object, JSON_CONTENTS_KEY, contents); error: return error->code; }
int add_metadata(json_t *object, json_t *avus, baton_error_t *error) { init_baton_error(error); if (!json_is_object(object)) { set_baton_error(error, -1, "Failed to add AVU data: " "target not a JSON object"); goto error; } return json_object_set_new(object, JSON_AVUS_KEY, avus); error: return error->code; }
int add_permissions(json_t *object, json_t *perms, baton_error_t *error) { init_baton_error(error); if (!json_is_object(object)) { set_baton_error(error, -1, "Failed to add permissions data: " "target not a JSON object"); goto error; } return json_object_set_new(object, JSON_ACCESS_KEY, perms); error: return error->code; }
int add_checksum(json_t *object, json_t *checksum, baton_error_t *error) { init_baton_error(error); if (!json_is_object(object)) { set_baton_error(error, -1, "Failed to add checksum data: " "target not a JSON object"); goto error; } return json_object_set_new(object, JSON_CHECKSUM_KEY, checksum); error: return error->code; }
json_t *collection_path_to_json(const char *path, baton_error_t *error) { init_baton_error(error); json_t *result = json_pack("{s:s}", JSON_COLLECTION_KEY, path); if (!result) { set_baton_error(error, -1, "Failed to pack collection '%s' as JSON", path); goto error; } return result; error: return NULL; }
json_t *get_specific(json_t *object, baton_error_t *error) { json_t *specific = get_json_value(object, "path spec", JSON_SPECIFIC_KEY, NULL, error); if (!json_is_object(specific)) { set_baton_error(error, CAT_INVALID_ARGUMENT, "Invalid '%s' attribute: not a JSON object", JSON_SPECIFIC_KEY); goto error; } return specific; error: return NULL; }
json_t *make_timestamp(const char* key, const char *value, const char *format, const char *replicate, baton_error_t *error) { init_baton_error(error); char *formatted = format_timestamp(value, format); json_t *result = json_pack("{s:s}", key, formatted); if (!result) { set_baton_error(error, -1, "Failed to pack timestamp '%s': '%s' as JSON", key, value); goto error; } if (replicate) { int base = 10; char *endptr; int repl = strtoul(replicate, &endptr, base); if (*endptr) { set_baton_error(error, -1, "Failed to parse replicate number from " "string '%s'", replicate); goto error; } json_object_set_new(result, JSON_REPLICATE_KEY, json_integer(repl)); } free(formatted); return result; error: if (formatted) free(formatted); return NULL; }
int add_timestamps(json_t *object, const char *created, const char *modified, const char *replicate, baton_error_t *error) { json_t *iso_created = NULL; // Ref to be stolen by result json_t *iso_modified = NULL; // Ref to be stolen by result json_t *timestamps; init_baton_error(error); if (!json_is_object(object)) { set_baton_error(error, -1, "Failed to add timestamp data: " "target not a JSON object"); goto error; } iso_created = make_timestamp(JSON_CREATED_KEY, created, ISO8601_FORMAT, replicate, error); if (error->code != 0) goto error; iso_modified = make_timestamp(JSON_MODIFIED_KEY, modified, ISO8601_FORMAT, replicate, error); if (error->code != 0) goto error; timestamps = json_pack("[o, o]", iso_created, iso_modified); if (!timestamps) { set_baton_error(error, -1, "Failed to pack timestamp array"); goto error; } return json_object_set_new(object, JSON_TIMESTAMPS_KEY, timestamps); error: if (iso_created) json_decref(iso_created); if (iso_modified) json_decref(iso_modified); return error->code; }
json_t *get_avus(json_t *object, baton_error_t *error) { init_baton_error(error); json_t *avus = get_json_value(object, "path spec", JSON_AVUS_KEY, NULL, error); if (error->code != 0) goto error; if (!json_is_array(avus)) { set_baton_error(error, CAT_INVALID_ARGUMENT, "Invalid '%s' attribute: not a JSON array", JSON_AVUS_KEY); goto error; } return avus; error: return NULL; }
json_t *data_object_parts_to_json(const char *coll_name, const char *data_name, baton_error_t *error) { init_baton_error(error); json_t *result = json_pack("{s:s, s:s}", JSON_COLLECTION_KEY, coll_name, JSON_DATA_OBJECT_KEY, data_name); if (!result) { set_baton_error(error, -1, "Failed to pack data object '%s/%s' as JSON", coll_name, data_name); goto error; } return result; error: return NULL; }
json_t *get_timestamps(json_t *object, baton_error_t *error) { init_baton_error(error); json_t *timestamps = get_json_value(object, "path spec", JSON_TIMESTAMPS_KEY, JSON_TIMESTAMPS_SHORT_KEY, error); if (error->code != 0) goto error; if (!json_is_array(timestamps)) { set_baton_error(error, CAT_INVALID_ARGUMENT, "Invalid '%s' attribute: not a JSON array", JSON_TIMESTAMPS_KEY); goto error; } return timestamps; error: return NULL; }
int do_modify_permissions(FILE *input, recursive_op recurse, option_flags oflags) { int item_count = 0; int error_count = 0; rodsEnv env; rcComm_t *conn = rods_login(&env); if (!conn) goto error; while (!feof(input)) { size_t flags = JSON_DISABLE_EOF_CHECK | JSON_REJECT_DUPLICATES; json_error_t load_error; json_t *target = json_loadf(input, flags, &load_error); if (!target) { if (!feof(input)) { logmsg(ERROR, "JSON error at line %d, column %d: %s", load_error.line, load_error.column, load_error.text); } continue; } item_count++; if (!json_is_object(target)) { logmsg(ERROR, "Item %d in stream was not a JSON object; skipping", item_count); error_count++; json_decref(target); continue; } baton_error_t path_error; char *path = json_to_path(target, &path_error); if (add_error_report(target, &path_error)) { error_count++; } else { json_t *perms = json_object_get(target, JSON_ACCESS_KEY); if (!json_is_array(perms)) { error_count++; set_baton_error(&path_error, -1, "Permissions data for %s is not in " "a JSON array", path); add_error_report(target, &path_error); } else { rodsPath_t rods_path; resolve_rods_path(conn, &env, &rods_path, path, oflags, &path_error); if (add_error_report(target, &path_error)) { error_count++; } else { for (size_t i = 0; i < json_array_size(perms); i++) { json_t *perm = json_array_get(perms, i); baton_error_t mod_error; modify_json_permissions(conn, &rods_path, recurse, perm, &mod_error); if (add_error_report(target, &mod_error)) { error_count++; } } if (rods_path.rodsObjStat) free(rods_path.rodsObjStat); } } } print_json(target); if (unbuffered_flag) fflush(stdout); json_decref(target); if (path) free(path); } // while rcDisconnect(conn); if (error_count > 0) { logmsg(WARN, "Processed %d items with %d errors", item_count, error_count); } else { logmsg(DEBUG, "Processed %d items with %d errors", item_count, error_count); } return error_count; error: if (conn) rcDisconnect(conn); logmsg(ERROR, "Processed %d items with %d errors", item_count, error_count); return 1; }
int do_list_paths(FILE *input, print_flags pflags) { int path_count = 0; int error_count = 0; rodsEnv env; rcComm_t *conn = rods_login(&env); if (!conn) goto error; size_t jflags = JSON_DISABLE_EOF_CHECK | JSON_REJECT_DUPLICATES; while (!feof(input)) { json_error_t load_error; json_t *target = json_loadf(input, jflags, &load_error); if (!target) { if (!feof(input)) { log(ERROR, "JSON error at line %d, column %d: %s", load_error.line, load_error.column, load_error.text); } continue; } baton_error_t path_error; char *path = json_to_path(target, &path_error); path_count++; if (path_error.code != 0) { error_count++; add_error_value(target, &path_error); print_json(target); } else { rodsPath_t rods_path; int status = resolve_rods_path(conn, &env, &rods_path, path); if (status < 0) { error_count++; set_baton_error(&path_error, status, "Failed to resolve path '%s'", path); add_error_value(target, &path_error); print_json(target); } else { baton_error_t error; json_t *results = list_path(conn, &rods_path, pflags, &error); if (error.code != 0) { error_count++; add_error_value(target, &error); print_json(target); } else { print_json(results); json_decref(results); } } if (rods_path.rodsObjStat) free(rods_path.rodsObjStat); } if (unbuffered_flag) fflush(stdout); json_decref(target); free(path); } // while rcDisconnect(conn); log(DEBUG, "Processed %d paths with %d errors", path_count, error_count); return error_count; error: if (conn) rcDisconnect(conn); log(ERROR, "Processed %d paths with %d errors", path_count, error_count); return 1; }
json_t *make_replicate(const char *resource, const char *location, const char *checksum, const char *replicate, const char *status, baton_error_t *error) { json_t *result = NULL; json_t *is_valid = NULL; // Ref to be stolen by result json_t *ck_value = NULL; // Ref to be stolen by result init_baton_error(error); int base = 10; char *endptr; int repl = strtoul(replicate, &endptr, base); if (*endptr) { set_baton_error(error, -1, "Failed to parse replicate number from string '%s'", replicate); goto error; } if (str_equals(status, INVALID_REPLICATE, 1)) { is_valid = json_false(); } else if (str_equals(status, VALID_REPLICATE, 1)) { is_valid = json_true(); } else { set_baton_error(error, CAT_INVALID_ARGUMENT, "Invalid replicate status '%s'", status); goto error; } if (checksum) { ck_value = json_string(checksum); } else { ck_value = json_null(); } result = json_pack("{s:s, s:s, s:o, s:i, s:o}", JSON_RESOURCE_KEY, resource, JSON_LOCATION_KEY, location, JSON_CHECKSUM_KEY, ck_value, JSON_REPLICATE_NUMBER_KEY, repl, JSON_REPLICATE_STATUS_KEY, is_valid); if (!result) { set_baton_error(error, -1, "Failed to pack replicate object"); goto error; } return result; error: if (result) { json_decref(result); } else { // Only decref these if they were not stolen by a succesfully // created result if (is_valid) json_decref(is_valid); if (ck_value) json_decref(ck_value); } return NULL; }