/* return the fd of a local copy, to operate on */ int dfs_get_local_copy(pentry_t *pe, const char * const remote, int flags) { int fd; dpl_dict_t *metadata = NULL; dpl_dict_t *headers = NULL; struct get_data get_data = { .fd = -1, .buf = NULL }; dpl_status_t rc = DPL_FAILURE; char *local = NULL; unsigned encryption = 0; local = tmpstr_printf("%s%s", conf->cache_dir, remote); LOG(LOG_DEBUG, "bucket=%s, path=%s, local=%s", ctx->cur_bucket, remote, local); if (-1 == download_headers((char *)remote, &headers)) { LOG(LOG_NOTICE, "%s: can't download headers", remote); fd = -1; goto end; } metadata = dpl_dict_new(13); if (! metadata) { LOG(LOG_ERR, "dpl_dict_new: can't allocate memory"); fd = -1; goto end; } if (DPL_FAILURE == dpl_get_metadata_from_headers( #if defined(DPL_VERSION_MAJOR) && defined(DPL_VERSION_MINOR) && (DPL_VERSION_MAJOR == 0 && DPL_VERSION_MINOR >= 2) || (DPL_VERSION_MAJOR > 0) ctx, #endif headers, metadata)) { LOG(LOG_ERR, "%s: metadata extraction failed", remote); fd = -1; goto end; } if (-1 == pentry_set_metadata(pe, metadata)) { LOG(LOG_ERR, "can't update metadata"); fd = -1; goto end; } if (-1 == check_permissions(pe, metadata)) { LOG(LOG_NOTICE, "permission denied"); fd = -1; goto end; } /* If the remote MD5 matches a cache file, we don't have to download * it again, just return the (open) file descriptor of the cache file */ if (0 == compare_digests(pe, headers)) { fd = pentry_get_fd(pe); goto end; } /* a cache file already exists, its MD5 digest is different, so * just remove it */ if (0 == access(local, F_OK)) { LOG(LOG_DEBUG, "removing cache file '%s'", local); if (-1 == unlink(local)) LOG(LOG_ERR, "unlink(%s): %s", local, strerror(errno)); } get_data.fd = open(local, O_RDWR|O_CREAT|O_TRUNC, 0600); if (-1 == get_data.fd) { LOG(LOG_ERR, "open: %s: %s (%d)", local, strerror(errno), errno); fd = -1; goto end; } encryption = check_encryption_flag(metadata); rc = dpl_openread(ctx, (char *)remote, encryption, NULL, cb_get_buffered, &get_data, &metadata); if (DPL_SUCCESS != rc) { LOG(LOG_ERR, "dpl_openread: %s", dpl_status_str(rc)); close(get_data.fd); fd = -1; goto end; } /* If the file is compressed, uncompress it! */ if(-1 == handle_compression(remote, local, &get_data, metadata)) { fd = -1; goto end; } if (-1 == close(get_data.fd)) { LOG(LOG_ERR, "close(path=%s, fd=%d): %s", local, get_data.fd, strerror(errno)); fd = -1; goto end; } fd = open(local, flags, 0600); if (-1 == fd) { LOG(LOG_ERR, "open(path=%s, fd=%d): %s", local, fd, strerror(errno)); fd = -1; goto end; } end: if (metadata) dpl_dict_free(metadata); if (headers) dpl_dict_free(headers); return fd; }
int cmd_get(int argc, char **argv) { int ret; char opt; char *path = NULL; dpl_dict_t *metadata = NULL; struct get_data get_data; int do_stdout = 0; int kflag = 0; char *local_file = NULL; int start = -1; int start_inited = 0; int end = -1; int end_inited = 0; int mflag = 0; memset(&get_data, 0, sizeof (get_data)); get_data.fd = -1; var_set("status", "1", VAR_CMD_SET, NULL); optind = 0; while ((opt = getopt(argc, argv, usage_getoptstr(get_usage))) != -1) switch (opt) { case 'm': mflag = 1; break ; case 's': start = strtol(optarg, NULL, 0); start_inited = 1; break ; case 'e': end = strtol(optarg, NULL, 0); end_inited = 1; break ; case 'k': kflag = 1; break ; case '?': default: usage_help(&get_cmd); return SHELL_CONT; } argc -= optind; argv += optind; if (start_inited != end_inited) { fprintf(stderr, "please provide -s and -e\n"); return SHELL_CONT; } if (2 == argc) { path = argv[0]; local_file = argv[1]; } else if (1 == argc) { path = argv[0]; local_file = rindex(path, '/'); if (NULL != local_file) local_file++; else local_file = path; } else { usage_help(&get_cmd); return SHELL_CONT; } if (!strcmp(local_file, "-")) { get_data.fd = 1; do_stdout = 1; } else if ('|' == local_file[0]) { get_data.pipe = popen(local_file + 1, "w"); if (NULL == get_data.pipe) { fprintf(stderr, "pipe failed\n"); goto end; } } else { ret = access(local_file, F_OK); if (0 == ret) { if (1 == ask_for_confirmation("file already exists, overwrite?")) return SHELL_CONT; } get_data.fd = open(local_file, O_WRONLY|O_CREAT, 0600); if (-1 == get_data.fd) { perror("open"); goto end; } } if (1 == start_inited && 1 == end_inited) { char *data_buf; u_int data_len; ret = dpl_openread_range(ctx, path, (1 == kflag ? DPL_VFILE_FLAG_ENCRYPT : 0u), NULL, start, end, &data_buf, &data_len, &metadata); if (DPL_SUCCESS != ret) { fprintf(stderr, "status: %s (%d)\n", dpl_status_str(ret), ret); goto end; } ret = write_all(get_data.fd, data_buf, data_len); free(data_buf); if (0 != ret) { fprintf(stderr, "short write\n"); goto end; } if (1 == mflag) dpl_dict_iterate(metadata, cb_print_metadata, NULL); } else { ret = dpl_openread(ctx, path, (1 == kflag ? DPL_VFILE_FLAG_ENCRYPT : 0u), NULL, cb_get_buffered, &get_data, &metadata); if (DPL_SUCCESS != ret) { fprintf(stderr, "status: %s (%d)\n", dpl_status_str(ret), ret); goto end; } if (1 == mflag) dpl_dict_iterate(metadata, cb_print_metadata, NULL); } var_set("status", "0", VAR_CMD_SET, NULL); end: if (NULL != metadata) dpl_dict_free(metadata); if (0 == do_stdout) { if (-1 != get_data.fd) close(get_data.fd); if (NULL != get_data.pipe) pclose(get_data.pipe); } return SHELL_CONT; }