Separated ftp listing parser module. It now supports Windows NT listings. Added unittests for the listing parser module.
This commit is contained in:
@@ -1,11 +1,18 @@
|
||||
## Process this file with automake to produce Makefile.in
|
||||
SUBDIRS = compat
|
||||
|
||||
DIST_SUBDIRS = $(SUBDIRS) tests
|
||||
|
||||
bin_PROGRAMS = curlftpfs
|
||||
|
||||
curlftpfs_SOURCES = ftpfs.c cache.c cache.h
|
||||
curlftpfs_SOURCES = ftpfs.c ftpfs.h cache.c cache.h ftpfs-ls.c ftpfs-ls.h
|
||||
curlftpfs_CPPFLAGS = -DFUSE_USE_VERSION=25
|
||||
|
||||
if FUSE_OPT_COMPAT
|
||||
curlftpfs_LDADD = compat/libcompat.la
|
||||
endif
|
||||
|
||||
check: test
|
||||
|
||||
test:
|
||||
@(cd tests; $(MAKE) test)
|
||||
|
5
cache.h
5
cache.h
@@ -1,3 +1,6 @@
|
||||
#ifndef __CURLFTPFS_CACHE_H__
|
||||
#define __CURLFTPFS_CACHE_H__
|
||||
|
||||
/*
|
||||
Caching file system proxy
|
||||
Copyright (C) 2004 Miklos Szeredi <miklos@szeredi.hu>
|
||||
@@ -27,3 +30,5 @@ int cache_parse_options(struct fuse_args *args);
|
||||
void cache_add_attr(const char *path, const struct stat *stbuf);
|
||||
void cache_add_dir(const char *path, char **dir);
|
||||
void cache_add_link(const char *path, const char *link, size_t size);
|
||||
|
||||
#endif /* __CURLFTPFS_CACHE_H__ */
|
||||
|
@@ -20,9 +20,9 @@ LIBS="$GLIB_LIBS $FUSE_LIBS $LIBCURL"
|
||||
have_fuse_opt_parse=no
|
||||
AC_CHECK_FUNC([fuse_opt_parse], [have_fuse_opt_parse=yes])
|
||||
if test "$have_fuse_opt_parse" = no; then
|
||||
CFLAGS="$CFLAGS -Icompat"
|
||||
CFLAGS="$CFLAGS -Icompat -I../compat"
|
||||
fi
|
||||
AM_CONDITIONAL(FUSE_OPT_COMPAT, test "$have_fuse_opt_parse" = no)
|
||||
|
||||
AC_CONFIG_FILES([Makefile compat/Makefile])
|
||||
AC_CONFIG_FILES([Makefile compat/Makefile tests/Makefile])
|
||||
AC_OUTPUT
|
||||
|
229
ftpfs-ls.c
Normal file
229
ftpfs-ls.c
Normal file
@@ -0,0 +1,229 @@
|
||||
#define _XOPEN_SOURCE
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <glib.h>
|
||||
|
||||
#include "ftpfs.h"
|
||||
#include "ftpfs-ls.h"
|
||||
|
||||
static int parse_dir_unix(const char *line,
|
||||
struct stat *sbuf,
|
||||
char *file,
|
||||
char *link) {
|
||||
char mode[12];
|
||||
long nlink = 1;
|
||||
char user[33];
|
||||
char group[33];
|
||||
long size;
|
||||
char month[4];
|
||||
char day[3];
|
||||
char year[6];
|
||||
char date[20];
|
||||
struct tm tm;
|
||||
time_t tt;
|
||||
int res;
|
||||
|
||||
memset(file, 0, sizeof(char)*1024);
|
||||
memset(&tm, 0, sizeof(tm));
|
||||
memset(&tt, 0, sizeof(tt));
|
||||
|
||||
res = sscanf(line, "%11s%*[ \t]%lu%*[ \t]%32s%*[ \t]%32s%*[ \t]%lu%*[ \t]%3s%*[ \t]%2s%*[ \t]%5s%*[ \t]%1023c",
|
||||
mode, &nlink, user, group, &size, month, day, year, file);
|
||||
if (res < 9) {
|
||||
res = sscanf(line, "%11s%*[ \t]%32s%*[ \t]%32s%*[ \t]%lu%*[ \t]%3s%*[ \t]%2s%*[ \t]%5s%*[ \t]%1023c",
|
||||
mode, user, group, &size, month, day, year, file);
|
||||
if (res < 8) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
char *link_marker = strstr(file, " -> ");
|
||||
if (link_marker) {
|
||||
strcpy(link, link_marker + 4);
|
||||
*link_marker = '\0';
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
if (mode[i] == 'd') {
|
||||
sbuf->st_mode |= S_IFDIR;
|
||||
} else if (mode[i] == 'l') {
|
||||
sbuf->st_mode |= S_IFLNK;
|
||||
} else {
|
||||
sbuf->st_mode |= S_IFREG;
|
||||
}
|
||||
for (i = 1; i < 10; ++i) {
|
||||
if (mode[i] != '-') {
|
||||
sbuf->st_mode |= 1 << (9 - i);
|
||||
}
|
||||
}
|
||||
|
||||
sbuf->st_nlink = nlink;
|
||||
|
||||
sbuf->st_size = size;
|
||||
if (ftpfs.blksize) {
|
||||
sbuf->st_blksize = ftpfs.blksize;
|
||||
sbuf->st_blocks =
|
||||
((size + ftpfs.blksize - 1) & ~(ftpfs.blksize - 1)) >> 9;
|
||||
}
|
||||
|
||||
sprintf(date,"%s,%s,%s", year, month, day);
|
||||
tt = time(NULL);
|
||||
gmtime_r(&tt, &tm);
|
||||
tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
|
||||
if(strchr(year, ':'))
|
||||
strptime(date, "%H:%M,%b,%d", &tm);
|
||||
else
|
||||
strptime(date, "%Y,%b,%d", &tm);
|
||||
|
||||
sbuf->st_atime = sbuf->st_ctime = sbuf->st_mtime = mktime(&tm);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int parse_dir_win(const char *line,
|
||||
struct stat *sbuf,
|
||||
char *file,
|
||||
char *link) {
|
||||
char date[9];
|
||||
char hour[8];
|
||||
char size[33];
|
||||
struct tm tm;
|
||||
time_t tt;
|
||||
int res;
|
||||
(void)link;
|
||||
|
||||
memset(file, 0, sizeof(char)*1024);
|
||||
memset(&tm, 0, sizeof(tm));
|
||||
memset(&tt, 0, sizeof(tt));
|
||||
|
||||
res = sscanf(line, "%8s%*[ \t]%7s%*[ \t]%32s%*[ \t]%1023c",
|
||||
date, hour, size, file);
|
||||
if (res < 4) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEBUG("date: %s hour: %s size: %s file: %s\n", date, hour, size, file);
|
||||
|
||||
tt = time(NULL);
|
||||
gmtime_r(&tt, &tm);
|
||||
tm.tm_sec = tm.tm_min = tm.tm_hour = 0;
|
||||
strptime(date, "%m-%d-%y", &tm);
|
||||
strptime(hour, "%I:%M%p", &tm);
|
||||
|
||||
sbuf->st_atime = sbuf->st_ctime = sbuf->st_mtime = mktime(&tm);
|
||||
|
||||
sbuf->st_nlink = 1;
|
||||
|
||||
if (!strcmp(size, "<DIR>")) {
|
||||
sbuf->st_mode |= S_IFDIR;
|
||||
} else {
|
||||
int nsize = strtol(size, NULL, 0);
|
||||
sbuf->st_mode |= S_IFREG;
|
||||
sbuf->st_size = nsize;
|
||||
if (ftpfs.blksize) {
|
||||
sbuf->st_blksize = ftpfs.blksize;
|
||||
sbuf->st_blocks =
|
||||
((nsize + ftpfs.blksize - 1) & ~(ftpfs.blksize - 1)) >> 9;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int parse_dir_netware(const char *line,
|
||||
struct stat *sbuf,
|
||||
char *file,
|
||||
char *link) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int parse_dir(const char* list, const char* dir,
|
||||
const char* name, struct stat* sbuf,
|
||||
char* linkbuf, int linklen,
|
||||
fuse_cache_dirh_t h, fuse_cache_dirfil_t filler) {
|
||||
char *file;
|
||||
char *link;
|
||||
const char *start = list;
|
||||
const char *end = list;
|
||||
char found = 0;
|
||||
struct stat stat_buf;
|
||||
|
||||
if (sbuf) memset(sbuf, 0, sizeof(struct stat));
|
||||
|
||||
if (name && sbuf && name[0] == '\0') {
|
||||
sbuf->st_mode |= S_IFDIR;
|
||||
sbuf->st_mode |= 0755;
|
||||
sbuf->st_size = 1024;
|
||||
return 0;
|
||||
}
|
||||
|
||||
file = (char *)malloc(1024*sizeof(char));
|
||||
link = (char *)malloc(1024*sizeof(char));
|
||||
|
||||
while ((end = strchr(start, '\n')) != NULL) {
|
||||
char* line;
|
||||
|
||||
memset(&stat_buf, 0, sizeof(stat_buf));
|
||||
|
||||
if (end > start && *(end-1) == '\r') end--;
|
||||
|
||||
line = (char*)malloc(end - start + 1);
|
||||
strncpy(line, start, end - start);
|
||||
line[end - start] = '\0';
|
||||
start = *end == '\r' ? end + 2 : end + 1;
|
||||
|
||||
file[0] = link[0] = '\0';
|
||||
int res = parse_dir_unix(line, &stat_buf, file, link) ||
|
||||
parse_dir_win(line, &stat_buf, file, link) ||
|
||||
parse_dir_netware(line, &stat_buf, file, link);
|
||||
|
||||
if (res) {
|
||||
char *full_path = g_strdup_printf("%s%s", dir, file);
|
||||
|
||||
if (link[0]) {
|
||||
char *reallink;
|
||||
if (link[0] == '/' && ftpfs.symlink_prefix_len) {
|
||||
reallink = g_strdup_printf("%s%s", ftpfs.symlink_prefix, link);
|
||||
} else {
|
||||
reallink = g_strdup(link);
|
||||
}
|
||||
int linksize = strlen(reallink);
|
||||
cache_add_link(full_path, reallink, linksize+1);
|
||||
DEBUG("cache_add_link: %s %s\n", full_path, reallink);
|
||||
if (linkbuf && linklen) {
|
||||
if (linksize > linklen) linksize = linklen - 1;
|
||||
strncpy(linkbuf, reallink, linksize);
|
||||
linkbuf[linksize] = '\0';
|
||||
}
|
||||
free(reallink);
|
||||
}
|
||||
|
||||
if (h && filler) {
|
||||
DEBUG("filler: %s\n", file);
|
||||
filler(h, file, &stat_buf);
|
||||
} else {
|
||||
DEBUG("cache_add_attr: %s\n", full_path);
|
||||
cache_add_attr(full_path, &stat_buf);
|
||||
}
|
||||
|
||||
DEBUG("comparing %s %s\n", name, file);
|
||||
if (name && !strcmp(name, file)) {
|
||||
if (sbuf) *sbuf = stat_buf;
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
|
||||
free(line);
|
||||
}
|
||||
|
||||
free(file);
|
||||
free(link);
|
||||
|
||||
return !found;
|
||||
}
|
11
ftpfs-ls.h
Normal file
11
ftpfs-ls.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#ifndef __CURLFTPFS_FTPFS_LS_H__
|
||||
#define __CURLFTPFS_FTPFS_LS_H__
|
||||
|
||||
#include "cache.h"
|
||||
|
||||
int parse_dir(const char* list, const char* dir,
|
||||
const char* name, struct stat* sbuf,
|
||||
char* linkbuf, int linklen,
|
||||
fuse_cache_dirh_t h, fuse_cache_dirfil_t filler);
|
||||
|
||||
#endif /* __CURLFTPFS_FTPFS_LS_H__ */
|
248
ftpfs.c
248
ftpfs.c
@@ -19,61 +19,16 @@
|
||||
#include <netinet/in.h>
|
||||
#include <fuse.h>
|
||||
#include <fuse_opt.h>
|
||||
#include <curl/curl.h>
|
||||
#include <curl/easy.h>
|
||||
#include <glib.h>
|
||||
|
||||
#include "ftpfs-ls.h"
|
||||
#include "cache.h"
|
||||
#include "ftpfs.h"
|
||||
|
||||
#define CURLFTPFS_BAD_NOBODY 0x070f02
|
||||
#define CURLFTPFS_BAD_SSL 0x070f03
|
||||
|
||||
static char* MonthStrings[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
|
||||
|
||||
struct ftpfs {
|
||||
char* host;
|
||||
char* mountpoint;
|
||||
CURL* connection;
|
||||
unsigned blksize;
|
||||
GHashTable *filetab;
|
||||
int verbose;
|
||||
int debug;
|
||||
int transform_symlinks;
|
||||
int disable_epsv;
|
||||
int tcp_nodelay;
|
||||
int disable_eprt;
|
||||
int connect_timeout;
|
||||
int use_ssl;
|
||||
int no_verify_hostname;
|
||||
char* cert;
|
||||
char* cert_type;
|
||||
char* key;
|
||||
char* key_type;
|
||||
char* key_password;
|
||||
char* engine;
|
||||
char* cacert;
|
||||
char* capath;
|
||||
char* ciphers;
|
||||
char* interface;
|
||||
char* krb4;
|
||||
char* proxy;
|
||||
int proxytunnel;
|
||||
int proxyanyauth;
|
||||
int proxybasic;
|
||||
int proxydigest;
|
||||
int proxyntlm;
|
||||
char* user;
|
||||
char* proxy_user;
|
||||
int ssl_version;
|
||||
int ip_version;
|
||||
char symlink_prefix[PATH_MAX+1];
|
||||
size_t symlink_prefix_len;
|
||||
curl_version_info_data* curl_version;
|
||||
int safe_nobody;
|
||||
};
|
||||
|
||||
static struct ftpfs ftpfs;
|
||||
struct ftpfs ftpfs;
|
||||
static char error_buf[CURL_ERROR_SIZE];
|
||||
|
||||
struct buffer {
|
||||
@@ -84,13 +39,6 @@ struct buffer {
|
||||
|
||||
static void usage(const char* progname);
|
||||
static char* get_dir_path(const char* path, int strip);
|
||||
static int parse_dir(struct buffer* buf, const char* dir,
|
||||
const char* name, struct stat* sbuf,
|
||||
char* linkbuf, int linklen,
|
||||
fuse_cache_dirh_t h, fuse_cache_dirfil_t filler);
|
||||
|
||||
#define DEBUG(args...) \
|
||||
do { if (ftpfs.debug) fprintf(stderr, args); } while(0)
|
||||
|
||||
static inline void buf_init(struct buffer* buf, size_t size)
|
||||
{
|
||||
@@ -344,7 +292,6 @@ static size_t read_data(void *ptr, size_t size, size_t nmemb, void *data) {
|
||||
|
||||
static int ftpfs_getdir(const char* path, fuse_cache_dirh_t h,
|
||||
fuse_cache_dirfil_t filler) {
|
||||
int err;
|
||||
CURLcode curl_res;
|
||||
char* dir_path = get_dir_path(path, 0);
|
||||
|
||||
@@ -360,7 +307,7 @@ static int ftpfs_getdir(const char* path, fuse_cache_dirh_t h,
|
||||
}
|
||||
buf_add_mem(&buf, "\0", 1);
|
||||
|
||||
err = parse_dir(&buf, dir_path + strlen(ftpfs.host) - 1, NULL, NULL, NULL, 0, h, filler);
|
||||
parse_dir(buf.p, dir_path + strlen(ftpfs.host) - 1, NULL, NULL, NULL, 0, h, filler);
|
||||
|
||||
free(dir_path);
|
||||
buf_free(&buf);
|
||||
@@ -386,183 +333,6 @@ static char* get_dir_path(const char* path, int strip) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int parse_dir(struct buffer* buf, const char* dir,
|
||||
const char* name, struct stat* sbuf,
|
||||
char* linkbuf, int linklen,
|
||||
fuse_cache_dirh_t h, fuse_cache_dirfil_t filler) {
|
||||
char *start = buf->p;
|
||||
char *end = buf->p;
|
||||
char found = 0;
|
||||
|
||||
if (sbuf) memset(sbuf, 0, sizeof(struct stat));
|
||||
|
||||
if (name && sbuf && name[0] == '\0') {
|
||||
sbuf->st_mode |= S_IFDIR;
|
||||
sbuf->st_mode |= 0755;
|
||||
sbuf->st_size = 1024;
|
||||
return 0;
|
||||
}
|
||||
|
||||
while ((end = strchr(start, '\n')) != NULL)
|
||||
{
|
||||
char* line;
|
||||
char* file;
|
||||
struct stat stat_buf;
|
||||
memset(&stat_buf, 0, sizeof(stat_buf));
|
||||
|
||||
if (end > start && *(end-1) == '\r') end--;
|
||||
|
||||
line = (char*)malloc(end - start + 1);
|
||||
strncpy(line, start, end - start);
|
||||
line[end - start] = '\0';
|
||||
start = *end == '\r' ? end + 2 : end + 1;
|
||||
|
||||
if (!strncmp(line, "total", 5)) continue;
|
||||
|
||||
int i = 0;
|
||||
char *p;
|
||||
if (line[i] == 'd') {
|
||||
stat_buf.st_mode |= S_IFDIR;
|
||||
} else if (line[i] == 'l') {
|
||||
stat_buf.st_mode |= S_IFLNK;
|
||||
} else {
|
||||
stat_buf.st_mode |= S_IFREG;
|
||||
}
|
||||
for (i = 1; i < 10; ++i) {
|
||||
if (line[i] != '-') {
|
||||
stat_buf.st_mode |= 1 << (9 - i);
|
||||
}
|
||||
}
|
||||
|
||||
// Advance whitespace
|
||||
while (line[i] && isspace(line[i])) ++i;
|
||||
|
||||
stat_buf.st_nlink = strtol(line+i, &p, 10);
|
||||
i = p - line;
|
||||
|
||||
// Advance whitespace
|
||||
while (line[i] && isspace(line[i])) ++i;
|
||||
// Advance username
|
||||
while (line[i] && !isspace(line[i])) ++i;
|
||||
// Advance whitespace
|
||||
while (line[i] && isspace(line[i])) ++i;
|
||||
// Advance group
|
||||
while (line[i] && !isspace(line[i])) ++i;
|
||||
|
||||
off_t size = strtol(line+i, &p, 10);
|
||||
stat_buf.st_size = size;
|
||||
if (ftpfs.blksize) {
|
||||
stat_buf.st_blksize = ftpfs.blksize;
|
||||
stat_buf.st_blocks =
|
||||
((size + ftpfs.blksize - 1) & ~(ftpfs.blksize - 1)) >> 9;
|
||||
}
|
||||
|
||||
i = p - line;
|
||||
++i;
|
||||
|
||||
// Date
|
||||
int month;
|
||||
for (month = 0; month < 12; ++month) {
|
||||
if (!strncmp(MonthStrings[month], line+i, 3)) break;
|
||||
}
|
||||
if (month < 12) {
|
||||
i += 3;
|
||||
int day = strtol(line+i, &p, 10);
|
||||
if (p != line+i) {
|
||||
i = p - line;
|
||||
int year_or_hour = strtol(line+i, &p, 10);
|
||||
struct tm current_time;
|
||||
time_t now = time(NULL);
|
||||
localtime_r(&now, ¤t_time);
|
||||
if (p != line+i) {
|
||||
i = p - line;
|
||||
struct tm parsed_time;
|
||||
memset(&parsed_time, 0, sizeof(parsed_time));
|
||||
if (*p == ':') {
|
||||
// Hour
|
||||
++i;
|
||||
int minute = strtol(line+i, &p, 10);
|
||||
i = p - line;
|
||||
parsed_time.tm_mday = day;
|
||||
parsed_time.tm_mon = month;
|
||||
parsed_time.tm_year = current_time.tm_year;
|
||||
parsed_time.tm_hour = year_or_hour;
|
||||
parsed_time.tm_min = minute;
|
||||
stat_buf.st_atime = mktime(&parsed_time);
|
||||
if (stat_buf.st_atime > now) {
|
||||
parsed_time.tm_year--;
|
||||
stat_buf.st_atime = mktime(&parsed_time);
|
||||
}
|
||||
stat_buf.st_mtime = stat_buf.st_atime;
|
||||
stat_buf.st_ctime = stat_buf.st_atime;
|
||||
} else {
|
||||
// Year
|
||||
parsed_time.tm_mday = day;
|
||||
parsed_time.tm_mon = month;
|
||||
parsed_time.tm_year = year_or_hour - 1900;
|
||||
stat_buf.st_atime = mktime(&parsed_time);
|
||||
stat_buf.st_mtime = stat_buf.st_atime;
|
||||
stat_buf.st_ctime = stat_buf.st_atime;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Symbolic links
|
||||
const char* link = strstr(line, " -> ");
|
||||
|
||||
file = line + i + 1;
|
||||
if (link) {
|
||||
file = g_strndup(file, link - file);
|
||||
} else {
|
||||
file = g_strdup(file);
|
||||
}
|
||||
DEBUG("%s\n", file);
|
||||
|
||||
char *full_path = g_strdup_printf("%s%s", dir, file);
|
||||
|
||||
if (link) {
|
||||
link += 4;
|
||||
char *reallink;
|
||||
if (link[0] == '/' && ftpfs.symlink_prefix_len) {
|
||||
reallink = g_strdup_printf("%s%s", ftpfs.symlink_prefix, link);
|
||||
} else {
|
||||
reallink = g_strdup(link);
|
||||
}
|
||||
int linksize = strlen(reallink);
|
||||
cache_add_link(full_path, reallink, linksize+1);
|
||||
DEBUG("cache_add_link: %s %s\n", full_path, reallink);
|
||||
if (linkbuf && linklen) {
|
||||
if (linksize > linklen) linksize = linklen - 1;
|
||||
strncpy(linkbuf, reallink, linksize);
|
||||
linkbuf[linksize] = '\0';
|
||||
}
|
||||
free(reallink);
|
||||
}
|
||||
|
||||
|
||||
if (h && filler) {
|
||||
DEBUG("filler: %s\n", file);
|
||||
filler(h, file, &stat_buf);
|
||||
} else {
|
||||
DEBUG("cache_add_attr: %s\n", full_path);
|
||||
cache_add_attr(full_path, &stat_buf);
|
||||
}
|
||||
|
||||
if (name && !strcmp(name, file)) {
|
||||
if (sbuf) *sbuf = stat_buf;
|
||||
found = 1;
|
||||
}
|
||||
|
||||
free(full_path);
|
||||
free(line);
|
||||
free(file);
|
||||
}
|
||||
|
||||
if (found) return 0;
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static int ftpfs_getattr(const char* path, struct stat* sbuf) {
|
||||
int err;
|
||||
CURLcode curl_res;
|
||||
@@ -582,11 +352,12 @@ static int ftpfs_getattr(const char* path, struct stat* sbuf) {
|
||||
|
||||
char* name = strrchr(path, '/');
|
||||
++name;
|
||||
err = parse_dir(&buf, dir_path + strlen(ftpfs.host) - 1, name, sbuf, NULL, 0, NULL, NULL);
|
||||
err = parse_dir(buf.p, dir_path + strlen(ftpfs.host) - 1, name, sbuf, NULL, 0, NULL, NULL);
|
||||
|
||||
free(dir_path);
|
||||
buf_free(&buf);
|
||||
return err;
|
||||
if (err) return -ENOENT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ftpfs_open(const char* path, struct fuse_file_info* fi) {
|
||||
@@ -880,11 +651,12 @@ static int ftpfs_readlink(const char *path, char *linkbuf, size_t size) {
|
||||
|
||||
char* name = strrchr(path, '/');
|
||||
++name;
|
||||
err = parse_dir(&buf, dir_path + strlen(ftpfs.host) - 1, name, NULL, linkbuf, size, NULL, NULL);
|
||||
err = parse_dir(buf.p, dir_path + strlen(ftpfs.host) - 1, name, NULL, linkbuf, size, NULL, NULL);
|
||||
|
||||
free(dir_path);
|
||||
buf_free(&buf);
|
||||
return err;
|
||||
if (err) return -ENOENT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if FUSE_VERSION >= 25
|
||||
|
55
ftpfs.h
Normal file
55
ftpfs.h
Normal file
@@ -0,0 +1,55 @@
|
||||
#ifndef __CURLFTPFS_FTPFS_H__
|
||||
#define __CURLFTPFS_FTPFS_H__
|
||||
|
||||
#include <curl/curl.h>
|
||||
#include <curl/easy.h>
|
||||
#include <glib.h>
|
||||
|
||||
struct ftpfs {
|
||||
char* host;
|
||||
char* mountpoint;
|
||||
CURL* connection;
|
||||
unsigned blksize;
|
||||
GHashTable *filetab;
|
||||
int verbose;
|
||||
int debug;
|
||||
int transform_symlinks;
|
||||
int disable_epsv;
|
||||
int tcp_nodelay;
|
||||
int disable_eprt;
|
||||
int connect_timeout;
|
||||
int use_ssl;
|
||||
int no_verify_hostname;
|
||||
char* cert;
|
||||
char* cert_type;
|
||||
char* key;
|
||||
char* key_type;
|
||||
char* key_password;
|
||||
char* engine;
|
||||
char* cacert;
|
||||
char* capath;
|
||||
char* ciphers;
|
||||
char* interface;
|
||||
char* krb4;
|
||||
char* proxy;
|
||||
int proxytunnel;
|
||||
int proxyanyauth;
|
||||
int proxybasic;
|
||||
int proxydigest;
|
||||
int proxyntlm;
|
||||
char* user;
|
||||
char* proxy_user;
|
||||
int ssl_version;
|
||||
int ip_version;
|
||||
char symlink_prefix[PATH_MAX+1];
|
||||
size_t symlink_prefix_len;
|
||||
curl_version_info_data* curl_version;
|
||||
int safe_nobody;
|
||||
};
|
||||
|
||||
extern struct ftpfs ftpfs;
|
||||
|
||||
#define DEBUG(args...) \
|
||||
do { if (ftpfs.debug) fprintf(stderr, args); } while(0)
|
||||
|
||||
#endif /* __CURLFTPFS_FTPFS_H__ */
|
13
tests/Makefile.am
Normal file
13
tests/Makefile.am
Normal file
@@ -0,0 +1,13 @@
|
||||
EXTRA_DIST = run_tests.sh
|
||||
|
||||
noinst_PROGRAMS = ftpfs-ls_unittest
|
||||
|
||||
ftpfs_ls_unittest_SOURCES = ftpfs-ls_unittest.c ../ftpfs-ls.c ../ftpfs-ls.h ../cache.h ../cache.c
|
||||
ftpfs_ls_unittest_CPPFLAGS = -DFUSE_USE_VERSION=25
|
||||
|
||||
if FUSE_OPT_COMPAT
|
||||
ftpfs_ls_unittest_LDADD = ../compat/libcompat.la
|
||||
endif
|
||||
|
||||
test: all
|
||||
@./run_tests.sh
|
100
tests/ftpfs-ls_unittest.c
Normal file
100
tests/ftpfs-ls_unittest.c
Normal file
@@ -0,0 +1,100 @@
|
||||
#include "ftpfs.h"
|
||||
#include "ftpfs-ls.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
struct ftpfs ftpfs;
|
||||
|
||||
#define check(sbuf, dev, ino, mode, nlink, uid, gid, \
|
||||
rdev, size, blksize, blocks, date) \
|
||||
do { \
|
||||
struct tm tm; \
|
||||
time_t tt; \
|
||||
memset(&tm, 0, sizeof(tm)); \
|
||||
strptime(date, "%H:%M:%S %d/%m/%Y", &tm); \
|
||||
tt = mktime(&tm); \
|
||||
assert(sbuf.st_dev == dev); \
|
||||
assert(sbuf.st_ino == ino); \
|
||||
assert(sbuf.st_mode == mode); \
|
||||
assert(sbuf.st_nlink == nlink); \
|
||||
assert(sbuf.st_uid == uid); \
|
||||
assert(sbuf.st_gid == gid); \
|
||||
assert(sbuf.st_rdev == rdev); \
|
||||
assert(sbuf.st_size == size); \
|
||||
assert(sbuf.st_blksize == blksize); \
|
||||
assert(sbuf.st_blocks == blocks); \
|
||||
assert(sbuf.st_atime == tt); \
|
||||
assert(sbuf.st_ctime == tt); \
|
||||
assert(sbuf.st_mtime == tt); \
|
||||
} while (0);
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
const char *list;
|
||||
struct fuse_cache_operations dummy_oper;
|
||||
struct stat sbuf;
|
||||
int err;
|
||||
struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
|
||||
char linkbuf[1024];
|
||||
char year[5];
|
||||
char date[20];
|
||||
time_t tt;
|
||||
|
||||
tt = time(NULL);
|
||||
strftime(year, 5, "%Y", gmtime(&tt));
|
||||
ftpfs.blksize = 4096;
|
||||
|
||||
memset(&dummy_oper, 0, sizeof(dummy_oper));
|
||||
err = cache_parse_options(&args);
|
||||
cache_init(&dummy_oper);
|
||||
|
||||
list = "05-22-03 12:13PM <DIR> chinese_pr\r\n";
|
||||
err = parse_dir(list, "/", "chinese_pr", &sbuf, NULL, 0, NULL, NULL);
|
||||
assert(err == 0);
|
||||
check(sbuf, 0, 0, S_IFDIR, 1, 0, 0, 0, 0, 0, 0, "12:13:00 22/05/2003");
|
||||
|
||||
err = parse_dir(list, "/", "hinese_pr", &sbuf, NULL, 0, NULL, NULL);
|
||||
assert(err == 1);
|
||||
|
||||
list = "05-14-03 02:49PM 40448 PR_AU13_CH.doc\r\n";
|
||||
err = parse_dir(list, "/", "PR_AU13_CH.doc", &sbuf, NULL, 0, NULL, NULL);
|
||||
assert(err == 0);
|
||||
check(sbuf, 0, 0, S_IFREG, 1, 0, 0, 0, 40448, 4096, 80, "14:49:00 14/05/2003");
|
||||
|
||||
list = "11-25-04 09:17AM 20075882 242_310_Condor_en_ok.pdf\r\n";
|
||||
err = parse_dir(list, "/", "242_310_Condor_en_ok.pdf", &sbuf, NULL, 0, NULL, NULL);
|
||||
assert(err == 0);
|
||||
check(sbuf, 0, 0, S_IFREG, 1, 0, 0, 0, 20075882, 4096, 39216, "09:17:00 25/11/2004");
|
||||
|
||||
list = "lrwxrwxrwx 1 1 17 Nov 24 2002 lg -> cidirb/documentos\r\n";
|
||||
err = parse_dir(list, "/", "lg", &sbuf, linkbuf, 1024, NULL, NULL);
|
||||
assert(err == 0);
|
||||
assert(!strcmp(linkbuf, "cidirb/documentos"));
|
||||
check(sbuf, 0, 0, S_IFLNK|S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH, 1, 0, 0, 0, 17, 4096, 8, "00:00:00 24/11/2002");
|
||||
|
||||
list = "lrwxrwxrwx 1 1137 1100 14 Mar 12 2004 molbio -> Science/molbio\r\n";
|
||||
err = parse_dir(list, "/", "molbio", &sbuf, linkbuf, 1024, NULL, NULL);
|
||||
assert(err == 0);
|
||||
assert(!strcmp(linkbuf, "Science/molbio"));
|
||||
check(sbuf, 0, 0, S_IFLNK|S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH, 1, 0, 0, 0, 14, 4096, 8, "00:00:00 12/03/2004");
|
||||
|
||||
list = "drwxr-xr-x 4 robson users 4096 Apr 3 15:50 tests\r\n";
|
||||
err = parse_dir(list, "/", "tests", &sbuf, NULL, 0, NULL, NULL);
|
||||
assert(err == 0);
|
||||
sprintf(date, "15:50:00 03/04/%s", year);
|
||||
check(sbuf, 0, 0, S_IFDIR|S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH, 4, 0, 0, 0, 4096, 4096, 8, date);
|
||||
|
||||
list = "dr-xr-xr-x 2 root 512 Apr 8 1994 etc\r\n";
|
||||
err = parse_dir(list, "/", "etc", &sbuf, NULL, 0, NULL, NULL);
|
||||
assert(err == 0);
|
||||
check(sbuf, 0, 0, S_IFDIR|S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH, 2, 0, 0, 0, 512, 4096, 8, "00:00:00 08/04/1994");
|
||||
|
||||
list = "---------- 1 owner group 1803128 Jul 10 10:18 ls-lR.Z\r\n";
|
||||
err = parse_dir(list, "/", "ls-lR.Z", &sbuf, NULL, 0, NULL, NULL);
|
||||
assert(err == 0);
|
||||
sprintf(date, "10:18:00 10/07/%s", year);
|
||||
check(sbuf, 0, 0, S_IFREG, 1, 0, 0, 0, 1803128, 4096, 3528, date);
|
||||
|
||||
return 0;
|
||||
}
|
17
tests/run_tests.sh
Executable file
17
tests/run_tests.sh
Executable file
@@ -0,0 +1,17 @@
|
||||
#!/bin/sh
|
||||
|
||||
echo "Running unittests:"
|
||||
|
||||
failed=0
|
||||
for i in *_unittest; do
|
||||
echo -n "$i... "
|
||||
`./$i > /dev/null 2>&1`
|
||||
if [ $? == 0 ]; then
|
||||
echo "PASS"
|
||||
else
|
||||
echo "FAILED"
|
||||
failed=1;
|
||||
fi
|
||||
done
|
||||
|
||||
exit $failed
|
Reference in New Issue
Block a user