On 30/09/15 09:30 -0600, Martin Sebor wrote: >On 09/30/2015 05:01 AM, Jonathan Wakely wrote: >>On 29/09/15 12:54 -0600, Martin Sebor wrote: >>>On 09/29/2015 05:37 AM, Jonathan Wakely wrote: >>>>POSIX says that dirent::d_name has an unspecified length, so calls to >>>>readdir_r must pass a buffer with enough trailing space for >>>>{NAME_MAX}+1 characters. I wasn't doing that, which works OK on >>>>GNU/Linux and BSD where d_name is a large array, but fails on Solaris >>>>32-bit. >>>> >>>>This uses pathconf to get NAME_MAX and allocates a buffer. >>>> >>>>Tested powerpc64le-linux and x86_64-dragonfly4.1, I'm going to commit >>>>this to trunk today (and backport all the filesystem fixes to >>>>gcc-5-branch). >>> >>>Calling pathconf is only necessary when _POSIX_NO_TRUNC is zero >>>which I think exists mainly for legacy file systems. Otherwise, >>>it's safe to use NAME_MAX instead. Avoiding the call to pathconf >> >>Oh, nice. I was using NAME_MAX originally but the glibc readdir_r(3) >>man-page has an example using pathconf and says that should be used, >>so I went down that route. > >GLIBC pathconf calls statfs to get the NAME_MAX value from the OS, >so there's some chance that some unusual file system will define >it as greater than 255. I tested all those on my Fedora PC and on >my RHEL 7.2 powerpc64le box and didn't find one. > >There also isn't one in the Wikipedia comparison of file systems: > https://en.wikipedia.org/wiki/Comparison_of_file_systems > >But to be 100% safe, we would need to call pathconf if readdir >failed due to truncation. > >>Can we be sure NAME_MAX will never be too big for the stack? > >When it's defined I think it's probably safe in practice but not >guaranteed. Also, like all of these constants, it's not >guaranteed to be defined at all when the implementation doesn't >impose a limit. I believe AIX is one implementation that doesn't >define it. So some preprocessor magic will be required to deal >with that. OK, latest version attached. This defines a helper type, dirent_buffer, which either contains aligned_union or unique_ptr depending on whether NAME_MAX is defined or whether we have to use pathconf at run-time. The dirent_buffer is created as part of the directory_iterator or recursive_directory_iterator internals, so only once per iterator, and shared between copies of that iterator. When NAME_MAX is defined there is no second allocation, we just allocate a bit more space. Tested powerpc64le-linux and x86_64-dragonfly. I've started a build on powerpc-aix too but I don't know when the tests for that will finish.