Skip to contentSkip to conversation

New: Incorrect fts_pathlen in fts(3) man page

Bug 216275 [email protected] 1 participant 3 messages Jul 23, 2022 – Jul 24, 2022 Man-pages: manual pages for Linux -- Sections 2, 3, 4, 5, and 7

lore
Share & tools
lore
#0 lore raw

https://bugzilla.kernel.org/show_bug.cgi?id=216275

Bug ID: 216275
Summary: Incorrect fts_pathlen in fts(3) man page
Product: Documentation
Version: unspecified
Hardware: All
OS: Linux
Status: NEW
Severity: normal
Priority: P1
Component: man-pages
Assignee: [email protected]
Reporter: [email protected]
Regression: No

In the fts(3) man page, fts_pathlen is described as:

```
short           fts_pathlen;  /* strlen(fts_path) +
                                 strlen(fts_name) */
```

This was changed from strlen(fts_path) in the following commit:

<https://git.kernel.org/pub/scm/docs/man-pages/man-pages.git/commit/?id=10b6adae8ac6026b2bb69bc66d1e0fcb37c81696>

This is only correct when fts_children() is called, however. When only fts_read() is used, the original fts_pathlen = strlen(fts_path) is correct. This feels like a glibc bug to me, seeing as the original behaviour is listed in the glibc source:

<https://sourceware.org/git/?p=glibc.git;a=blob;f=io/fts.h;h=e00575d154b1457ddd02a0ab67a4a5e3b10237c0;hb=HEAD#l98>

Assuming that glibc won't change, I think the man page should document both behaviours.

The following program demonstrates the difference in behaviour:

```
#include <fts.h>
#include <pwd.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

void test_fts_children(char *paths[])
{
        FTS* fts = fts_open(paths, FTS_LOGICAL, NULL);
        FTSENT* ftsent = fts_read(fts);
        FTSENT* child = fts_children(fts, 0);
        while (child != NULL) {
                printf("    %s %s %d %lu\n", child->fts_path, child->fts_name,
                                child->fts_pathlen, strlen(child->fts_path));
                child = child->fts_link;
        }
        fts_close(fts);
}

void test_fts_read(char *paths[])
{
        FTS* fts = fts_open(paths, FTS_LOGICAL, NULL);
        FTSENT* ftsent = fts_read(fts);
        for (; ftsent != NULL; ftsent = fts_read(fts)) {
                /* Don't go any deeper */
                if (ftsent->fts_level > 0 && (ftsent->fts_info & FTS_D)) {
                        fts_set(fts, ftsent, FTS_SKIP);
                        continue;
                }
                printf("    %s %s %d %lu\n", ftsent->fts_path,
ftsent->fts_name,
                                ftsent->fts_pathlen, strlen(ftsent->fts_path));
        }
        fts_close(fts);
}

int main() {
        struct passwd *pwd_entry = getpwuid(getuid());
        char *paths[] = {pwd_entry->pw_dir, NULL};
        printf("fts_children:\n");
        test_fts_children(paths);
        printf("\nfts_read:\n");
        test_fts_read(paths);
        return 0;
}
```

Sample output:

```
fts_children:
    /home/phil/ Templates 20 11
    /home/phil/ bin 14 11
    /home/phil/ Pictures 19 11
    /home/phil/ Public 17 11
    /home/phil/ Videos 17 11
    /home/phil/ Downloads 20 11
    /home/phil/ Music 16 11
    /home/phil/ Desktop 18 11
    /home/phil/ Documents 20 11

fts_read:
    /home/phil phil 10 10
    /home/phil/Templates Templates 20 20
    /home/phil/bin bin 14 14
    /home/phil/Pictures Pictures 19 19
    /home/phil/Public Public 17 17
    /home/phil/Videos Videos 17 17
    /home/phil/Downloads Downloads 20 20
    /home/phil/Music Music 16 16
    /home/phil/Desktop Desktop 18 18
    /home/phil/Documents Documents 20 20
    /home/phil phil 10 10
```
Signature · 4 lines
You may reply to this email to add a comment.

You are receiving this mail because:
You are watching the assignee of the bug.
#1 lore raw

[Bug 216275] Incorrect fts_pathlen in fts(3) man page

https://bugzilla.kernel.org/show_bug.cgi?id=216275

--- Comment #1 from Philip Jones ([email protected]) ---
Another minor discrepancy I forgot to mention: the man page documents both fts_pathlen and fts_namelen as having type short, but the glibc source assigns type unsigned short to each.

Signature · 4 lines
You may reply to this email to add a comment.

You are receiving this mail because:
You are watching the assignee of the bug.
#2 lore raw

[Bug 216275] Incorrect fts_pathlen in fts(3) man page

In reply to [email protected]

https://bugzilla.kernel.org/show_bug.cgi?id=216275

--- Comment #2 from Alejandro Colomar (man-pages) ([email protected]) --- Hi Philip,

Quoted 33 lines · On 7/23/22 14:56, [email protected] wrote:

https://bugzilla.kernel.org/show_bug.cgi?id=216275

Bug ID: 216275
Summary: Incorrect fts_pathlen in fts(3) man page
Product: Documentation
Version: unspecified
Hardware: All
OS: Linux
Status: NEW
Severity: normal
Priority: P1
Component: man-pages
Assignee: [email protected]
Reporter: [email protected]
Regression: No

In the fts(3) man page, fts_pathlen is described as:

```
short           fts_pathlen;  /* strlen(fts_path) +
                                  strlen(fts_name) */
```

This was changed from strlen(fts_path) in the following commit:

<https://git.kernel.org/pub/scm/docs/man-pages/man-pages.git/commit/?id=10b6adae8ac6026b2bb69bc66d1e0fcb37c81696>

This is only correct when fts_children() is called, however. When only fts_read() is used, the original fts_pathlen = strlen(fts_path) is correct. This feels like a glibc bug to me, seeing as the original behaviour is listed in the glibc source:

Quoted 4 lines

<https://sourceware.org/git/?p=glibc.git;a=blob;f=io/fts.h;h=e00575d154b1457ddd02a0ab67a4a5e3b10237c0;hb=HEAD#l98>

Assuming that glibc won't change, I think the man page should document both behaviours.

I replied CCing the glibc list, in case someone from there wants to comment.

Quoted 72 lines

The following program demonstrates the difference in behaviour:

```
#include <fts.h>
#include <pwd.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

void test_fts_children(char *paths[])
{
         FTS* fts = fts_open(paths, FTS_LOGICAL, NULL);
         FTSENT* ftsent = fts_read(fts);
         FTSENT* child = fts_children(fts, 0);
         while (child != NULL) {
                 printf("    %s %s %d %lu\n", child->fts_path,
                 child->fts_name,
                                 child->fts_pathlen,
                                 strlen(child->fts_path));
                 child = child->fts_link;
         }
         fts_close(fts);
}

void test_fts_read(char *paths[])
{
         FTS* fts = fts_open(paths, FTS_LOGICAL, NULL);
         FTSENT* ftsent = fts_read(fts);
         for (; ftsent != NULL; ftsent = fts_read(fts)) {
                 /* Don't go any deeper */
                 if (ftsent->fts_level > 0 && (ftsent->fts_info & FTS_D)) {
                         fts_set(fts, ftsent, FTS_SKIP);
                         continue;
                 }
                 printf("    %s %s %d %lu\n", ftsent->fts_path,
ftsent->fts_name,
                                 ftsent->fts_pathlen,
                                 strlen(ftsent->fts_path));
         }
         fts_close(fts);
}

int main() {
         struct passwd *pwd_entry = getpwuid(getuid());
         char *paths[] = {pwd_entry->pw_dir, NULL};
         printf("fts_children:\n");
         test_fts_children(paths);
         printf("\nfts_read:\n");
         test_fts_read(paths);
         return 0;
}
```

Sample output:

```
fts_children:
     /home/phil/ Templates 20 11
     /home/phil/ bin 14 11
     /home/phil/ Pictures 19 11
     /home/phil/ Public 17 11
     /home/phil/ Videos 17 11
     /home/phil/ Downloads 20 11
     /home/phil/ Music 16 11
     /home/phil/ Desktop 18 11
     /home/phil/ Documents 20 11

fts_read:
     /home/phil phil 10 10
     /home/phil/Templates Templates 20 20
     /home/phil/bin bin 14 14
     /home/phil/Pictures Pictures 19 19
Quoted 9 lines
     /home/phil/Public Public 17 17
     /home/phil/Videos Videos 17 17
     /home/phil/Downloads Downloads 20 20
     /home/phil/Music Music 16 16
     /home/phil/Desktop Desktop 18 18
     /home/phil/Documents Documents 20 20
     /home/phil phil 10 10
```

Thanks,

Alex

Signature · 4 lines
You may reply to this email to add a comment.

You are receiving this mail because:
You are watching the assignee of the bug.