Separated ftp listing parser module. It now supports Windows NT listings. Added unittests for the listing parser module.

This commit is contained in:
braga
2006-04-05 01:36:57 +00:00
parent 5d75159bf5
commit cbd0716730
10 changed files with 450 additions and 241 deletions

View File

@@ -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)

View File

@@ -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__ */

View File

@@ -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
View 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
View 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
View File

@@ -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, &current_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
View 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
View 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
View 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
View 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