Annotation of embedaddon/pimd/libite/dir.c, revision 1.1.1.1
1.1 misho 1: /* Functions for operating on files in directories.
2: *
3: * Copyright (c) 2008-2014 Joachim Nilsson <troglobit@gmail.com>
4: *
5: * Permission to use, copy, modify, and/or distribute this software for any
6: * purpose with or without fee is hereby granted, provided that the above
7: * copyright notice and this permission notice appear in all copies.
8: *
9: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16: */
17:
18: #include <assert.h>
19: #include <dirent.h>
20: #include <stdio.h>
21: #include <stdlib.h>
22: #include <string.h>
23:
24: static const char *matcher_type = NULL;
25: static int (*matcher_filter) (const char *file) = NULL;
26: static int matcher(const struct dirent *entry)
27: {
28: char *pos = strrchr(entry->d_name, '.');
29:
30: if (matcher_filter && !matcher_filter(entry->d_name))
31: /* User matcher overrides the rest. */
32: return 0;
33:
34: /* Skip current dir "." from list of files. */
35: if ((1 == strlen(entry->d_name) && entry->d_name[0] == '.') ||
36: (2 == strlen(entry->d_name) && !strcmp(entry->d_name, "..")))
37: return 0;
38:
39: /* filetype == "" */
40: if (matcher_type[0] == 0)
41: return 1;
42:
43: /* Entry has no "." */
44: if (!pos)
45: return 0;
46:
47: return !strcmp(pos, matcher_type);
48: }
49:
50: /**
51: * dir - List all files of a certain type in the given directory.
52: * @dir: Base directory for dir operation.
53: * @type: File type suffix, e.g. ".cfg".
54: * @filter: Optional file name filter.
55: * @list: Pointer to an array of file names.
56: * @strip: Flag, if set dir() strips the file type.
57: *
58: * This function returns a @list of files, matching the @type suffix,
59: * in the given directory @dir.
60: *
61: * The @list argument is a pointer to where to store the dynamically
62: * allocated list of file names. This list should be free'd by first
63: * calling free() on each file name and then on the list itself.
64: *
65: * If @filter is not %NULL it will be called for each file found. If
66: * @filter returns non-zero the @file argument will be included in the
67: * resulting @list. If @filter returns zero for given @file it will
68: * be discarded.
69: *
70: * If the @strip flag is set the resulting @list of files has their
71: * file type stripped, including the dot. So a match "config0.cfg"
72: * would be returned as "config0".
73: *
74: * Returns:
75: * Number of files in @list, zero if no matching files of @type.
76: */
77: int dir(const char *dir, const char *type, int (*filter) (const char *file), char ***list, int strip)
78: {
79: int i, n, num = 0;
80: char **files;
81: struct dirent **namelist;
82:
83: assert(list);
84:
85: if (!dir)
86: /* Assuming current directory */
87: dir = ".";
88: if (!type)
89: /* Assuming all files. */
90: type = "";
91:
92: matcher_type = type;
93: matcher_filter = filter;
94: n = scandir(dir, &namelist, matcher, alphasort);
95: if (n < 0) {
96: perror("scandir");
97: } else if (n > 0) {
98: files = (char **)malloc(n * sizeof(char *));
99: for (i = 0; i < n; i++) {
100: if (files) {
101: char *name = namelist[i]->d_name;
102: char *type = strrchr(name, '.');
103:
104: if (type && strip)
105: *type = 0;
106:
107: files[i] = strdup(name);
108: num++;
109: }
110: free(namelist[i]);
111: }
112: if (num)
113: *list = files;
114: }
115:
116: if (namelist)
117: free(namelist);
118:
119: return num;
120: }
121:
122: #ifdef UNITTEST
123: #include <errno.h>
124: #include <sys/stat.h>
125: #include <fcntl.h>
126: #include "lite.h"
127:
128: #define DIR_TYPE_IMAGE ".img"
129: #define DIR_TYPE_SYSLOG ""
130: #define DIR_TYPE_CONFIG ".cfg"
131: #define STARTUP_CONFIG "startup-config.cfg"
132:
133: int simulate_files(int creat)
134: {
135: int i;
136: char *files[] =
137: { "config0.cfg", "config1.cfg", "config2.cfg", "config3.cfg",
138: "rr109.img", "rx100.img", "rx107.img", "rm957.img", "messages"
139: };
140:
141: for (i = 0; i < NELEMS(files); i++) {
142: if (creat)
143: touch(files[i]);
144: else
145: erase(files[i]);
146: }
147:
148: if (creat)
149: symlink("config2.cfg", STARTUP_CONFIG);
150: else
151: erase(STARTUP_CONFIG);
152:
153: return 0;
154: }
155:
156: static int cfg_dir_filter(const char *file)
157: {
158: /* Skip the STARTUP_CONFIG file, it is a symbolic link to the
159: * current startup configuration. */
160: return ! !strcmp(file, STARTUP_CONFIG);
161: }
162:
163: int main(int argc, char *argv[])
164: {
165: int i, num;
166: char *type = DIR_TYPE_CONFIG;
167: char **files;
168: int once = 1;
169:
170: int is_startup_config(const char *entry) {
171: static char file[80];
172:
173: if (once) {
174: int len = readlink(STARTUP_CONFIG, file, sizeof(file));
175:
176: if (len == -1)
177: return 0;
178:
179: file[len] = 0;
180: once = 0; /* Only once per call to dir() */
181: }
182: //printf ("Comparing link %s with entry %s\n", file, entry);
183: return !strcmp(file, entry);
184: }
185:
186: simulate_files(1);
187:
188: if (argc >= 2) {
189: if (!strcasecmp("CONFIG", argv[1])) {
190: type = DIR_TYPE_CONFIG;
191: system("ls -l *" DIR_TYPE_CONFIG);
192: }
193: if (!strcasecmp("IMAGE", argv[1])) {
194: type = DIR_TYPE_IMAGE;
195: system("ls -l *" DIR_TYPE_IMAGE);
196: }
197: if (!strcasecmp("SYSLOG", argv[1])) {
198: type = DIR_TYPE_SYSLOG;
199: system("ls -l *");
200: }
201: }
202:
203: num = dir(NULL, type, cfg_dir_filter, &files, 0);
204: if (num) {
205: for (i = 0; i < num; i++) {
206: printf("%s", files[i]);
207: if (is_startup_config(files[i]))
208: printf(" --> startup-config");
209: printf("\n");
210:
211: free(files[i]);
212: }
213: free(files);
214: }
215:
216: simulate_files(0);
217:
218: return 0;
219: }
220: #endif /* UNITTEST */
221:
222: /**
223: * Local Variables:
224: * compile-command: "make V=1 -f dir.mk"
225: * version-control: t
226: * indent-tabs-mode: t
227: * c-file-style: "linux"
228: * End:
229: */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>