home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / std_unix / volume.17 / text0069.txt < prev    next >
Encoding:
Internet Message Format  |  1990-01-06  |  5.4 KB

  1. From: Doug Gwyn <uunet!smoke.brl.mil!gwyn>
  2.  
  3. In article <448@longway.TIC.COM> dmr@research.att.com (Dennis Ritchie) writes:
  4. >I wish Gwyn et. al had sounded a bit more embarrassed about using
  5. >`char d_name[1]' in struct dirent.
  6.  
  7. Here is the line in question taken directly from my PD dirent implementation:
  8.     char        d_name[1];    /* name of file */    /* non-ANSI */
  9. You will note that I'm well aware that a trick is being used here.
  10.  
  11. I don't like such tricks either.  The problem is, the alternatives
  12. were all worse:
  13.     char    *d_name;    /* programs need to know whether d_name
  14.                    specifies an array or not, due to a
  15.                    generic C botch in using array names;
  16.                    P1003 used to be ambiguous about this
  17.                    but finally required it to be an array */
  18.     char    d_name[HUGE_NUMBER];    /* valid, but wastes a lot of space */
  19.     char    d_name[0];    /* worse than [1] according to ANSI C */
  20.     char    d_name[];    /* almost certain to cause a diagnostic */
  21.  
  22. >There is no such type as char[], and `char d_name[]' may not appear
  23. >in a structure, and if the declaration is `char d_name[1]' then
  24. >you may not refer to d_name[i] when i>1.
  25.  
  26. Certainly it is unportable usage, i.e. not guaranteed to work
  27. by the C language specification.  However, there is a large body
  28. of existing C code (typically implementing network protocols) that
  29. relies on exactly this trick, precisely because there is no really
  30. good alternative.  I have yet to hear of a production UNIX system
  31. where this trick fails.  (Perhaps 10th Edition UNIX is one?)
  32.  
  33. Probably what I really should have done was to parameterize the "1":
  34.     char    d_name[1+_DNAME_LEN];    /* _DNAME_LEN=0 if you can,
  35.                        _DNAME_LEN=PATH_MAX otherwise */
  36. That would allow the dirent package installer a quick solution for
  37. C environments that are fussier about this than the typical UNIX ones.
  38. I may do this for future releases of my package.
  39.  
  40. >I don't have the POSIX wording at hand, but if it forbids
  41. >`struct dirent d = *readdir(dp)' then it is flaky.
  42.  
  43. It says:
  44.     The readdir() function returns a pointer to an object of type
  45.     struct dirent that includes the member:
  46.  
  47.         Member    Member
  48.          Type     Name        Description
  49.         ______    ______    ________________________
  50.         char[]    d_name    Null-terminated filename
  51.  
  52.     The character array d_name is of unspecified size, but the
  53.     number of bytes preceding the terminating null character
  54.     shall not exceed {NAME_MAX}.
  55.  
  56. I believe my implementation meets these specifications, taken
  57. literally.
  58.  
  59. At one time, the description of readdir() contained a warning about
  60. copying struct dirents, but by the time of the final Std 1003.1 the
  61. entire section had been rewritten and this got lost in the shuffle.
  62. I think some other unwanted changes were introduced too, but at the
  63. moment I can't recall what they were.  (We also have to keep beating
  64. down attempts to legislate support for seekdir() and telldir().)
  65.  
  66. Anyway, the whole point of the words "unspecified size" really was to
  67. permit implementations to use the [1] trick so they could allocate
  68. a relatively small struct_dirent+secret_extension if the C compiler
  69. permitted it.  Otherwise either NAME_MAX+1 or some other defined
  70. implementation constant would have been specified in Std 1003.1
  71. (as for c_cc[NCCS]).
  72.  
  73. I would have preferred char*d_name; however, that would be as hard
  74. for an application to copy as a struct_dirent+secret_extension.
  75.  
  76. Certainly
  77.     char    d_name[1+PATH_MAX];    /* use actual value for PATH_MAX */
  78. is a legal and portable declaration for d_name that meets the POSIX
  79. specs.  I happen not to like it because PATH_MAX is potentially
  80. unbounded in an ideal networked universe, and always allocating big
  81. chunks of space of which a tiny portion is used bothers me more than
  82. this particular well-known implementation-specific cheat.
  83.  
  84. My advice for applications using dirent facilities is NOT to assume
  85. that a literal copy of the struct dirent is good for anything.  If
  86. you need to keep the entry string around, you should allocate storage
  87. for it based on its strlen().  (Since the other members of a struct
  88. dirent are unspecified, you can't use them anyway in a POSIX-portable
  89. application.)
  90.  
  91. There are numerous related issues with IEEE Std 1003.1 that we could
  92. get into.  For example, it is not stated whether or not it is safe
  93. for an application to use a copy of a struct dirent or of several other
  94. system data structures where the struct has a different address from
  95. the one that the allocator (e.g. readdir()) assigned.  (Presumably an
  96. implementation could depend on the object residing in a known place.)
  97. Also, since there are no constraints on other struct dirent member
  98. names, the traditional practice of using d_* for these is unsafe;
  99. instead the "always reserved for the implementation" name space must
  100. be used to avoid problems like
  101.     #define d_namlen 42
  102.     #include <dirent.h>
  103. I don't know if there's much point into going into such problems in
  104. more detail.  My personal feeling is that 1003.1 serves ONE useful
  105. purpose:  By specifying it in OS procurements (in ADDITION to more
  106. useful specs such as ANSI/ISO C and SVID), one can obtain portable
  107. interfaces for some otherwise problematic areas such as reliable
  108. signals and terminal modes.  I wish I could say the same about other
  109. 1003.* standards-in-progress, but I cannot.  1003.2 in particular
  110. seems to be legislating an utterly horrible environment instead of
  111. specifying cleanly the UNIX utility subset of interest to portable
  112. applications.  You can bet I'm not going to include it in procurement
  113. specifications.
  114.  
  115. Volume-Number: Volume 17, Number 78
  116.  
  117.  
  118.