1 /* librepo - A library providing (libcURL like) API to downloading repository
2 * Copyright (C) 2013 Tomas Mlcoch
3 *
4 * Licensed under the GNU Lesser General Public License Version 2.1
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #include <glib.h>
22 #include <assert.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <glib/gprintf.h>
26
27 #include "util.h"
28 #include "downloadtarget.h"
29 #include "downloadtarget_internal.h"
30 #include "cleanup.h"
31 #include "handle_internal.h"
32
33 LrDownloadTargetChecksum *
lr_downloadtargetchecksum_new(LrChecksumType type,const gchar * value)34 lr_downloadtargetchecksum_new(LrChecksumType type, const gchar *value)
35 {
36 LrDownloadTargetChecksum *dtch = lr_malloc0(sizeof(*dtch));
37 dtch->type = type;
38 dtch->value = g_strdup(value);
39 return dtch;
40 }
41
42 void
lr_downloadtargetchecksum_free(LrDownloadTargetChecksum * dtch)43 lr_downloadtargetchecksum_free(LrDownloadTargetChecksum *dtch)
44 {
45 if (!dtch) return;
46 g_free(dtch->value);
47 g_free(dtch);
48 }
49
50 LrDownloadTarget *
lr_downloadtarget_new(LrHandle * handle,const char * path,const char * baseurl,int fd,const char * fn,GSList * possiblechecksums,gint64 expectedsize,gboolean resume,LrProgressCb progresscb,void * cbdata,LrEndCb endcb,LrMirrorFailureCb mirrorfailurecb,void * userdata,gint64 byterangestart,gint64 byterangeend,char * range,gboolean no_cache,gboolean is_zchunk)51 lr_downloadtarget_new(LrHandle *handle,
52 const char *path,
53 const char *baseurl,
54 int fd,
55 const char *fn,
56 GSList *possiblechecksums,
57 gint64 expectedsize,
58 gboolean resume,
59 LrProgressCb progresscb,
60 void *cbdata,
61 LrEndCb endcb,
62 LrMirrorFailureCb mirrorfailurecb,
63 void *userdata,
64 gint64 byterangestart,
65 gint64 byterangeend,
66 char *range,
67 gboolean no_cache,
68 gboolean is_zchunk)
69 {
70 LrDownloadTarget *target;
71 _cleanup_free_ gchar *final_path = NULL;
72 _cleanup_free_ gchar *final_baseurl = NULL;
73
74 assert(path);
75 assert((fd >= 0 && !fn) || (fd < 0 && fn));
76
77 if (byterangestart && resume) {
78 g_warning("Cannot specify byterangestart and set resume to TRUE at the same time");
79 return NULL;
80 }
81
82 // Substitute variables in URLs
83 if (handle && handle->urlvars) {
84 final_path = lr_url_substitute(path, handle->urlvars);
85 final_baseurl = lr_url_substitute(baseurl, handle->urlvars);
86 } else {
87 final_path = g_strdup(path);
88 final_baseurl = g_strdup(baseurl);
89 }
90
91
92 target = lr_malloc0(sizeof(*target));
93
94 target->handle = handle;
95 target->chunk = g_string_chunk_new(0);
96 target->path = g_string_chunk_insert(target->chunk, final_path);
97 target->baseurl = lr_string_chunk_insert(target->chunk, final_baseurl);
98 target->fd = fd;
99 target->fn = lr_string_chunk_insert(target->chunk, fn);
100 target->checksums = possiblechecksums;
101 target->expectedsize = expectedsize;
102 target->origsize = expectedsize;
103 target->resume = resume;
104 target->progresscb = progresscb;
105 target->cbdata = cbdata;
106 target->endcb = endcb;
107 target->mirrorfailurecb = mirrorfailurecb;
108 target->rcode = LRE_UNFINISHED;
109 target->userdata = userdata;
110 target->byterangestart = byterangestart;
111 target->byterangeend = byterangeend;
112 target->range = range;
113 target->no_cache = no_cache;
114 target->is_zchunk = is_zchunk;
115
116 return target;
117 }
118
119 void
lr_downloadtarget_reset(LrDownloadTarget * target)120 lr_downloadtarget_reset(LrDownloadTarget *target)
121 {
122 if (!target)
123 return;
124
125 target->usedmirror = NULL;
126 target->effectiveurl = NULL;
127 target->rcode = LRE_OK;
128 target->err = NULL;
129 }
130
131 void
lr_downloadtarget_free(LrDownloadTarget * target)132 lr_downloadtarget_free(LrDownloadTarget *target)
133 {
134 if (!target)
135 return;
136
137 g_slist_free_full(target->checksums,
138 (GDestroyNotify) lr_downloadtargetchecksum_free);
139 g_string_chunk_free(target->chunk);
140 lr_free(target);
141 }
142
143 void
lr_downloadtarget_set_error(LrDownloadTarget * target,LrRc code,const char * format,...)144 lr_downloadtarget_set_error(LrDownloadTarget *target,
145 LrRc code,
146 const char *format,
147 ...)
148 {
149 assert(target);
150 assert(code == LRE_OK || format);
151
152 if (format) {
153 int ret;
154 va_list vl;
155 gchar *message = NULL;
156
157 va_start(vl, format);
158 ret = g_vasprintf(&message, format, vl);
159 va_end(vl);
160
161 if (ret < 0) {
162 assert(0);
163 target->err = "";
164 return;
165 }
166
167 target->err = lr_string_chunk_insert(target->chunk, message);
168 g_free(message);
169 } else {
170 target->err = NULL;
171 }
172
173 target->rcode = code;
174 }
175
176 void
lr_downloadtarget_set_usedmirror(LrDownloadTarget * target,const char * url)177 lr_downloadtarget_set_usedmirror(LrDownloadTarget *target, const char *url)
178 {
179 assert(target);
180 target->usedmirror = lr_string_chunk_insert(target->chunk, url);
181 }
182
183 void
lr_downloadtarget_set_effectiveurl(LrDownloadTarget * target,const char * url)184 lr_downloadtarget_set_effectiveurl(LrDownloadTarget *target, const char *url)
185 {
186 assert(target);
187 target->effectiveurl = lr_string_chunk_insert(target->chunk, url);
188 }
189