net-snmp 5.7
file_utils.c
00001 #include <net-snmp/net-snmp-config.h>
00002 #include <net-snmp/net-snmp-features.h>
00003 #include <net-snmp/net-snmp-includes.h>
00004 
00005 #include <stdio.h>
00006 #include <ctype.h>
00007 #if HAVE_STDLIB_H
00008 #   include <stdlib.h>
00009 #endif
00010 #if HAVE_UNISTD_H
00011 #   include <unistd.h>
00012 #endif
00013 #if HAVE_STRING_H
00014 #   include <string.h>
00015 #else
00016 #  include <strings.h>
00017 #endif
00018 
00019 #include <sys/types.h>
00020 
00021 #if HAVE_SYS_PARAM_H
00022 #   include <sys/param.h>
00023 #endif
00024 #ifdef HAVE_SYS_STAT_H
00025 #   include <sys/stat.h>
00026 #endif
00027 #ifdef HAVE_FCNTL_H
00028 #   include <fcntl.h>
00029 #endif
00030 
00031 #include <errno.h>
00032 
00033 #if HAVE_DMALLOC_H
00034 #  include <dmalloc.h>
00035 #endif
00036 
00037 #include <net-snmp/types.h>
00038 #include <net-snmp/library/container.h>
00039 #include <net-snmp/library/file_utils.h>
00040 
00041 netsnmp_feature_child_of(file_utils_all, libnetsnmp)
00042 netsnmp_feature_child_of(file_utils, file_utils_all)
00043 netsnmp_feature_child_of(file_close, file_utils_all)
00044 
00045 #ifndef NETSNMP_FEATURE_REMOVE_FILE_UTILS
00046 /*------------------------------------------------------------------
00047  *
00048  * Prototypes
00049  *
00050  */
00051 
00052 
00053 
00054 
00055 /*------------------------------------------------------------------
00056  *
00057  * Core Functions
00058  *
00059  */
00060 
00067 netsnmp_file *
00068 netsnmp_file_create(void)
00069 {
00070     netsnmp_file *filei = SNMP_MALLOC_TYPEDEF(netsnmp_file);
00071 
00072     /*
00073      * 0 is a valid file descriptor, so init to -1
00074      */
00075     if (NULL != filei)
00076         filei->fd = -1;
00077     else {
00078         snmp_log(LOG_WARNING,"failed to malloc netsnmp_file structure\n");
00079     }
00080 
00081     return filei;
00082 }
00083 
00087 netsnmp_file *
00088 netsnmp_file_new(const char *name, int fs_flags, mode_t mode, u_int ns_flags)
00089 {
00090     netsnmp_file *filei = netsnmp_file_fill(NULL, name, fs_flags, mode, 0);
00091     if (NULL == filei)
00092         return NULL;
00093 
00094     if (ns_flags & NETSNMP_FILE_STATS) {
00095         filei->stats = (struct stat*)calloc(1, sizeof(*(filei->stats)));
00096         if (NULL == filei->stats)
00097             DEBUGMSGT(("nsfile:new", "no memory for stats\n"));
00098         else if (stat(name, filei->stats) != 0)
00099             DEBUGMSGT(("nsfile:new", "error getting stats\n"));
00100     }
00101 
00102     if (ns_flags & NETSNMP_FILE_AUTO_OPEN)
00103         netsnmp_file_open(filei);
00104 
00105     return filei;
00106 }
00107 
00108         
00118 netsnmp_file *
00119 netsnmp_file_fill(netsnmp_file * filei, const char* name,
00120                   int fs_flags, mode_t mode, u_int ns_flags)
00121 {
00122     if (NULL == filei) {
00123         filei = netsnmp_file_create();
00124         if (NULL == filei) /* failure already logged */
00125             return NULL;
00126     }
00127 
00128     if (NULL != name)
00129         filei->name = strdup(name);
00130 
00131     filei->fs_flags = fs_flags;
00132     filei->ns_flags = ns_flags;
00133     filei->mode = mode;
00134 
00135     return filei;
00136 }
00137 
00143 int
00144 netsnmp_file_release(netsnmp_file * filei)
00145 {
00146     int rc = 0;
00147 
00148     if (NULL == filei)
00149         return -1;
00150 
00151     if ((filei->fd > 0) && NS_FI_AUTOCLOSE(filei->ns_flags))
00152         rc = close(filei->fd);
00153 
00154     if (NULL != filei->name)
00155         free(filei->name); /* no point in SNMP_FREE */
00156 
00157     if (NULL != filei->extras)
00158         netsnmp_free_all_list_data(filei->extras);
00159 
00160     if (NULL != filei->stats)
00161         free(filei->stats);
00162 
00163     SNMP_FREE(filei);
00164 
00165     return rc;
00166 }
00167 
00174 int
00175 netsnmp_file_open(netsnmp_file * filei)
00176 {
00177     /*
00178      * basic sanity checks
00179      */
00180     if ((NULL == filei) || (NULL == filei->name))
00181         return -1;
00182 
00183     /*
00184      * if file is already open, just return the fd.
00185      */
00186     if (-1 != filei->fd)
00187         return filei->fd;
00188 
00189     /*
00190      * try to open the file, loging an error if we failed
00191      */
00192     if (0 == filei->mode)
00193         filei->fd = open(filei->name, filei->fs_flags);
00194     else
00195         filei->fd = open(filei->name, filei->fs_flags, filei->mode);
00196 
00197     if (filei->fd < 0) {
00198         snmp_log(LOG_ERR, "error opening %s (%d)\n", filei->name, errno);
00199     }
00200 
00201     /*
00202      * return results
00203      */
00204     return filei->fd;
00205 }
00206 
00207 
00214 #ifndef NETSNMP_FEATURE_REMOVE_FILE_CLOSE
00215 int
00216 netsnmp_file_close(netsnmp_file * filei)
00217 {
00218     int rc;
00219 
00220     /*
00221      * basic sanity checks
00222      */
00223     if ((NULL == filei) || (NULL != filei->name))
00224         return -1;
00225 
00226     /*
00227      * make sure it's not already closed
00228      */
00229     if (-1 == filei->fd) {
00230         return 0;
00231     }
00232 
00233     /*
00234      * close the file, logging an error if we failed
00235      */
00236     rc = close(filei->fd);
00237     if (rc < 0) {
00238         snmp_log(LOG_ERR, "error closing %s (%d)\n", filei->name, errno);
00239     }
00240     else
00241         filei->fd = -1;
00242 
00243     return rc;
00244 }
00245 #endif /* NETSNMP_FEATURE_REMOVE_FILE_CLOSE */
00246 
00247 void
00248 netsnmp_file_container_free(netsnmp_file *file, void *context)
00249 {
00250     netsnmp_file_release(file);
00251 }
00252 
00253 int
00254 netsnmp_file_compare_name(netsnmp_file *lhs, netsnmp_file *rhs)
00255 {
00256     netsnmp_assert((NULL != lhs) && (NULL != rhs));
00257     netsnmp_assert((NULL != lhs->name) && (NULL != rhs->name));
00258 
00259     return strcmp(lhs->name, rhs->name);
00260 }
00261 #else /* NETSNMP_FEATURE_REMOVE_FILE_UTILS */
00262 netsnmp_feature_unused(file_utils);
00263 #endif /* NETSNMP_FEATURE_REMOVE_FILE_UTILS */