📄 s3-device.c
字号:
case ACCESS_WRITE: /* delete all files */ last_file = find_last_file(self); if (last_file < 0) return FALSE; for (file = 0; file <= last_file; file++) { if (!delete_file(self, file)) return FALSE; } /* write a new amanda header */ if (!write_amanda_header(self, label, timestamp)) { return FALSE; } break; case ACCESS_APPEND: return seek_to_end(self); break; case ACCESS_NULL: g_assert_not_reached(); } g_assert(pself->access_mode == mode); return TRUE;}/* }}} */static gboolean s3_device_property_get(Device * p_self, DevicePropertyId id, GValue * val) { S3Device * self; const DevicePropertyBase * base; self = S3_DEVICE(p_self); g_return_val_if_fail(self != NULL, FALSE); base = device_property_get_by_id(id); g_return_val_if_fail(self != NULL, FALSE); g_value_unset_init(val, base->type); if (id == PROPERTY_S3_SECRET_KEY) { if (self->secret_key != NULL) { g_value_set_string(val, self->secret_key); return TRUE; } else { return FALSE; } } else if (id == PROPERTY_S3_ACCESS_KEY) { if (self->access_key != NULL) { g_value_set_string(val, self->access_key); return TRUE; } else { return FALSE; } }#ifdef WANT_DEVPAY else if (id == PROPERTY_S3_USER_TOKEN) { if (self->user_token != NULL) { g_value_set_string(val, self->user_token); return TRUE; } else { return FALSE; } }#endif /* WANT_DEVPAY */ else if (id == PROPERTY_VERBOSE) { g_value_set_boolean(val, self->verbose); return TRUE; } else { /* chain up */ if (parent_class->property_get) { return (parent_class->property_get)(p_self, id, val); } else { return FALSE; } } g_assert_not_reached();}static gboolean s3_device_property_set(Device * p_self, DevicePropertyId id, GValue * val) { S3Device * self; const DevicePropertyBase * base; self = S3_DEVICE(p_self); g_return_val_if_fail(self != NULL, FALSE); base = device_property_get_by_id(id); g_return_val_if_fail(self != NULL, FALSE); g_return_val_if_fail(G_VALUE_HOLDS(val, base->type), FALSE); if (id == PROPERTY_S3_SECRET_KEY) { if (p_self->access_mode != ACCESS_NULL) return FALSE; amfree(self->secret_key); self->secret_key = g_value_dup_string(val); device_clear_volume_details(p_self); return TRUE; } else if (id == PROPERTY_S3_ACCESS_KEY) { if (p_self->access_mode != ACCESS_NULL) return FALSE; amfree(self->access_key); self->access_key = g_value_dup_string(val); device_clear_volume_details(p_self); return TRUE; }#ifdef WANT_DEVPAY else if (id == PROPERTY_S3_USER_TOKEN) { if (p_self->access_mode != ACCESS_NULL) return FALSE; amfree(self->user_token); self->user_token = g_value_dup_string(val); device_clear_volume_details(p_self); return TRUE; }#endif /* WANT_DEVPAY */ else if (id == PROPERTY_VERBOSE) { self->verbose = g_value_get_boolean(val); /* Our S3 handle may not yet have been instantiated; if so, it will * get the proper verbose setting when it is created */ if (self->s3) s3_verbose(self->s3, self->verbose); return TRUE; } else { if (parent_class->property_set) { return (parent_class->property_set)(p_self, id, val); } else { return FALSE; } } g_assert_not_reached();}/* functions for writing *//* {{{ s3_device_start_file */static gbooleans3_device_start_file (Device *pself, const dumpfile_t *jobInfo) { S3Device *self = S3_DEVICE(pself); char *amanda_header; int header_size; gboolean header_fits, result; char *key; g_return_val_if_fail (self != NULL, FALSE); /* Build the amanda header. */ amanda_header = device_build_amanda_header(pself, jobInfo, &header_size, &header_fits); g_return_val_if_fail(amanda_header != NULL, FALSE); g_return_val_if_fail(header_fits, FALSE); /* set the file and block numbers correctly */ pself->file = (pself->file > 0)? pself->file+1 : 1; pself->block = 0; pself->in_file = TRUE; /* write it out as a special block (not the 0th) */ key = special_file_to_key(self, "filestart", pself->file); result = s3_upload(self->s3, self->bucket, key, amanda_header, header_size); g_free(amanda_header); g_free(key); if (!result) { fprintf(stderr, _("While writing filestart header: %s\n"), s3_strerror(self->s3)); return FALSE; } return TRUE;}/* }}} *//* {{{ s3_device_write_block */static gbooleans3_device_write_block (Device * pself, guint size, gpointer data, gboolean last_block) { gboolean result; char *filename; S3Device * self = S3_DEVICE(pself);; g_assert (self != NULL); g_assert (data != NULL); filename = file_and_block_to_key(self, pself->file, pself->block); result = s3_upload(self->s3, self->bucket, filename, data, size); g_free(filename); if (!result) { fprintf(stderr, _("While writing data block to S3: %s\n"), s3_strerror(self->s3)); return FALSE; } pself->block++; /* if this is the last block, finish the file */ if (last_block) { return s3_device_finish_file(pself); } return TRUE;}/* }}} *//* {{{ s3_device_finish_file */static gbooleans3_device_finish_file (Device * pself) { /* we're not in a file anymore */ pself->in_file = FALSE; return TRUE;}/* }}} *//* {{{ s3_device_recycle_file */static gbooleans3_device_recycle_file(Device *pself, guint file) { S3Device *self = S3_DEVICE(pself); return delete_file(self, file);}/* }}} *//* functions for reading *//* {{{ s3_device_seek_file */static dumpfile_t*s3_device_seek_file(Device *pself, guint file) { S3Device *self = S3_DEVICE(pself); gboolean result; char *key; gpointer buf; guint buf_size; dumpfile_t *amanda_header; pself->file = file; pself->block = 0; pself->in_file = TRUE; /* read it in */ key = special_file_to_key(self, "filestart", pself->file); result = s3_read(self->s3, self->bucket, key, &buf, &buf_size, S3_DEVICE_MAX_BLOCK_SIZE); g_free(key); if (!result) { guint response_code; s3_error_code_t s3_error_code; s3_error(self->s3, NULL, &response_code, &s3_error_code, NULL, NULL, NULL); /* if it's an expected error (not found), check what to do. */ if (response_code == 404 && s3_error_code == S3_ERROR_NoSuchKey) { int next_file; pself->file = -1; pself->in_file = FALSE; next_file = find_next_file(self, pself->file); if (next_file > 0) { /* Note short-circut of dispatcher. */ return s3_device_seek_file(pself, next_file); } else if (next_file == 0) { /* No next file. Check if we are one past the end. */ key = special_file_to_key(self, "filestart", pself->file - 1); result = s3_read(self->s3, self->bucket, key, &buf, &buf_size, S3_DEVICE_MAX_BLOCK_SIZE); g_free(key); if (result) { return make_tapeend_header(); } else { return NULL; } } } else { /* An error occured finding out if we are the last file. */ return NULL; } } /* and make a dumpfile_t out of it */ g_assert(buf != NULL); amanda_header = g_new(dumpfile_t, 1); fh_init(amanda_header); parse_file_header(buf, amanda_header, buf_size); g_free(buf); switch (amanda_header->type) { case F_DUMPFILE: case F_CONT_DUMPFILE: case F_SPLIT_DUMPFILE: return amanda_header; default: fprintf(stderr, _("Invalid amanda header while reading file header\n")); g_free(amanda_header); return NULL; }}/* }}} *//* {{{ s3_device_seek_block */static gbooleans3_device_seek_block(Device *pself, guint64 block) { pself->block = block; return TRUE;}/* }}} *//* {{{ s3_device_read_block */static ints3_device_read_block (Device * pself, gpointer data, int *size_req) { S3Device * self = S3_DEVICE(pself); char *key; gpointer buf; gboolean result; guint buf_size; g_assert (self != NULL); /* get the file*/ key = file_and_block_to_key(self, pself->file, pself->block); g_assert(key != NULL); if (self->cached_key && (0 == strcmp(key, self->cached_key))) { /* use the cached copy and clear the cache */ buf = self->cached_buf; buf_size = self->cached_size; self->cached_buf = NULL; g_free(self->cached_key); self->cached_key = NULL; } else { /* clear the cache and actually download the file */ if (self->cached_buf) { g_free(self->cached_buf); self->cached_buf = NULL; } if (self->cached_key) { g_free(self->cached_key); self->cached_key = NULL; } result = s3_read(self->s3, self->bucket, key, &buf, &buf_size, S3_DEVICE_MAX_BLOCK_SIZE); if (!result) { guint response_code; s3_error_code_t s3_error_code; s3_error(self->s3, NULL, &response_code, &s3_error_code, NULL, NULL, NULL); g_free(key); key = NULL; /* if it's an expected error (not found), just return -1 */ if (response_code == 404 && s3_error_code == S3_ERROR_NoSuchKey) { pself->is_eof = TRUE; return -1; } /* otherwise, log it and return FALSE */ fprintf(stderr, _("While reading data block from S3: %s\n"), s3_strerror(self->s3)); return -1; } } /* INVARIANT: cache is NULL */ g_assert(self->cached_buf == NULL); g_assert(self->cached_key == NULL); /* now see how the caller wants to deal with that */ if (data == NULL || *size_req < 0 || buf_size > (guint)*size_req) { /* A size query or short buffer -- load the cache and return the size*/ self->cached_buf = buf; self->cached_key = key; self->cached_size = buf_size; *size_req = buf_size; return 0; } else { /* ok, all checks are passed -- copy the data */ *size_req = buf_size; g_memmove(data, buf, buf_size); g_free(key); g_free(buf); /* move on to the next block */ pself->block++; return buf_size; }}/* }}} */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -