Loading...
Searching...
No Matches
ls.c
Go to the documentation of this file.
/**
\file lib/gis/ls.c
\brief Functions to list the files in a directory.
\author Paul Kelly
(C) 2007, 2008 by the GRASS Development Team
This program is free software under the GNU General Public
License (>=v2). Read the file COPYING that comes with GRASS
for details.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>
#include <grass/gis.h>
#include <grass/config.h>
#include <grass/glocale.h>
#ifdef HAVE_TERMIOS_H
#include <termios.h>
#endif
#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif
typedef int ls_filter_func(const char * /*filename */, void * /*closure */);
static struct state {
ls_filter_func *ls_filter;
void *ls_closure;
ls_filter_func *ls_ex_filter;
void *ls_ex_closure;
} state;
static struct state *st = &state;
static int cmp_names(const void *aa, const void *bb)
{
char *const *a = (char *const *)aa;
char *const *b = (char *const *)bb;
return strcmp(*a, *b);
}
/**
* \brief Sets a function and its complementary data for G_ls2 filtering.
*
* Defines a filter function and its rule data that allow G_ls2 to filter out
* unwanted file names. Call this function before G_ls2.
*
* \param func Filter callback function to compare a file name and closure
* pattern (if NULL, no filter will be used).
* func(filename, closure) should return 1 on success, 0 on
* failure.
* \param closure Data used to determine if a file name matches the rule.
**/
void G_set_ls_filter(ls_filter_func *func, void *closure)
{
st->ls_filter = func;
st->ls_closure = closure;
}
void G_set_ls_exclude_filter(ls_filter_func *func, void *closure)
{
st->ls_ex_filter = func;
st->ls_ex_closure = closure;
}
/**
* \brief Stores a sorted directory listing in an array
*
* The filenames in the specified directory are stored in an array of
* strings, then sorted alphabetically. Each filename has space allocated
* using G_store(), which can be freed using G_free() if necessary. The
* same goes for the array itself.
*
*
* \param dir Directory to list
* \param num_files Pointer to an integer in which the total number of
* files listed will be stored
*
* \return Pointer to array of strings containing the listing
**/
char **G_ls2(const char *dir, int *num_files)
{
struct dirent *dp;
DIR *dfd;
char **dir_listing = NULL;
int n = 0;
if ((dfd = opendir(dir)) == NULL)
G_fatal_error(_("Unable to open directory %s"), dir);
while ((dp = readdir(dfd)) != NULL) {
if (dp->d_name[0] == '.') /* Don't list hidden files */
continue;
if (st->ls_filter && !(*st->ls_filter)(dp->d_name, st->ls_closure))
continue;
if (st->ls_ex_filter &&
(*st->ls_ex_filter)(dp->d_name, st->ls_ex_closure))
continue;
dir_listing = (char **)G_realloc(dir_listing, (1 + n) * sizeof(char *));
dir_listing[n] = G_store(dp->d_name);
n++;
}
closedir(dfd);
/* Sort list of filenames alphabetically */
qsort(dir_listing, n, sizeof(char *), cmp_names);
*num_files = n;
return dir_listing;
}
/**
* \brief Prints a directory listing to a stream, in prettified column format
*
* A replacement for system("ls -C"). Lists the contents of the directory
* specified to the given stream, e.g. stderr. Tries to determine an
* appropriate column width to keep the number of lines used to a minimum
* and look pretty on the screen.
*
* \param dir Directory to list
* \param stream Stream to print listing to
**/
void G_ls(const char *dir, FILE *stream)
{
int i, n;
char **dir_listing = G_ls2(dir, &n);
G_ls_format(dir_listing, n, 0, stream);
for (i = 0; i < n; i++)
G_free(dir_listing[i]);
G_free(dir_listing);
}
/**
* \brief Prints a listing of items to a stream, in prettified column format
*
* Lists the contents of the array passed to the given stream, e.g. stderr.
* Prints the number of items specified by "perline" to each line, unless
* perline is given as 0 in which case the function tries to determine an
* appropriate column width to keep the number of lines used to a minimum
* and look pretty on the screen.
*
* \param list Array of strings containing items to be printed
* \param num_items Number of items in the array
* \param perline Number of items to print per line, 0 for autodetect
* \param stream Stream to print listing to
**/
void G_ls_format(char **list, int num_items, int perline, FILE *stream)
{
int i;
int field_width, column_height;
int screen_width = 80; /* Default width of 80 columns */
if (num_items < 1)
return; /* Nothing to print */
#ifdef TIOCGWINSZ
/* Determine screen_width if possible */
{
struct winsize size;
if (ioctl(fileno(stream), TIOCGWINSZ, (char *)&size) == 0)
screen_width = size.ws_col;
}
#endif
if (perline == 0) {
unsigned int max_len = 0;
for (i = 0; i < num_items; i++) {
/* Find maximum filename length */
if (strlen(list[i]) > max_len)
max_len = strlen(list[i]);
}
/* Auto-fit the number of items that will
* fit per line (+1 because of space after item) */
perline = screen_width / (max_len + 1);
if (perline < 1)
perline = 1;
}
/* Field width to accommodate longest filename */
field_width = screen_width / perline;
/* Longest column height (i.e. num_items <= perline * column_height) */
column_height = (num_items / perline) + ((num_items % perline) > 0);
{
const int max = num_items + column_height - (num_items % column_height);
char **next;
for (i = 1, next = list; i <= num_items; i++) {
char **cur = next;
next += column_height;
if (next >= list + num_items) {
/* the next item has to be on the other line */
next -= (max - 1 - (next < list + max ? column_height : 0));
fprintf(stream, "%s\n", *cur);
}
else {
fprintf(stream, "%-*s", field_width, *cur);
}
}
}
}
G_free
void G_free(void *buf)
Free allocated memory.
Definition alloc.c:147
NULL
#define NULL
Definition ccmath.h:32
b
double b
Definition driver/set_window.c:5
screen_width
int screen_width
Definition driver/init.c:29
G_fatal_error
void G_fatal_error(const char *msg,...)
Print a fatal error message to stderr.
Definition gis/error.c:159
G_ls
void G_ls(const char *dir, FILE *stream)
Prints a directory listing to a stream, in prettified column format.
Definition ls.c:137
G_ls_format
void G_ls_format(char **list, int num_items, int perline, FILE *stream)
Prints a listing of items to a stream, in prettified column format.
Definition ls.c:165
G_set_ls_filter
void G_set_ls_filter(ls_filter_func *func, void *closure)
Sets a function and its complementary data for G_ls2 filtering.
Definition ls.c:66
G_ls2
char ** G_ls2(const char *dir, int *num_files)
Stores a sorted directory listing in an array.
Definition ls.c:94
ls_filter_func
int ls_filter_func(const char *, void *)
Definition ls.c:34
G_set_ls_exclude_filter
void G_set_ls_exclude_filter(ls_filter_func *func, void *closure)
Definition ls.c:72
max
#define max(a, b)
Definition pngdriver/draw_bitmap.c:22
list
struct list * list
Definition read_list.c:24
G_store
char * G_store(const char *s)
Copy string to allocated memory.
Definition strings.c:87