From 57db677d1f02ec282effe5e2170a72933ef3ae04 Mon Sep 17 00:00:00 2001 From: Eric Coissac Date: Sat, 23 May 2015 16:29:06 +0300 Subject: [PATCH] First minimal implementation of what should be the creation, opening and closing of an OBIDMS --- src/obidms.c | 149 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/obidms.h | 123 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 272 insertions(+) create mode 100644 src/obidms.c create mode 100644 src/obidms.h diff --git a/src/obidms.c b/src/obidms.c new file mode 100644 index 0000000..d694911 --- /dev/null +++ b/src/obidms.c @@ -0,0 +1,149 @@ +/* + * obidms.c + * + * @date 23 May 2015 + * @Author: coissac + */ + +#include + +/** + * Internal function building the directory name from a OBIDMS name. + * + * The function build the directory name corresponding to a OBIDMS. + * It checks also that the name is not too long. + * + * @warning The returned pointer has to be freed by the caller. + * + * @param name the name of the OBIDMS + * + * @return a pointer to the directory name + * @retvalue if everything is ok + * @retvalue NULL if an error occurs + * + * ###Error values + * - OBIDMS_MEMORY_ERROR : something wrong occurs during memory allocation. + * - OBIDMS_LONG_NAME_ERROR : the database name exceeds the limit. + * + * @since May 2015 + * @author Eric Coissac (eric.coissac@metabarcoding.org) + */ +static char *build_directory_name(const char *name) { + + char *dirdbname; + + // Build the database directory name + if (asprintf(&dirdbname,"%s.obidms",name) < 0) + { + obi_set_errno(OBIDMS_MEMORY_ERROR); + return NULL; + } + + // Test if the database name is not too long + if (strlen(dirdbname) >= OBIDMS_MAX_NAME) + { + obi_set_errno(OBIDMS_LONG_NAME_ERROR); + free(dirdbname); + return NULL; + } + + return dirdbname; +} + +OBIDMS_p obi_create_dms(const char *name) { + OBIDMS_p dms=NULL; + char *dirdbname; + + // Build and check the directory name + dirdbname = build_directory_name(name); + if (dirdbname==NULL) + return NULL; + + + // Try to create the directory + if (mkdir(dirdbname,) < 0) + { + if (errno==EEXIST) + obi_set_errno(OBIDMS_EXIST_ERROR); + else + obi_set_errno(OBIDMS_UNKNOWN_ERROR); + + free(dirdbname); + return NULL; + } + + free(dirdbname); + + return obi_open_dms(name); +} + +OBIDMS_p obi_open_dms(const char *name) { + OBIDMS_p dms=NULL; + char *dirdbname; + DIR *directory; + + // Build and check the directory name + dirdbname = build_directory_name(name); + if (dirdbname==NULL) + return NULL; + + // try to open the directory + directory = opendir(dirdbname); + if (directory==NULL) { + switch (errno) { + case ENOENT: + obi_set_errno(OBIDMS_NOT_EXIST_ERROR); + break; + + case EACCES: + obi_set_errno(OBIDMS_ACCESS_ERROR); + break; + + case ENOMEM: + obi_set_errno(OBIDMS_MEMORY_ERROR); + break; + + default: + obi_set_errno(OBIDMS_UNKNOWN_ERROR); + } + free(dirdbname); + return NULL; + } + + // Allocate the data structure + dms = malloc(sizeof(OBIDMS_t)); + + if (dms==NULL) + { + obi_set_errno(OBIDMS_MEMORY_ERROR); + free(dirdbname); + return NULL; + } + + // Initialise the data structure + strcpy(dms->dirname,dirdbname); + dms->directory=directory; + + free(dirdbname); + return dms; +} + + +int obi_close_dms(OBIDMS_p dms) { + + if (dms != NULL) + { + if (closedir(dms->directory) < 0) + { + obi_set_errno(OBIDMS_MEMORY_ERROR); + free(dms); + return -1; + } + + free(dms); + + } + + return 0; +} + diff --git a/src/obidms.h b/src/obidms.h new file mode 100644 index 0000000..6e80d3c --- /dev/null +++ b/src/obidms.h @@ -0,0 +1,123 @@ +/* + * obidms.h + * + * Created on: 23 mai 2015 + * Author: coissac + */ + +#ifndef OBIDMS_H_ +#define OBIDMS_H_ + +#include +#include +#include +#include + +#include + +#define OBIDMS_MAX_NAME (2048) /**< The maximum length of an OBIDMS name + */ + +/** @brief A structure decribing an OBIDMS instance + * + * A pointer to this structure is returned on creation + * and opening of an OBITools Data Management System (DMS) + */ + +typedef struct OBIDMS { + char dirname[OBIDMS_MAX_NAME+1]; /**< The name of the directory + * containing the DMS + */ + DIR *directory /**< A directory entry usable to + * refer and scan the database directory + */ +} OBIDMS_t, *OBIDMS_p; + +/** + * @defgroup OBIDMSErrors OBIDMS related error codes + * + * Error codes set in errno following an error related + * to the manipulation of an OBIDMS. + * + * @{ + */ +#define OBIDMS_EXIST_ERROR (1) /**< Try to create an OBIDMS with a name + * that corresponds to an existing OBIDMS + */ +#define OBIDMS_NOT_EXIST_ERROR (2) /**< Try to open a non-existing OBIDMS + */ +#define OBIDMS_LONG_NAME_ERROR (3) /**< The specified OBIDMS name is too long + */ +#define OBIDMS_MEMORY_ERROR (4) /**< A memory error occurred during allocation + */ +#define OBIDMS_UNKNOWN_ERROR (5) /**< Not determined error + */ +#define OBIDMS_ACCESS_ERROR (6) /**< Permission error for accessing to the database + */ +/**@}*/ + + +/** + * @brief Create a new OBITools Data Management instance (OBIDMS). + * + * A `DMS` is implemented as a directory. This function takes care + * to check if a directory with this name does not already exist + * before creating the new database + * + * @param name a pointer to a C string containing the name of the database + * the actual directory name used to store the DMS will be + * `.obidms` + * + * @return a pointer to an OBIDMS structure describing the newly created DMS + * @retval NULL on error and the `obi_errno` variable is set. + * + * ###Error values + * - OBIDMS_EXIST_ERROR : a database with the same name already exists. + * - OBIDMS_LONG_NAME_ERROR : the database name exceeds the limit. + * - OBIDMS_MEMORY_ERROR : something wrong occurs during memory allocation. + * + * @see obi_close_dms() + * @since May 2015 + * @author Eric Coissac (eric.coissac@metabarcoding.org) + */ +OBIDMS_p obi_create_dms(const char *name); + +/** + * @brief Open an existing OBITools Data Management instance (OBIDMS). + * + * @param name a pointer to a C string containing the name of the database + * the actual directory name used to store the DMS will be + * `.obidms` + * + * @return a pointer to an OBIDMS structure describing the newly created DMS + * @retval NULL on error and the `obi_errno`variable is set. + * + * ###Error values + * - OBIDMS_EXIST_ERROR : a database with the same name already exists. + * - OBIDMS_LONG_NAME_ERROR : the database name exceeds the limit. + * - OBIDMS_MEMORY_ERROR : something wrong occurs during memory allocation. + * + * @see obi_close_dms() + * @since May 2015 + * @author Eric Coissac (eric.coissac@metabarcoding.org) + */ +OBIDMS_p obi_open_dms(const char *name); + +/** + * @brief Close an opened OBITools Data Management instance (OBIDMS). + * + * @param dms a pointer as returned by obi_create_dms() or obi_open_dms() + * + * @return an integer value indicating the success of the operation. Even on + * error, the `OBIDMS` structure is freed + * @retvalue 0 on success + * @retvalue -1 on failure and the `obi_errno` variable is set. + * + * @see obi_create_dms() + * @see obi_open_dms() + * @since May 2015 + * @author Eric Coissac (eric.coissac@metabarcoding.org) + */ +int obi_close_dms(OBIDMS_p dms); + +#endif /* OBIDMS_H_ */