~vcs-imports/gawk/master

« back to all changes in this revision

Viewing changes to extension/readdir.c

Update README.solaris.

Show diffs side-by-side

added added

removed removed

Lines of Context:
7
7
 *
8
8
 * Andrew Schorr and Arnold Robbins: further fixes 8/2012.
9
9
 * Simplified 11/2012.
10
 
 * Improved 3/2019.
11
10
 */
12
11
 
13
12
/*
14
 
 * Copyright (C) 2012-2014, 2017, 2018, 2019, 2021, 2023,
15
 
 * the Free Software Foundation, Inc.
16
 
 *
 
13
 * Copyright (C) 2012, 2013 the Free Software Foundation, Inc.
 
14
 * 
17
15
 * This file is part of GAWK, the GNU implementation of the
18
16
 * AWK Programming Language.
19
 
 *
 
17
 * 
20
18
 * GAWK is free software; you can redistribute it and/or modify
21
19
 * it under the terms of the GNU General Public License as published by
22
20
 * the Free Software Foundation; either version 3 of the License, or
23
21
 * (at your option) any later version.
24
 
 *
 
22
 * 
25
23
 * GAWK is distributed in the hope that it will be useful,
26
24
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27
25
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
28
26
 * GNU General Public License for more details.
29
 
 *
 
27
 * 
30
28
 * You should have received a copy of the GNU General Public License
31
29
 * along with this program; if not, write to the Free Software
32
30
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
42
40
#include <stdlib.h>
43
41
#include <string.h>
44
42
#include <unistd.h>
45
 
#include <stdbool.h>
46
43
 
47
44
#include <sys/types.h>
48
45
#include <sys/stat.h>
54
51
#ifdef HAVE_DIRENT_H
55
52
#include <dirent.h>
56
53
#else
57
 
#error Cannot compile the readdir extension on this system!
 
54
#error Cannot compile the dirent extension on this system!
58
55
#endif
59
56
 
60
57
#ifdef __MINGW32__
70
67
#define _(msgid)  gettext(msgid)
71
68
#define N_(msgid) msgid
72
69
 
73
 
#ifndef PATH_MAX
74
 
#define PATH_MAX        1024    /* a good guess */
75
 
#endif
76
 
 
77
70
static const gawk_api_t *api;   /* for convenience macros to work */
78
 
static awk_ext_id_t ext_id;
79
 
static const char *ext_version = "readdir extension: version 3.0";
 
71
static awk_ext_id_t *ext_id;
 
72
static const char *ext_version = "readdir extension: version 1.0";
80
73
 
81
74
static awk_bool_t init_readdir(void);
82
75
static awk_bool_t (*init_func)(void) = init_readdir;
88
81
typedef struct open_directory {
89
82
        DIR *dp;
90
83
        char *buf;
91
 
        union {
92
 
                awk_fieldwidth_info_t fw;
93
 
                char buf[awk_fieldwidth_info_size(3)];
94
 
        } u;
95
 
        bool override;
96
84
} open_directory_t;
97
 
#define fw u.fw
98
85
 
99
86
/* ftype --- return type of file as a single character string */
100
87
 
112
99
        case DT_REG:    return "f";
113
100
        case DT_SOCK:   return "s";
114
101
        default:
115
 
        case DT_UNKNOWN: break; // JFS returns 'u', so fall through and stat
 
102
        case DT_UNKNOWN: return "u";
116
103
        }
117
 
#endif
 
104
#else
118
105
        char fname[PATH_MAX];
119
106
        struct stat sbuf;
120
107
 
121
 
        sprintf(fname, "%s/%s", dirname, entry->d_name);
 
108
        strcpy(fname, dirname);
 
109
        strcat(fname, "/");
 
110
        strcat(fname, entry->d_name);
122
111
        if (stat(fname, &sbuf) == 0) {
123
112
                if (S_ISBLK(sbuf.st_mode))
124
113
                        return "b";
140
129
#endif
141
130
        }
142
131
        return "u";
 
132
#endif
143
133
}
144
134
 
145
135
/* get_inode --- get the inode of a file */
146
 
 
 
136
#ifdef ZOS_USS
 
137
static long
 
138
#else
147
139
static long long
 
140
#endif
148
141
get_inode(struct dirent *entry, const char *dirname)
149
142
{
150
143
#ifdef __MINGW32__
151
144
        char fname[PATH_MAX];
152
145
        HANDLE fh;
153
 
        BOOL ok;
154
146
        BY_HANDLE_FILE_INFORMATION info;
155
147
 
156
148
        sprintf(fname, "%s\\%s", dirname, entry->d_name);
158
150
                        FILE_FLAG_BACKUP_SEMANTICS, NULL);
159
151
        if (fh == INVALID_HANDLE_VALUE)
160
152
                return 0;
161
 
        ok = GetFileInformationByHandle(fh, &info);
162
 
        CloseHandle(fh);
163
 
        if (ok) {
 
153
        if (GetFileInformationByHandle(fh, &info)) {
164
154
                long long inode = info.nFileIndexHigh;
165
155
 
166
156
                inode <<= 32;
178
168
 
179
169
static int
180
170
dir_get_record(char **out, awk_input_buf_t *iobuf, int *errcode,
181
 
                char **rt_start, size_t *rt_len,
182
 
                const awk_fieldwidth_info_t **field_width)
 
171
                char **rt_start, size_t *rt_len)
183
172
{
184
173
        DIR *dp;
185
174
        struct dirent *dirent;
186
 
        int len, flen;
 
175
        int len;
187
176
        open_directory_t *the_dir;
188
177
        const char *ftstr;
 
178
#ifdef ZOS_USS
 
179
        unsigned long ino;
 
180
#else
189
181
        unsigned long long ino;
 
182
#endif
190
183
 
191
184
        /*
192
185
         * The caller sets *errcode to 0, so we should set it only if an
209
202
                return EOF;
210
203
        }
211
204
 
212
 
        ino = get_inode(dirent, iobuf->name);
 
205
        ino = get_inode (dirent, iobuf->name);
213
206
 
214
 
#if __MINGW32__
215
 
        len = sprintf(the_dir->buf, "%I64u", ino);
 
207
#if defined(ZOS_USS)
 
208
        len = sprintf(the_dir->buf, "%lu/%s", ino, dirent->d_name);
 
209
#elif __MINGW32__
 
210
        len = sprintf(the_dir->buf, "%I64u/%s", ino, dirent->d_name);
216
211
#else
217
 
        len = sprintf(the_dir->buf, "%llu", ino);
 
212
        len = sprintf(the_dir->buf, "%llu/%s", ino, dirent->d_name);
218
213
#endif
219
 
        the_dir->fw.fields[0].len = len;
220
 
        len += (flen = sprintf(the_dir->buf + len, "/%s", dirent->d_name));
221
 
        the_dir->fw.fields[1].len = flen-1;
222
214
 
223
215
        ftstr = ftype(dirent, iobuf->name);
224
 
        len += (flen = sprintf(the_dir->buf + len, "/%s", ftstr));
225
 
        the_dir->fw.fields[2].len = flen-1;
 
216
        len += sprintf(the_dir->buf + len, "/%s", ftstr);
226
217
 
227
218
        *out = the_dir->buf;
228
219
 
229
220
        *rt_start = NULL;
230
221
        *rt_len = 0;    /* set RT to "" */
231
 
        if (field_width != NULL && the_dir->override)
232
 
                *field_width = & the_dir->fw;
233
222
        return len;
234
223
}
235
224
 
246
235
        the_dir = (open_directory_t *) iobuf->opaque;
247
236
 
248
237
        closedir(the_dir->dp);
249
 
        gawk_free(the_dir->buf);
250
 
        gawk_free(the_dir);
 
238
        free(the_dir->buf);
 
239
        free(the_dir);
251
240
 
252
241
        iobuf->fd = -1;
253
242
}
260
249
        if (iobuf == NULL)
261
250
                return awk_false;
262
251
 
263
 
        return (S_ISDIR(iobuf->sbuf.st_mode));
 
252
        return (iobuf->fd != INVALID_HANDLE && S_ISDIR(iobuf->sbuf.st_mode));
264
253
}
265
254
 
266
255
/*
281
270
        dp = fdopendir(iobuf->fd);
282
271
#else
283
272
        dp = opendir(iobuf->name);
284
 
        if (dp != NULL) {
285
 
                if (iobuf->fd != INVALID_HANDLE)
286
 
                        (void) close(iobuf->fd);
 
273
        if (dp != NULL)
287
274
                iobuf->fd = dirfd(dp);
288
 
        }
289
275
#endif
290
276
        if (dp == NULL) {
291
 
                warning(ext_id, _("dir_take_control_of: %s: opendir/fdopendir failed: %s"),
292
 
                                iobuf->name, strerror(errno));
 
277
                warning(ext_id, _("dir_take_control_of: opendir/fdopendir failed: %s"),
 
278
                                strerror(errno));
293
279
                update_ERRNO_int(errno);
294
280
                return awk_false;
295
281
        }
296
282
 
297
283
        emalloc(the_dir, open_directory_t *, sizeof(open_directory_t), "dir_take_control_of");
298
284
        the_dir->dp = dp;
299
 
        /* pre-populate the field_width struct with constant values: */
300
 
        the_dir->fw.use_chars = awk_false;
301
 
        the_dir->fw.nf = 3;
302
 
        the_dir->fw.fields[0].skip = 0; /* no leading space */
303
 
        the_dir->fw.fields[1].skip = 1; /* single '/' separator */
304
 
        the_dir->fw.fields[2].skip = 1; /* single '/' separator */
305
285
        size = sizeof(struct dirent) + 21 /* max digits in inode */ + 2 /* slashes */;
306
286
        emalloc(the_dir->buf, char *, size, "dir_take_control_of");
307
287
 
309
289
        iobuf->get_record = dir_get_record;
310
290
        iobuf->close_func = dir_close;
311
291
 
312
 
        awk_value_t array, index, value;
313
 
        static const char readdir_override[] = "readdir_override";
314
 
 
315
 
        if (! sym_lookup("PROCINFO", AWK_ARRAY, & array)) {
316
 
                the_dir->override = false;
317
 
        } else {
318
 
                (void) make_const_string(readdir_override, strlen(readdir_override), & index);
319
 
                the_dir->override = get_array_element(array.array_cookie, & index, AWK_UNDEFINED, & value);
320
 
        }
321
 
 
322
292
        return awk_true;
323
293
}
324
294
 
352
322
}
353
323
 
354
324
static awk_ext_func_t func_table[] = {
355
 
        { NULL, NULL, 0, 0, awk_false, NULL }
 
325
        { NULL, NULL, 0 }
356
326
};
357
327
 
358
328
/* define the dl_load function using the boilerplate macro */