tarruby 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. data/README.txt +99 -0
  2. data/ext/extconf.rb +19 -0
  3. data/ext/libtar/COPYRIGHT +35 -0
  4. data/ext/libtar/ChangeLog +243 -0
  5. data/ext/libtar/ChangeLog-1.0.x +141 -0
  6. data/ext/libtar/INSTALL +183 -0
  7. data/ext/libtar/Makefile.in +51 -0
  8. data/ext/libtar/README +121 -0
  9. data/ext/libtar/TODO +10 -0
  10. data/ext/libtar/autoconf/ac_path_generic.m4 +136 -0
  11. data/ext/libtar/autoconf/aclocal.m4 +199 -0
  12. data/ext/libtar/autoconf/encap.m4 +133 -0
  13. data/ext/libtar/autoconf/install-sh +251 -0
  14. data/ext/libtar/autom4te.cache/output.0 +8102 -0
  15. data/ext/libtar/autom4te.cache/requests +112 -0
  16. data/ext/libtar/autom4te.cache/traces.0 +382 -0
  17. data/ext/libtar/compat/ChangeLog +31 -0
  18. data/ext/libtar/compat/README +12 -0
  19. data/ext/libtar/compat/TODO +4 -0
  20. data/ext/libtar/compat/basename.c +91 -0
  21. data/ext/libtar/compat/compat.h +260 -0
  22. data/ext/libtar/compat/dirname.c +96 -0
  23. data/ext/libtar/compat/fnmatch.c +237 -0
  24. data/ext/libtar/compat/gethostbyname_r.c +41 -0
  25. data/ext/libtar/compat/gethostname.c +36 -0
  26. data/ext/libtar/compat/getservbyname_r.c +41 -0
  27. data/ext/libtar/compat/glob.c +898 -0
  28. data/ext/libtar/compat/inet_aton.c +27 -0
  29. data/ext/libtar/compat/module.ac +591 -0
  30. data/ext/libtar/compat/snprintf.c +788 -0
  31. data/ext/libtar/compat/strdup.c +62 -0
  32. data/ext/libtar/compat/strlcat.c +72 -0
  33. data/ext/libtar/compat/strlcpy.c +68 -0
  34. data/ext/libtar/compat/strmode.c +199 -0
  35. data/ext/libtar/compat/strrstr.c +40 -0
  36. data/ext/libtar/compat/strsep.c +87 -0
  37. data/ext/libtar/config.h.in +187 -0
  38. data/ext/libtar/configure +8102 -0
  39. data/ext/libtar/configure.ac +114 -0
  40. data/ext/libtar/doc/Makefile.in +152 -0
  41. data/ext/libtar/doc/tar_append_file.3 +50 -0
  42. data/ext/libtar/doc/tar_block_read.3 +24 -0
  43. data/ext/libtar/doc/tar_extract_all.3 +43 -0
  44. data/ext/libtar/doc/tar_extract_file.3 +84 -0
  45. data/ext/libtar/doc/tar_open.3 +97 -0
  46. data/ext/libtar/doc/th_get_pathname.3 +63 -0
  47. data/ext/libtar/doc/th_print_long_ls.3 +22 -0
  48. data/ext/libtar/doc/th_read.3 +34 -0
  49. data/ext/libtar/doc/th_set_from_stat.3 +45 -0
  50. data/ext/libtar/lib/Makefile.in +92 -0
  51. data/ext/libtar/lib/append.c +272 -0
  52. data/ext/libtar/lib/block.c +384 -0
  53. data/ext/libtar/lib/decode.c +130 -0
  54. data/ext/libtar/lib/encode.c +237 -0
  55. data/ext/libtar/lib/extract.c +656 -0
  56. data/ext/libtar/lib/handle.c +150 -0
  57. data/ext/libtar/lib/internal.h +46 -0
  58. data/ext/libtar/lib/libtar.h +311 -0
  59. data/ext/libtar/lib/output.c +146 -0
  60. data/ext/libtar/lib/util.c +153 -0
  61. data/ext/libtar/lib/wrapper.c +175 -0
  62. data/ext/libtar/libtar/Makefile.in +73 -0
  63. data/ext/libtar/libtar/libtar.c +363 -0
  64. data/ext/libtar/listhash/ChangeLog +15 -0
  65. data/ext/libtar/listhash/TODO +21 -0
  66. data/ext/libtar/listhash/hash.c.in +344 -0
  67. data/ext/libtar/listhash/hash_new.3.in +74 -0
  68. data/ext/libtar/listhash/list.c.in +458 -0
  69. data/ext/libtar/listhash/list_new.3.in +86 -0
  70. data/ext/libtar/listhash/listhash.h.in +196 -0
  71. data/ext/libtar/listhash/module.ac +21 -0
  72. data/ext/libtar/win32/config.h +190 -0
  73. data/ext/libtar/win32/dirent.c +115 -0
  74. data/ext/libtar/win32/dirent.h +24 -0
  75. data/ext/libtar/win32/grp.h +4 -0
  76. data/ext/libtar/win32/listhash/libtar_hash.c +344 -0
  77. data/ext/libtar/win32/listhash/libtar_list.c +458 -0
  78. data/ext/libtar/win32/listhash/libtar_listhash.h +196 -0
  79. data/ext/libtar/win32/pwd.h +4 -0
  80. data/ext/libtar/win32/sys/param.h +8 -0
  81. data/ext/libtar/win32/tar.h +35 -0
  82. data/ext/libtar/win32/utime.h +6 -0
  83. data/ext/libtar/win32/win32/types.h +10 -0
  84. data/ext/tarruby.c +648 -0
  85. metadata +150 -0
@@ -0,0 +1,898 @@
1
+ /*
2
+ * Copyright (c) 1989, 1993
3
+ * The Regents of the University of California. All rights reserved.
4
+ *
5
+ * This code is derived from software contributed to Berkeley by
6
+ * Guido van Rossum.
7
+ *
8
+ * Redistribution and use in source and binary forms, with or without
9
+ * modification, are permitted provided that the following conditions
10
+ * are met:
11
+ * 1. Redistributions of source code must retain the above copyright
12
+ * notice, this list of conditions and the following disclaimer.
13
+ * 2. Redistributions in binary form must reproduce the above copyright
14
+ * notice, this list of conditions and the following disclaimer in the
15
+ * documentation and/or other materials provided with the distribution.
16
+ * 3. All advertising materials mentioning features or use of this software
17
+ * must display the following acknowledgement:
18
+ * This product includes software developed by the University of
19
+ * California, Berkeley and its contributors.
20
+ * 4. Neither the name of the University nor the names of its contributors
21
+ * may be used to endorse or promote products derived from this software
22
+ * without specific prior written permission.
23
+ *
24
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34
+ * SUCH DAMAGE.
35
+ */
36
+
37
+ // modified by SUGAWARA Genki <sgwr_dts@yahoo.co.jp>
38
+ #ifdef _WIN32
39
+ #pragma warning(disable:4101)
40
+ #pragma warning(disable:4244)
41
+ #endif
42
+
43
+ #if defined(LIBC_SCCS) && !defined(lint)
44
+ #if 0
45
+ static char sccsid[] = "@(#)glob.c 8.3 (Berkeley) 10/13/93";
46
+ #else
47
+ static char rcsid[] = "$OpenBSD: glob.c,v 1.8 1998/08/14 21:39:30 deraadt Exp $";
48
+ #endif
49
+ #endif /* LIBC_SCCS and not lint */
50
+
51
+ /*
52
+ * glob(3) -- a superset of the one defined in POSIX 1003.2.
53
+ *
54
+ * The [!...] convention to negate a range is supported (SysV, Posix, ksh).
55
+ *
56
+ * Optional extra services, controlled by flags not defined by POSIX:
57
+ *
58
+ * GLOB_QUOTE:
59
+ * Escaping convention: \ inhibits any special meaning the following
60
+ * character might have (except \ at end of string is retained).
61
+ * GLOB_MAGCHAR:
62
+ * Set in gl_flags if pattern contained a globbing character.
63
+ * GLOB_NOMAGIC:
64
+ * Same as GLOB_NOCHECK, but it will only append pattern if it did
65
+ * not contain any magic characters. [Used in csh style globbing]
66
+ * GLOB_ALTDIRFUNC:
67
+ * Use alternately specified directory access functions.
68
+ * GLOB_TILDE:
69
+ * expand ~user/foo to the /home/dir/of/user/foo
70
+ * GLOB_BRACE:
71
+ * expand {1,2}{a,b} to 1a 1b 2a 2b
72
+ * gl_matchc:
73
+ * Number of matches in the current invocation of glob.
74
+ */
75
+
76
+ #include <config.h>
77
+
78
+ #include <sys/param.h>
79
+ #include <sys/stat.h>
80
+
81
+ #include <dirent.h>
82
+ #include <errno.h>
83
+ #include <pwd.h>
84
+ #include <stdio.h>
85
+
86
+ #ifdef STDC_HEADERS
87
+ # include <stdlib.h>
88
+ # include <string.h>
89
+ #endif
90
+
91
+ #ifdef HAVE_UNISTD_H
92
+ # include <unistd.h>
93
+ #endif
94
+
95
+ #include <compat.h>
96
+
97
+
98
+ #define DOLLAR '$'
99
+ #define DOT '.'
100
+ #define EOS '\0'
101
+ #define LBRACKET '['
102
+ #define NOT '!'
103
+ #define QUESTION '?'
104
+ #define QUOTE '\\'
105
+ #define RANGE '-'
106
+ #define RBRACKET ']'
107
+ #define SEP '/'
108
+ #define STAR '*'
109
+ #define TILDE '~'
110
+ #define UNDERSCORE '_'
111
+ #define LBRACE '{'
112
+ #define RBRACE '}'
113
+ #define SLASH '/'
114
+ #define COMMA ','
115
+
116
+ #ifndef DEBUG
117
+
118
+ #define M_QUOTE 0x8000
119
+ #define M_PROTECT 0x4000
120
+ #define M_MASK 0xffff
121
+ #define M_ASCII 0x00ff
122
+
123
+ typedef u_short Char;
124
+
125
+ #else
126
+
127
+ #define M_QUOTE 0x80
128
+ #define M_PROTECT 0x40
129
+ #define M_MASK 0xff
130
+ #define M_ASCII 0x7f
131
+
132
+ typedef char Char;
133
+
134
+ #endif
135
+
136
+
137
+ #define CHAR(c) ((Char)((c)&M_ASCII))
138
+ #define META(c) ((Char)((c)|M_QUOTE))
139
+ #define M_ALL META('*')
140
+ #define M_END META(']')
141
+ #define M_NOT META('!')
142
+ #define M_ONE META('?')
143
+ #define M_RNG META('-')
144
+ #define M_SET META('[')
145
+ #define ismeta(c) (((c)&M_QUOTE) != 0)
146
+
147
+ // modified by SUGAWARA Genki <sgwr_dts@yahoo.co.jp>
148
+ #ifdef _WIN32
149
+ #define __P(protos) protos
150
+ #define S_ISDIR(m) (((m) & (_S_IFMT)) == (_S_IFDIR))
151
+ #define S_ISLNK(m) (0)
152
+ #define lstat(p, b) stat((p), (b))
153
+ #endif
154
+
155
+ static int compare (const void *, const void *);
156
+ static void g_Ctoc (const Char *, char *);
157
+ static int g_lstat (Char *, struct stat *, glob_t *);
158
+ static DIR *g_opendir (Char *, glob_t *);
159
+ static Char *g_strchr (Char *, int);
160
+ #ifdef notdef
161
+ static Char *g_strcat (Char *, const Char *);
162
+ #endif
163
+ static int g_stat (Char *, struct stat *, glob_t *);
164
+ static int glob0 (const Char *, glob_t *);
165
+ static int glob1 (Char *, glob_t *);
166
+ static int glob2 (Char *, Char *, Char *, glob_t *);
167
+ static int glob3 (Char *, Char *, Char *, Char *, glob_t *);
168
+ static int globextend (const Char *, glob_t *);
169
+ static const Char * globtilde (const Char *, Char *, size_t, glob_t *);
170
+ static int globexp1 (const Char *, glob_t *);
171
+ static int globexp2 (const Char *, const Char *, glob_t *, int *);
172
+ static int match (Char *, Char *, Char *);
173
+ #ifdef DEBUG
174
+ static void qprintf (const char *, Char *);
175
+ #endif
176
+
177
+ int
178
+ openbsd_glob(pattern, flags, errfunc, pglob)
179
+ const char *pattern;
180
+ int flags, (*errfunc) __P((const char *, int));
181
+ glob_t *pglob;
182
+ {
183
+ const u_char *patnext;
184
+ int c;
185
+ Char *bufnext, *bufend, patbuf[MAXPATHLEN+1];
186
+
187
+ patnext = (u_char *) pattern;
188
+ if (!(flags & GLOB_APPEND)) {
189
+ pglob->gl_pathc = 0;
190
+ pglob->gl_pathv = NULL;
191
+ if (!(flags & GLOB_DOOFFS))
192
+ pglob->gl_offs = 0;
193
+ }
194
+ pglob->gl_flags = flags & ~GLOB_MAGCHAR;
195
+ pglob->gl_errfunc = errfunc;
196
+ pglob->gl_matchc = 0;
197
+
198
+ bufnext = patbuf;
199
+ bufend = bufnext + MAXPATHLEN;
200
+ if (flags & GLOB_NOESCAPE)
201
+ while (bufnext < bufend && (c = *patnext++) != EOS)
202
+ *bufnext++ = c;
203
+ else {
204
+ /* Protect the quoted characters. */
205
+ while (bufnext < bufend && (c = *patnext++) != EOS)
206
+ if (c == QUOTE) {
207
+ if ((c = *patnext++) == EOS) {
208
+ c = QUOTE;
209
+ --patnext;
210
+ }
211
+ *bufnext++ = c | M_PROTECT;
212
+ }
213
+ else
214
+ *bufnext++ = c;
215
+ }
216
+ *bufnext = EOS;
217
+
218
+ if (flags & GLOB_BRACE)
219
+ return globexp1(patbuf, pglob);
220
+ else
221
+ return glob0(patbuf, pglob);
222
+ }
223
+
224
+ /*
225
+ * Expand recursively a glob {} pattern. When there is no more expansion
226
+ * invoke the standard globbing routine to glob the rest of the magic
227
+ * characters
228
+ */
229
+ static int globexp1(pattern, pglob)
230
+ const Char *pattern;
231
+ glob_t *pglob;
232
+ {
233
+ const Char* ptr = pattern;
234
+ int rv;
235
+
236
+ /* Protect a single {}, for find(1), like csh */
237
+ if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS)
238
+ return glob0(pattern, pglob);
239
+
240
+ while ((ptr = (const Char *) g_strchr((Char *) ptr, LBRACE)) != NULL)
241
+ if (!globexp2(ptr, pattern, pglob, &rv))
242
+ return rv;
243
+
244
+ return glob0(pattern, pglob);
245
+ }
246
+
247
+
248
+ /*
249
+ * Recursive brace globbing helper. Tries to expand a single brace.
250
+ * If it succeeds then it invokes globexp1 with the new pattern.
251
+ * If it fails then it tries to glob the rest of the pattern and returns.
252
+ */
253
+ static int globexp2(ptr, pattern, pglob, rv)
254
+ const Char *ptr, *pattern;
255
+ glob_t *pglob;
256
+ int *rv;
257
+ {
258
+ int i;
259
+ Char *lm, *ls;
260
+ const Char *pe, *pm, *pl;
261
+ Char patbuf[MAXPATHLEN + 1];
262
+
263
+ /* copy part up to the brace */
264
+ for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++)
265
+ continue;
266
+ ls = lm;
267
+
268
+ /* Find the balanced brace */
269
+ for (i = 0, pe = ++ptr; *pe; pe++)
270
+ if (*pe == LBRACKET) {
271
+ /* Ignore everything between [] */
272
+ for (pm = pe++; *pe != RBRACKET && *pe != EOS; pe++)
273
+ continue;
274
+ if (*pe == EOS) {
275
+ /*
276
+ * We could not find a matching RBRACKET.
277
+ * Ignore and just look for RBRACE
278
+ */
279
+ pe = pm;
280
+ }
281
+ }
282
+ else if (*pe == LBRACE)
283
+ i++;
284
+ else if (*pe == RBRACE) {
285
+ if (i == 0)
286
+ break;
287
+ i--;
288
+ }
289
+
290
+ /* Non matching braces; just glob the pattern */
291
+ if (i != 0 || *pe == EOS) {
292
+ *rv = glob0(patbuf, pglob);
293
+ return 0;
294
+ }
295
+
296
+ for (i = 0, pl = pm = ptr; pm <= pe; pm++)
297
+ switch (*pm) {
298
+ case LBRACKET:
299
+ /* Ignore everything between [] */
300
+ for (pl = pm++; *pm != RBRACKET && *pm != EOS; pm++)
301
+ continue;
302
+ if (*pm == EOS) {
303
+ /*
304
+ * We could not find a matching RBRACKET.
305
+ * Ignore and just look for RBRACE
306
+ */
307
+ pm = pl;
308
+ }
309
+ break;
310
+
311
+ case LBRACE:
312
+ i++;
313
+ break;
314
+
315
+ case RBRACE:
316
+ if (i) {
317
+ i--;
318
+ break;
319
+ }
320
+ /* FALLTHROUGH */
321
+ case COMMA:
322
+ if (i && *pm == COMMA)
323
+ break;
324
+ else {
325
+ /* Append the current string */
326
+ for (lm = ls; (pl < pm); *lm++ = *pl++)
327
+ continue;
328
+ /*
329
+ * Append the rest of the pattern after the
330
+ * closing brace
331
+ */
332
+ for (pl = pe + 1; (*lm++ = *pl++) != EOS;)
333
+ continue;
334
+
335
+ /* Expand the current pattern */
336
+ #ifdef DEBUG
337
+ qprintf("globexp2:", patbuf);
338
+ #endif
339
+ *rv = globexp1(patbuf, pglob);
340
+
341
+ /* move after the comma, to the next string */
342
+ pl = pm + 1;
343
+ }
344
+ break;
345
+
346
+ default:
347
+ break;
348
+ }
349
+ *rv = 0;
350
+ return 0;
351
+ }
352
+
353
+
354
+
355
+ /*
356
+ * expand tilde from the passwd file.
357
+ */
358
+ static const Char *
359
+ globtilde(pattern, patbuf, patbuf_len, pglob)
360
+ const Char *pattern;
361
+ Char *patbuf;
362
+ size_t patbuf_len;
363
+ glob_t *pglob;
364
+ {
365
+ struct passwd *pwd;
366
+ char *h;
367
+ const Char *p;
368
+ Char *b, *eb;
369
+
370
+ if (*pattern != TILDE || !(pglob->gl_flags & GLOB_TILDE))
371
+ return pattern;
372
+
373
+ /* Copy up to the end of the string or / */
374
+ eb = &patbuf[patbuf_len - 1];
375
+ for (p = pattern + 1, h = (char *) patbuf;
376
+ h < (char *)eb && *p && *p != SLASH; *h++ = *p++)
377
+ continue;
378
+
379
+ *h = EOS;
380
+
381
+ if (((char *) patbuf)[0] == EOS) {
382
+ /*
383
+ * handle a plain ~ or ~/ by expanding $HOME
384
+ * first and then trying the password file
385
+ */
386
+ #ifdef HAVE_ISSETUGID
387
+ if (issetugid() != 0 || (h = getenv("HOME")) == NULL) {
388
+ #endif
389
+ #ifndef _WIN32 // modified by SUGAWARA Genki <sgwr_dts@yahoo.co.jp>
390
+ if ((pwd = getpwuid(getuid())) == NULL)
391
+ return pattern;
392
+ else
393
+ h = pwd->pw_dir;
394
+ #else
395
+ if ((h = getenv("USERPROFILE")) == NULL) {
396
+ return pattern;
397
+ }
398
+ #endif
399
+ #ifdef HAVE_ISSETUGID
400
+ }
401
+ #endif
402
+ }
403
+ else {
404
+ /*
405
+ * Expand a ~user
406
+ */
407
+ #ifndef _WIN32 // modified by SUGAWARA Genki <sgwr_dts@yahoo.co.jp>
408
+ if ((pwd = getpwnam((char*) patbuf)) == NULL)
409
+ return pattern;
410
+ else
411
+ h = pwd->pw_dir;
412
+ #else
413
+ if ((h = getenv("USERPROFILE")) == NULL) {
414
+ return pattern;
415
+ }
416
+ #endif
417
+ }
418
+
419
+ /* Copy the home directory */
420
+ for (b = patbuf; b < eb && *h; *b++ = *h++)
421
+ continue;
422
+
423
+ /* Append the rest of the pattern */
424
+ while (b < eb && (*b++ = *p++) != EOS)
425
+ continue;
426
+ *b = EOS;
427
+
428
+ return patbuf;
429
+ }
430
+
431
+
432
+ /*
433
+ * The main glob() routine: compiles the pattern (optionally processing
434
+ * quotes), calls glob1() to do the real pattern matching, and finally
435
+ * sorts the list (unless unsorted operation is requested). Returns 0
436
+ * if things went well, nonzero if errors occurred. It is not an error
437
+ * to find no matches.
438
+ */
439
+ static int
440
+ glob0(pattern, pglob)
441
+ const Char *pattern;
442
+ glob_t *pglob;
443
+ {
444
+ const Char *qpatnext;
445
+ int c, err, oldpathc;
446
+ Char *bufnext, patbuf[MAXPATHLEN+1];
447
+
448
+ qpatnext = globtilde(pattern, patbuf, sizeof(patbuf) / sizeof(Char),
449
+ pglob);
450
+ oldpathc = pglob->gl_pathc;
451
+ bufnext = patbuf;
452
+
453
+ /* We don't need to check for buffer overflow any more. */
454
+ while ((c = *qpatnext++) != EOS) {
455
+ switch (c) {
456
+ case LBRACKET:
457
+ c = *qpatnext;
458
+ if (c == NOT)
459
+ ++qpatnext;
460
+ if (*qpatnext == EOS ||
461
+ g_strchr((Char *) qpatnext+1, RBRACKET) == NULL) {
462
+ *bufnext++ = LBRACKET;
463
+ if (c == NOT)
464
+ --qpatnext;
465
+ break;
466
+ }
467
+ *bufnext++ = M_SET;
468
+ if (c == NOT)
469
+ *bufnext++ = M_NOT;
470
+ c = *qpatnext++;
471
+ do {
472
+ *bufnext++ = CHAR(c);
473
+ if (*qpatnext == RANGE &&
474
+ (c = qpatnext[1]) != RBRACKET) {
475
+ *bufnext++ = M_RNG;
476
+ *bufnext++ = CHAR(c);
477
+ qpatnext += 2;
478
+ }
479
+ } while ((c = *qpatnext++) != RBRACKET);
480
+ pglob->gl_flags |= GLOB_MAGCHAR;
481
+ *bufnext++ = M_END;
482
+ break;
483
+ case QUESTION:
484
+ pglob->gl_flags |= GLOB_MAGCHAR;
485
+ *bufnext++ = M_ONE;
486
+ break;
487
+ case STAR:
488
+ pglob->gl_flags |= GLOB_MAGCHAR;
489
+ /* collapse adjacent stars to one,
490
+ * to avoid exponential behavior
491
+ */
492
+ if (bufnext == patbuf || bufnext[-1] != M_ALL)
493
+ *bufnext++ = M_ALL;
494
+ break;
495
+ default:
496
+ *bufnext++ = CHAR(c);
497
+ break;
498
+ }
499
+ }
500
+ *bufnext = EOS;
501
+ #ifdef DEBUG
502
+ qprintf("glob0:", patbuf);
503
+ #endif
504
+
505
+ if ((err = glob1(patbuf, pglob)) != 0)
506
+ return(err);
507
+
508
+ /*
509
+ * If there was no match we are going to append the pattern
510
+ * if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was specified
511
+ * and the pattern did not contain any magic characters
512
+ * GLOB_NOMAGIC is there just for compatibility with csh.
513
+ */
514
+ if (pglob->gl_pathc == oldpathc) {
515
+ if ((pglob->gl_flags & GLOB_NOCHECK) ||
516
+ ((pglob->gl_flags & GLOB_NOMAGIC) &&
517
+ !(pglob->gl_flags & GLOB_MAGCHAR)))
518
+ return(globextend(pattern, pglob));
519
+ else
520
+ return(GLOB_NOMATCH);
521
+ }
522
+ if (!(pglob->gl_flags & GLOB_NOSORT))
523
+ qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc,
524
+ pglob->gl_pathc - oldpathc, sizeof(char *), compare);
525
+ return(0);
526
+ }
527
+
528
+ static int
529
+ compare(p, q)
530
+ const void *p, *q;
531
+ {
532
+ return(strcmp(*(char **)p, *(char **)q));
533
+ }
534
+
535
+ static int
536
+ glob1(pattern, pglob)
537
+ Char *pattern;
538
+ glob_t *pglob;
539
+ {
540
+ Char pathbuf[MAXPATHLEN+1];
541
+
542
+ /* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */
543
+ if (*pattern == EOS)
544
+ return(0);
545
+ return(glob2(pathbuf, pathbuf, pattern, pglob));
546
+ }
547
+
548
+ /*
549
+ * The functions glob2 and glob3 are mutually recursive; there is one level
550
+ * of recursion for each segment in the pattern that contains one or more
551
+ * meta characters.
552
+ */
553
+ static int
554
+ glob2(pathbuf, pathend, pattern, pglob)
555
+ Char *pathbuf, *pathend, *pattern;
556
+ glob_t *pglob;
557
+ {
558
+ struct stat sb;
559
+ Char *p, *q;
560
+ int anymeta;
561
+
562
+ /*
563
+ * Loop over pattern segments until end of pattern or until
564
+ * segment with meta character found.
565
+ */
566
+ for (anymeta = 0;;) {
567
+ if (*pattern == EOS) { /* End of pattern? */
568
+ *pathend = EOS;
569
+ if (g_lstat(pathbuf, &sb, pglob))
570
+ return(0);
571
+
572
+ if (((pglob->gl_flags & GLOB_MARK) &&
573
+ pathend[-1] != SEP) && (S_ISDIR(sb.st_mode)
574
+ || (S_ISLNK(sb.st_mode) &&
575
+ (g_stat(pathbuf, &sb, pglob) == 0) &&
576
+ S_ISDIR(sb.st_mode)))) {
577
+ *pathend++ = SEP;
578
+ *pathend = EOS;
579
+ }
580
+ ++pglob->gl_matchc;
581
+ return(globextend(pathbuf, pglob));
582
+ }
583
+
584
+ /* Find end of next segment, copy tentatively to pathend. */
585
+ q = pathend;
586
+ p = pattern;
587
+ while (*p != EOS && *p != SEP) {
588
+ if (ismeta(*p))
589
+ anymeta = 1;
590
+ *q++ = *p++;
591
+ }
592
+
593
+ if (!anymeta) { /* No expansion, do next segment. */
594
+ pathend = q;
595
+ pattern = p;
596
+ while (*pattern == SEP)
597
+ *pathend++ = *pattern++;
598
+ } else /* Need expansion, recurse. */
599
+ return(glob3(pathbuf, pathend, pattern, p, pglob));
600
+ }
601
+ /* NOTREACHED */
602
+ }
603
+
604
+ static int
605
+ glob3(pathbuf, pathend, pattern, restpattern, pglob)
606
+ Char *pathbuf, *pathend, *pattern, *restpattern;
607
+ glob_t *pglob;
608
+ {
609
+ register struct dirent *dp;
610
+ DIR *dirp;
611
+ int err;
612
+ char buf[MAXPATHLEN];
613
+
614
+ /*
615
+ * The readdirfunc declaration can't be prototyped, because it is
616
+ * assigned, below, to two functions which are prototyped in glob.h
617
+ * and dirent.h as taking pointers to differently typed opaque
618
+ * structures.
619
+ */
620
+ struct dirent *(*readdirfunc)();
621
+
622
+ *pathend = EOS;
623
+ errno = 0;
624
+
625
+ if ((dirp = g_opendir(pathbuf, pglob)) == NULL) {
626
+ /* TODO: don't call for ENOENT or ENOTDIR? */
627
+ if (pglob->gl_errfunc) {
628
+ g_Ctoc(pathbuf, buf);
629
+ if (pglob->gl_errfunc(buf, errno) ||
630
+ pglob->gl_flags & GLOB_ERR)
631
+ return (GLOB_ABORTED);
632
+ }
633
+ return(0);
634
+ }
635
+
636
+ err = 0;
637
+
638
+ /* Search directory for matching names. */
639
+ if (pglob->gl_flags & GLOB_ALTDIRFUNC)
640
+ readdirfunc = pglob->gl_readdir;
641
+ else
642
+ readdirfunc = readdir;
643
+ while ((dp = (*readdirfunc)(dirp))) {
644
+ register u_char *sc;
645
+ register Char *dc;
646
+
647
+ /* Initial DOT must be matched literally. */
648
+ if (dp->d_name[0] == DOT && *pattern != DOT)
649
+ continue;
650
+ for (sc = (u_char *) dp->d_name, dc = pathend;
651
+ (*dc++ = *sc++) != EOS;)
652
+ continue;
653
+ if (!match(pathend, pattern, restpattern)) {
654
+ *pathend = EOS;
655
+ continue;
656
+ }
657
+ err = glob2(pathbuf, --dc, restpattern, pglob);
658
+ if (err)
659
+ break;
660
+ }
661
+
662
+ if (pglob->gl_flags & GLOB_ALTDIRFUNC)
663
+ (*pglob->gl_closedir)(dirp);
664
+ else
665
+ closedir(dirp);
666
+ return(err);
667
+ }
668
+
669
+
670
+ /*
671
+ * Extend the gl_pathv member of a glob_t structure to accomodate a new item,
672
+ * add the new item, and update gl_pathc.
673
+ *
674
+ * This assumes the BSD realloc, which only copies the block when its size
675
+ * crosses a power-of-two boundary; for v7 realloc, this would cause quadratic
676
+ * behavior.
677
+ *
678
+ * Return 0 if new item added, error code if memory couldn't be allocated.
679
+ *
680
+ * Invariant of the glob_t structure:
681
+ * Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and
682
+ * gl_pathv points to (gl_offs + gl_pathc + 1) items.
683
+ */
684
+ static int
685
+ globextend(path, pglob)
686
+ const Char *path;
687
+ glob_t *pglob;
688
+ {
689
+ register char **pathv;
690
+ register int i;
691
+ u_int newsize;
692
+ char *copy;
693
+ const Char *p;
694
+
695
+ newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs);
696
+ pathv = pglob->gl_pathv ?
697
+ realloc((char *)pglob->gl_pathv, newsize) :
698
+ malloc(newsize);
699
+ if (pathv == NULL) {
700
+ if (pglob->gl_pathv)
701
+ free(pglob->gl_pathv);
702
+ return(GLOB_NOSPACE);
703
+ }
704
+
705
+ if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) {
706
+ /* first time around -- clear initial gl_offs items */
707
+ pathv += pglob->gl_offs;
708
+ for (i = pglob->gl_offs; --i >= 0; )
709
+ *--pathv = NULL;
710
+ }
711
+ pglob->gl_pathv = pathv;
712
+
713
+ for (p = path; *p++;)
714
+ continue;
715
+ if ((copy = malloc(p - path)) != NULL) {
716
+ g_Ctoc(path, copy);
717
+ pathv[pglob->gl_offs + pglob->gl_pathc++] = copy;
718
+ }
719
+ pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
720
+ return(copy == NULL ? GLOB_NOSPACE : 0);
721
+ }
722
+
723
+
724
+ /*
725
+ * pattern matching function for filenames. Each occurrence of the *
726
+ * pattern causes a recursion level.
727
+ */
728
+ static int
729
+ match(name, pat, patend)
730
+ register Char *name, *pat, *patend;
731
+ {
732
+ int ok, negate_range;
733
+ Char c, k;
734
+
735
+ while (pat < patend) {
736
+ c = *pat++;
737
+ switch (c & M_MASK) {
738
+ case M_ALL:
739
+ if (pat == patend)
740
+ return(1);
741
+ do
742
+ if (match(name, pat, patend))
743
+ return(1);
744
+ while (*name++ != EOS);
745
+ return(0);
746
+ case M_ONE:
747
+ if (*name++ == EOS)
748
+ return(0);
749
+ break;
750
+ case M_SET:
751
+ ok = 0;
752
+ if ((k = *name++) == EOS)
753
+ return(0);
754
+ if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS)
755
+ ++pat;
756
+ while (((c = *pat++) & M_MASK) != M_END)
757
+ if ((*pat & M_MASK) == M_RNG) {
758
+ if (c <= k && k <= pat[1])
759
+ ok = 1;
760
+ pat += 2;
761
+ } else if (c == k)
762
+ ok = 1;
763
+ if (ok == negate_range)
764
+ return(0);
765
+ break;
766
+ default:
767
+ if (*name++ != c)
768
+ return(0);
769
+ break;
770
+ }
771
+ }
772
+ return(*name == EOS);
773
+ }
774
+
775
+ /* Free allocated data belonging to a glob_t structure. */
776
+ void
777
+ openbsd_globfree(pglob)
778
+ glob_t *pglob;
779
+ {
780
+ register int i;
781
+ register char **pp;
782
+
783
+ if (pglob->gl_pathv != NULL) {
784
+ pp = pglob->gl_pathv + pglob->gl_offs;
785
+ for (i = pglob->gl_pathc; i--; ++pp)
786
+ if (*pp)
787
+ free(*pp);
788
+ free(pglob->gl_pathv);
789
+ }
790
+ }
791
+
792
+ static DIR *
793
+ g_opendir(str, pglob)
794
+ register Char *str;
795
+ glob_t *pglob;
796
+ {
797
+ char buf[MAXPATHLEN];
798
+
799
+ if (!*str)
800
+ strcpy(buf, ".");
801
+ else
802
+ g_Ctoc(str, buf);
803
+
804
+ if (pglob->gl_flags & GLOB_ALTDIRFUNC)
805
+ return((*pglob->gl_opendir)(buf));
806
+
807
+ return(opendir(buf));
808
+ }
809
+
810
+ static int
811
+ g_lstat(fn, sb, pglob)
812
+ register Char *fn;
813
+ struct stat *sb;
814
+ glob_t *pglob;
815
+ {
816
+ char buf[MAXPATHLEN];
817
+
818
+ g_Ctoc(fn, buf);
819
+ if (pglob->gl_flags & GLOB_ALTDIRFUNC)
820
+ return((*pglob->gl_lstat)(buf, sb));
821
+ return(lstat(buf, sb));
822
+ }
823
+
824
+ static int
825
+ g_stat(fn, sb, pglob)
826
+ register Char *fn;
827
+ struct stat *sb;
828
+ glob_t *pglob;
829
+ {
830
+ char buf[MAXPATHLEN];
831
+
832
+ g_Ctoc(fn, buf);
833
+ if (pglob->gl_flags & GLOB_ALTDIRFUNC)
834
+ return((*pglob->gl_stat)(buf, sb));
835
+ return(stat(buf, sb));
836
+ }
837
+
838
+ static Char *
839
+ g_strchr(str, ch)
840
+ Char *str;
841
+ int ch;
842
+ {
843
+ do {
844
+ if (*str == ch)
845
+ return (str);
846
+ } while (*str++);
847
+ return (NULL);
848
+ }
849
+
850
+ #ifdef notdef
851
+ static Char *
852
+ g_strcat(dst, src)
853
+ Char *dst;
854
+ const Char* src;
855
+ {
856
+ Char *sdst = dst;
857
+
858
+ while (*dst++)
859
+ continue;
860
+ --dst;
861
+ while((*dst++ = *src++) != EOS)
862
+ continue;
863
+
864
+ return (sdst);
865
+ }
866
+ #endif
867
+
868
+ static void
869
+ g_Ctoc(str, buf)
870
+ register const Char *str;
871
+ char *buf;
872
+ {
873
+ register char *dc;
874
+
875
+ for (dc = buf; (*dc++ = *str++) != EOS;)
876
+ continue;
877
+ }
878
+
879
+ #ifdef DEBUG
880
+ static void
881
+ qprintf(str, s)
882
+ const char *str;
883
+ register Char *s;
884
+ {
885
+ register Char *p;
886
+
887
+ (void)printf("%s:\n", str);
888
+ for (p = s; *p; p++)
889
+ (void)printf("%c", CHAR(*p));
890
+ (void)printf("\n");
891
+ for (p = s; *p; p++)
892
+ (void)printf("%c", *p & M_PROTECT ? '"' : ' ');
893
+ (void)printf("\n");
894
+ for (p = s; *p; p++)
895
+ (void)printf("%c", ismeta(*p) ? '_' : ' ');
896
+ (void)printf("\n");
897
+ }
898
+ #endif