Following Symbolic Links

View: New views
2 Messages — Rating Filter:   Alert me  

Following Symbolic Links

by Leo L. Schwab-3 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

        A colleague had trouble running 'gtags' in a source tree with
recursive symlinks.  Next thing I knew, I was bashing this out.

        This patch adds a new argument to gtags: --follow-links.  Note that
I completely wrote this before I found last month's email thread on the
subject, so my embodiment may not be precisely what everyone had in mind.

        I hacked this together in a few hours, and it has received minimal
testing.  At the very least it should be good as a basis for discussion.
All feedback welcome.

                                        Thanks,
                                        Schwab
----
diff -ur --exclude='*.o' global-5.7.5/doc/gtags.ref global-5.7.5-hacking/doc/gtags.ref
--- global-5.7.5/doc/gtags.ref 2009-03-13 17:30:38.000000000 -0700
+++ global-5.7.5-hacking/doc/gtags.ref 2009-06-26 15:56:43.000000000 -0700
@@ -4,7 +4,7 @@
 @unnumberedsubsec SYNOPSIS
 @noindent
 @quotation
-gtags [-ciIOqvw][-f file][-n number][dbpath]@*
+gtags [-ciIOqvw][-f file][-n number][-l arg][dbpath]@*
 @end quotation
 @unnumberedsubsec DESCRIPTION
 Gtags recursively collect the source files under
@@ -52,6 +52,14 @@
 @item @samp{-i}, @samp{--incremental}
 Update tag files incrementally. You had better use
 global(1) with the -u option.
+@item @samp{-l}, @samp{--follow-links} dirs|files|both|none
+Control how symbolic links are followed.
+By default, gtags will follow all symbolic links.  Depending on
+how your source tree is arranged, this may not be desirable.
+The argument dirs will cause gtags to only follow symbolic
+links that point to directories, files will only follow
+links to files, both will follow all links, and none
+will ignore all symbolic links.
 @item @samp{-n}, @samp{--max-args} number
 Maximum number of arguments for gtags-parser(1).
 By default, gtags invokes gtags-parser with arguments
diff -ur --exclude='*.o' global-5.7.5/gtags/const.h global-5.7.5-hacking/gtags/const.h
--- global-5.7.5/gtags/const.h 2009-03-13 17:30:38.000000000 -0700
+++ global-5.7.5-hacking/gtags/const.h 2009-06-26 15:56:43.000000000 -0700
@@ -1,6 +1,6 @@
 /* This file is generated automatically by convert.pl from gtags/manual.in. */
 const char *progname = "gtags";
-const char *usage_const = "Usage: gtags [-ciIOqvw][-f file][-n number][dbpath]\n";
+const char *usage_const = "Usage: gtags [-ciIOqvw][-f file][-n number][-l arg][dbpath]\n";
 const char *help_const = "Options:\n\
 -c, --compact\n\
        Make GTAGS in compact format.\n\
@@ -26,6 +26,14 @@
 -i, --incremental\n\
        Update tag files incrementally. You had better use\n\
        global(1) with the -u option.\n\
+-l, --follow-links dirs|files|both|none\n\
+       Control how symbolic links are followed.\n\
+       By default, gtags will follow all symbolic links.  Depending on\n\
+       how your source tree is arranged, this may not be desirable.\n\
+       The argument dirs will cause gtags to only follow symbolic\n\
+       links that point to directories, files will only follow\n\
+       links to files, both will follow all links, and none\n\
+       will ignore all symbolic links.\n\
 -n, --max-args number\n\
        Maximum number of arguments for gtags-parser(1).\n\
        By default, gtags invokes gtags-parser with arguments\n\
diff -ur --exclude='*.o' global-5.7.5/gtags/gtags.1 global-5.7.5-hacking/gtags/gtags.1
--- global-5.7.5/gtags/gtags.1 2009-03-13 17:30:38.000000000 -0700
+++ global-5.7.5-hacking/gtags/gtags.1 2009-06-26 15:56:43.000000000 -0700
@@ -3,7 +3,7 @@
 .SH NAME
 gtags \- create tag files for global.
 .SH SYNOPSIS
-\fBgtags\fP [-ciIOqvw][-f \fIfile\fP][-n \fInumber\fP][\fIdbpath\fP]
+\fBgtags\fP [-ciIOqvw][-f \fIfile\fP][-n \fInumber\fP][-l \fIarg\fP][\fIdbpath\fP]
 .br
 .SH DESCRIPTION
 \fBGtags\fP recursively collect the source files under
@@ -58,6 +58,15 @@
 Update tag files incrementally. You had better use
 \fBglobal\fP(1) with the -u option.
 .TP
+\fB-l\fP, \fB--follow-links\fP \fIdirs|files|both|none\fP
+Control how symbolic links are followed.
+By default, gtags will follow all symbolic links.  Depending on
+how your source tree is arranged, this may not be desirable.
+The argument \fIdirs\fP will cause gtags to only follow symbolic
+links that point to directories, \fIfiles\fP will only follow
+links to files, \fIboth\fP will follow all links, and \fInone\fP
+will ignore all symbolic links.
+.TP
 \fB-n\fP, \fB--max-args\fP \fInumber\fP
 Maximum number of arguments for \fBgtags-parser\fP(1).
 By default, gtags invokes \fBgtags-parser\fP with arguments
diff -ur --exclude='*.o' global-5.7.5/gtags/gtags.c global-5.7.5-hacking/gtags/gtags.c
--- global-5.7.5/gtags/gtags.c 2009-03-13 17:30:37.000000000 -0700
+++ global-5.7.5-hacking/gtags/gtags.c 2009-06-26 16:09:59.000000000 -0700
@@ -85,6 +85,7 @@
  */
 int do_path;
 int convert_type = PATH_RELATIVE;
+int followflags = FOLLOWF_BOTH;
 
 int extractmethod;
 int total;
@@ -122,6 +123,7 @@
  {"quiet", no_argument, NULL, 'q'},
  {"verbose", no_argument, NULL, 'v'},
  {"warning", no_argument, NULL, 'w'},
+ {"follow-links", required_argument, NULL, 'l'},
 
  /*
  * The following are long name only.
@@ -162,7 +164,7 @@
  int optchar;
  int option_index = 0;
 
- while ((optchar = getopt_long(argc, argv, "cf:iIn:oOqvwse", long_options, &option_index)) != EOF) {
+ while ((optchar = getopt_long(argc, argv, "cf:iIl:n:oOqvwse", long_options, &option_index)) != EOF) {
  switch (optchar) {
  case 0:
  /* already flags set */
@@ -201,6 +203,18 @@
  case 'I':
  Iflag++;
  break;
+ case 'l':
+ if (!strncmp (optarg, "files", 5))
+ followflags = FOLLOWF_FILE;
+ else if (!strncmp (optarg, "dirs", 4))
+ followflags = FOLLOWF_DIR;
+ else if (!strncmp (optarg, "both", 4))
+ followflags = FOLLOWF_BOTH;
+ else if (!strncmp (optarg, "none", 4))
+ followflags = FOLLOWF_NONE;
+ else
+ die ("Unknown --follow-flags argument: %s", optarg);
+ break;
  case 'n':
  max_args = atoi(optarg);
  if (max_args <= 0)
@@ -502,7 +516,7 @@
  if (file_list)
  find_open_filelist(file_list, root);
  else
- find_open(NULL);
+ find_open(NULL, followflags);
  total = 0;
  while ((path = find_read()) != NULL) {
  const char *fid;
@@ -806,7 +820,7 @@
  if (file_list)
  find_open_filelist(file_list, root);
  else
- find_open(NULL);
+ find_open(NULL, followflags);
  /*
  * Add tags.
  */
diff -ur --exclude='*.o' global-5.7.5/gtags/manual.in global-5.7.5-hacking/gtags/manual.in
--- global-5.7.5/gtags/manual.in 2009-03-13 17:30:37.000000000 -0700
+++ global-5.7.5-hacking/gtags/manual.in 2009-06-26 15:35:25.000000000 -0700
@@ -25,7 +25,7 @@
 @HEADER GTAGS,1,January 2009,GNU Project
 @NAME gtags - create tag files for global.
 @SYNOPSIS
- @name{gtags} [-ciIOqvw][-f @arg{file}][-n @arg{number}][@arg{dbpath}]
+ @name{gtags} [-ciIOqvw][-f @arg{file}][-n @arg{number}][-l @arg{arg}][@arg{dbpath}]
 @DESCRIPTION
  @name{Gtags} recursively collect the source files under
  the current directory,
@@ -72,6 +72,14 @@
  @item{@option{-i}, @option{--incremental}}
  Update tag files incrementally. You had better use
  @xref{global,1} with the -u option.
+ @item{@option{-l}, @option{--follow-links} @arg{dirs|files|both|none}}
+ Control how symbolic links are followed.
+ By default, gtags will follow all symbolic links.  Depending on
+ how your source tree is arranged, this may not be desirable.
+ The argument @arg{dirs} will cause gtags to only follow symbolic
+ links that point to directories, @arg{files} will only follow
+ links to files, @arg{both} will follow all links, and @arg{none}
+ will ignore all symbolic links.
  @item{@option{-n}, @option{--max-args} @arg{number}}
  Maximum number of arguments for @xref{gtags-parser,1}.
  By default, gtags invokes @name{gtags-parser} with arguments
diff -ur --exclude='*.o' global-5.7.5/libutil/find.c global-5.7.5-hacking/libutil/find.c
--- global-5.7.5/libutil/find.c 2009-03-13 17:30:37.000000000 -0700
+++ global-5.7.5-hacking/libutil/find.c 2009-06-26 16:11:32.000000000 -0700
@@ -78,6 +78,7 @@
 static regex_t *suff = &suff_area; /* regex for suffixes */
 static STRBUF *list;
 static int list_count;
+static int follow_flags;
 static char **listarray; /* list for skipping full path */
 static FILE *ip;
 static FILE *temp;
@@ -372,8 +373,9 @@
  * r) -1: error, 0: normal
  *
  * format of directory list:
- * |ddir1\0ffile1\0llink\0|
- * means directory 'dir1', file 'file1' and symbolic link 'link'.
+ * |ddir1\0ffile1\0Dlinkeddir\0Flinkedfile\0llink\0|
+ * means directory 'dir1', file 'file1', symbolic link to 'linkeddir',
+ * symbolic link to 'linkedfile', and symbolic link 'link'.
  */
 static int
 getdirs(const char *dir, STRBUF *sb)
@@ -381,6 +383,7 @@
  DIR *dirp;
  struct dirent *dp;
  struct stat st;
+ char islink;
 
  if ((dirp = opendir(dir)) == NULL)
  return -1;
@@ -389,14 +392,24 @@
  continue;
  if (!strcmp(dp->d_name, ".."))
  continue;
- if (stat(makepath(dir, dp->d_name, NULL), &st) < 0) {
- warning("cannot stat '%s'. (Ignored)", dp->d_name);
+ if (lstat(makepath(dir, dp->d_name, NULL), &st) < 0) {
+ warning("cannot lstat '%s'. (Ignored)", dp->d_name);
  continue;
  }
+
+ if (S_ISLNK(st.st_mode)) {
+ if (stat(makepath(dir, dp->d_name, NULL), &st) < 0) {
+ warning("cannot stat '%s'. (Ignored)", dp->d_name);
+ continue;
+ }
+ islink = 1;
+ } else
+ islink = 0;
+
  if (S_ISDIR(st.st_mode))
- strbuf_putc(sb, 'd');
+ strbuf_putc(sb, islink ? 'D' : 'd');
  else if (S_ISREG(st.st_mode))
- strbuf_putc(sb, 'f');
+ strbuf_putc(sb, islink ? 'F' : 'f');
  else
  strbuf_putc(sb, ' ');
  strbuf_puts(sb, dp->d_name);
@@ -412,14 +425,18 @@
  * If NULL, assumed '.' directory.
  */
 void
-find_open(const char *start)
+find_open(const char *start, int cl_follow_flags)
 {
  struct stack_entry *curp;
+
  assert(find_mode == 0);
  find_mode = FIND_OPEN;
 
  if (!start)
  start = "./";
+
+ follow_flags = cl_follow_flags;
+
  /*
  * setup stack.
  */
@@ -531,6 +548,17 @@
  */
  /* makepath() returns unsafe module local area. */
  strlimcpy(path, makepath(dir, unit, NULL), sizeof(path));
+ if (type == 'D') {
+ /*  Softlink to dir.  */
+ if (!(follow_flags & FOLLOWF_DIR))
+ continue;
+ type = 'd';
+ } else if (type == 'F') {
+ /*  Softlink to file.  */
+ if (!(follow_flags & FOLLOWF_FILE))
+ continue;
+ type = 'f';
+ }
  if (type == 'd')
  strcat(path, "/");
  if (skipthisfile(path))
@@ -541,6 +569,7 @@
  * o directory
  * o file which does not exist
  * o dead symbolic link
+ * XXX ewhac: Is this test necessary?  Is stat(2) known to lie?
  */
  if (!test("f", path)) {
  if (test("d", path))
diff -ur --exclude='*.o' global-5.7.5/libutil/find.h global-5.7.5-hacking/libutil/find.h
--- global-5.7.5/libutil/find.h 2009-03-13 17:30:37.000000000 -0700
+++ global-5.7.5-hacking/libutil/find.h 2009-06-26 14:58:31.000000000 -0700
@@ -21,9 +21,15 @@
 #ifndef _FIND_H_
 #define _FIND_H_
 
-void find_open(const char *);
+void find_open(const char *, int follow_flags);
 void find_open_filelist(const char *, const char *);
 char *find_read(void);
 void find_close(void);
 
+/*  follow_flags  */
+#define FOLLOWF_NONE    0
+#define FOLLOWF_FILE    1
+#define FOLLOWF_DIR     2
+#define FOLLOWF_BOTH    (FOLLOWF_FILE | FOLLOWF_DIR)
+
 #endif /* ! _FIND_H_ */


_______________________________________________
Bug-global mailing list
Bug-global@...
http://lists.gnu.org/mailman/listinfo/bug-global

Re: Following Symbolic Links

by Petr Uzel-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi,

On Fri, Jun 26, 2009 at 05:51:53PM -0700, Leo L. Schwab wrote:

> A colleague had trouble running 'gtags' in a source tree with
> recursive symlinks.  Next thing I knew, I was bashing this out.
>
> This patch adds a new argument to gtags: --follow-links.  Note that
> I completely wrote this before I found last month's email thread on the
> subject, so my embodiment may not be precisely what everyone had in mind.
>
> I hacked this together in a few hours, and it has received minimal
> testing.  At the very least it should be good as a basis for discussion.
> All feedback welcome.

I did a simple test with a quilt usecase (as described in [1]) and
'gtags -l files' works OK. Many thanks for the patch!

[1] http://www.mail-archive.com/bug-global@.../msg00523.html


>
> Thanks,
> Schwab
> ----
> diff -ur --exclude='*.o' global-5.7.5/doc/gtags.ref global-5.7.5-hacking/doc/gtags.ref
> --- global-5.7.5/doc/gtags.ref 2009-03-13 17:30:38.000000000 -0700
> +++ global-5.7.5-hacking/doc/gtags.ref 2009-06-26 15:56:43.000000000 -0700
> @@ -4,7 +4,7 @@
>  @unnumberedsubsec SYNOPSIS
>  @noindent
>  @quotation
> -gtags [-ciIOqvw][-f file][-n number][dbpath]@*
> +gtags [-ciIOqvw][-f file][-n number][-l arg][dbpath]@*
>  @end quotation
>  @unnumberedsubsec DESCRIPTION
>  Gtags recursively collect the source files under
> @@ -52,6 +52,14 @@
>  @item @samp{-i}, @samp{--incremental}
>  Update tag files incrementally. You had better use
>  global(1) with the -u option.
> +@item @samp{-l}, @samp{--follow-links} dirs|files|both|none
> +Control how symbolic links are followed.
> +By default, gtags will follow all symbolic links.  Depending on
> +how your source tree is arranged, this may not be desirable.
> +The argument dirs will cause gtags to only follow symbolic
> +links that point to directories, files will only follow
> +links to files, both will follow all links, and none
> +will ignore all symbolic links.
>  @item @samp{-n}, @samp{--max-args} number
>  Maximum number of arguments for gtags-parser(1).
>  By default, gtags invokes gtags-parser with arguments
> diff -ur --exclude='*.o' global-5.7.5/gtags/const.h global-5.7.5-hacking/gtags/const.h
> --- global-5.7.5/gtags/const.h 2009-03-13 17:30:38.000000000 -0700
> +++ global-5.7.5-hacking/gtags/const.h 2009-06-26 15:56:43.000000000 -0700
> @@ -1,6 +1,6 @@
>  /* This file is generated automatically by convert.pl from gtags/manual.in. */
>  const char *progname = "gtags";
> -const char *usage_const = "Usage: gtags [-ciIOqvw][-f file][-n number][dbpath]\n";
> +const char *usage_const = "Usage: gtags [-ciIOqvw][-f file][-n number][-l arg][dbpath]\n";
>  const char *help_const = "Options:\n\
>  -c, --compact\n\
>         Make GTAGS in compact format.\n\
> @@ -26,6 +26,14 @@
>  -i, --incremental\n\
>         Update tag files incrementally. You had better use\n\
>         global(1) with the -u option.\n\
> +-l, --follow-links dirs|files|both|none\n\
> +       Control how symbolic links are followed.\n\
> +       By default, gtags will follow all symbolic links.  Depending on\n\
> +       how your source tree is arranged, this may not be desirable.\n\
> +       The argument dirs will cause gtags to only follow symbolic\n\
> +       links that point to directories, files will only follow\n\
> +       links to files, both will follow all links, and none\n\
> +       will ignore all symbolic links.\n\
>  -n, --max-args number\n\
>         Maximum number of arguments for gtags-parser(1).\n\
>         By default, gtags invokes gtags-parser with arguments\n\
> diff -ur --exclude='*.o' global-5.7.5/gtags/gtags.1 global-5.7.5-hacking/gtags/gtags.1
> --- global-5.7.5/gtags/gtags.1 2009-03-13 17:30:38.000000000 -0700
> +++ global-5.7.5-hacking/gtags/gtags.1 2009-06-26 15:56:43.000000000 -0700
> @@ -3,7 +3,7 @@
>  .SH NAME
>  gtags \- create tag files for global.
>  .SH SYNOPSIS
> -\fBgtags\fP [-ciIOqvw][-f \fIfile\fP][-n \fInumber\fP][\fIdbpath\fP]
> +\fBgtags\fP [-ciIOqvw][-f \fIfile\fP][-n \fInumber\fP][-l \fIarg\fP][\fIdbpath\fP]
>  .br
>  .SH DESCRIPTION
>  \fBGtags\fP recursively collect the source files under
> @@ -58,6 +58,15 @@
>  Update tag files incrementally. You had better use
>  \fBglobal\fP(1) with the -u option.
>  .TP
> +\fB-l\fP, \fB--follow-links\fP \fIdirs|files|both|none\fP
> +Control how symbolic links are followed.
> +By default, gtags will follow all symbolic links.  Depending on
> +how your source tree is arranged, this may not be desirable.
> +The argument \fIdirs\fP will cause gtags to only follow symbolic
> +links that point to directories, \fIfiles\fP will only follow
> +links to files, \fIboth\fP will follow all links, and \fInone\fP
> +will ignore all symbolic links.
> +.TP
>  \fB-n\fP, \fB--max-args\fP \fInumber\fP
>  Maximum number of arguments for \fBgtags-parser\fP(1).
>  By default, gtags invokes \fBgtags-parser\fP with arguments
> diff -ur --exclude='*.o' global-5.7.5/gtags/gtags.c global-5.7.5-hacking/gtags/gtags.c
> --- global-5.7.5/gtags/gtags.c 2009-03-13 17:30:37.000000000 -0700
> +++ global-5.7.5-hacking/gtags/gtags.c 2009-06-26 16:09:59.000000000 -0700
> @@ -85,6 +85,7 @@
>   */
>  int do_path;
>  int convert_type = PATH_RELATIVE;
> +int followflags = FOLLOWF_BOTH;
>  
>  int extractmethod;
>  int total;
> @@ -122,6 +123,7 @@
>   {"quiet", no_argument, NULL, 'q'},
>   {"verbose", no_argument, NULL, 'v'},
>   {"warning", no_argument, NULL, 'w'},
> + {"follow-links", required_argument, NULL, 'l'},
>  
>   /*
>   * The following are long name only.
> @@ -162,7 +164,7 @@
>   int optchar;
>   int option_index = 0;
>  
> - while ((optchar = getopt_long(argc, argv, "cf:iIn:oOqvwse", long_options, &option_index)) != EOF) {
> + while ((optchar = getopt_long(argc, argv, "cf:iIl:n:oOqvwse", long_options, &option_index)) != EOF) {
>   switch (optchar) {
>   case 0:
>   /* already flags set */
> @@ -201,6 +203,18 @@
>   case 'I':
>   Iflag++;
>   break;
> + case 'l':
> + if (!strncmp (optarg, "files", 5))
> + followflags = FOLLOWF_FILE;
> + else if (!strncmp (optarg, "dirs", 4))
> + followflags = FOLLOWF_DIR;
> + else if (!strncmp (optarg, "both", 4))
> + followflags = FOLLOWF_BOTH;
> + else if (!strncmp (optarg, "none", 4))
> + followflags = FOLLOWF_NONE;
> + else
> + die ("Unknown --follow-flags argument: %s", optarg);
> + break;
>   case 'n':
>   max_args = atoi(optarg);
>   if (max_args <= 0)
> @@ -502,7 +516,7 @@
>   if (file_list)
>   find_open_filelist(file_list, root);
>   else
> - find_open(NULL);
> + find_open(NULL, followflags);
>   total = 0;
>   while ((path = find_read()) != NULL) {
>   const char *fid;
> @@ -806,7 +820,7 @@
>   if (file_list)
>   find_open_filelist(file_list, root);
>   else
> - find_open(NULL);
> + find_open(NULL, followflags);
>   /*
>   * Add tags.
>   */
> diff -ur --exclude='*.o' global-5.7.5/gtags/manual.in global-5.7.5-hacking/gtags/manual.in
> --- global-5.7.5/gtags/manual.in 2009-03-13 17:30:37.000000000 -0700
> +++ global-5.7.5-hacking/gtags/manual.in 2009-06-26 15:35:25.000000000 -0700
> @@ -25,7 +25,7 @@
>  @HEADER GTAGS,1,January 2009,GNU Project
>  @NAME gtags - create tag files for global.
>  @SYNOPSIS
> - @name{gtags} [-ciIOqvw][-f @arg{file}][-n @arg{number}][@arg{dbpath}]
> + @name{gtags} [-ciIOqvw][-f @arg{file}][-n @arg{number}][-l @arg{arg}][@arg{dbpath}]
>  @DESCRIPTION
>   @name{Gtags} recursively collect the source files under
>   the current directory,
> @@ -72,6 +72,14 @@
>   @item{@option{-i}, @option{--incremental}}
>   Update tag files incrementally. You had better use
>   @xref{global,1} with the -u option.
> + @item{@option{-l}, @option{--follow-links} @arg{dirs|files|both|none}}
> + Control how symbolic links are followed.
> + By default, gtags will follow all symbolic links.  Depending on
> + how your source tree is arranged, this may not be desirable.
> + The argument @arg{dirs} will cause gtags to only follow symbolic
> + links that point to directories, @arg{files} will only follow
> + links to files, @arg{both} will follow all links, and @arg{none}
> + will ignore all symbolic links.
>   @item{@option{-n}, @option{--max-args} @arg{number}}
>   Maximum number of arguments for @xref{gtags-parser,1}.
>   By default, gtags invokes @name{gtags-parser} with arguments
> diff -ur --exclude='*.o' global-5.7.5/libutil/find.c global-5.7.5-hacking/libutil/find.c
> --- global-5.7.5/libutil/find.c 2009-03-13 17:30:37.000000000 -0700
> +++ global-5.7.5-hacking/libutil/find.c 2009-06-26 16:11:32.000000000 -0700
> @@ -78,6 +78,7 @@
>  static regex_t *suff = &suff_area; /* regex for suffixes */
>  static STRBUF *list;
>  static int list_count;
> +static int follow_flags;
>  static char **listarray; /* list for skipping full path */
>  static FILE *ip;
>  static FILE *temp;
> @@ -372,8 +373,9 @@
>   * r) -1: error, 0: normal
>   *
>   * format of directory list:
> - * |ddir1\0ffile1\0llink\0|
> - * means directory 'dir1', file 'file1' and symbolic link 'link'.
> + * |ddir1\0ffile1\0Dlinkeddir\0Flinkedfile\0llink\0|
> + * means directory 'dir1', file 'file1', symbolic link to 'linkeddir',
> + * symbolic link to 'linkedfile', and symbolic link 'link'.
>   */
>  static int
>  getdirs(const char *dir, STRBUF *sb)
> @@ -381,6 +383,7 @@
>   DIR *dirp;
>   struct dirent *dp;
>   struct stat st;
> + char islink;
>  
>   if ((dirp = opendir(dir)) == NULL)
>   return -1;
> @@ -389,14 +392,24 @@
>   continue;
>   if (!strcmp(dp->d_name, ".."))
>   continue;
> - if (stat(makepath(dir, dp->d_name, NULL), &st) < 0) {
> - warning("cannot stat '%s'. (Ignored)", dp->d_name);
> + if (lstat(makepath(dir, dp->d_name, NULL), &st) < 0) {
> + warning("cannot lstat '%s'. (Ignored)", dp->d_name);
>   continue;
>   }
> +
> + if (S_ISLNK(st.st_mode)) {
> + if (stat(makepath(dir, dp->d_name, NULL), &st) < 0) {
> + warning("cannot stat '%s'. (Ignored)", dp->d_name);
> + continue;
> + }
> + islink = 1;
> + } else
> + islink = 0;
> +
>   if (S_ISDIR(st.st_mode))
> - strbuf_putc(sb, 'd');
> + strbuf_putc(sb, islink ? 'D' : 'd');
>   else if (S_ISREG(st.st_mode))
> - strbuf_putc(sb, 'f');
> + strbuf_putc(sb, islink ? 'F' : 'f');
>   else
>   strbuf_putc(sb, ' ');
>   strbuf_puts(sb, dp->d_name);
> @@ -412,14 +425,18 @@
>   * If NULL, assumed '.' directory.
>   */
>  void
> -find_open(const char *start)
> +find_open(const char *start, int cl_follow_flags)
>  {
>   struct stack_entry *curp;
> +
>   assert(find_mode == 0);
>   find_mode = FIND_OPEN;
>  
>   if (!start)
>   start = "./";
> +
> + follow_flags = cl_follow_flags;
> +
>   /*
>   * setup stack.
>   */
> @@ -531,6 +548,17 @@
>   */
>   /* makepath() returns unsafe module local area. */
>   strlimcpy(path, makepath(dir, unit, NULL), sizeof(path));
> + if (type == 'D') {
> + /*  Softlink to dir.  */
> + if (!(follow_flags & FOLLOWF_DIR))
> + continue;
> + type = 'd';
> + } else if (type == 'F') {
> + /*  Softlink to file.  */
> + if (!(follow_flags & FOLLOWF_FILE))
> + continue;
> + type = 'f';
> + }
>   if (type == 'd')
>   strcat(path, "/");
>   if (skipthisfile(path))
> @@ -541,6 +569,7 @@
>   * o directory
>   * o file which does not exist
>   * o dead symbolic link
> + * XXX ewhac: Is this test necessary?  Is stat(2) known to lie?
>   */
>   if (!test("f", path)) {
>   if (test("d", path))
> diff -ur --exclude='*.o' global-5.7.5/libutil/find.h global-5.7.5-hacking/libutil/find.h
> --- global-5.7.5/libutil/find.h 2009-03-13 17:30:37.000000000 -0700
> +++ global-5.7.5-hacking/libutil/find.h 2009-06-26 14:58:31.000000000 -0700
> @@ -21,9 +21,15 @@
>  #ifndef _FIND_H_
>  #define _FIND_H_
>  
> -void find_open(const char *);
> +void find_open(const char *, int follow_flags);
>  void find_open_filelist(const char *, const char *);
>  char *find_read(void);
>  void find_close(void);
>  
> +/*  follow_flags  */
> +#define FOLLOWF_NONE    0
> +#define FOLLOWF_FILE    1
> +#define FOLLOWF_DIR     2
> +#define FOLLOWF_BOTH    (FOLLOWF_FILE | FOLLOWF_DIR)
> +
>  #endif /* ! _FIND_H_ */
>
>
> _______________________________________________
> Bug-global mailing list
> Bug-global@...
> http://lists.gnu.org/mailman/listinfo/bug-global

--
Best regards / s pozdravem

Petr Uzel, Packages maintainer
---------------------------------------------------------------------
SUSE LINUX, s.r.o.                          e-mail: puzel@...
Lihovarská 1060/12                          http://www.suse.cz
190 00 Prague 9                            
Czech Republic                              


_______________________________________________
Bug-global mailing list
Bug-global@...
http://lists.gnu.org/mailman/listinfo/bug-global