4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 1995-2003 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
32 * routines to ascertain the current status of all of the files
33 * described by a set of rules. Some of the routines that update
34 * file status information are also called later (during reconcilation)
35 * to reflect the changes that have been made to files.
38 * evaluate top level - evaluate one side of one base
39 * add_file_arg (static) add a file to the list of files to evaluate
40 * eval_file (static) stat a specific file, recurse on directories
41 * walker (static) node visitor for recursive descent
42 * note_info update a file_info structure from a stat structure
43 * do_update (static) update one file_info structure from another
44 * update_info update the baseline file_info from the prevailng side
45 * fakedata (static) make it look like one side hasn't changed
46 * check_inum (static) sanity check to detect wrong-dir errors
47 * add_glob (static) expand a wildcard in an include rule
48 * add_run (static) run a program to generate an include list
51 * pay careful attention to the use of the LISTED and EVALUATE
52 * flags in each file description structure.
55 #pragma ident "%Z%%M% %I% %E% SMI"
64 #include <sys/mkdev.h>
75 static errmask_t
eval_file(struct base
*, struct file
*);
76 static errmask_t
add_file_arg(struct base
*, char *);
77 static int walker(const char *, const struct stat
*, int, struct FTW
*);
78 static errmask_t
add_glob(struct base
*, char *);
79 static errmask_t
add_run(struct base
*, char *);
80 static void check_inum(struct file
*, int);
81 static void fakedata(struct file
*, int);
86 static bool_t usingsrc
; /* this pass is on the source side */
87 static int walk_errs
; /* errors found in tree walk */
88 static struct file
*cur_dir
; /* base directory for this pass */
89 static struct base
*cur_base
; /* base pointer for this pass */
96 * to build up a baseline description for all of the files
97 * under one side of one base pair (as specified by the rules
98 * for that base pair).
101 * pointer to the base to be evaluated
102 * source/destination indication
103 * are we restricted to new rules
109 * we evaluate source and destination separately, and
110 * reinterpret the include rules on each side (since there
111 * may be wild cards and programs that must be evaluated
112 * in a specific directory context). Similarly the ignore
113 * rules must be interpreted anew for each base.
116 evaluate(struct base
*bp
, side_t srcdst
, bool_t newrules
)
117 { errmask_t errs
= 0;
122 /* see if this base is still relevant */
123 if ((bp
->b_flags
& F_LISTED
) == 0)
126 /* figure out what this pass is all about */
127 usingsrc
= (srcdst
== OPT_SRC
);
130 * the ignore engine maintains considerable per-base-directory
131 * state, and so must be reset at the start of a new tree.
135 /* all evaluation must happen from the appropriate directory */
136 dir
= usingsrc
? bp
->b_src_name
: bp
->b_dst_name
;
137 if (chdir(dir
) < 0) {
138 fprintf(stderr
, gettext(ERR_chdir
), dir
);
141 * if we have -n -o we are actually willing to
142 * pretend that nothing has changed on the missing
143 * side. This is actually useful on a disconnected
144 * notebook to ask what has been changed so far.
146 if (opt_onesided
== (usingsrc
? OPT_DST
: OPT_SRC
)) {
147 for (fp
= bp
->b_files
; fp
; fp
= fp
->f_next
)
148 fakedata(fp
, srcdst
);
150 if (opt_debug
& DBG_EVAL
)
151 fprintf(stderr
, "EVAL: FAKE DATA %s dir=%s\n",
152 usingsrc
? "SRC" : "DST", dir
);
158 if (opt_debug
& DBG_EVAL
)
159 fprintf(stderr
, "EVAL: base=%d, %s dir=%s\n",
160 bp
->b_ident
, usingsrc
? "SRC" : "DST", dir
);
162 /* assemble the include list */
163 for (rp
= bp
->b_includes
; rp
; rp
= rp
->r_next
) {
165 /* see if we are skipping old rules */
166 if (newrules
&& ((rp
->r_flags
& R_NEW
) == 0))
169 if (rp
->r_flags
& R_PROGRAM
)
170 errs
|= add_run(bp
, rp
->r_file
);
171 else if (rp
->r_flags
& R_WILD
)
172 errs
|= add_glob(bp
, rp
->r_file
);
174 errs
|= add_file_arg(bp
, rp
->r_file
);
177 /* assemble the base-specific exclude list */
178 for (rp
= bp
->b_excludes
; rp
; rp
= rp
->r_next
)
179 if (rp
->r_flags
& R_PROGRAM
)
180 ignore_pgm(rp
->r_file
);
181 else if (rp
->r_flags
& R_WILD
)
182 ignore_expr(rp
->r_file
);
184 ignore_file(rp
->r_file
);
186 /* add in the global excludes */
187 for (rp
= omnibase
.b_excludes
; rp
; rp
= rp
->r_next
)
188 if (rp
->r_flags
& R_WILD
)
189 ignore_expr(rp
->r_file
);
191 ignore_file(rp
->r_file
);
194 * because of restriction lists and new-rules, the baseline
195 * may contain many more files than we are actually supposed
196 * to look at during the impending evaluation/analysis phases
198 * when LIST arguments are encountered within a rule, we turn
199 * on the LISTED flag for the associated files. We only evaluate
200 * files that have the LISTED flag. We turn the LISTED flag off
201 * after evaluating them because just because a file was enumerated
202 * in the source doesn't mean that will necessarily be enumerated
203 * in the destination.
205 for (fp
= bp
->b_files
; fp
; fp
= fp
->f_next
)
206 if (fp
->f_flags
& F_LISTED
) {
207 errs
|= eval_file(bp
, fp
);
208 fp
->f_flags
&= ~F_LISTED
;
211 /* note that this base has been evaluated */
212 bp
->b_flags
|= F_EVALUATE
;
222 * to create file node(s) under a specified base for an explictly
226 * pointer to associated base
233 * the trick is that an include LIST argument need not be a file
234 * in the base directory, but may be a path passing through
235 * several intermediate directories. If this is the case we
236 * need to ensure that all of those directories are added to
237 * the tree SPARSELY since it is not intended that they be
238 * expanded during the course of evaluation.
240 * we ignore arguments that end in .. because they have the
241 * potential to walk out of the base tree, because it can
242 * result in different names for a single file, and because
243 * should never be necessary to specify files that way.
246 add_file_arg(struct base
*bp
, char *path
)
252 char name
[ MAX_NAME
];
255 * see if someone is trying to feed us a ..
257 if (strcmp(path
, "..") == 0 || prefix(path
, "../") ||
258 suffix(path
, "/..") || contains(path
, "/../")) {
259 fprintf(stderr
, gettext(WARN_ignore
), path
);
260 return (ERR_MISSING
);
264 * strip off any trailing "/." or "/"
265 * since noone will miss these, it is safe to actually
266 * take them off the name. When we fall out of this
267 * loop, s will point where the null belongs. We don't
268 * actually null the end of string yet because we want
269 * to leave it pristine for error messages.
271 for (s
= path
; *s
; s
++);
277 if (s
[-1] == '.' && s
> &path
[1] && s
[-2] == '/') {
285 * skip over leading "/" and "./" (but not over a lone ".")
287 for (p
= path
; p
< s
; ) {
292 if (*p
== '.' && s
> &p
[1] && p
[1] == '/') {
300 * if there is nothing left, we're miffed, but done
303 fprintf(stderr
, gettext(WARN_ignore
), path
);
304 return (ERR_MISSING
);
307 * this is actually storing a null into the argument,
308 * but it is OK to do this because the stuff we are
309 * truncating really is garbage that noone will ever
317 * see if there are any restrictions that would force
318 * us to ignore this argument
320 if (check_restr(bp
, path
) == 0)
324 /* lex off the next name component */
325 for (i
= 0; path
[i
] && path
[i
] != '/'; i
++)
329 /* add it into the database */
330 fp
= (dp
== 0) ? add_file_to_base(bp
, name
)
331 : add_file_to_dir(dp
, name
);
333 /* see if this was an intermediate directory */
334 if (path
[i
] == '/') {
335 fp
->f_flags
|= F_LISTED
| F_SPARSE
;
338 fp
->f_flags
|= F_LISTED
;
353 * to evaluate one named file under a particular directory
356 * pointer to base structure
357 * pointer to file structure
361 * filled in evaluations in the baseline
364 * due to new rules and other restrictions we may not be expected
365 * to evaluate the entire tree. We should only be called on files
366 * that are LISTed, and we should only invoke ourselves recursively
370 eval_file(struct base
*bp
, struct file
*fp
)
371 { errmask_t errs
= 0;
377 if (opt_debug
& DBG_EVAL
)
378 fprintf(stderr
, "EVAL: FILE, flags=%s, name=%s\n",
379 showflags(fileflags
, fp
->f_flags
), fp
->f_name
);
381 /* stat the file and fill in the file structure information */
385 /* see if we should simulated a stat error on this file */
386 if (opt_errors
&& (errno
= dbg_chk_error(name
, usingsrc
? 's' : 'S')))
390 rc
= lstat(name
, &statb
);
393 if (opt_debug
& DBG_EVAL
)
394 fprintf(stderr
, "EVAL: FAIL lstat, errno=%d\n", errno
);
397 fp
->f_flags
|= F_STAT_ERROR
;
400 fp
->f_flags
|= F_STAT_ERROR
;
401 return (ERR_UNRESOLVED
);
403 return (ERR_MISSING
);
407 /* record the information we've just gained */
408 note_info(fp
, &statb
, usingsrc
? OPT_SRC
: OPT_DST
);
411 * checking for ACLs is expensive, so we only do it if we
412 * have been asked to, or if we have reason to believe that
413 * the file has an ACL
415 if (opt_acls
|| fp
->f_info
[OPT_BASE
].f_numacls
)
416 (void) get_acls(name
,
417 &fp
->f_info
[usingsrc
? OPT_SRC
: OPT_DST
]);
420 /* note that this file has been evaluated */
421 fp
->f_flags
|= F_EVALUATE
;
423 /* if it is not a directory, a simple stat will suffice */
424 if ((statb
.st_mode
& S_IFMT
) != S_IFDIR
)
428 * as a sanity check, we look for changes in the I-node
429 * numbers associated with LISTed directories ... on the
430 * assumption that these are high-enough up on the tree
431 * that they aren't likely to change, and so a change
432 * might indicate trouble.
434 if (fp
->f_flags
& F_LISTED
)
435 check_inum(fp
, usingsrc
);
438 * sparse directories are on the path between a base and
439 * a listed directory. As such, we don't walk these
440 * directories. Rather, we just enumerate the LISTed
443 if (fp
->f_flags
& F_SPARSE
) {
444 push_name(fp
->f_name
);
446 /* this directory isn't supposed to be fully walked */
447 for (cp
= fp
->f_files
; cp
; cp
= cp
->f_next
)
448 if (cp
->f_flags
& F_LISTED
) {
449 errs
|= eval_file(bp
, cp
);
450 cp
->f_flags
&= ~F_LISTED
;
454 /* fully walk the tree beneath this directory */
458 nftw(get_name(fp
), &walker
, MAX_DEPTH
, FTW_PHYS
|FTW_MOUNT
);
470 * node visitor for recursive directory enumeration
474 * pointer to stat buffer for file
476 * FTW structure (base name offset, walk-depth)
483 * Ignoring files is easy, but ignoring directories is harder.
484 * Ideally we would just decline to walk the trees beneath
485 * ignored directories, but ftw doesn't allow the walker to
486 * tell it to "don't enter this directory, but continue".
488 * Instead, we have to set a global to tell us to ignore
489 * everything under that tree. The variable ignore_level
490 * is set to a level, below which, everything should be
491 * ignored. Once the enumeration rises above that level
492 * again, we clear it.
495 walker(const char *name
, const struct stat
*sp
, int type
,
502 static struct file
*dirstack
[ MAX_DEPTH
+ 1 ];
503 static int ignore_level
= 0;
505 path
= &name
[ftwx
->base
];
507 which
= usingsrc
? OPT_SRC
: OPT_DST
;
510 * see if we are ignoring all files in this sub-tree
512 if (ignore_level
> 0 && level
>= ignore_level
) {
513 if (opt_debug
& DBG_EVAL
)
514 fprintf(stderr
, "EVAL: SKIP file=%s\n", name
);
517 ignore_level
= 0; /* we're through ignoring */
520 /* see if we should simulated a stat error on this file */
521 if (opt_errors
&& dbg_chk_error(name
, usingsrc
? 'n' : 'N'))
526 case FTW_F
: /* file */
527 case FTW_SL
: /* symbolic link */
529 * filter out files of inappropriate types
531 switch (sp
->st_mode
& S_IFMT
) {
532 default: /* anything else we ignore */
539 if (opt_debug
& DBG_EVAL
)
541 "EVAL: WALK lvl=%d, file=%s\n",
544 /* see if we were told to ignore this one */
545 if (ignore_check(path
))
548 fp
= add_file_to_dir(dirstack
[level
-1], path
);
549 note_info(fp
, sp
, which
);
551 /* note that this file has been evaluated */
552 fp
->f_flags
|= F_EVALUATE
;
554 /* see if we should check ACLs */
555 if ((sp
->st_mode
& S_IFMT
) == S_IFLNK
)
558 if (fp
->f_info
[OPT_BASE
].f_numacls
|| opt_acls
)
559 (void) get_acls(name
,
565 case FTW_D
: /* enter directory */
566 if (opt_debug
& DBG_EVAL
)
567 fprintf(stderr
, "EVAL: WALK lvl=%d, dir=%s\n",
571 * if we have been told to ignore this directory, we should
572 * ignore all files under it. Similarly, if we are outside
573 * of our restrictions, we should ignore the entire subtree
575 restr
= check_restr(cur_base
, name
);
576 if (restr
== FALSE
|| ignore_check(path
)) {
577 ignore_level
= level
+ 1;
581 fp
= (level
== 0) ? cur_dir
:
582 add_file_to_dir(dirstack
[level
-1], path
);
584 note_info(fp
, sp
, which
);
586 /* see if we should be checking ACLs */
587 if (opt_acls
|| fp
->f_info
[OPT_BASE
].f_numacls
)
588 (void) get_acls(name
, &fp
->f_info
[which
]);
590 /* note that this file has been evaluated */
591 fp
->f_flags
|= F_EVALUATE
;
593 /* note the parent of the children to come */
594 dirstack
[ level
] = fp
;
597 * PROBLEM: given the information that nftw provides us with,
598 * how do we know that we have confirmed the fact
599 * that a file no longer exists. Or to rephrase
600 * this in filesync terms, how do we know when to
601 * set the EVALUATE flag for a file we didn't find.
603 * if we are going to fully scan this directory (we
604 * are completely within our restrictions) then we
605 * will be confirming the non-existance of files that
606 * used to be here. Thus any file that was in the
607 * base line under this directory should be considered
608 * to have been evaluated (whether we found it or not).
610 * if, however, we are only willing to scan selected
611 * files (due to restrictions), or the file was not
612 * in the baseline, then we should not assume that this
613 * pass will evaluate it.
616 for (fp
= fp
->f_files
; fp
; fp
= fp
->f_next
) {
617 if ((fp
->f_flags
& F_IN_BASELINE
) == 0)
619 fp
->f_flags
|= F_EVALUATE
;
624 case FTW_DP
: /* end of directory */
625 dirstack
[ level
] = 0;
628 case FTW_DNR
: /* unreadable directory */
629 walk_errs
|= ERR_PERM
;
631 case FTW_NS
: /* unstatable file */
632 if (opt_debug
& DBG_EVAL
)
633 fprintf(stderr
, "EVAL: walker can't stat/read %s\n",
635 fp
= (level
== 0) ? cur_dir
:
636 add_file_to_dir(dirstack
[level
-1], path
);
637 fp
->f_flags
|= F_STAT_ERROR
;
638 walk_errs
|= ERR_UNRESOLVED
;
650 * to record information about a file in its file node
655 * which file info structure to fill in (0-2)
661 note_info(struct file
*fp
, const struct stat
*sp
, side_t which
)
662 { struct fileinfo
*ip
;
663 static int flags
[3] = { F_IN_BASELINE
, F_IN_SOURCE
, F_IN_DEST
};
665 ip
= &fp
->f_info
[ which
];
667 ip
->f_ino
= sp
->st_ino
;
668 ip
->f_d_maj
= major(sp
->st_dev
);
669 ip
->f_d_min
= minor(sp
->st_dev
);
670 ip
->f_type
= sp
->st_mode
& S_IFMT
;
671 ip
->f_size
= sp
->st_size
;
672 ip
->f_mode
= sp
->st_mode
& S_IAMB
;
673 ip
->f_uid
= sp
->st_uid
;
674 ip
->f_gid
= sp
->st_gid
;
675 ip
->f_modtime
= sp
->st_mtim
.tv_sec
;
676 ip
->f_modns
= sp
->st_mtim
.tv_nsec
;
677 ip
->f_nlink
= sp
->st_nlink
;
678 ip
->f_rd_maj
= major(sp
->st_rdev
);
679 ip
->f_rd_min
= minor(sp
->st_rdev
);
681 /* indicate where this file has been found */
682 fp
->f_flags
|= flags
[which
];
684 if (opt_debug
& DBG_STAT
)
686 "STAT: list=%d, file=%s, mod=%08lx.%08lx, nacl=%d\n",
687 which
, fp
->f_name
, ip
->f_modtime
, ip
->f_modns
,
696 * to copy information from one side into the baseline in order
697 * to reflect the effects of recent reconciliation actions
700 * fileinfo structure to be updated
701 * fileinfo structure to be updated from
707 * we play fast and loose with the copying of acl chains
708 * here, but noone is going to free or reuse any of this
709 * memory anyway. None the less, I do feel embarassed.
712 do_update(struct fileinfo
*np
, struct fileinfo
*ip
)
714 /* get most of the fields from the designated "right" copy */
715 np
->f_type
= ip
->f_type
;
716 np
->f_size
= ip
->f_size
;
717 np
->f_mode
= ip
->f_mode
;
718 np
->f_uid
= ip
->f_uid
;
719 np
->f_gid
= ip
->f_gid
;
720 np
->f_rd_maj
= ip
->f_rd_maj
;
721 np
->f_rd_min
= ip
->f_rd_min
;
723 /* see if facls have to be propagated */
724 np
->f_numacls
= ip
->f_numacls
;
725 np
->f_acls
= ip
->f_acls
;
733 * to update the baseline to reflect recent reconcliations
737 * which file info structure to trust (1/2)
743 * after we update this I-node we run down the entire
744 * change list looking for links and update them too.
745 * This is to ensure that when subsequent links get
746 * reconciled, they are already found to be up-to-date.
749 update_info(struct file
*fp
, side_t which
)
751 /* first update the specified fileinfo structure */
752 do_update(&fp
->f_info
[ OPT_BASE
], &fp
->f_info
[ which
]);
754 if (opt_debug
& DBG_STAT
)
756 "STAT: UPDATE from=%d, file=%s, mod=%08lx.%08lx\n",
757 which
, fp
->f_name
, fp
->f_info
[ which
].f_modtime
,
758 fp
->f_info
[ which
].f_modns
);
766 * to populate a tree we cannot analyze with information from the baseline
773 * We would never use this for real reconciliation, but it is useful
774 * if a disconnected notebook user wants to find out what has been
775 * changed so far. We only do this if we are notouch and oneway.
778 fakedata(struct file
*fp
, int which
)
781 /* pretend we actually found the file */
782 fp
->f_flags
|= (which
== OPT_SRC
) ? F_IN_SOURCE
: F_IN_DEST
;
784 /* update the specified side from the baseline */
785 do_update(&fp
->f_info
[ which
], &fp
->f_info
[ OPT_BASE
]);
786 fp
->f_info
[which
].f_nlink
= (which
== OPT_SRC
) ? fp
->f_s_nlink
:
788 fp
->f_info
[which
].f_modtime
= (which
== OPT_SRC
) ? fp
->f_s_modtime
:
791 for (lp
= fp
->f_files
; lp
; lp
= lp
->f_next
)
800 * sanity check inode #s on directories that are unlikely to change
803 * pointer to file node
804 * are we using the source
807 * the purpose of this sanity check is to catch a case where we
808 * have somehow been pointed at a directory that is not the one
809 * we expected to be reconciling against. It could happen if a
810 * variable wasn't properly set, or if we were in a new domain
811 * where an old path no longer worked. This could result in
812 * bazillions of inappropriate propagations and deletions.
815 check_inum(struct file
*fp
, int src
)
816 { struct fileinfo
*ip
;
819 * we validate the inode number and the major device numbers ... minor
820 * device numbers for NFS devices are arbitrary
823 ip
= &fp
->f_info
[ OPT_SRC
];
824 if (ip
->f_ino
== fp
->f_s_inum
&& ip
->f_d_maj
== fp
->f_s_maj
)
827 /* if file was newly created/deleted, this isn't warnable */
828 if (fp
->f_s_inum
== 0 || ip
->f_ino
== 0)
832 fprintf(stdout
, V_change
, fp
->f_name
, TXT_src
,
833 fp
->f_s_maj
, fp
->f_s_min
, fp
->f_s_inum
,
834 ip
->f_d_maj
, ip
->f_d_min
, ip
->f_ino
);
836 ip
= &fp
->f_info
[ OPT_DST
];
837 if (ip
->f_ino
== fp
->f_d_inum
&& ip
->f_d_maj
== fp
->f_d_maj
)
840 /* if file was newly created/deleted, this isn't warnable */
841 if (fp
->f_d_inum
== 0 || ip
->f_ino
== 0)
845 fprintf(stdout
, V_change
, fp
->f_name
, TXT_dst
,
846 fp
->f_d_maj
, fp
->f_d_min
, fp
->f_d_inum
,
847 ip
->f_d_maj
, ip
->f_d_min
, ip
->f_ino
);
850 /* note that something has changed */
859 * to evaluate a wild-carded expression into names, and add them
860 * to the evaluation list.
870 * we don't want to allow any patterns to expand to a . because
871 * that could result in re-evaluation of a tree under a different
872 * name. The real thing we are worried about here is ".*" which
873 * is meant to pick up . files, but shouldn't pick up . and ..
876 add_glob(struct base
*bp
, char *expr
)
883 /* expand the regular expression */
884 i
= glob(expr
, GLOB_NOSORT
, 0, >
);
885 if (i
== GLOB_NOMATCH
)
886 return (ERR_MISSING
);
888 /* this shouldn't happen, so it's cryptic message time */
889 fprintf(stderr
, "EVAL: add_glob globfail expr=%s, ret=%d\n",
894 for (i
= 0; i
< gt
.gl_pathc
; i
++) {
895 /* make sure we don't let anything expand to a . */
896 s
= basename(gt
.gl_pathv
[i
]);
897 if (strcmp(s
, ".") == 0) {
898 fprintf(stderr
, gettext(WARN_ignore
), gt
.gl_pathv
[i
]);
903 errs
|= add_file_arg(bp
, gt
.gl_pathv
[i
]);
909 * in 2.4 the glob function was completely broken. The
910 * easiest way to get around this problem is to just ask
911 * the shell to do the work for us. This is much slower
912 * but produces virtually identical results. Given that
913 * the 2.4 version is internal use only, I probably won't
914 * worry about the performance difference (less than 2
915 * seconds for a typical filesync command, and no hit
916 * at all if they don't use regular expressions in
919 char cmdbuf
[MAX_LINE
];
921 sprintf(cmdbuf
, "ls -d %s 2> /dev/null", expr
);
922 errs
|= add_run(bp
, cmdbuf
);
934 * to run a command and capture the names it outputs in the
945 add_run(struct base
*bp
, char *cmd
)
948 char inbuf
[ MAX_LINE
];
952 if (opt_debug
& DBG_EVAL
)
953 fprintf(stderr
, "EVAL: RUN %s\n", cmd
);
955 /* run the command and collect its ouput */
956 fp
= popen(cmd
, "r");
958 fprintf(stderr
, gettext(ERR_badrun
), cmd
);
962 while (fgets(inbuf
, sizeof (inbuf
), fp
) != 0) {
963 /* strip off any trailing newline */
964 for (s
= inbuf
; *s
&& *s
!= '\n'; s
++);
967 /* skip any leading white space */
968 for (s
= inbuf
; *s
== ' ' || *s
== '\t'; s
++);
970 /* make sure we don't let anything expand to a . */
972 if (strcmp(p
, ".") == 0) {
973 fprintf(stderr
, gettext(WARN_ignore
), s
);
978 /* add this file to the list */
980 errs
|= add_file_arg(bp
, s
);
989 * if we are being used to simulate libc glob, and we didn't
990 * return anything, we should probably assume that the regex
991 * was unable to match anything