first ever published version
This commit is contained in:
parent
25648ad947
commit
71339f13b8
|
@ -1,5 +1,5 @@
|
|||
tmp
|
||||
*.o
|
||||
mount-http-dir
|
||||
*_test.txt
|
||||
*.kate-swp
|
||||
httpdirfs
|
||||
|
|
4
Makefile
4
Makefile
|
@ -5,10 +5,10 @@ OBJ = main.o network.o
|
|||
%.o: %.c
|
||||
$(CC) -c -o $@ $< $(CFLAGS)
|
||||
|
||||
mount-http-dir: $(OBJ)
|
||||
httpdirfs: $(OBJ)
|
||||
$(CC) -o $@ $^ $(CFLAGS)
|
||||
|
||||
.PHONY: clean
|
||||
|
||||
clean:
|
||||
rm -f *.o mount-http-dir
|
||||
rm -f *.o httpdirfs
|
||||
|
|
8
data.h
8
data.h
|
@ -8,13 +8,11 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
/** \brief use this data type for buffer */
|
||||
typedef struct MemoryStruct MemoryStruct;
|
||||
typedef struct BufferStruct BufferStruct;
|
||||
|
||||
struct MemoryStruct {
|
||||
struct BufferStruct {
|
||||
size_t size;
|
||||
char *memory;
|
||||
char *data;
|
||||
};
|
||||
|
||||
void MemoryStruct_free(MemoryStruct *ms);
|
||||
|
||||
#endif
|
||||
|
|
40
main.c
40
main.c
|
@ -9,20 +9,32 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
static char *BASE_URL;
|
||||
|
||||
static int fs_getattr(const char *path, struct stat *stbuf);
|
||||
static int fs_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
|
||||
off_t offset, struct fuse_file_info *fi);
|
||||
static int fs_open(const char *path, struct fuse_file_info *fi);
|
||||
static int fs_read(const char *path, char *buf, size_t size, off_t offset,
|
||||
struct fuse_file_info *fi);
|
||||
static void *fs_init(struct fuse_conn_info *conn);
|
||||
|
||||
|
||||
static struct fuse_operations fs_oper = {
|
||||
.getattr = fs_getattr,
|
||||
.readdir = fs_readdir,
|
||||
.open = fs_open,
|
||||
.read = fs_read,
|
||||
.init = fs_init
|
||||
};
|
||||
|
||||
static void *fs_init(struct fuse_conn_info *conn)
|
||||
{
|
||||
(void) conn;
|
||||
network_init(BASE_URL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void fs_usage()
|
||||
{
|
||||
fprintf(stderr,
|
||||
|
@ -39,7 +51,7 @@ int main(int argc, char **argv) {
|
|||
fs_usage();
|
||||
}
|
||||
|
||||
network_init(argv[argc-2]);
|
||||
BASE_URL = argv[argc-2];
|
||||
argv[argc-2] = argv[argc-1];
|
||||
argv[argc-1] = NULL;
|
||||
argc--;
|
||||
|
@ -139,29 +151,13 @@ static int fs_read(const char *path, char *buf, size_t size, off_t offset,
|
|||
struct fuse_file_info *fi)
|
||||
{
|
||||
(void) fi;
|
||||
Link *link;
|
||||
link = path_to_Link(path);
|
||||
|
||||
if (!link) {
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
MemoryStruct ms;
|
||||
|
||||
fprintf(stderr, "fs_read(): Link_download(%s, %ld, %lu)\n",
|
||||
link->f_url,
|
||||
offset,
|
||||
size
|
||||
);
|
||||
fprintf(stderr, "fs_read(): path: %s, offset: %ld, size: %lu\n",
|
||||
path, offset, size);
|
||||
fflush(stderr);
|
||||
size_t bytes_downloaded = Link_download(link, &ms, offset, size);
|
||||
fprintf(stderr,
|
||||
"fs_read(): returning from Link_download(), with %lu bytes.\n",
|
||||
bytes_downloaded);
|
||||
long received = Link_download(path, buf, size, offset);
|
||||
fprintf(stderr, "fs_read(): received %ld bytes.\n", received);
|
||||
fflush(stderr);
|
||||
|
||||
memcpy(buf, ms.memory, size);
|
||||
// free(ms.memory);
|
||||
|
||||
return bytes_downloaded;
|
||||
return received;
|
||||
}
|
||||
|
|
127
network.c
127
network.c
|
@ -21,7 +21,7 @@ static void HTML_to_LinkTable(GumboNode *node, LinkTable *linktbl);
|
|||
static int is_valid_link_p_url(const char *n);
|
||||
static void Link_free(Link *link);
|
||||
static Link *Link_new(const char *p_url);
|
||||
static void Link_curl_init(Link *link);
|
||||
static CURL *Link_to_curl(Link *link);
|
||||
static void LinkTable_free(LinkTable *linktbl);
|
||||
static void LinkTable_add(LinkTable *linktbl, Link *link);
|
||||
static void LinkTable_fill(LinkTable *linktbl);
|
||||
|
@ -65,22 +65,26 @@ void network_init(const char *url)
|
|||
|
||||
}
|
||||
|
||||
static void Link_curl_init(Link *link)
|
||||
static CURL *Link_to_curl(Link *link)
|
||||
{
|
||||
link->curl = curl_easy_init();
|
||||
CURL *curl = curl_easy_init();
|
||||
|
||||
/* set up some basic curl stuff */
|
||||
curl_easy_setopt(link->curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
|
||||
curl_easy_setopt(link->curl, CURLOPT_USERAGENT, "mount-http-dir/libcurl");
|
||||
curl_easy_setopt(link->curl, CURLOPT_VERBOSE, 0);
|
||||
curl_easy_setopt(link->curl, CURLOPT_FOLLOWLOCATION, 1);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
|
||||
curl_easy_setopt(curl, CURLOPT_USERAGENT, "mount-http-dir/libcurl");
|
||||
curl_easy_setopt(curl, CURLOPT_VERBOSE, 0);
|
||||
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
|
||||
/*
|
||||
* only 1 redirection is really needed
|
||||
* - for following directories without the '/'
|
||||
*/
|
||||
curl_easy_setopt(link->curl, CURLOPT_MAXREDIRS, 3);
|
||||
curl_easy_setopt(link->curl, CURLOPT_URL, link->f_url);
|
||||
curl_easy_setopt(link->curl, CURLOPT_SHARE, curl_share);
|
||||
curl_easy_setopt(curl, CURLOPT_MAXREDIRS, 3);
|
||||
curl_easy_setopt(curl, CURLOPT_URL, link->f_url);
|
||||
fprintf(stderr, "Link_to_curl: %s\n", link->f_url);
|
||||
fflush(stderr);
|
||||
curl_easy_setopt(curl, CURLOPT_SHARE, curl_share);
|
||||
|
||||
return curl;
|
||||
}
|
||||
|
||||
|
||||
|
@ -196,18 +200,29 @@ static void do_transfer_(CURL *curl)
|
|||
static size_t
|
||||
WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp)
|
||||
{
|
||||
MemoryStruct *mem = (MemoryStruct *)userp;
|
||||
size_t realsize = size * nmemb;
|
||||
BufferStruct *buf = (BufferStruct *)userp;
|
||||
size_t recv_size = size * nmemb;
|
||||
|
||||
mem->memory = malloc(realsize + 1);
|
||||
if(!mem->memory) {
|
||||
/* out of memory! */
|
||||
printf("not enough memory (realloc returned NULL)\n");
|
||||
return 0;
|
||||
if ( !(buf->size) ) {
|
||||
buf->data = malloc(recv_size + 1);
|
||||
buf->data[recv_size] = '\0';
|
||||
if(!buf->data) {
|
||||
fprintf(stderr,
|
||||
"WriteMemoryCallback(): cannot malloc.\n");
|
||||
fflush(stderr);
|
||||
return 0;
|
||||
}
|
||||
memmove(buf->data, contents, recv_size);
|
||||
return recv_size;
|
||||
} else {
|
||||
if(recv_size < buf->size) {
|
||||
memmove(buf->data, contents, recv_size);
|
||||
return recv_size;
|
||||
} else {
|
||||
memmove(buf->data, contents, buf->size);
|
||||
return buf->size;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(mem->memory, contents, realsize);
|
||||
return realsize - 1;
|
||||
}
|
||||
|
||||
static Link *Link_new(const char *p_url)
|
||||
|
@ -229,39 +244,53 @@ static Link *Link_new(const char *p_url)
|
|||
|
||||
static void Link_free(Link *link)
|
||||
{
|
||||
curl_easy_cleanup(link->curl);
|
||||
free(link);
|
||||
link = NULL;
|
||||
}
|
||||
|
||||
size_t Link_download(Link *link, MemoryStruct *ms, off_t offset,
|
||||
size_t size)
|
||||
long Link_download(const char *path, char *output_buf, size_t size,
|
||||
off_t offset)
|
||||
{
|
||||
Link *link;
|
||||
link = path_to_Link(path);
|
||||
if (!link) {
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
size_t start = offset;
|
||||
size_t end = start + size;
|
||||
Link_curl_init(link);
|
||||
CURL *curl = Link_to_curl(link);
|
||||
char range_str[64];
|
||||
snprintf(range_str, sizeof(range_str), "%lu-%lu", start, end);
|
||||
|
||||
curl_easy_setopt(link->curl, CURLOPT_RANGE, range_str);
|
||||
curl_easy_setopt(link->curl, CURLOPT_WRITEDATA, (void *)ms);
|
||||
BufferStruct buf;
|
||||
buf.size = size;
|
||||
buf.data = output_buf;
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&buf);
|
||||
curl_easy_setopt(curl, CURLOPT_RANGE, range_str);
|
||||
|
||||
do_transfer(link->curl);
|
||||
|
||||
do_transfer(curl);
|
||||
|
||||
long http_resp;
|
||||
curl_easy_getinfo(link->curl, CURLINFO_RESPONSE_CODE, &http_resp);
|
||||
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_resp);
|
||||
if ( (http_resp != HTTP_OK) && ( http_resp != HTTP_PARTIAL_CONTENT) ) {
|
||||
fprintf(stderr, "Link_download(): Could not download %s, HTTP %ld\n",
|
||||
link->f_url, http_resp);
|
||||
fflush(stdout);
|
||||
return 0;
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
double dl;
|
||||
curl_easy_getinfo(link->curl, CURLINFO_SIZE_DOWNLOAD, &dl);
|
||||
size_t s = dl;
|
||||
curl_easy_cleanup(link->curl);
|
||||
return s;
|
||||
curl_easy_getinfo(curl, CURLINFO_SIZE_DOWNLOAD, &dl);
|
||||
|
||||
size_t recv = dl;
|
||||
if (recv > size) {
|
||||
recv = size;
|
||||
}
|
||||
|
||||
curl_easy_cleanup(curl);
|
||||
return recv;
|
||||
}
|
||||
|
||||
LinkTable *LinkTable_new(const char *url)
|
||||
|
@ -275,15 +304,17 @@ LinkTable *LinkTable_new(const char *url)
|
|||
strncpy(head_link->f_url, url, URL_LEN_MAX);
|
||||
|
||||
/* start downloading the base URL */
|
||||
Link_curl_init(head_link);
|
||||
MemoryStruct ms;
|
||||
curl_easy_setopt(head_link->curl, CURLOPT_WRITEDATA, (void *)&ms);
|
||||
CURL *curl = Link_to_curl(head_link);
|
||||
BufferStruct buf;
|
||||
buf.size = 0;
|
||||
buf.data = NULL;
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&buf);
|
||||
|
||||
do_transfer(head_link->curl);
|
||||
do_transfer(curl);
|
||||
|
||||
/* if downloading base URL failed */
|
||||
long http_resp;
|
||||
curl_easy_getinfo(head_link->curl, CURLINFO_RESPONSE_CODE, &http_resp);
|
||||
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_resp);
|
||||
if (http_resp != HTTP_OK) {
|
||||
fprintf(stderr, "link.c: LinkTable_new() cannot retrive the base URL, \
|
||||
URL: %s, HTTP %ld\n", url, http_resp);
|
||||
|
@ -291,11 +322,11 @@ URL: %s, HTTP %ld\n", url, http_resp);
|
|||
linktbl = NULL;
|
||||
return linktbl;
|
||||
};
|
||||
curl_easy_cleanup(head_link->curl);
|
||||
curl_easy_cleanup(curl);
|
||||
|
||||
/* Otherwise parsed the received data */
|
||||
GumboOutput* output = gumbo_parse(ms.memory);
|
||||
free(ms.memory);
|
||||
GumboOutput* output = gumbo_parse(buf.data);
|
||||
free(buf.data);
|
||||
HTML_to_LinkTable(output->root, linktbl);
|
||||
gumbo_destroy_output(&kGumboDefaultOptions, output);
|
||||
|
||||
|
@ -335,18 +366,16 @@ void LinkTable_fill(LinkTable *linktbl)
|
|||
strncpy(this_link->f_url, url, URL_LEN_MAX);
|
||||
free(url);
|
||||
|
||||
Link_curl_init(this_link);
|
||||
curl_easy_setopt(this_link->curl, CURLOPT_NOBODY, 1);
|
||||
CURL *curl = Link_to_curl(this_link);
|
||||
curl_easy_setopt(curl, CURLOPT_NOBODY, 1);
|
||||
|
||||
do_transfer(this_link->curl);
|
||||
do_transfer(curl);
|
||||
|
||||
long http_resp;
|
||||
curl_easy_getinfo(this_link->curl, CURLINFO_RESPONSE_CODE,
|
||||
&http_resp);
|
||||
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_resp);
|
||||
if (http_resp == HTTP_OK) {
|
||||
double cl;
|
||||
curl_easy_getinfo(this_link->curl,
|
||||
CURLINFO_CONTENT_LENGTH_DOWNLOAD, &cl);
|
||||
curl_easy_getinfo(curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &cl);
|
||||
if (cl == -1) {
|
||||
this_link->content_length = 0;
|
||||
this_link->type = LINK_DIR;
|
||||
|
@ -357,8 +386,8 @@ void LinkTable_fill(LinkTable *linktbl)
|
|||
} else {
|
||||
this_link->type = LINK_INVALID;
|
||||
}
|
||||
curl_easy_cleanup(curl);
|
||||
}
|
||||
curl_easy_cleanup(this_link->curl);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -33,7 +33,6 @@ struct Link {
|
|||
char p_url[LINK_LEN_MAX];
|
||||
char f_url[URL_LEN_MAX];
|
||||
LinkType type;
|
||||
CURL *curl;
|
||||
size_t content_length;
|
||||
LinkTable *next_table;
|
||||
};
|
||||
|
@ -53,8 +52,8 @@ void network_init(const char *url);
|
|||
* \brief download a link */
|
||||
/* \return the number of bytes downloaded
|
||||
*/
|
||||
size_t Link_download(Link *link, MemoryStruct *mem, off_t offset,
|
||||
size_t size);
|
||||
long Link_download(const char *path, char *output_buf, size_t size,
|
||||
off_t offset);
|
||||
|
||||
/** \brief create a new LinkTable */
|
||||
LinkTable *LinkTable_new(const char *url);
|
||||
|
|
Loading…
Reference in New Issue