more changes to the subsonic module
completed sonic_gen_auth_str() completed sonic_gen_url_first_part() change calloc to CALLOC (the wrapper function with error handling)
This commit is contained in:
parent
eaabc877a0
commit
1a9c10f783
|
@ -13,7 +13,7 @@ much faster than ``rclone mount``.
|
|||
|
||||
## Usage
|
||||
|
||||
./httpdirfs -f --cache -f $URL $YOUR_MOUNT_POINT
|
||||
./httpdirfs -f --cache $URL $YOUR_MOUNT_POINT
|
||||
|
||||
An example URL would be
|
||||
[Debian CD Image Server](https://cdimage.debian.org/debian-cd/). The ``-f`` flag
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
## Coding Convention
|
||||
- External variables: capital letters
|
||||
- Static global variables: lower case letters
|
||||
- Function names: TypeName_verb or verb_noun
|
||||
- Type names: camel case with the first letter capitalised, e.g. CamelCase
|
24
src/cache.c
24
src/cache.c
|
@ -211,11 +211,8 @@ blksz: %d, segbc: %ld\n", cf->path, cf->content_length, cf->blksz, cf->segbc);
|
|||
fprintf(stderr, "Meta_read(): Error: segbc: %ld\n", cf->segbc);
|
||||
return EMEM;
|
||||
}
|
||||
cf->seg = calloc(cf->segbc, sizeof(Seg));
|
||||
if (!cf->seg) {
|
||||
fprintf(stderr, "Meta_read(): calloc failure: %s\n", strerror(errno));
|
||||
return EMEM;
|
||||
}
|
||||
cf->seg = CALLOC(cf->segbc, sizeof(Seg));
|
||||
|
||||
/* Read all the segment */
|
||||
nmemb = fread(cf->seg, sizeof(Seg), cf->segbc, fp);
|
||||
|
||||
|
@ -474,11 +471,7 @@ int CacheDir_create(const char *dirn)
|
|||
*/
|
||||
static Cache *Cache_alloc()
|
||||
{
|
||||
Cache *cf = calloc(1, sizeof(Cache));
|
||||
if (!cf) {
|
||||
fprintf(stderr, "Cache_new(): calloc failure!\n");
|
||||
exit_failure();
|
||||
}
|
||||
Cache *cf = CALLOC(1, sizeof(Cache));
|
||||
|
||||
if (pthread_mutex_init(&cf->seek_lock, NULL)) {
|
||||
fprintf(stderr, "Cache_alloc(): seek_lock initialisation failed!\n");
|
||||
|
@ -680,12 +673,7 @@ int Cache_create(Link *this_link)
|
|||
cf->content_length = this_link->content_length;
|
||||
cf->blksz = DATA_BLK_SZ;
|
||||
cf->segbc = (cf->content_length / cf->blksz) + 1;
|
||||
cf->seg = calloc(cf->segbc, sizeof(Seg));
|
||||
|
||||
if (!cf->seg) {
|
||||
fprintf(stderr, "Cache_create(): cf->seg calloc failure!\n");
|
||||
exit_failure();
|
||||
}
|
||||
cf->seg = CALLOC(cf->segbc, sizeof(Seg));
|
||||
|
||||
if (Meta_create(cf)) {
|
||||
fprintf(stderr, "Cache_create(): cannot create metadata.\n");
|
||||
|
@ -914,7 +902,7 @@ static void *Cache_bgdl(void *arg)
|
|||
pthread_self());
|
||||
#endif
|
||||
PTHREAD_MUTEX_LOCK(&cf->w_lock);
|
||||
uint8_t *recv_buf = calloc(cf->blksz, sizeof(uint8_t));
|
||||
uint8_t *recv_buf = CALLOC(cf->blksz, sizeof(uint8_t));
|
||||
fprintf(stderr, "Cache_bgdl(): thread %lu: ", pthread_self());
|
||||
long recv = path_download(cf->path, (char *) recv_buf, cf->blksz,
|
||||
cf->next_dl_offset);
|
||||
|
@ -976,7 +964,7 @@ long Cache_read(Cache *cf, char * const output_buf, const off_t len,
|
|||
|
||||
/* ------------------------Download the segment -------------------------*/
|
||||
|
||||
uint8_t *recv_buf = calloc(cf->blksz, sizeof(uint8_t));
|
||||
uint8_t *recv_buf = CALLOC(cf->blksz, sizeof(uint8_t));
|
||||
fprintf(stderr, "Cache_read(): thread %lu: ", pthread_self());
|
||||
long recv = path_download(cf->path, (char *) recv_buf, cf->blksz,
|
||||
dl_offset);
|
||||
|
|
33
src/link.c
33
src/link.c
|
@ -48,11 +48,8 @@ static void LinkTable_add(LinkTable *linktbl, Link *link)
|
|||
|
||||
static Link *Link_new(const char *linkname, LinkType type)
|
||||
{
|
||||
Link *link = calloc(1, sizeof(Link));
|
||||
if (!link) {
|
||||
fprintf(stderr, "Link_new(): calloc failure!\n");
|
||||
exit_failure();
|
||||
}
|
||||
Link *link = CALLOC(1, sizeof(Link));
|
||||
|
||||
strncpy(link->linkname, linkname, MAX_FILENAME_LEN);
|
||||
link->type = type;
|
||||
|
||||
|
@ -172,11 +169,8 @@ void Link_req_file_stat(Link *this_link)
|
|||
*
|
||||
* It gets freed in curl_multi_perform_once();
|
||||
*/
|
||||
TransferStruct *transfer = calloc(1, sizeof(TransferStruct));
|
||||
if (!transfer) {
|
||||
fprintf(stderr, "Link_get_size(): malloc failed!\n");
|
||||
exit_failure();
|
||||
}
|
||||
TransferStruct *transfer = CALLOC(1, sizeof(TransferStruct));
|
||||
|
||||
transfer->link = this_link;
|
||||
transfer->type = FILESTAT;
|
||||
curl_easy_setopt(curl, CURLOPT_PRIVATE, transfer);
|
||||
|
@ -326,11 +320,7 @@ LinkTable *LinkTable_new(const char *url)
|
|||
pthread_self());
|
||||
#endif
|
||||
PTHREAD_MUTEX_LOCK(&link_lock);
|
||||
LinkTable *linktbl = calloc(1, sizeof(LinkTable));
|
||||
if (!linktbl) {
|
||||
fprintf(stderr, "LinkTable_new(): calloc failure!\n");
|
||||
exit_failure();
|
||||
}
|
||||
LinkTable *linktbl = CALLOC(1, sizeof(LinkTable));
|
||||
|
||||
/* populate the base URL */
|
||||
LinkTable_add(linktbl, Link_new("/", LINK_HEAD));
|
||||
|
@ -507,19 +497,12 @@ LinkTable *LinkTable_disk_open(const char *dirn)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
LinkTable *linktbl = calloc(1, sizeof(LinkTable));
|
||||
if (!linktbl) {
|
||||
fprintf(stderr, "LinkTable_disk_open(): calloc linktbl failed!\n");
|
||||
return NULL;
|
||||
}
|
||||
LinkTable *linktbl = CALLOC(1, sizeof(LinkTable));
|
||||
|
||||
fread(&linktbl->num, sizeof(int), 1, fp);
|
||||
linktbl->links = calloc(linktbl->num, sizeof(Link *));
|
||||
linktbl->links = CALLOC(linktbl->num, sizeof(Link *));
|
||||
for (int i = 0; i < linktbl->num; i++) {
|
||||
linktbl->links[i] = calloc(1, sizeof(Link));
|
||||
if (!linktbl->links[i]) {
|
||||
fprintf(stderr, "LinkTable_disk_open(): calloc links[i] failed!\n");
|
||||
}
|
||||
linktbl->links[i] = CALLOC(1, sizeof(Link));
|
||||
fread(linktbl->links[i]->linkname, sizeof(char), MAX_FILENAME_LEN, fp);
|
||||
fread(linktbl->links[i]->f_url, sizeof(char), MAX_PATH_LEN, fp);
|
||||
fread(&linktbl->links[i]->type, sizeof(LinkType), 1, fp);
|
||||
|
|
|
@ -50,6 +50,11 @@ struct Link {
|
|||
int cache_opened;
|
||||
/** \brief The pointer associated with the cache file */
|
||||
Cache *cache_ptr;
|
||||
/**
|
||||
* \brief Subsonic Music Directory ID
|
||||
* \details We use linkname to store filename
|
||||
*/
|
||||
int sonic_id;
|
||||
};
|
||||
|
||||
struct LinkTable {
|
||||
|
|
|
@ -241,7 +241,7 @@ static void print_help(char *program_name, int long_help)
|
|||
static void print_version()
|
||||
{
|
||||
fprintf(stderr,
|
||||
"HTTPDirFS version %s\n", VERSION);
|
||||
"HTTPDirFS version " VERSION "\n");
|
||||
}
|
||||
|
||||
static void print_long_help()
|
||||
|
|
|
@ -239,7 +239,7 @@ void network_config_init()
|
|||
NETWORK_CONFIG.proxy_user = NULL;
|
||||
NETWORK_CONFIG.proxy_pass = NULL;
|
||||
NETWORK_CONFIG.max_conns = DEFAULT_NETWORK_MAX_CONNS;
|
||||
NETWORK_CONFIG.user_agent = "HTTPDirFS";
|
||||
NETWORK_CONFIG.user_agent = DEFAULT_USER_AGENT;
|
||||
NETWORK_CONFIG.cache_enabled = 0;
|
||||
NETWORK_CONFIG.cache_dir = NULL;
|
||||
}
|
||||
|
|
|
@ -8,6 +8,11 @@
|
|||
|
||||
#include "link.h"
|
||||
|
||||
/**
|
||||
* \brief the default user agent string
|
||||
*/
|
||||
#define DEFAULT_USER_AGENT "HTTPDirFS-" VERSION
|
||||
|
||||
typedef enum {
|
||||
FILESTAT = 's',
|
||||
DATA = 'd'
|
||||
|
|
113
src/sonic.c
113
src/sonic.c
|
@ -1,48 +1,96 @@
|
|||
#include "util.h"
|
||||
#include "sonic.h"
|
||||
|
||||
#include "util.h"
|
||||
#include "network.h"
|
||||
|
||||
|
||||
#include <openssl/md5.h>
|
||||
#include <uuid/uuid.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define MD5_HASH_LEN 32
|
||||
#define SALT_LEN 36
|
||||
typedef struct {
|
||||
char *server;
|
||||
char *username;
|
||||
char *password;
|
||||
char *client;
|
||||
char *api_version;
|
||||
} SonicConfigStruct;
|
||||
|
||||
static SonicConfigStruct SONIC_CONFIG;
|
||||
|
||||
/**
|
||||
* \brief generate the salt for authentication string
|
||||
* \details this effectively generates a UUID string, which we use as the salt
|
||||
* \return a pointer to a 37-char array with the salt.
|
||||
* \brief initalise Subsonic configuration struct
|
||||
*/
|
||||
char *generate_salt()
|
||||
void sonic_config_init(const char *server, const char *username,
|
||||
const char *password)
|
||||
{
|
||||
char *out;
|
||||
out = calloc(SALT_LEN + 1, sizeof(char));
|
||||
uuid_t uu;
|
||||
uuid_generate(uu);
|
||||
uuid_unparse(uu, out);
|
||||
return out;
|
||||
SONIC_CONFIG.server = strndup(server, MAX_PATH_LEN);
|
||||
/* Correct for the extra '/' */
|
||||
size_t server_url_len = strnlen(SONIC_CONFIG.server, MAX_PATH_LEN) - 1;
|
||||
if (SONIC_CONFIG.server[server_url_len] == '/') {
|
||||
SONIC_CONFIG.server[server_url_len] = '\0';
|
||||
}
|
||||
SONIC_CONFIG.username = strndup(username, MAX_FILENAME_LEN);
|
||||
SONIC_CONFIG.password = strndup(password, MAX_FILENAME_LEN);
|
||||
SONIC_CONFIG.client = DEFAULT_USER_AGENT;
|
||||
/*
|
||||
* API 1.13.0 is the minimum version that supports
|
||||
* salt authentication scheme
|
||||
*/
|
||||
SONIC_CONFIG.api_version = "1.13.0";
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief generate the md5sum of a string
|
||||
* \param[in] str a character array for the input string
|
||||
* \return a pointer to a 33-char array with the salt
|
||||
* \brief generate authentication string
|
||||
*/
|
||||
char *generate_md5sum(const char *str)
|
||||
static char *sonic_gen_auth_str()
|
||||
{
|
||||
MD5_CTX c;
|
||||
unsigned char md5[MD5_DIGEST_LENGTH];
|
||||
size_t len = strnlen(str, MAX_PATH_LEN);
|
||||
char *out = calloc(MD5_HASH_LEN + 1, sizeof(char));
|
||||
char *salt = generate_salt();
|
||||
size_t password_len = strnlen(SONIC_CONFIG.password, MAX_FILENAME_LEN);
|
||||
size_t password_salt_len = password_len + strnlen(salt, MAX_FILENAME_LEN);
|
||||
char *password_salt = CALLOC(password_salt_len + 1, sizeof(char));
|
||||
strncat(password_salt, SONIC_CONFIG.password, MAX_FILENAME_LEN);
|
||||
strncat(password_salt + password_len, salt, MAX_FILENAME_LEN);
|
||||
char *token = generate_md5sum(password_salt);
|
||||
char *auth_str = CALLOC(MAX_PATH_LEN + 1, sizeof(char));
|
||||
snprintf(auth_str, MAX_PATH_LEN,
|
||||
".view?u=%s&t=%s&s=%s&v=%s&c=%s",
|
||||
SONIC_CONFIG.username, token, salt,
|
||||
SONIC_CONFIG.api_version, SONIC_CONFIG.client);
|
||||
free(salt);
|
||||
free(token);
|
||||
return auth_str;
|
||||
}
|
||||
|
||||
MD5_Init(&c);
|
||||
MD5_Update(&c, str, len);
|
||||
MD5_Final(md5, &c);
|
||||
/**
|
||||
* \brief generate the first half of the request URL
|
||||
*/
|
||||
static char *sonic_gen_url_first_part(char *method)
|
||||
{
|
||||
char *auth_str = sonic_gen_auth_str();
|
||||
char *url = CALLOC(MAX_PATH_LEN + 1, sizeof(char));
|
||||
snprintf(url, MAX_PATH_LEN, "%s/rest/%s%s", SONIC_CONFIG.server, method,
|
||||
auth_str);
|
||||
free(auth_str);
|
||||
return url;
|
||||
}
|
||||
|
||||
for(int i = 0; i < MD5_DIGEST_LENGTH; i++) {
|
||||
sprintf(out + 2 * i, "%02x", md5[i]);
|
||||
LinkTable *sonic_LinkTable_new(int id)
|
||||
{
|
||||
char *url;
|
||||
if (id > 0) {
|
||||
char *first_part = sonic_gen_url_first_part("getMusicDirectory");
|
||||
url = CALLOC(MAX_PATH_LEN + 1, sizeof(char));
|
||||
snprintf(url, MAX_PATH_LEN, "%s&id=%d", first_part, id);
|
||||
free(first_part);
|
||||
} else {
|
||||
url = sonic_gen_url_first_part("getIndexes");
|
||||
}
|
||||
return out;
|
||||
|
||||
printf("%s\n", url);
|
||||
LinkTable *linktbl = CALLOC(1, sizeof(LinkTable));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
|
@ -50,8 +98,7 @@ int main(int argc, char **argv)
|
|||
(void) argc;
|
||||
(void) argv;
|
||||
|
||||
char *salt = generate_salt();
|
||||
char *md5sum = generate_md5sum(salt);
|
||||
|
||||
printf("%s\n%s\n", salt, md5sum);
|
||||
sonic_config_init(argv[1], argv[2], argv[3]);
|
||||
sonic_LinkTable_new(0);
|
||||
sonic_LinkTable_new(3);
|
||||
}
|
||||
|
|
11
src/sonic.h
11
src/sonic.h
|
@ -1,4 +1,15 @@
|
|||
#ifndef SONIC_H
|
||||
#define SONIC_H
|
||||
/**
|
||||
* \file sonic.h
|
||||
* \brief Subsonic related function
|
||||
*/
|
||||
|
||||
#include "link.h"
|
||||
|
||||
/**
|
||||
* \brief Initialise SubSonic configuration.
|
||||
*/
|
||||
void sonic_config_init(const char *server, const char *username,
|
||||
const char *password);
|
||||
#endif
|
||||
|
|
50
src/util.c
50
src/util.c
|
@ -1,12 +1,17 @@
|
|||
#include "util.h"
|
||||
|
||||
#include <openssl/md5.h>
|
||||
#include <uuid/uuid.h>
|
||||
|
||||
#include <execinfo.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#define BT_BUF_SIZE 100
|
||||
#define MD5_HASH_LEN 32
|
||||
#define SALT_LEN 36
|
||||
|
||||
char *path_append(const char *path, const char *filename)
|
||||
{
|
||||
|
@ -18,11 +23,7 @@ char *path_append(const char *path, const char *filename)
|
|||
char *str;
|
||||
size_t ul = strnlen(path, MAX_PATH_LEN);
|
||||
size_t sl = strnlen(filename, MAX_FILENAME_LEN);
|
||||
str = calloc(ul + sl + needs_separator + 1, sizeof(char));
|
||||
if (!str) {
|
||||
fprintf(stderr, "path_append(): calloc failure!\n");
|
||||
exit_failure();
|
||||
}
|
||||
str = CALLOC(ul + sl + needs_separator + 1, sizeof(char));
|
||||
strncpy(str, path, ul);
|
||||
if (needs_separator) {
|
||||
str[ul] = '/';
|
||||
|
@ -85,3 +86,40 @@ void erase_string(FILE *file, size_t max_len, char *s)
|
|||
fprintf(file, "\b");
|
||||
}
|
||||
}
|
||||
|
||||
char *generate_salt()
|
||||
{
|
||||
char *out;
|
||||
out = CALLOC(SALT_LEN + 1, sizeof(char));
|
||||
uuid_t uu;
|
||||
uuid_generate(uu);
|
||||
uuid_unparse(uu, out);
|
||||
return out;
|
||||
}
|
||||
|
||||
char *generate_md5sum(const char *str)
|
||||
{
|
||||
MD5_CTX c;
|
||||
unsigned char md5[MD5_DIGEST_LENGTH];
|
||||
size_t len = strnlen(str, MAX_PATH_LEN);
|
||||
char *out = CALLOC(MD5_HASH_LEN + 1, sizeof(char));
|
||||
|
||||
MD5_Init(&c);
|
||||
MD5_Update(&c, str, len);
|
||||
MD5_Final(md5, &c);
|
||||
|
||||
for(int i = 0; i < MD5_DIGEST_LENGTH; i++) {
|
||||
sprintf(out + 2 * i, "%02x", md5[i]);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
void *CALLOC(size_t nmemb, size_t size)
|
||||
{
|
||||
void *ptr = calloc(nmemb, size);
|
||||
if (!ptr) {
|
||||
fprintf(stderr, "calloc() failed, %s!\n", strerror(errno));
|
||||
exit_failure();
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
|
25
src/util.h
25
src/util.h
|
@ -36,17 +36,17 @@ char *path_append(const char *path, const char *filename);
|
|||
int64_t round_div(int64_t a, int64_t b);
|
||||
|
||||
/**
|
||||
* \brief wrapper for pthread_mutex_lock()
|
||||
* \brief wrapper for pthread_mutex_lock(), with error handling
|
||||
*/
|
||||
void PTHREAD_MUTEX_LOCK(pthread_mutex_t *x);
|
||||
|
||||
/**
|
||||
* \brief wrapper for pthread_mutex_unlock()
|
||||
* \brief wrapper for pthread_mutex_unlock(), with error handling
|
||||
*/
|
||||
void PTHREAD_MUTEX_UNLOCK(pthread_mutex_t *x);
|
||||
|
||||
/**
|
||||
* \brief wrapper for exit(EXIT_FAILURE)
|
||||
* \brief wrapper for exit(EXIT_FAILURE), with error handling
|
||||
*/
|
||||
void exit_failure(void);
|
||||
|
||||
|
@ -55,4 +55,23 @@ void exit_failure(void);
|
|||
*/
|
||||
void erase_string(FILE *file, size_t max_len, char *s);
|
||||
|
||||
/**
|
||||
* \brief generate the salt for authentication string
|
||||
* \details this effectively generates a UUID string, which we use as the salt
|
||||
* \return a pointer to a 37-char array with the salt.
|
||||
*/
|
||||
char *generate_salt();
|
||||
|
||||
/**
|
||||
* \brief generate the md5sum of a string
|
||||
* \param[in] str a character array for the input string
|
||||
* \return a pointer to a 33-char array with the salt
|
||||
*/
|
||||
char *generate_md5sum(const char *str);
|
||||
|
||||
/**
|
||||
* \brief wrapper for calloc(), with error handling
|
||||
*/
|
||||
void *CALLOC(size_t nmemb, size_t size);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue