GRASS 8 Programmer's Manual 8.6.0dev(2026)-1878fdfec5
Loading...
Searching...
No Matches
ls.c
Go to the documentation of this file.
1/**
2 \file lib/gis/ls.c
3
4 \brief Functions to list the files in a directory.
5
6 \author Paul Kelly
7
8 SPDX-FileCopyrightText: 2007, 2008 GRASS Development Team
9 SPDX-License-Identifier: GPL-2.0-or-later
10*/
11
12#include <stdio.h>
13#include <stdlib.h>
14#include <string.h>
15#include <sys/types.h>
16#include <dirent.h>
17#include <unistd.h>
18
19#include <grass/gis.h>
20#include <grass/config.h>
21#include <grass/glocale.h>
22
23#ifdef HAVE_TERMIOS_H
24#include <termios.h>
25#endif
26
27#ifdef HAVE_SYS_IOCTL_H
28#include <sys/ioctl.h>
29#endif
30
31typedef int ls_filter_func(const char * /*filename */, void * /*closure */);
32
33static struct state {
34 ls_filter_func *ls_filter;
35 void *ls_closure;
36 ls_filter_func *ls_ex_filter;
37 void *ls_ex_closure;
38} state;
39
40static struct state *st = &state;
41
42static int cmp_names(const void *aa, const void *bb)
43{
44 char *const *a = (char *const *)aa;
45 char *const *b = (char *const *)bb;
46
47 return strcmp(*a, *b);
48}
49
50/**
51 * \brief Sets a function and its complementary data for G_ls2 filtering.
52 *
53 * Defines a filter function and its rule data that allow G_ls2 to filter out
54 * unwanted file names. Call this function before G_ls2.
55 *
56 * \param func Filter callback function to compare a file name and closure
57 * pattern (if NULL, no filter will be used).
58 * func(filename, closure) should return 1 on success, 0 on
59 * failure.
60 * \param closure Data used to determine if a file name matches the rule.
61 **/
62
63void G_set_ls_filter(ls_filter_func *func, void *closure)
64{
65 st->ls_filter = func;
66 st->ls_closure = closure;
67}
68
69void G_set_ls_exclude_filter(ls_filter_func *func, void *closure)
70{
71 st->ls_ex_filter = func;
72 st->ls_ex_closure = closure;
73}
74
75/**
76 * \brief Stores a sorted directory listing in an array
77 *
78 * The filenames in the specified directory are stored in an array of
79 * strings, then sorted alphabetically. Each filename has space allocated
80 * using G_store(), which can be freed using G_free() if necessary. The
81 * same goes for the array itself.
82 *
83 *
84 * \param dir Directory to list
85 * \param num_files Pointer to an integer in which the total number of
86 * files listed will be stored
87 *
88 * \return Pointer to array of strings containing the listing
89 **/
90
91char **G_ls2(const char *dir, int *num_files)
92{
93 struct dirent *dp;
94 DIR *dfd;
95 char **dir_listing = NULL;
96 int n = 0;
97
98 if ((dfd = opendir(dir)) == NULL)
99 G_fatal_error(_("Unable to open directory %s"), dir);
100
101 while ((dp = readdir(dfd)) != NULL) {
102 if (dp->d_name[0] == '.') /* Don't list hidden files */
103 continue;
104 if (st->ls_filter && !(*st->ls_filter)(dp->d_name, st->ls_closure))
105 continue;
106 if (st->ls_ex_filter &&
107 (*st->ls_ex_filter)(dp->d_name, st->ls_ex_closure))
108 continue;
109 dir_listing = (char **)G_realloc(dir_listing, (1 + n) * sizeof(char *));
110 dir_listing[n] = G_store(dp->d_name);
111 n++;
112 }
113 closedir(dfd);
114
115 /* Sort list of filenames alphabetically */
116 qsort(dir_listing, n, sizeof(char *), cmp_names);
117
118 *num_files = n;
119 return dir_listing;
120}
121
122/**
123 * \brief Prints a directory listing to a stream, in prettified column format
124 *
125 * A replacement for system("ls -C"). Lists the contents of the directory
126 * specified to the given stream, e.g. stderr. Tries to determine an
127 * appropriate column width to keep the number of lines used to a minimum
128 * and look pretty on the screen.
129 *
130 * \param dir Directory to list
131 * \param stream Stream to print listing to
132 **/
133
134void G_ls(const char *dir, FILE *stream)
135{
136 int i, n;
137 char **dir_listing = G_ls2(dir, &n);
138
139 G_ls_format(dir_listing, n, 0, stream);
140
141 for (i = 0; i < n; i++)
143
145}
146
147/**
148 * \brief Prints a listing of items to a stream, in prettified column format
149 *
150 * Lists the contents of the array passed to the given stream, e.g. stderr.
151 * Prints the number of items specified by "perline" to each line, unless
152 * perline is given as 0 in which case the function tries to determine an
153 * appropriate column width to keep the number of lines used to a minimum
154 * and look pretty on the screen.
155 *
156 * \param list Array of strings containing items to be printed
157 * \param num_items Number of items in the array
158 * \param perline Number of items to print per line, 0 for autodetect
159 * \param stream Stream to print listing to
160 **/
161
162void G_ls_format(char **list, int num_items, int perline, FILE *stream)
163{
164 int i;
165
167 int screen_width = 80; /* Default width of 80 columns */
168
169 if (num_items < 1)
170 return; /* Nothing to print */
171
172#ifdef TIOCGWINSZ
173 /* Determine screen_width if possible */
174 {
175 struct winsize size;
176
177 if (ioctl(fileno(stream), TIOCGWINSZ, (char *)&size) == 0)
178 screen_width = size.ws_col;
179 }
180#endif
181
182 if (perline == 0) {
183 unsigned int max_len = 0;
184
185 for (i = 0; i < num_items; i++) {
186 /* Find maximum filename length */
187 if (strlen(list[i]) > max_len)
188 max_len = strlen(list[i]);
189 }
190 /* Auto-fit the number of items that will
191 * fit per line (+1 because of space after item) */
192 perline = screen_width / (max_len + 1);
193 if (perline < 1)
194 perline = 1;
195 }
196
197 /* Field width to accommodate longest filename */
199 /* Longest column height (i.e. num_items <= perline * column_height) */
201
202 {
204 char **next;
205
206 for (i = 1, next = list; i <= num_items; i++) {
207 char **cur = next;
208
209 next += column_height;
210 if (next >= list + num_items) {
211 /* the next item has to be on the other line */
212 next -= (max - 1 - (next < list + max ? column_height : 0));
213 fprintf(stream, "%s\n", *cur);
214 }
215 else {
216 fprintf(stream, "%-*s", field_width, *cur);
217 }
218 }
219 }
220}
#define NULL
Definition ccmath.h:32
void G_free(void *)
Free allocated memory.
Definition gis/alloc.c:145
#define G_realloc(p, n)
Definition defs/gis.h:138
void void void void G_fatal_error(const char *,...) __attribute__((format(printf
char * G_store(const char *)
Copy string to allocated memory.
Definition strings.c:85
struct DIR DIR
Definition dirent.h:18
#define max(x, y)
Definition draw2.c:30
int screen_width
Definition driver/init.c:27
#define _(str)
Definition glocale.h:10
void G_ls(const char *dir, FILE *stream)
Prints a directory listing to a stream, in prettified column format.
Definition ls.c:134
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:162
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:63
char ** G_ls2(const char *dir, int *num_files)
Stores a sorted directory listing in an array.
Definition ls.c:91
int ls_filter_func(const char *, void *)
Definition ls.c:31
void G_set_ls_exclude_filter(ls_filter_func *func, void *closure)
Definition ls.c:69
DIR * opendir(const char *name)
Definition msvc/dirent.c:15
struct dirent * readdir(DIR *dir)
Definition msvc/dirent.c:75
int closedir(DIR *dir)
Definition msvc/dirent.c:54
double b
Definition r_raster.c:37
Definition manage.h:4