Subject: bug#24730: rmdir/mkdir error(s) and/or not working "reciprocally" w/each other

From: Linda Walsh <[email-masked]>
Date: Tue, 18 Oct 2016 14:35:55 -0700

Assaf Gordon wrote:
> Hello,
> 
> Before deciding on the wording, it's worth nothing that the errors and 
> reasons for the errors are different between mkdir and rmdir, and 
> between the two cases.
> 
> On 10/18/2016 03:49 PM, L. A. Walsh wrote:
> 
>> mkdir -p ./a/b/c   # no error
>> rmdir -p ./a/b/c   # get error msg, but a,b,c removed.
> 
> The error in this case (at least on Linux) is "Invalid Argument",
> because 'rmdir .' is invalid and rejected by the kernel (EINVAL)
> while 'mkdir .' returns EEXISTS - and '-p' specifically instruct it to 
> silently ignore EEXIST.
----
	I see... so in ".a/b/c", a,b,c are removed, but the error
comes in "."?

>     $ strace -e rmdir rmdir .
>     rmdir(".")                              = -1 EINVAL (Invalid argument)
>     rmdir: failed to remove '.': Invalid argument
> 
> This is also mandated by posix:
>    http://pubs.opengroup.org/onlinepubs/9699919799/functions/rmdir.html
>    "If the path argument refers to a path whose final component is 
> either dot or dot-dot, rmdir() shall fail."
---
	Ok, but is "-p" a posix switch in mkdir or rmdir?
If not, wouldn't the behavior be undefined?

>> mkdir -p a/../b      # no error
>> rmdir -p a/../b      # error, but a & b removed
> 
> At least on my system (Linux kernel 3.13), 'a' is not removed in the 
> above example,
> and the error is due to non-empty directory:
---
	Right..., my bad, only checked 'b'. (*duh*)

> Note that coreutils' mkdir contains an optimization not to try and make 
> '..' as it is
> guaranteed to exist (implemented in gnulib's mkancesdirs.c).
---
	Right, same when rmdir traverses, when it hits "..", that
must exist (even in '/').  

> However, by definition, when 'rmdir' traverses the directories on the 
> given path,
> the directory 'a/..' is not empty (it contains 'a') - so this must fail.
----
	with "-p"?  Am talking about the case where you 
create a dir with "mkdir -p "$dirname"
and later, rmdir -p "$dirname" (where dirname is passed as a parameter, but
is not user-input).

> 
> 
> If you want to 'rmdir' to silently ignore non-empty directories,
> there's a gnu extension option of 'rmdir --ignore-fail-on-non-empty':
> 
>     $ strace -e rmdir rmdir --ignore-fail-on-non-empty -p a/../b
>     rmdir("a/../b")                         = 0
>     rmdir("a/..")                           = -1 ENOTEMPTY (Directory 
> not empty)
>     +++ exited with 0 +++
> 
> But note that this causes 'rmdir' to stop upon first failure, and 'a' is 
> still not removed.
> 
>> ======> seems to be best wording & solution:
>>
>> "mkdir -p", it seems should really be restated to:
>>
>>    follow given path and make directories as possible"
>>
>> then "rmdir -p" could be
>>
>>    "follow given path and delete directories if empty"
> 
> This does not accurately reflect how 'rmdir' is currently implemented.
> A more accurate description is "follow given path and delete 
> directories, until the first encountered failure".
----
	Right, but am trying to get rmdir to be a useful
"opposite" to a "mkdir" -- at least w/r/t "-p"...

> If you want a behavior where 'rmdir' will continue beyond the first failure
> and try to delete all directories in the given path (e.g. a/b/c in the 
> example above),
> then it sounds like a new feature request, and a non-standard behavior 
> which will be a gnu extension (and also quite confusing behavior, IMHO).
---
	Yeah -- new feature, but confusing?

I think the fact that you can mkdir -p XXX and later  canNOT
rmdir -p XXX, is quite confusing behavior...

But is -p's behavior in mkdir and rmdir mandated by POSIX?