Why does it say "We must not include limits.h!" in dirent.h?
Asked Answered
S

3

6

When we include <dirent.h> and <limits.h> to a c file, dirent structs' d_name variable shows We must not include limits.h! in the variable description in the ide. When I look at the file /usr/include/x86_64-linux-gnu/bits/dirent.h it contains the following code piece.

...
struct dirent
  {
#ifndef __USE_FILE_OFFSET64
    __ino_t d_ino;
    __off_t d_off;
#else
    __ino64_t d_ino;
    __off64_t d_off;
#endif
    unsigned short int d_reclen;
    unsigned char d_type;
    char d_name[256];       /* We must not include limits.h! */
  };
...

My question is why we must not include limits.h. I've searched online, but I couldn't find any satisfying answer.

Streeter answered 16/10, 2019 at 20:33 Comment(5)
I think its a sarcasm, like why should we include limits.h and use an appropriate value instead of hardcoding 256 =)Whist
@unlut: It's not sarcasm.Schultz
it seems that filename length is universally 255 max: serverfault.com/a/9548Elevator
@Jean-FrançoisFabre Have a look at Reiser4... ;)Efren
of course, it's not guaranteed, but looks like it's enough for most names so the length stuck so indexing may hold on an unsigned char size? @Ctx. We can only guess hereElevator
S
5

Each standard header has a specification for what it exposes or may expose. dirent.h exposes struct dirent, DIR, and the relevant functions, and reserves names starting with d_. Some headers are also permitted but not required to expose things exposed by certain other headers; dirent.h is not one of these. So indirectly including limits.h would be a violation of the namespace and would break conforming programs that assume they can use names that limits.h would expose for their own identifiers.

Schultz answered 16/10, 2019 at 20:42 Comment(16)
This sounds plausible, but do you have any reference for these claims?Efren
probably because there's a max file name len in limits.hElevator
I checked limits.h and included files and could not find a max filename len, though. But maybe it's somewhere and I didn't find it.Elevator
@Jean-FrançoisFabre If you are using linux there is NAME_MAX in /usr/include/linux/limits.h NAME_MAX, but probably not cross-platform.Whist
that would explain a lot. And anyway, the programmers know that the limit is 256. They just have to adapt it if the value changes in limits.h. After all a set of include files is a coherent whole. Maintanability issues aren't the priorityElevator
I think I finally understand what you mean, but can you show an example why would you want to use same name with a standard definition in your own definition?Whist
@Whist NAME_MAX is not guaranteed to be defined. Per POSIX <limits.h>: "A definition of one of the values shall be omitted from the <limits.h> header on specific implementations where the corresponding value is equal to or greater than the stated minimum, but where the value can vary depending on the file to which it is applied. ... NAME_MAX..."Lainelainey
@AndrewHenle Your quote does not explain why I can't include limits.h in dirent.h, or if does but I didn't understand can you explain?Whist
@unlut: Why it can't is covered here: pubs.opengroup.org/onlinepubs/9699919799/functions/…Schultz
@Whist If NAME_MAX can't be guaranteed to be defined, there's no point in including limits.h.Lainelainey
@AndrewHenle If NAME_MAX if defined you can use it, and if its not you can fall back to magic number 256.Whist
@Whist Well, as Linux supports filesystems with different maximum pathname lengths, NAME_MAX being defined would be a defect that shouldn't be counted on. Again - no point.Lainelainey
@R.. Thank you for the reference, does C standard also guarantee this or is this just a POSIX thing?Whist
@Whist NAME_MAX does not exist in the C standard.Lainelainey
@AndrewHenle I am not asking whether NAME_MAX is defined or not, but whether including a C header file must not define something reserved that belongs to another C header file.Whist
@R.. I accepted this answer as correct. I am using VS Code as IDE. When I include only dirent.h, the helping window shows only the details of d_name when I hover the mouse on it. But when I also include limits.h, it shows We must not include limits.h! comment. I thought there is a header conflict and I shouldn't include limits.h. Now I understand why. I have never thought VS Code is that smart. Thank you.Streeter
O
1

The maximum number of characters in a file name (component) is NAME_MAX. The number 256 equals NAME_MAX + 1 (or is the maximum of that on any targeted system). Naturally using a bare magic number like this is generally frowned upon.

But that macro is defined only in <limits.h>. It cannot be included in <dirent.h> because the latter is not supposed to define any of these macros.

Overt answered 16/10, 2019 at 21:0 Comment(1)
And as I noted above, POSIX specifies that NAME_MAX shall not be defined should there not be a fixed maximum file name length. And Linux supports filesystems that have different filename lengths...Lainelainey
L
1

Additionally, values such as NAME_MAX may not be guaranteed to be defined.

Per POSIX <limits.h>(bolding mine):

The values in the following list may be constants within an implementation or may vary from one pathname to another. For example, file systems or directories may have different characteristics.

A definition of one of the values shall be omitted from the <limits.h> header on specific implementations where the corresponding value is equal to or greater than the stated minimum, but where the value can vary depending on the file to which it is applied. The actual value supported for a specific pathname shall be provided by the pathconf() function.

...

{PATH_MAX}

Maximum number of bytes in a pathname, including the terminating null character.

Minimum Acceptable Value: {_POSIX_PATH_MAX}

Minimum Acceptable Value: {_XOPEN_PATH_MAX}

As noted in the comments, Linux supports filesystems with different maximum pathname lengths.

Lainelainey answered 16/10, 2019 at 21:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.