Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Store etag in xattr #8

Merged
merged 2 commits into from
Dec 4, 2015
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
137 changes: 111 additions & 26 deletions src/download.c
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,106 @@ void a_try_decompress_file (gchar *name)
#endif
}

#define VIKING_ETAG_XATTR "xattr::viking.etag"

static gboolean get_etag_xattr(const char *fn, DownloadFileOptions *file_options)
{
gboolean result = FALSE;
GFileInfo *fileinfo;
GFile *file;

file = g_file_new_for_path(fn);
fileinfo = g_file_query_info(file, VIKING_ETAG_XATTR, G_FILE_QUERY_INFO_NONE, NULL, NULL);
if (fileinfo) {
const char *etag = g_file_info_get_attribute_string(fileinfo, VIKING_ETAG_XATTR);
if (etag) {
file_options->etag = g_strdup(etag);
result = !!file_options->etag;
}
g_object_unref(fileinfo);
}
g_object_unref(file);

if (result)
g_debug("%s: Get etag (xattr) from %s: %s", __FUNCTION__, fn, file_options->etag);

return result;
}

static gboolean get_etag_file(const char *fn, DownloadFileOptions *file_options)
{
gboolean result = FALSE;
gchar *etag_filename;

etag_filename = g_strdup_printf("%s.etag", fn);
if (etag_filename) {
result = g_file_get_contents(etag_filename, &file_options->etag, NULL, NULL);
g_free(etag_filename);
}

if (result)
g_debug("%s: Get etag (file) from %s: %s", __FUNCTION__, fn, file_options->etag);

return result;
}

static void get_etag(const char *fn, DownloadFileOptions *file_options)
{
/* first try to get etag from xattr, then fall back to plain file */
if (!get_etag_xattr(fn, file_options) && !get_etag_file(fn, file_options)) {
g_debug("%s: Failed to get etag from %s", __FUNCTION__, fn);
return;
}

/* check if etag is short enough */
if (strlen(file_options->etag) > 100) {
g_free(file_options->etag);
file_options->etag = NULL;
}

/* TODO: should check that etag is a valid string */
}

static gboolean set_etag_xattr(const char *fn, DownloadFileOptions *file_options)
{
gboolean result = FALSE;
GFile *file;

file = g_file_new_for_path(fn);
result = g_file_set_attribute_string(file, VIKING_ETAG_XATTR, file_options->new_etag, G_FILE_QUERY_INFO_NONE, NULL, NULL);
g_object_unref(file);

if (result)
g_debug("%s: Set etag (xattr) on %s: %s", __FUNCTION__, fn, file_options->new_etag);

return result;
}

static gboolean set_etag_file(const char *fn, DownloadFileOptions *file_options)
{
gboolean result = FALSE;
gchar *etag_filename;

etag_filename = g_strdup_printf("%s.etag", fn);
if (etag_filename) {
result = g_file_set_contents(etag_filename, file_options->new_etag, -1, NULL);
g_free(etag_filename);
}

if (result)
g_debug("%s: Set etag (file) on %s: %s", __FUNCTION__, fn, file_options->new_etag);

return result;
}

static void set_etag(const char *fn, const char *fntmp, DownloadFileOptions *file_options)
{
/* first try to store etag in extended attribute, then fall back to plain file */
if (!set_etag_xattr(fntmp, file_options) && !set_etag_file(fn, file_options)) {
g_debug("%s: Failed to set etag on %s", __FUNCTION__, fn);
}
}

static DownloadResult_t download( const char *hostname, const char *uri, const char *fn, DownloadMapOptions *options, gboolean ftp, void *handle)
{
FILE *f;
Expand Down Expand Up @@ -291,19 +391,7 @@ static DownloadResult_t download( const char *hostname, const char *uri, const c
file_options.time_condition = file_time;
}
if (options != NULL && options->use_etag) {
gchar *etag_filename = g_strdup_printf("%s.etag", fn);
gsize etag_length = 0;
g_file_get_contents (etag_filename, &(file_options.etag), &etag_length, NULL);
g_free (etag_filename);
etag_filename = NULL;

/* check if etag is short enough */
if (etag_length > 100) {
g_free(file_options.etag);
file_options.etag = NULL;
}

/* TODO: should check that etag is a valid string */
get_etag(fn, &file_options);
}

} else {
Expand Down Expand Up @@ -365,19 +453,6 @@ static DownloadResult_t download( const char *hostname, const char *uri, const c
return result;
}

if ( options != NULL && options->convert_file )
options->convert_file ( tmpfilename );

if ( options != NULL && options->use_etag ) {
if (file_options.new_etag) {
/* server returned an etag value */
gchar *etag_filename = g_strdup_printf("%s.etag", fn);
g_file_set_contents (etag_filename, file_options.new_etag, -1, NULL);
g_free (etag_filename);
etag_filename = NULL;
}
}

if (ret == CURL_DOWNLOAD_NO_NEWER_FILE) {
(void)g_remove ( tmpfilename );
// update mtime of local copy
Expand All @@ -386,6 +461,16 @@ static DownloadResult_t download( const char *hostname, const char *uri, const c
if ( g_utime ( fn, NULL ) != 0 )
g_warning ( "%s couldn't set time on: %s", __FUNCTION__, fn );
} else {
if ( options != NULL && options->convert_file )
options->convert_file ( tmpfilename );

if ( options != NULL && options->use_etag ) {
if (file_options.new_etag) {
/* server returned an etag value */
set_etag(fn, tmpfilename, &file_options);
}
}

/* move completely-downloaded file to permanent location */
if ( g_rename ( tmpfilename, fn ) )
g_warning ("%s: file rename failed [%s] to [%s]", __FUNCTION__, tmpfilename, fn );
Expand Down