File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / pimd / libite / dir.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Jun 14 09:12:58 2017 UTC (7 years, 3 months ago) by misho
Branches: pimd, MAIN
CVS tags: v2_3_2, HEAD
libite

    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>