Coverage Report

Created: 2023-06-07 06:43

/src/net-snmp/snmplib/file_utils.c
Line
Count
Source (jump to first uncovered line)
1
#include <net-snmp/net-snmp-config.h>
2
#include <net-snmp/net-snmp-features.h>
3
#include <net-snmp/net-snmp-includes.h>
4
5
#ifdef HAVE_IO_H
6
#include <io.h>
7
#endif
8
#include <stdio.h>
9
#include <ctype.h>
10
#ifdef HAVE_STDLIB_H
11
#   include <stdlib.h>
12
#endif
13
#ifdef HAVE_UNISTD_H
14
#   include <unistd.h>
15
#endif
16
#ifdef HAVE_STRING_H
17
#   include <string.h>
18
#else
19
#  include <strings.h>
20
#endif
21
22
#include <sys/types.h>
23
24
#ifdef HAVE_SYS_PARAM_H
25
#   include <sys/param.h>
26
#endif
27
#ifdef HAVE_SYS_STAT_H
28
#   include <sys/stat.h>
29
#endif
30
#ifdef HAVE_FCNTL_H
31
#   include <fcntl.h>
32
#endif
33
34
#include <errno.h>
35
36
#include <net-snmp/types.h>
37
#include <net-snmp/library/container.h>
38
#include <net-snmp/library/file_utils.h>
39
40
netsnmp_feature_child_of(file_utils_all, libnetsnmp);
41
netsnmp_feature_child_of(file_utils, file_utils_all);
42
netsnmp_feature_child_of(file_close, file_utils_all);
43
44
#ifndef NETSNMP_FEATURE_REMOVE_FILE_UTILS
45
/*------------------------------------------------------------------
46
 *
47
 * Prototypes
48
 *
49
 */
50
51
52
53
54
/*------------------------------------------------------------------
55
 *
56
 * Core Functions
57
 *
58
 */
59
60
/**
61
 * allocate a netsnmp_file structure
62
 *
63
 * This routine should be used instead of allocating on the stack,
64
 * for future compatability.
65
 */
66
netsnmp_file *
67
netsnmp_file_create(void)
68
0
{
69
0
    netsnmp_file *filei = SNMP_MALLOC_TYPEDEF(netsnmp_file);
70
71
    /*
72
     * 0 is a valid file descriptor, so init to -1
73
     */
74
0
    if (NULL != filei)
75
0
        filei->fd = -1;
76
0
    else {
77
0
        snmp_log(LOG_WARNING,"failed to malloc netsnmp_file structure\n");
78
0
    }
79
80
0
    return filei;
81
0
}
82
83
/**
84
 * open file and get stats
85
 */
86
netsnmp_file *
87
netsnmp_file_new(const char *name, int fs_flags, mode_t mode, u_int ns_flags)
88
0
{
89
0
    netsnmp_file *filei = netsnmp_file_fill(NULL, name, fs_flags, mode, 0);
90
0
    if (NULL == filei)
91
0
        return NULL;
92
93
0
    if (ns_flags & NETSNMP_FILE_STATS) {
94
0
        filei->stats = calloc(1, sizeof(*(filei->stats)));
95
0
        if (NULL == filei->stats)
96
0
            DEBUGMSGT(("nsfile:new", "no memory for stats\n"));
97
0
        else if (stat(name, filei->stats) != 0)
98
0
            DEBUGMSGT(("nsfile:new", "error getting stats\n"));
99
0
    }
100
101
0
    if (ns_flags & NETSNMP_FILE_AUTO_OPEN)
102
0
        netsnmp_file_open(filei);
103
104
0
    return filei;
105
0
}
106
107
        
108
/**
109
 * fill core members in a netsnmp_file structure
110
 *
111
 * @param filei      structure to fill; if NULL, a new one will be allocated
112
 * @param name       file name
113
 * @param fs_flags   filesystem flags passed to open()
114
 * @param mode       optional filesystem open modes passed to open()
115
 * @param ns_flags   net-snmp flags
116
 */
117
netsnmp_file *
118
netsnmp_file_fill(netsnmp_file * filei, const char* name,
119
                  int fs_flags, mode_t mode, u_int ns_flags)
120
0
{
121
0
    if (NULL == filei) {
122
0
        filei = netsnmp_file_create();
123
0
        if (NULL == filei) /* failure already logged */
124
0
            return NULL;
125
0
    }
126
127
0
    if (NULL != name)
128
0
        filei->name = strdup(name);
129
130
0
    filei->fs_flags = fs_flags;
131
0
    filei->ns_flags = ns_flags;
132
0
    filei->mode = mode;
133
134
0
    return filei;
135
0
}
136
137
/**
138
 * release a netsnmp_file structure
139
 *
140
 * @retval  see close() man page
141
 */
142
int
143
netsnmp_file_release(netsnmp_file * filei)
144
0
{
145
0
    int rc = 0;
146
147
0
    if (NULL == filei)
148
0
        return -1;
149
150
0
    if ((filei->fd > 0) && NS_FI_AUTOCLOSE(filei->ns_flags))
151
0
        rc = close(filei->fd);
152
153
0
    if (NULL != filei->name)
154
0
        free(filei->name); /* no point in SNMP_FREE */
155
156
0
    if (NULL != filei->extras)
157
0
        netsnmp_free_all_list_data(filei->extras);
158
159
0
    if (NULL != filei->stats)
160
0
        free(filei->stats);
161
162
0
    SNMP_FREE(filei);
163
164
0
    return rc;
165
0
}
166
167
/**
168
 * open the file associated with a netsnmp_file structure
169
 *
170
 * @retval -1  : error opening file
171
 * @retval >=0 : file descriptor for opened file
172
 */
173
int
174
netsnmp_file_open(netsnmp_file * filei)
175
0
{
176
    /*
177
     * basic sanity checks
178
     */
179
0
    if ((NULL == filei) || (NULL == filei->name))
180
0
        return -1;
181
182
    /*
183
     * if file is already open, just return the fd.
184
     */
185
0
    if (-1 != filei->fd)
186
0
        return filei->fd;
187
188
    /*
189
     * try to open the file, loging an error if we failed
190
     */
191
0
    if (0 == filei->mode)
192
0
        filei->fd = open(filei->name, filei->fs_flags);
193
0
    else
194
0
        filei->fd = open(filei->name, filei->fs_flags, filei->mode);
195
196
0
    if (filei->fd < 0) {
197
0
        DEBUGMSGTL(("netsnmp_file", "error opening %s (%d)\n", filei->name, errno));
198
0
    }
199
200
    /*
201
     * return results
202
     */
203
0
    return filei->fd;
204
0
}
205
206
207
/**
208
 * close the file associated with a netsnmp_file structure
209
 *
210
 * @retval  0 : success
211
 * @retval -1 : error
212
 */
213
#ifndef NETSNMP_FEATURE_REMOVE_FILE_CLOSE
214
int
215
netsnmp_file_close(netsnmp_file * filei)
216
0
{
217
0
    int rc;
218
219
    /*
220
     * basic sanity checks
221
     */
222
0
    if ((NULL == filei) || (NULL != filei->name))
223
0
        return -1;
224
225
    /*
226
     * make sure it's not already closed
227
     */
228
0
    if (-1 == filei->fd) {
229
0
        return 0;
230
0
    }
231
232
    /*
233
     * close the file, logging an error if we failed
234
     */
235
0
    rc = close(filei->fd);
236
0
    if (rc < 0) {
237
0
        DEBUGMSGTL(("netsnmp_file", "error closing %s (%d)\n", filei->name, errno));
238
0
    }
239
0
    else
240
0
        filei->fd = -1;
241
242
0
    return rc;
243
0
}
244
#endif /* NETSNMP_FEATURE_REMOVE_FILE_CLOSE */
245
246
void
247
netsnmp_file_container_free(netsnmp_file *file, void *context)
248
0
{
249
0
    netsnmp_file_release(file);
250
0
}
251
252
int
253
netsnmp_file_compare_name(netsnmp_file *lhs, netsnmp_file *rhs)
254
0
{
255
0
    netsnmp_assert((NULL != lhs) && (NULL != rhs));
256
0
    netsnmp_assert((NULL != lhs->name) && (NULL != rhs->name));
257
258
0
    return strcmp(lhs->name, rhs->name);
259
0
}
260
#else /* NETSNMP_FEATURE_REMOVE_FILE_UTILS */
261
netsnmp_feature_unused(file_utils);
262
#endif /* NETSNMP_FEATURE_REMOVE_FILE_UTILS */