From 88766588104495c21b26d301b55f861cdf9c0031 Mon Sep 17 00:00:00 2001 From: Klaas Freitag Date: Thu, 23 Aug 2012 17:48:24 +0300 Subject: [PATCH] Added functions to read the file tree from database. --- src/csync_dbtree.c | 226 +++++++++++++++++++++++++++++++++++++++++++++ src/csync_dbtree.h | 60 ++++++++++++ 2 files changed, 286 insertions(+) create mode 100644 src/csync_dbtree.c create mode 100644 src/csync_dbtree.h diff --git a/src/csync_dbtree.c b/src/csync_dbtree.c new file mode 100644 index 000000000..47a2f0ba7 --- /dev/null +++ b/src/csync_dbtree.c @@ -0,0 +1,226 @@ +/* + * libcsync -- a library to sync a directory with another + * + * Copyright (c) 2012 by Klaas Freitag + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "config.h" + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include "csync_dbtree.h" +#include "c_lib.h" +#include "csync_private.h" +#include "csync_statedb.h" +#include "csync_util.h" + + +#define CSYNC_LOG_CATEGORY_NAME "csync.dbtree" +#include "csync_log.h" + +struct dir_listing { + c_list_t *list; + unsigned int cnt; + c_list_t *entry; + char *dir; +}; + +csync_vio_method_handle_t *csync_dbtree_opendir(CSYNC *ctx, const char *name) +{ + char *stmt = NULL; + char *column = NULL; + const char *path = NULL; + csync_vio_file_stat_t *fs = NULL; + unsigned int c = 0; + c_strlist_t *list = NULL; + struct dir_listing *listing = NULL; + + /* "phash INTEGER(8)," + "pathlen INTEGER," + "path VARCHAR(4096)," + "inode INTEGER," + "uid INTEGER," + "gid INTEGER," + "mode INTEGER," + "modtime INTEGER(8)," + "type INTEGER," + "md5 VARCHAR(32)," + */ + + int col_count = 9; + + path = name + strlen(ctx->remote.uri)+1; + + if( asprintf( &stmt, "SELECT phash, path, inode, uid, gid, mode, modtime, type, md5 " + "FROM metadata WHERE path GLOB('%s/*')", path ) < 0 ) { + return NULL; + } + CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "SQL: %s", stmt); + + list = csync_statedb_query( ctx, stmt ); + /* list count must be a multiple of col_count */ + if( list->count % col_count != 0 ) { + CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR, "Wrong size of query result list"); + return NULL; + } + + listing = c_malloc(sizeof(struct dir_listing)); + if( listing == NULL ) { + errno = ENOMEM; + return NULL; + } + + listing->dir = c_strdup(path); + + for( c = 0; c < (list->count / col_count); c++) { + int base = c*col_count; + int cnt = 0; + int tpath_len = 0; + int type = 0; + + char *tpath = list->vector[base+1]; + /* check if the result points to a file directly below the search path + * by checking if there is another / in the result. + * If yes, skip it. + * FIXME: Find a better filter solution here. + */ + tpath += strlen(path)+1; /* jump over the search path */ + tpath_len = strlen( tpath ); + while( cnt < tpath_len ) { + + if(*(tpath+cnt) == '/') { + CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "Skipping entry: %s", list->vector[base+1]); + break; + } + cnt++; + } + if( cnt < tpath_len ) continue; + + fs = csync_vio_file_stat_new(); + fs->fields = CSYNC_VIO_FILE_STAT_FIELDS_NONE; + + column = list->vector[base+0]; /* phash */ + + column = list->vector[base+1]; /* path */ + fs->name = c_strdup(column+strlen(path)+1); + + column = list->vector[base+2]; /* inode */ + fs->inode = atoi(column); + fs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_INODE; + + column = list->vector[base+3]; /* uid */ + fs->uid = atoi(column); + fs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_UID; + + column = list->vector[base+4]; /* gid */ + fs->gid = atoi(column); + fs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_GID; + + column = list->vector[base+5]; /* mode */ + fs->mode = atoi(column); + // fs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_M; + + column = list->vector[base+6]; /* modtime */ + fs->mtime = strtoul(column, NULL, 10); + fs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_MTIME; + + column = list->vector[base+7]; /* type */ + type = atoi(column); + /* Attention: the type of csync_ftw_type_e which is the source for + * the database entry is different from csync_vio_file_type_e which + * is the target file type here. Mapping is needed! + */ + switch( type ) { + case CSYNC_FTW_TYPE_DIR: + fs->type = CSYNC_VIO_FILE_TYPE_DIRECTORY; + break; + case CSYNC_FTW_TYPE_FILE: + fs->type = CSYNC_VIO_FILE_TYPE_REGULAR; + break; + case CSYNC_FTW_TYPE_SLINK: + fs->type = CSYNC_VIO_FILE_TYPE_SYMBOLIC_LINK; + break; + default: + fs->type = CSYNC_VIO_FILE_TYPE_UNKNOWN; + } + fs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_TYPE; + + column = list->vector[base+8]; /* type */ + fs->md5 = c_strdup(column); + fs->fields |= CSYNC_VIO_FILE_STAT_FIELDS_MD5; + + /* store into result list. */ + listing->list = c_list_append( listing->list, fs ); + listing->cnt++; + } + listing->entry = c_list_first( listing->list ); + + return listing; +} + +int csync_dbtree_closedir(CSYNC *ctx, csync_vio_method_handle_t *dhandle) +{ + struct dir_listing *dl = NULL; + int rc = 0; + + c_list_t *entry = NULL; + csync_vio_file_stat_t *fs = NULL; + + if( dhandle != NULL ) { + dl = (struct dir_listing*) dhandle; +#if 0 + entry = c_list_first( dl->list ); + + while( entry ) { + + fs = (csync_vio_file_stat_t*) entry->data; + // csync_vio_file_stat_destroy(fs); + entry = c_list_next(dl->list); + } +#endif + } + return rc; +} + +csync_vio_file_stat_t *csync_dbtree_readdir(CSYNC *ctx, csync_vio_method_handle_t *dhandle) +{ + csync_vio_file_stat_t *fs = NULL; + struct dir_listing *dl = NULL; + + if( dhandle != NULL ) { + dl = (struct dir_listing*) dhandle; + if( dl->entry != NULL ) { + fs = (csync_vio_file_stat_t*) dl->entry->data; + + dl->entry = c_list_next( dl->entry); + } + } + + return fs; +} + +/* vim: set ts=8 sw=2 et cindent: */ diff --git a/src/csync_dbtree.h b/src/csync_dbtree.h new file mode 100644 index 000000000..297a9995f --- /dev/null +++ b/src/csync_dbtree.h @@ -0,0 +1,60 @@ +/* + * libcsync -- a library to sync a directory with another + * + * Copyright (c) 2012 by Klaas Freitag + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @file csync_dbtree.h + * + * @brief Private interface of csync + * + * @defgroup csyncdbtreeInternals csync statedb internals + * @ingroup csyncInternalAPI + * + * @{ + */ + +#ifndef _CSYNC_DBTREE_H +#define _CSYNC_DBTREE_H + +#include "c_lib.h" +#include "csync_private.h" +#include "vio/csync_vio_handle.h" + +/** + * @brief Open a directory based on the statedb. + * + * This function reads the list of files within a directory from statedb and + * builds up a list in memory. + * + * @param ctx The csync context. + * @param name The directory name. + * + * @return 0 on success, less than 0 if an error occured with errno set. + */ +csync_vio_method_handle_t *csync_dbtree_opendir(CSYNC *ctx, const char *name); + +int csync_dbtree_closedir(CSYNC *ctx, csync_vio_method_handle_t *dhandle); + +csync_vio_file_stat_t *csync_dbtree_readdir(CSYNC *ctx, csync_vio_method_handle_t *dhandle); + +/** + * }@ + */ +#endif /* _CSYNC_DBTREE_H */ +/* vim: set ft=c.doxygen ts=8 sw=2 et cindent: */