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