source: trunk/essentials/sys-apps/gawk/extension/filefuncs.c

Last change on this file was 3076, checked in by bird, 18 years ago

gawk 3.1.5

File size: 7.4 KB
Line 
1/*
2 * filefuncs.c - Builtin functions that provide initial minimal iterface
3 * to the file system.
4 *
5 * Arnold Robbins, update for 3.1, Mon Nov 23 12:53:39 EST 1998
6 * Arnold Robbins and John Haque, update for 3.1.4, applied Mon Jun 14 13:55:30 IDT 2004
7 */
8
9/*
10 * Copyright (C) 2001, 2004, 2005 the Free Software Foundation, Inc.
11 *
12 * This file is part of GAWK, the GNU implementation of the
13 * AWK Programming Language.
14 *
15 * GAWK is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
19 *
20 * GAWK is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
28 */
29
30#include "awk.h"
31
32#include <sys/sysmacros.h>
33
34/* do_chdir --- provide dynamically loaded chdir() builtin for gawk */
35
36static NODE *
37do_chdir(tree)
38NODE *tree;
39{
40 NODE *newdir;
41 int ret = -1;
42
43 if (do_lint && get_curfunc_arg_count() != 1)
44 lintwarn("chdir: called with incorrect number of arguments");
45
46 newdir = get_scalar_argument(tree, 0, FALSE);
47 (void) force_string(newdir);
48 ret = chdir(newdir->stptr);
49 if (ret < 0)
50 update_ERRNO();
51 free_temp(newdir);
52
53 /* Set the return value */
54 set_value(tmp_number((AWKNUM) ret));
55
56 /* Just to make the interpreter happy */
57 return tmp_number((AWKNUM) 0);
58}
59
60/* format_mode --- turn a stat mode field into something readable */
61
62static char *
63format_mode(fmode)
64unsigned long fmode;
65{
66 static char outbuf[12];
67 int i;
68
69 strcpy(outbuf, "----------");
70 /* first, get the file type */
71 i = 0;
72 switch (fmode & S_IFMT) {
73#ifdef S_IFSOCK
74 case S_IFSOCK:
75 outbuf[i] = 's';
76 break;
77#endif
78#ifdef S_IFLNK
79 case S_IFLNK:
80 outbuf[i] = 'l';
81 break;
82#endif
83 case S_IFREG:
84 outbuf[i] = '-'; /* redundant */
85 break;
86 case S_IFBLK:
87 outbuf[i] = 'b';
88 break;
89 case S_IFDIR:
90 outbuf[i] = 'd';
91 break;
92#ifdef S_IFDOOR /* Solaris weirdness */
93 case S_IFDOOR:
94 outbuf[i] = 'D';
95 break;
96#endif /* S_IFDOOR */
97 case S_IFCHR:
98 outbuf[i] = 'c';
99 break;
100#ifdef S_IFIFO
101 case S_IFIFO:
102 outbuf[i] = 'p';
103 break;
104#endif
105 }
106
107 i++;
108 if ((fmode & S_IRUSR) != 0)
109 outbuf[i] = 'r';
110 i++;
111 if ((fmode & S_IWUSR) != 0)
112 outbuf[i] = 'w';
113 i++;
114 if ((fmode & S_IXUSR) != 0)
115 outbuf[i] = 'x';
116 i++;
117
118 if ((fmode & S_IRGRP) != 0)
119 outbuf[i] = 'r';
120 i++;
121 if ((fmode & S_IWGRP) != 0)
122 outbuf[i] = 'w';
123 i++;
124 if ((fmode & S_IXGRP) != 0)
125 outbuf[i] = 'x';
126 i++;
127
128 if ((fmode & S_IROTH) != 0)
129 outbuf[i] = 'r';
130 i++;
131 if ((fmode & S_IWOTH) != 0)
132 outbuf[i] = 'w';
133 i++;
134 if ((fmode & S_IXOTH) != 0)
135 outbuf[i] = 'x';
136 i++;
137
138 outbuf[i] = '\0';
139
140 if ((fmode & S_ISUID) != 0) {
141 if (outbuf[3] == 'x')
142 outbuf[3] = 's';
143 else
144 outbuf[3] = 'S';
145 }
146
147 /* setgid without execute == locking */
148 if ((fmode & S_ISGID) != 0) {
149 if (outbuf[6] == 'x')
150 outbuf[6] = 's';
151 else
152 outbuf[6] = 'l';
153 }
154
155 if ((fmode & S_ISVTX) != 0) {
156 if (outbuf[9] == 'x')
157 outbuf[9] = 't';
158 else
159 outbuf[9] = 'T';
160 }
161
162 return outbuf;
163}
164
165/* do_stat --- provide a stat() function for gawk */
166
167static NODE *
168do_stat(tree)
169NODE *tree;
170{
171 NODE *file, *array;
172 struct stat sbuf;
173 int ret;
174 NODE **aptr;
175 char *pmode; /* printable mode */
176 char *type = "unknown";
177
178 if (do_lint && get_curfunc_arg_count() > 2)
179 lintwarn("stat: called with too many arguments");
180
181 /* directory is first arg, array to hold results is second */
182 file = get_scalar_argument(tree, 0, FALSE);
183 array = get_array_argument(tree, 1, FALSE);
184
185 /* empty out the array */
186 assoc_clear(array);
187
188 /* lstat the file, if error, set ERRNO and return */
189 (void) force_string(file);
190 ret = lstat(file->stptr, & sbuf);
191 if (ret < 0) {
192 update_ERRNO();
193
194 set_value(tmp_number((AWKNUM) ret));
195
196 free_temp(file);
197 return tmp_number((AWKNUM) 0);
198 }
199
200 /* fill in the array */
201 aptr = assoc_lookup(array, tmp_string("name", 4), FALSE);
202 *aptr = dupnode(file);
203
204 aptr = assoc_lookup(array, tmp_string("dev", 3), FALSE);
205 *aptr = make_number((AWKNUM) sbuf.st_dev);
206
207 aptr = assoc_lookup(array, tmp_string("ino", 3), FALSE);
208 *aptr = make_number((AWKNUM) sbuf.st_ino);
209
210 aptr = assoc_lookup(array, tmp_string("mode", 4), FALSE);
211 *aptr = make_number((AWKNUM) sbuf.st_mode);
212
213 aptr = assoc_lookup(array, tmp_string("nlink", 5), FALSE);
214 *aptr = make_number((AWKNUM) sbuf.st_nlink);
215
216 aptr = assoc_lookup(array, tmp_string("uid", 3), FALSE);
217 *aptr = make_number((AWKNUM) sbuf.st_uid);
218
219 aptr = assoc_lookup(array, tmp_string("gid", 3), FALSE);
220 *aptr = make_number((AWKNUM) sbuf.st_gid);
221
222 aptr = assoc_lookup(array, tmp_string("size", 4), FALSE);
223 *aptr = make_number((AWKNUM) sbuf.st_size);
224
225 aptr = assoc_lookup(array, tmp_string("blocks", 6), FALSE);
226 *aptr = make_number((AWKNUM) sbuf.st_blocks);
227
228 aptr = assoc_lookup(array, tmp_string("atime", 5), FALSE);
229 *aptr = make_number((AWKNUM) sbuf.st_atime);
230
231 aptr = assoc_lookup(array, tmp_string("mtime", 5), FALSE);
232 *aptr = make_number((AWKNUM) sbuf.st_mtime);
233
234 aptr = assoc_lookup(array, tmp_string("ctime", 5), FALSE);
235 *aptr = make_number((AWKNUM) sbuf.st_ctime);
236
237 /* for block and character devices, add rdev, major and minor numbers */
238 if (S_ISBLK(sbuf.st_mode) || S_ISCHR(sbuf.st_mode)) {
239 aptr = assoc_lookup(array, tmp_string("rdev", 4), FALSE);
240 *aptr = make_number((AWKNUM) sbuf.st_rdev);
241
242 aptr = assoc_lookup(array, tmp_string("major", 5), FALSE);
243 *aptr = make_number((AWKNUM) major(sbuf.st_rdev));
244
245 aptr = assoc_lookup(array, tmp_string("minor", 5), FALSE);
246 *aptr = make_number((AWKNUM) minor(sbuf.st_rdev));
247 }
248
249#ifdef HAVE_ST_BLKSIZE
250 aptr = assoc_lookup(array, tmp_string("blksize", 7), FALSE);
251 *aptr = make_number((AWKNUM) sbuf.st_blksize);
252#endif /* HAVE_ST_BLKSIZE */
253
254 aptr = assoc_lookup(array, tmp_string("pmode", 5), FALSE);
255 pmode = format_mode(sbuf.st_mode);
256 *aptr = make_string(pmode, strlen(pmode));
257
258 /* for symbolic links, add a linkval field */
259 if (S_ISLNK(sbuf.st_mode)) {
260 char buf[BUFSIZ*2];
261 int linksize;
262
263 linksize = readlink(file->stptr, buf, sizeof(buf) - 1);
264 if (linksize >= 0) {
265 /* should make this smarter */
266 if (linksize >= sizeof(buf) - 1)
267 fatal("size of symbolic link too big");
268 buf[linksize] = '\0';
269
270 aptr = assoc_lookup(array, tmp_string("linkval", 7), FALSE);
271 *aptr = make_string(buf, linksize);
272 }
273 }
274
275 /* add a type field */
276 switch (sbuf.st_mode & S_IFMT) {
277#ifdef S_IFSOCK
278 case S_IFSOCK:
279 type = "socket";
280 break;
281#endif
282#ifdef S_IFLNK
283 case S_IFLNK:
284 type = "symlink";
285 break;
286#endif
287 case S_IFREG:
288 type = "file";
289 break;
290 case S_IFBLK:
291 type = "blockdev";
292 break;
293 case S_IFDIR:
294 type = "directory";
295 break;
296#ifdef S_IFDOOR
297 case S_IFDOOR:
298 type = "door";
299 break;
300#endif
301 case S_IFCHR:
302 type = "chardev";
303 break;
304#ifdef S_IFIFO
305 case S_IFIFO:
306 type = "fifo";
307 break;
308#endif
309 }
310
311 aptr = assoc_lookup(array, tmp_string("type", 4), FALSE);
312 *aptr = make_string(type, strlen(type));
313
314 free_temp(file);
315
316 /* Set the return value */
317 set_value(tmp_number((AWKNUM) ret));
318
319 /* Just to make the interpreter happy */
320 return tmp_number((AWKNUM) 0);
321}
322
323/* dlload --- load new builtins in this library */
324
325NODE *
326dlload(tree, dl)
327NODE *tree;
328void *dl;
329{
330 make_builtin("chdir", do_chdir, 1);
331 make_builtin("stat", do_stat, 2);
332
333 return tmp_number((AWKNUM) 0);
334}
Note: See TracBrowser for help on using the repository browser.