obidmscolumndir.c 6.61 KB
Newer Older
1
/****************************************************************************
2
 * OBIDMS column directories functions                                      *
3 4 5
 ****************************************************************************/

/**
6
 * @file obidmscolumndir.c
7
 * @author Celine Mercier (celine.mercier@metabarcoding.org)
8
 * @date 18 June 2015
9
 * @brief Functions for OBIDMS column directories.
10 11 12 13 14 15
 */


#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
16
#include <sys/stat.h>
17 18 19 20
#include <dirent.h>
#include <fcntl.h>
#include <unistd.h>

21
#include "obidmscolumndir.h"
22 23 24
#include "obidms.h"
#include "private_at_functions.h"
#include "obierrno.h"
25 26 27
#include "obidebug.h"


28
#define DEBUG_LEVEL 0	// TODO has to be defined somewhere else (cython compil flag?)
29 30 31 32 33 34 35 36 37 38


/**************************************************************************
 *
 * D E C L A R A T I O N   O F   T H E   P R I V A T E   F U N C T I O N S
 *
 **************************************************************************/


/**
39
 * Internal function building the column directory name from an OBIDMS column name.
40
 *
41
 * The function builds the directory name corresponding to an OBIDMS column directory.
42 43 44 45
 * It checks also that the name is not too long.
 *
 * @warning The returned pointer has to be freed by the caller.
 *
46
 * @param column_name The name of the OBIDMS column.
47
 *
48 49
 * @returns A pointer to the OBIDMS column directory name.
 * @retval NULL if an error occurred.
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
 *
 * @since June 2015
 * @author Celine Mercier (celine.mercier@metabarcoding.org)
 */
static char* build_column_directory_name(const char* column_name);


/************************************************************************
 *
 * D E F I N I T I O N   O F   T H E   P R I V A T E   F U N C T I O N S
 *
 ************************************************************************/

static char* build_column_directory_name(const char* column_name)
{
	char* column_directory_name;

	// Build the database directory name
	if (asprintf(&column_directory_name, "%s.obicol", column_name) < 0)
	{
		obi_set_errno(OBICOLDIR_MEMORY_ERROR);
71
		obidebug(1, "\nError building a column directory name");
72 73 74 75
		return NULL;
	}

	// Test if the database name is not too long
76
	if (strlen(column_directory_name) >= OBIDMS_COLUMN_MAX_NAME)
77 78
	{
		obi_set_errno(OBICOLDIR_LONG_NAME_ERROR);
79
		obidebug(1, "\nError due to column name too long");
80 81 82 83 84 85 86 87 88 89 90 91 92 93
		free(column_directory_name);
		return NULL;
	}

	return column_directory_name;
}


/**********************************************************************
 *
 * D E F I N I T I O N   O F   T H E   P U B L I C   F U N C T I O N S
 *
 **********************************************************************/

94
int obi_column_directory_exists(OBIDMS_p dms, const char* column_name)
95 96 97 98 99 100 101 102 103 104 105 106
{
    struct 	stat buffer;
	char* 	column_directory_name;
	char* 	full_path;
    int 	check_dir;

	// Build and check the directory name
    column_directory_name = build_column_directory_name(column_name);
	if (column_directory_name == NULL)
		return -1;

	// Get the full path for the column directory
107
	full_path = get_full_path(dms->dir_fd, column_directory_name);
108 109 110
	if (full_path == NULL)
	{
		obi_set_errno(OBICOLDIR_UNKNOWN_ERROR);
111
		obidebug(1, "\nError getting path for an OBIDMS directory");
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
		free(column_directory_name);
		return -1;
	}

	check_dir = stat(full_path, &buffer);

	free(column_directory_name);
	free(full_path);

    if(check_dir == 0)
        return 1;
    else
        return 0;
}


128
OBIDMS_column_directory_p obi_create_column_directory(OBIDMS_p dms, const char* column_name)
129 130 131 132 133 134 135 136 137 138 139 140
{
	char* 	column_directory_name;

	// Build and check the directory name
	column_directory_name = build_column_directory_name(column_name);
	if (column_directory_name == NULL)
	{
		obi_set_errno(OBICOLDIR_UNKNOWN_ERROR);
		return NULL;
	}

	// Try to create the directory
141
	if (mkdirat(dms->dir_fd, column_directory_name, 00777) < 0)
142 143 144 145 146
	{
		if (errno == EEXIST)
			obi_set_errno(OBICOLDIR_EXIST_ERROR);
		else
			obi_set_errno(OBICOLDIR_UNKNOWN_ERROR);
147
		obidebug(1, "\nError creating a column directory");
148 149 150 151 152 153
		free(column_directory_name);
		return NULL;
	}

	free(column_directory_name);

154
	return obi_open_column_directory(dms, column_name);
155 156 157
}


158
OBIDMS_column_directory_p obi_open_column_directory(OBIDMS_p dms, const char* column_name)
159
{
160
	OBIDMS_column_directory_p	column_directory;
161 162
	char*	 					column_directory_name;
	DIR*						directory;
163

164
	column_directory = NULL;
165 166 167 168 169 170 171

	// Build and check the directory name
	column_directory_name = build_column_directory_name(column_name);
	if (column_directory_name == NULL)
		return NULL;

	// Try to open the column directory
172
	directory = private_opendirat(dms->dir_fd, column_directory_name);
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
	if (directory == NULL) {
		switch (errno)
		{
			case ENOENT:
				obi_set_errno(OBICOLDIR_NOT_EXIST_ERROR);
				break;

			case EACCES:
				obi_set_errno(OBICOLDIR_ACCESS_ERROR);
				break;

			case ENOMEM:
				obi_set_errno(OBICOLDIR_MEMORY_ERROR);
				break;

			default:
				obi_set_errno(OBICOLDIR_UNKNOWN_ERROR);
		}
191
		obidebug(1, "\nError opening a column directory");
192 193 194 195 196
		free(column_directory_name);
		return NULL;
	}

	// Allocate the column dir structure
197 198
	column_directory = (OBIDMS_column_directory_p) malloc(sizeof(OBIDMS_column_directory_t));
	if (column_directory == NULL)
199 200
	{
		obi_set_errno(OBICOLDIR_MEMORY_ERROR);
201
		obidebug(1, "\nError allocating the memory for an OBIDMS column directory structure");
202 203 204 205 206
		free(column_directory_name);
		return NULL;
	}

	// Initialize the data structure
207 208 209
	strcpy(column_directory->directory_name, column_directory_name);
	strcpy(column_directory->column_name, column_name);
	column_directory->directory = directory;
210

211 212 213 214 215 216 217 218 219
	column_directory->dir_fd = dirfd(directory);
	if (column_directory->dir_fd < 0)
	{
		obi_set_errno(OBICOLDIR_MEMORY_ERROR);
		obidebug(1, "\nError allocating the memory for an OBIDMS column directory structure");
		free(column_directory_name);
		free(column_directory);
	}

220 221
	free(column_directory_name);

222
	return column_directory;
223 224 225
}


226
OBIDMS_column_directory_p obi_column_directory(OBIDMS_p dms, const char* column_name)
227 228
{
	int exists;
229
	exists = obi_column_directory_exists(dms, column_name);
230 231 232 233

	switch (exists)
	{
		case 0:
234
			return obi_create_column_directory(dms, column_name);
235
		case 1:
236
			return obi_open_column_directory(dms, column_name);
237 238
	};

239
	obidebug(1, "\nError checking if a column directory exists");
240 241 242 243
	return NULL;
}


244
int obi_close_column_directory(OBIDMS_column_directory_p column_directory)
245
{
246
	if (column_directory != NULL)
247 248
	{
		// Close the column directory
249
		if (closedir(column_directory->directory) < 0)
250 251
		{
			obi_set_errno(OBICOLDIR_MEMORY_ERROR);
252
			obidebug(1, "\nError closing a column directory");
253
			free(column_directory);
254 255
			return -1;
		}
256
		free(column_directory);
257 258 259 260 261
	}

	return 0;
}