View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0000161 | 1003.1(2008)/Issue 7 | Shell and Utilities | public | 2009-10-03 23:17 | 2013-04-16 13:06 |
Reporter | eblake | Assigned To | ajosey | ||
Priority | normal | Severity | Objection | Type | Error |
Status | Closed | Resolution | Accepted As Marked | ||
Name | Eric Blake | ||||
Organization | N/A | ||||
User Reference | ebb.mkdir | ||||
Section | mkdir | ||||
Page Number | 2937 | ||||
Line Number | 96644 | ||||
Interp Status | Approved | ||||
Final Accepted Text | See 0000161:0000247 | ||||
Summary | 0000161: mkdir -p through dangling symlink | ||||
Description | The description of mkdir -p in terms of a shell script is incorrect in the presence of whitespace in the directory name. In particular, consider: mkdir -p "$(printf 'a b\n'/c')" which in practice creates the parent directory with a trailing newline, but which according to the spec effectively recursively calls mkdir(1) with two arguments and no newline, instead of a single argument. Furthermore, it seems inconsistent that: ln -s dir dangling mkdir -p dangling/sub is required to fail (since it recurses to 'mkdir -p dangling', but that must fail with EEXIST), while mkdir -p dangling/ is required to succeed (the recursion sees $(dirname dangling/) which is ".", and that exists; next the code has the same effect as mkdir("dangling/") which is required to follow through the symlink per mkdir(2)). (It doesn't help that GNU/Linux mkdir(2) fails with EEXIST when dealing with a symlink with trailing slash, in violation of the standard as written). Correctly describing the dirname operation in shell without losing a trailing newline gets rather lengthy. Providing a trailing slash to the recursive mkdir call solves the problem of stripping trailing newline. Furthermore, requiring a trailing slash on all intermediate components will give more predictable behavior, where a directory can be created through a dangling symlink. | ||||
Desired Action | Replace lines 96644-5: mkdir −p −m $(umask −S),u+wx $(dirname dir) && mkdir [−m mode] dir with: mkdir −p −m $(umask −S),u+wx \ "$(dirname "dir" | head -n -1; printf /)" && mkdir [−m mode] "dir" | ||||
Tags | tc1-2008 |
parent of | 0000682 | Applied | Online Pubs | html rendition of 'mkdir -p' is missing important text |
|
Typo in the Description: mkdir -p "$(printf 'a b\n'/c')" should be: mkdir -p "$(printf 'a b\n/c')" |
|
The desired action also has a typo; 'head -c -1' was intended instead of 'head -n -1'. But unfortunately, even that is not portable (unlike the counterpart of 'tail -c -1'). For that matter, the only portable means I could find for discarding only the trailing newline involves even more processes, including running the dirname command twice: mkdir −p −m $(umask −S),u+wx "$(dirname "dir" | dd bs=1 count=$(($(dirname "dir" | wc -c) - 1)) 2>/dev/null; echo /)" && mkdir [−m mode] "dir" |
|
Interpretation response ------------------------ The standard states the requirements for mkdir -p, and conforming implementations must conform to this. However, concerns have been raised about this which are being referred to the sponsor. Rationale: ------------- None. Notes to the Editor (not part of this interpretation): ------------------------------------------------------- Replace the description of -p with: -p Create any missing intermediate pathname components. For each dir operand that does not name an existing directory, before performing the actions described in the DESCRIPTION above the mkdir utility shall create any pathname components of the path prefix of dir that do not name an existing directory by performing actions equivalent to first calling the mkdir() function with the following arguments: 1. A pathname naming the missing pathname component, ending with a trailing <slash> character, as the path argument. 2. The value zero as the mode argument. and then calling the chmod() function with the following arguments: 1. The same path argument as in the mkdir() call. 2. The value (S_IWUSR|S_IXUSR|~filemask)&0777 as the mode argument, where filemask is the file mode creation mask of the process (see [xref to umask()]). Each dir operand that names an existing directory shall be ignored without error. |
Date Modified | Username | Field | Change |
---|---|---|---|
2009-10-03 23:17 | eblake | New Issue | |
2009-10-03 23:17 | eblake | Status | New => Under Review |
2009-10-03 23:17 | eblake | Assigned To | => ajosey |
2009-10-03 23:17 | eblake | Name | => Eric Blake |
2009-10-03 23:17 | eblake | Organization | => N/A |
2009-10-03 23:17 | eblake | User Reference | => ebb.mkdir |
2009-10-03 23:17 | eblake | Section | => mkdir |
2009-10-03 23:17 | eblake | Page Number | => 2937 |
2009-10-03 23:17 | eblake | Line Number | => 96644 |
2009-10-03 23:24 | eblake | Note Added: 0000245 | |
2009-10-03 23:38 | eblake | Note Added: 0000246 | |
2009-10-05 09:59 | geoffclare | Note Added: 0000247 | |
2009-10-05 10:00 | geoffclare | Note Edited: 0000247 | |
2009-10-05 10:01 | geoffclare | Note Edited: 0000247 | |
2009-10-08 16:22 | nick | Interp Status | => Pending |
2009-10-08 16:22 | nick | Final Accepted Text | => See 0000161:0000247 |
2009-10-08 16:22 | nick | Status | Under Review => Interpretation Required |
2009-10-08 16:22 | nick | Resolution | Open => Accepted As Marked |
2009-10-08 16:26 | nick | Note Edited: 0000247 | |
2009-10-09 08:12 | geoffclare | Note Edited: 0000247 | |
2009-11-07 07:20 | ajosey | Interp Status | Pending => Proposed |
2009-12-08 10:00 | ajosey | Interp Status | Proposed => Approved |
2010-09-21 11:25 | geoffclare | Tag Attached: tc1-2008 | |
2013-04-16 13:06 | ajosey | Status | Interpretation Required => Closed |
2013-04-23 17:52 | eblake | Relationship added | parent of 0000682 |