[cs631apue] About FTS

Yuxi Wang ywang286 at stevens.edu
Tue Oct 8 21:42:31 EDT 2019


void PrintFileNames(char *dir)
{
              FTS *filetree = NULL;
              FTSENT *file  = NULL;
              FTSENT *child = NULL;
              char *path[] = { dir, NULL };

              filetree = fts_open(path, FTS_PHYSICAL, NULL);
              if (filetree == NULL)
                             warn("fts_open failed");

              else
              {
                             while ((file = fts_read(filetree)) != NULL)
                             {
                                           child = fts_children(filetree, 0);
                                           warn("%d", errno);
                                           if (child == NULL)
                                                          warn("fts_children");
                                           printf("%s\n", child->fts_name);
                             }
              }
              if (errno != 0)
                             warn("fts_read failed");
              if (fts_close(filetree) < 0)
                             warn("fts_close");
}
int main(int argc, char *argv[])
{
              if (argc == 1)
                             PrintFileNames(".");
}

Hello,

Here is your code. I changed all the ErrorMessage functions to warn, so that I can output the error message more easily.

And this is the quote to fts(3):
if the FTSENT structure most recently returned by fts_read() is not a directory being visited in pre-order, or the directory does not contain any files, fts_children() returns NULL and sets errno to zero.

First time, you read dir-“.” in the while, and then you call fts_children. This time of loop works fine. var child has the information in dir-“.”.

Second time, fts_read begins to read into “.” And the first file it reads happens to be a regular file. This causes var child to be NULL and set errno to 0.
Then you call printf child->fts_name which references a NULL pointer. Here is the point that seg-fault occurs.

I don’t think “fts_children: Undefined error: 0.” Is an error message. It just tells the errno is 0 and 0 is not an error…

From: Marlon Seaton<mailto:mseaton at stevens.edu>
Sent: Tuesday, October 8, 2019 12:11 PM
To: Jan Schaumann<mailto:jschauma at stevens.edu>; cs631apue at lists.stevens.edu<mailto:cs631apue at lists.stevens.edu>
Subject: Re: [cs631apue] About FTS

Hello,
I am trying to use fts to traverse through the current directory without recursion and i either get a segfault of the following error when I call fts_children()

fts_children: Undefined error: 0.

Here's my code snippet below:

main
{
    if(argc == 1)
      PrintFileNames(".");
}
void PrintFileNames(char* dir )
{

   FTS *filetree = NULL;
   FTSENT *file  = NULL;
   FTSENT *child = NULL;
   char *path[] = {dir, NULL};

   filetree = fts_open(path, FTS_PHYSICAL, &compare);

   if(filetree == NULL)
      ErrorMessage("fts_open failed");

   else
   {

      while((file = fts_read(filetree)) != NULL)
      {

         child = fts_children(filetree, 0);

         if(child == NULL)
            ErrorMessage("fts_children");

         printf("%s\n",child->fts_name);

      }
   }

   if(errno != 0)
      ErrorMessage("fts_read failed");

   if( fts_close(filetree) < 0)
      ErrorMessage("fts_close");
}

Can anyone shed some light on what's going on?
Thanks.

From: cs631apue-bounces at lists.stevens.edu <cs631apue-bounces at lists.stevens.edu> on behalf of Jan Schaumann <jschauma at stevens.edu>
Sent: Sunday, October 6, 2019 4:35 PM
To: cs631apue at lists.stevens.edu <cs631apue at lists.stevens.edu>
Subject: Re: [cs631apue] About FTS

Yuxi Wang <ywang286 at stevens.edu> wrote:

> 1.To use these fields to reference any files represented by
> other FTSENT structures will require that the path buffer be modified
> using the information contained in that FTSENT structure's fts_pathlen
> field.  Any such modifications should be undone before further calls to
> fts_read() are attempted.  The fts_name field is always NUL-terminated.

I'm honestly struggling to come up with a useful
example, but the point is that you cannot manipulate
the buffers (e.g., via strcat(3) etc.) in e.g., your
comparison function, nor can you rely on the buffer to
be NULL terminated for a previously returned element.

That means that you can't keep a pointer to the
element returned and subsequently call e.g. strlen(3)
on _that_ element's fts_path field.

Let's say you want to write a program that will print
the path within the parent directory:

$ pwd
/tmp
$ ls
file
$ printParentPath file
tmp/file
$ printParentPath /var/tmp/subdir/file
subdir/file

This might require you to keep track of the parent
struct.  You might try to

- get strlen of current entry accpath, n
- get strlen of parent entry accpath, m
- malloc a buffer of size n + 1 + m
- sprintf parent, '/', current to buffer

But the parent entry's accpath may not be
NULL-terminated, thus strlen(3) giving you a bogus
result.

> 2.What does the fts_accpath represent for? I tracked
> the FTS structure and found it always equal
> fts_name.

fts_accpath will be different depending on whether
you've specified FTS_NOCHDIR or not.  With
FTS_NOCHDIR, fts_accpath will look like fts_path,
without, fts_accpath will look like fts_name.

I haven't verified, but I could imagine that results
will also differ based on whether you're following
symlinks and the hierarchy includes symlinks to
directories whereby directory traversal may encounter
the same subdir via multiple paths.

-Jan
_______________________________________________
cs631apue mailing list
cs631apue at lists.stevens.edu
https://lists.stevens.edu/mailman/listinfo/cs631apue

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.stevens.edu/pipermail/cs631apue/attachments/20191009/a3ca1618/attachment-0001.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: A1859320D69F46BE8605CCE90047ACDF.png
Type: image/png
Size: 159 bytes
Desc: A1859320D69F46BE8605CCE90047ACDF.png
URL: <http://lists.stevens.edu/pipermail/cs631apue/attachments/20191009/a3ca1618/attachment-0001.png>


More information about the cs631apue mailing list