Annotation of embedaddon/pimd/libite/dir.c, revision 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>