diff options
Diffstat (limited to 'snmplib/file_utils.c')
-rw-r--r-- | snmplib/file_utils.c | 263 |
1 files changed, 263 insertions, 0 deletions
diff --git a/snmplib/file_utils.c b/snmplib/file_utils.c new file mode 100644 index 0000000..5261431 --- /dev/null +++ b/snmplib/file_utils.c @@ -0,0 +1,263 @@ +#include <net-snmp/net-snmp-config.h> +#include <net-snmp/net-snmp-features.h> +#include <net-snmp/net-snmp-includes.h> + +#include <stdio.h> +#include <ctype.h> +#if HAVE_STDLIB_H +# include <stdlib.h> +#endif +#if HAVE_UNISTD_H +# include <unistd.h> +#endif +#if HAVE_STRING_H +# include <string.h> +#else +# include <strings.h> +#endif + +#include <sys/types.h> + +#if HAVE_SYS_PARAM_H +# include <sys/param.h> +#endif +#ifdef HAVE_SYS_STAT_H +# include <sys/stat.h> +#endif +#ifdef HAVE_FCNTL_H +# include <fcntl.h> +#endif + +#include <errno.h> + +#if HAVE_DMALLOC_H +# include <dmalloc.h> +#endif + +#include <net-snmp/types.h> +#include <net-snmp/library/container.h> +#include <net-snmp/library/file_utils.h> + +netsnmp_feature_child_of(file_utils_all, libnetsnmp) +netsnmp_feature_child_of(file_utils, file_utils_all) +netsnmp_feature_child_of(file_close, file_utils_all) + +#ifndef NETSNMP_FEATURE_REMOVE_FILE_UTILS +/*------------------------------------------------------------------ + * + * Prototypes + * + */ + + + + +/*------------------------------------------------------------------ + * + * Core Functions + * + */ + +/** + * allocate a netsnmp_file structure + * + * This routine should be used instead of allocating on the stack, + * for future compatability. + */ +netsnmp_file * +netsnmp_file_create(void) +{ + netsnmp_file *filei = SNMP_MALLOC_TYPEDEF(netsnmp_file); + + /* + * 0 is a valid file descriptor, so init to -1 + */ + if (NULL != filei) + filei->fd = -1; + else { + snmp_log(LOG_WARNING,"failed to malloc netsnmp_file structure\n"); + } + + return filei; +} + +/** + * open file and get stats + */ +netsnmp_file * +netsnmp_file_new(const char *name, int fs_flags, mode_t mode, u_int ns_flags) +{ + netsnmp_file *filei = netsnmp_file_fill(NULL, name, fs_flags, mode, 0); + if (NULL == filei) + return NULL; + + if (ns_flags & NETSNMP_FILE_STATS) { + filei->stats = (struct stat*)calloc(1, sizeof(*(filei->stats))); + if (NULL == filei->stats) + DEBUGMSGT(("nsfile:new", "no memory for stats\n")); + else if (stat(name, filei->stats) != 0) + DEBUGMSGT(("nsfile:new", "error getting stats\n")); + } + + if (ns_flags & NETSNMP_FILE_AUTO_OPEN) + netsnmp_file_open(filei); + + return filei; +} + + +/** + * fill core members in a netsnmp_file structure + * + * @param filei structure to fill; if NULL, a new one will be allocated + * @param name file name + * @param fs_flags filesystem flags passed to open() + * @param mode optional filesystem open modes passed to open() + * @param ns_flags net-snmp flags + */ +netsnmp_file * +netsnmp_file_fill(netsnmp_file * filei, const char* name, + int fs_flags, mode_t mode, u_int ns_flags) +{ + if (NULL == filei) { + filei = netsnmp_file_create(); + if (NULL == filei) /* failure already logged */ + return NULL; + } + + if (NULL != name) + filei->name = strdup(name); + + filei->fs_flags = fs_flags; + filei->ns_flags = ns_flags; + filei->mode = mode; + + return filei; +} + +/** + * release a netsnmp_file structure + * + * @retval see close() man page + */ +int +netsnmp_file_release(netsnmp_file * filei) +{ + int rc = 0; + + if (NULL == filei) + return -1; + + if ((filei->fd > 0) && NS_FI_AUTOCLOSE(filei->ns_flags)) + rc = close(filei->fd); + + if (NULL != filei->name) + free(filei->name); /* no point in SNMP_FREE */ + + if (NULL != filei->extras) + netsnmp_free_all_list_data(filei->extras); + + if (NULL != filei->stats) + free(filei->stats); + + SNMP_FREE(filei); + + return rc; +} + +/** + * open the file associated with a netsnmp_file structure + * + * @retval -1 : error opening file + * @retval >=0 : file descriptor for opened file + */ +int +netsnmp_file_open(netsnmp_file * filei) +{ + /* + * basic sanity checks + */ + if ((NULL == filei) || (NULL == filei->name)) + return -1; + + /* + * if file is already open, just return the fd. + */ + if (-1 != filei->fd) + return filei->fd; + + /* + * try to open the file, loging an error if we failed + */ + if (0 == filei->mode) + filei->fd = open(filei->name, filei->fs_flags); + else + filei->fd = open(filei->name, filei->fs_flags, filei->mode); + + if (filei->fd < 0) { + DEBUGMSGTL(("netsnmp_file", "error opening %s (%d)\n", filei->name, errno)); + } + + /* + * return results + */ + return filei->fd; +} + + +/** + * close the file associated with a netsnmp_file structure + * + * @retval 0 : success + * @retval -1 : error + */ +#ifndef NETSNMP_FEATURE_REMOVE_FILE_CLOSE +int +netsnmp_file_close(netsnmp_file * filei) +{ + int rc; + + /* + * basic sanity checks + */ + if ((NULL == filei) || (NULL != filei->name)) + return -1; + + /* + * make sure it's not already closed + */ + if (-1 == filei->fd) { + return 0; + } + + /* + * close the file, logging an error if we failed + */ + rc = close(filei->fd); + if (rc < 0) { + DEBUGMSGTL(("netsnmp_file", "error closing %s (%d)\n", filei->name, errno)); + } + else + filei->fd = -1; + + return rc; +} +#endif /* NETSNMP_FEATURE_REMOVE_FILE_CLOSE */ + +void +netsnmp_file_container_free(netsnmp_file *file, void *context) +{ + netsnmp_file_release(file); +} + +int +netsnmp_file_compare_name(netsnmp_file *lhs, netsnmp_file *rhs) +{ + netsnmp_assert((NULL != lhs) && (NULL != rhs)); + netsnmp_assert((NULL != lhs->name) && (NULL != rhs->name)); + + return strcmp(lhs->name, rhs->name); +} +#else /* NETSNMP_FEATURE_REMOVE_FILE_UTILS */ +netsnmp_feature_unused(file_utils); +#endif /* NETSNMP_FEATURE_REMOVE_FILE_UTILS */ |