Skip to content

Commit f42264d

Browse files
committed
Added single file mode
Implemented feature request #86
1 parent af45bcf commit f42264d

5 files changed

Lines changed: 155 additions & 146 deletions

File tree

src/cache.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -666,11 +666,15 @@ int Cache_create(const char *path)
666666
{
667667
Link *this_link = path_to_Link(path);
668668

669-
char *fn = "";
669+
char *fn = "__UNINITIALISED__";
670670
if (CONFIG.mode == NORMAL) {
671671
fn = curl_easy_unescape(NULL,
672672
this_link->f_url + ROOT_LINK_OFFSET, 0,
673673
NULL);
674+
} else if (CONFIG.mode == SINGLE) {
675+
fn = curl_easy_unescape(NULL,
676+
this_link->linkname, 0,
677+
NULL);
674678
} else if (CONFIG.mode == SONIC) {
675679
fn = this_link->sonic_id;
676680
} else {
@@ -751,7 +755,7 @@ Cache *Cache_open(const char *fn)
751755
/*
752756
* Check if both metadata and data file exist
753757
*/
754-
if (CONFIG.mode == NORMAL) {
758+
if (CONFIG.mode == NORMAL || CONFIG.mode == SINGLE) {
755759
if (Cache_exist(fn)) {
756760

757761
lprintf(cache_lock_debug,

src/config.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
typedef enum {
3030
NORMAL = 1,
3131
SONIC = 2,
32-
SINGLE_FILE = 3,
32+
SINGLE = 3,
3333
} OperationMode;
3434

3535
/**

src/fuse_local.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ fs_readdir(const char *path, void *buf, fuse_fill_dir_t dir_add,
152152
*/
153153
dir_add(buf, ".", NULL, 0);
154154
dir_add(buf, "..", NULL, 0);
155+
/* We skip the head link */
155156
for (int i = 1; i < linktbl->num; i++) {
156157
Link *link = linktbl->links[i];
157158
if (link->type != LINK_INVALID) {

src/link.c

Lines changed: 146 additions & 142 deletions
Original file line numberDiff line numberDiff line change
@@ -29,17 +29,155 @@ int ROOT_LINK_OFFSET = 0;
2929
*/
3030
static pthread_mutex_t link_lock;
3131

32+
/**
33+
* \brief create a new Link
34+
*/
35+
static Link *Link_new(const char *linkname, LinkType type)
36+
{
37+
Link *link = CALLOC(1, sizeof(Link));
38+
39+
strncpy(link->linkname, linkname, MAX_FILENAME_LEN);
40+
link->type = type;
41+
42+
/*
43+
* remove the '/' from linkname if it exists
44+
*/
45+
char *c =
46+
&(link->linkname[strnlen(link->linkname, MAX_FILENAME_LEN) - 1]);
47+
if (*c == '/') {
48+
*c = '\0';
49+
}
50+
51+
return link;
52+
}
53+
54+
static CURL *Link_to_curl(Link * link)
55+
{
56+
CURL *curl = curl_easy_init();
57+
if (!curl) {
58+
lprintf(fatal, "curl_easy_init() failed!\n");
59+
}
60+
/*
61+
* set up some basic curl stuff
62+
*/
63+
curl_easy_setopt(curl, CURLOPT_USERAGENT, CONFIG.user_agent);
64+
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
65+
/*
66+
* for following directories without the '/'
67+
*/
68+
curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 2);
69+
curl_easy_setopt(curl, CURLOPT_URL, link->f_url);
70+
curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1);
71+
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 15);
72+
curl_easy_setopt(curl, CURLOPT_SHARE, CURL_SHARE);
73+
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_memory_callback);
74+
if (CONFIG.insecure_tls) {
75+
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
76+
}
77+
// curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
78+
79+
if (CONFIG.http_username) {
80+
curl_easy_setopt(curl, CURLOPT_USERNAME, CONFIG.http_username);
81+
}
82+
83+
if (CONFIG.http_password) {
84+
curl_easy_setopt(curl, CURLOPT_PASSWORD, CONFIG.http_password);
85+
}
86+
87+
if (CONFIG.proxy) {
88+
curl_easy_setopt(curl, CURLOPT_PROXY, CONFIG.proxy);
89+
}
90+
91+
if (CONFIG.proxy_username) {
92+
curl_easy_setopt(curl, CURLOPT_PROXYUSERNAME,
93+
CONFIG.proxy_username);
94+
}
95+
96+
if (CONFIG.proxy_password) {
97+
curl_easy_setopt(curl, CURLOPT_PROXYPASSWORD,
98+
CONFIG.proxy_password);
99+
}
100+
101+
return curl;
102+
}
103+
104+
static void Link_req_file_stat(Link * this_link)
105+
{
106+
CURL *curl = Link_to_curl(this_link);
107+
curl_easy_setopt(curl, CURLOPT_NOBODY, 1);
108+
curl_easy_setopt(curl, CURLOPT_FILETIME, 1L);
109+
110+
/*
111+
* We need to put the variable on the heap, because otherwise the
112+
* variable gets popped from the stack as the function returns.
113+
*
114+
* It gets freed in curl_multi_perform_once();
115+
*/
116+
TransferStruct *transfer = CALLOC(1, sizeof(TransferStruct));
117+
118+
transfer->link = this_link;
119+
transfer->type = FILESTAT;
120+
curl_easy_setopt(curl, CURLOPT_PRIVATE, transfer);
121+
122+
transfer_nonblocking(curl);
123+
}
124+
125+
/**
126+
* \brief Fill in the uninitialised entries in a link table
127+
* \details Try and get the stats for each link in the link table. This will get
128+
* repeated until the uninitialised entry count drop to zero.
129+
*/
130+
static void LinkTable_uninitialised_fill(LinkTable * linktbl)
131+
{
132+
int u;
133+
char s[STATUS_LEN];
134+
lprintf(debug, "LinkTable_uninitialised_fill(): ... ");
135+
do {
136+
u = 0;
137+
for (int i = 0; i < linktbl->num; i++) {
138+
Link *this_link = linktbl->links[i];
139+
if (this_link->type == LINK_UNINITIALISED_FILE) {
140+
Link_req_file_stat(linktbl->links[i]);
141+
u++;
142+
}
143+
}
144+
/*
145+
* Block until the gaps are filled
146+
*/
147+
int n = curl_multi_perform_once();
148+
int i = 0;
149+
int j = 0;
150+
while ((i = curl_multi_perform_once())) {
151+
if (CONFIG.log_type & debug) {
152+
if (j) {
153+
erase_string(stderr, STATUS_LEN, s);
154+
}
155+
snprintf(s, STATUS_LEN, "%d / %d", n - i, n);
156+
fprintf(stderr, "%s", s);
157+
j++;
158+
}
159+
}
160+
}
161+
while (u);
162+
if (CONFIG.log_type & debug) {
163+
erase_string(stderr, STATUS_LEN, s);
164+
fprintf(stderr, "... Done!\n");
165+
}
166+
}
167+
32168
/**
33169
* \brief Create the root linktable for single file mode
34170
*/
35171
static LinkTable *single_LinkTable_new(const char *url)
36172
{
37-
char *ptr = strrchr(url, '/');
38-
int dir_len = ptr - url;
39-
char *dir_name = CALLOC(dir_len + 1, sizeof(char));
40-
41-
free(dir_name);
42-
return NULL;
173+
char *ptr = strrchr(url, '/') + 1;
174+
LinkTable *linktbl = LinkTable_alloc(url);
175+
Link *link = Link_new(ptr, LINK_UNINITIALISED_FILE);
176+
strncpy(link->f_url, url, MAX_FILENAME_LEN);
177+
LinkTable_add(linktbl, link);
178+
LinkTable_uninitialised_fill(linktbl);
179+
LinkTable_print(linktbl);
180+
return linktbl;
43181
}
44182

45183
LinkTable *LinkSystem_init(const char *raw_url)
@@ -79,6 +217,8 @@ LinkTable *LinkSystem_init(const char *raw_url)
79217
*/
80218
if (CONFIG.mode == NORMAL) {
81219
ROOT_LINK_TBL = LinkTable_new(url);
220+
} else if (CONFIG.mode == SINGLE) {
221+
ROOT_LINK_TBL = single_LinkTable_new(url);
82222
} else if (CONFIG.mode == SONIC) {
83223
sonic_config_init(url, CONFIG.sonic_username,
84224
CONFIG.sonic_password);
@@ -105,28 +245,6 @@ void LinkTable_add(LinkTable * linktbl, Link * link)
105245
linktbl->links[linktbl->num - 1] = link;
106246
}
107247

108-
/**
109-
* \brief create a new Link
110-
*/
111-
static Link *Link_new(const char *linkname, LinkType type)
112-
{
113-
Link *link = CALLOC(1, sizeof(Link));
114-
115-
strncpy(link->linkname, linkname, MAX_FILENAME_LEN);
116-
link->type = type;
117-
118-
/*
119-
* remove the '/' from linkname if it exists
120-
*/
121-
char *c =
122-
&(link->linkname[strnlen(link->linkname, MAX_FILENAME_LEN) - 1]);
123-
if (*c == '/') {
124-
*c = '\0';
125-
}
126-
127-
return link;
128-
}
129-
130248
static LinkType linkname_to_LinkType(const char *linkname)
131249
{
132250
/*
@@ -219,77 +337,6 @@ static void HTML_to_LinkTable(GumboNode * node, LinkTable * linktbl)
219337
return;
220338
}
221339

222-
static CURL *Link_to_curl(Link * link)
223-
{
224-
CURL *curl = curl_easy_init();
225-
if (!curl) {
226-
lprintf(fatal, "curl_easy_init() failed!\n");
227-
}
228-
/*
229-
* set up some basic curl stuff
230-
*/
231-
curl_easy_setopt(curl, CURLOPT_USERAGENT, CONFIG.user_agent);
232-
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
233-
/*
234-
* for following directories without the '/'
235-
*/
236-
curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 2);
237-
curl_easy_setopt(curl, CURLOPT_URL, link->f_url);
238-
curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1);
239-
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 15);
240-
curl_easy_setopt(curl, CURLOPT_SHARE, CURL_SHARE);
241-
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_memory_callback);
242-
if (CONFIG.insecure_tls) {
243-
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
244-
}
245-
// curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
246-
247-
if (CONFIG.http_username) {
248-
curl_easy_setopt(curl, CURLOPT_USERNAME, CONFIG.http_username);
249-
}
250-
251-
if (CONFIG.http_password) {
252-
curl_easy_setopt(curl, CURLOPT_PASSWORD, CONFIG.http_password);
253-
}
254-
255-
if (CONFIG.proxy) {
256-
curl_easy_setopt(curl, CURLOPT_PROXY, CONFIG.proxy);
257-
}
258-
259-
if (CONFIG.proxy_username) {
260-
curl_easy_setopt(curl, CURLOPT_PROXYUSERNAME,
261-
CONFIG.proxy_username);
262-
}
263-
264-
if (CONFIG.proxy_password) {
265-
curl_easy_setopt(curl, CURLOPT_PROXYPASSWORD,
266-
CONFIG.proxy_password);
267-
}
268-
269-
return curl;
270-
}
271-
272-
static void Link_req_file_stat(Link * this_link)
273-
{
274-
CURL *curl = Link_to_curl(this_link);
275-
curl_easy_setopt(curl, CURLOPT_NOBODY, 1);
276-
curl_easy_setopt(curl, CURLOPT_FILETIME, 1L);
277-
278-
/*
279-
* We need to put the variable on the heap, because otherwise the
280-
* variable gets popped from the stack as the function returns.
281-
*
282-
* It gets freed in curl_multi_perform_once();
283-
*/
284-
TransferStruct *transfer = CALLOC(1, sizeof(TransferStruct));
285-
286-
transfer->link = this_link;
287-
transfer->type = FILESTAT;
288-
curl_easy_setopt(curl, CURLOPT_PRIVATE, transfer);
289-
290-
transfer_nonblocking(curl);
291-
}
292-
293340
void Link_set_file_stat(Link * this_link, CURL * curl)
294341
{
295342
long http_resp;
@@ -315,49 +362,6 @@ void Link_set_file_stat(Link * this_link, CURL * curl)
315362
}
316363
}
317364

318-
/**
319-
* \brief Fill in the uninitialised entries in a link table
320-
* \details Try and get the stats for each link in the link table. This will get
321-
* repeated until the uninitialised entry count drop to zero.
322-
*/
323-
static void LinkTable_uninitialised_fill(LinkTable * linktbl)
324-
{
325-
int u;
326-
char s[STATUS_LEN];
327-
lprintf(debug, "LinkTable_uninitialised_fill(): ... ");
328-
do {
329-
u = 0;
330-
for (int i = 0; i < linktbl->num; i++) {
331-
Link *this_link = linktbl->links[i];
332-
if (this_link->type == LINK_UNINITIALISED_FILE) {
333-
Link_req_file_stat(linktbl->links[i]);
334-
u++;
335-
}
336-
}
337-
/*
338-
* Block until the gaps are filled
339-
*/
340-
int n = curl_multi_perform_once();
341-
int i = 0;
342-
int j = 0;
343-
while ((i = curl_multi_perform_once())) {
344-
if (CONFIG.log_type & debug) {
345-
if (j) {
346-
erase_string(stderr, STATUS_LEN, s);
347-
}
348-
snprintf(s, STATUS_LEN, "%d / %d", n - i, n);
349-
fprintf(stderr, "%s", s);
350-
j++;
351-
}
352-
}
353-
}
354-
while (u);
355-
if (CONFIG.log_type & debug) {
356-
erase_string(stderr, STATUS_LEN, s);
357-
fprintf(stderr, "... Done!\n");
358-
}
359-
}
360-
361365
static void LinkTable_fill(LinkTable * linktbl)
362366
{
363367
Link *head_link = linktbl->links[0];

src/main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ parse_arg_list(int argc, char **argv, char ***fuse_argv, int *fuse_argc)
295295
*/
296296
break;
297297
case 22:
298-
CONFIG.mode = SINGLE_FILE;
298+
CONFIG.mode = SINGLE;
299299
break;
300300
default:
301301
fprintf(stderr, "see httpdirfs -h for usage\n");

0 commit comments

Comments
 (0)