dd new iflag= oflag= flags directory, nolinks

2006-03-06 Thread Paul Eggert
I wanted to use dd iflag=directory (to test whether a file is a
directory, atomically), and noticed that dd didn't have it.  The use
was a fairly obscure one (just testing the O_DIRECTORY flag) but I
figured dd should support all the flags.  I noticed also that dd
doesn't support the Solaris 10 O_NOLINKS option.  So I installed this:

2006-03-05  Paul Eggert  <[EMAIL PROTECTED]>

* doc/coreutils.texi (dd invocation): New flags directory, nolinks.
Alphabetize nofollow.
* src/dd.c (flags, usage): New flags directory, nolinks.
* src/system.h (O_NOLINKS): Define to 0 if not already defined.

Index: doc/coreutils.texi
===
RCS file: /fetish/cu/doc/coreutils.texi,v
retrieving revision 1.315
diff -p -u -r1.315 coreutils.texi
--- doc/coreutils.texi  27 Feb 2006 10:47:23 -  1.315
+++ doc/coreutils.texi  6 Mar 2006 07:15:27 -
@@ -7003,7 +7003,8 @@ argument(s).  (No spaces around any comm
 Access the output file using the flags specified by the @var{flag}
 argument(s).  (No spaces around any comma(s).)
 
-Flags:
+Here are the flags.  Not every flag is supported on every operating
+system.
 
 @table @samp
 
@@ -7019,6 +7020,13 @@ contents of the file.  This flag makes s
 @cindex direct I/O
 Use direct I/O for data, avoiding the buffer cache.
 
[EMAIL PROTECTED] directory
[EMAIL PROTECTED] directory
[EMAIL PROTECTED] directory I/O
+
+Fail unless the file is a directory.  Most operating systems do not
+allow I/O to a directory, so this flag has limited utility.
+
 @item dsync
 @opindex dsync
 @cindex synchronized data reads
@@ -7043,11 +7051,6 @@ Use non-blocking I/O.
 @cindex access time
 Do not update the file's access time.
 
[EMAIL PROTECTED] nofollow
[EMAIL PROTECTED] nofollow
[EMAIL PROTECTED] symbolic links, following
-Do not follow symbolic links.
-
 @item noctty
 @opindex noctty
 @cindex controlling terminal
@@ -7056,6 +7059,16 @@ This has no effect when the file is not 
 On many hosts (e.g., @acronym{GNU}/Linux hosts), this option has no effect
 at all.
 
[EMAIL PROTECTED] nofollow
[EMAIL PROTECTED] nofollow
[EMAIL PROTECTED] symbolic links, following
+Do not follow symbolic links.
+
[EMAIL PROTECTED] nolinks
[EMAIL PROTECTED] nolinks
[EMAIL PROTECTED] hard links
+Fail if the file has multiple hard links.
+
 @item binary
 @opindex binary
 @cindex binary I/O
Index: src/dd.c
===
RCS file: /fetish/cu/src/dd.c,v
retrieving revision 1.190
diff -p -u -r1.190 dd.c
--- src/dd.c7 Dec 2005 21:12:12 -   1.190
+++ src/dd.c6 Mar 2006 07:15:27 -
@@ -263,10 +263,12 @@ static struct symbol_value const flags[]
   {"append",   O_APPEND},
   {"binary",   O_BINARY},
   {"direct",   O_DIRECT},
+  {"directory",O_DIRECTORY},
   {"dsync",O_DSYNC},
   {"noatime",  O_NOATIME},
   {"noctty",   O_NOCTTY},
   {"nofollow", O_NOFOLLOW},
+  {"nolinks",  O_NOLINKS},
   {"nonblock", O_NONBLOCK},
   {"sync", O_SYNC},
   {"text", O_TEXT},
@@ -460,6 +462,8 @@ Each FLAG symbol may be:\n\
 "), stdout);
   if (O_DIRECT)
fputs (_("  directuse direct I/O for data\n"), stdout);
+  if (O_DIRECTORY)
+   fputs (_("  directory fail unless a directory\n"), stdout);
   if (O_DSYNC)
fputs (_("  dsync use synchronized I/O for data\n"), stdout);
   if (O_SYNC)
@@ -468,11 +472,13 @@ Each FLAG symbol may be:\n\
fputs (_("  nonblock  use non-blocking I/O\n"), stdout);
   if (O_NOATIME)
fputs (_("  noatime   do not update access time\n"), stdout);
-  if (O_NOFOLLOW)
-   fputs (_("  nofollow  do not follow symlinks\n"), stdout);
   if (O_NOCTTY)
fputs (_("  nocttydo not assign controlling terminal from file\n"),
   stdout);
+  if (O_NOFOLLOW)
+   fputs (_("  nofollow  do not follow symlinks\n"), stdout);
+  if (O_NOLINKS)
+   fputs (_("  nolinks   fail if multiply-linked\n"), stdout);
   if (O_BINARY)
fputs (_("  binaryuse binary I/O for data\n"), stdout);
   if (O_TEXT)
Index: src/system.h
===
RCS file: /fetish/cu/src/system.h,v
retrieving revision 1.143
diff -p -u -r1.143 system.h
--- src/system.h26 Feb 2006 10:03:17 -  1.143
+++ src/system.h6 Mar 2006 07:15:27 -
@@ -193,6 +193,10 @@ initialize_exit_failure (int status)
 # define O_NOFOLLOW 0
 #endif
 
+#if !defined O_NOLINKS
+# define O_NOLINKS 0
+#endif
+
 #if !defined O_RSYNC
 # define O_RSYNC 0
 #endif


___
Bug-coreutils mailing list
Bug-coreutils@gnu.org
http://lists.gnu.org/mailman/listinfo/bug-coreutils


Re: dd new iflag= oflag= flags directory, nolinks

2006-03-07 Thread Phillip Susi
I'm confused.  You can't open() and write() to a directory, so how does 
it make any sense to ask dd to set O_DIRECTORY?


Paul Eggert wrote:

I wanted to use dd iflag=directory (to test whether a file is a
directory, atomically), and noticed that dd didn't have it.  The use
was a fairly obscure one (just testing the O_DIRECTORY flag) but I
figured dd should support all the flags.  I noticed also that dd
doesn't support the Solaris 10 O_NOLINKS option.  So I installed this:

2006-03-05  Paul Eggert  <[EMAIL PROTECTED]>

* doc/coreutils.texi (dd invocation): New flags directory, nolinks.
Alphabetize nofollow.
* src/dd.c (flags, usage): New flags directory, nolinks.
* src/system.h (O_NOLINKS): Define to 0 if not already defined.

Index: doc/coreutils.texi
===
RCS file: /fetish/cu/doc/coreutils.texi,v
retrieving revision 1.315
diff -p -u -r1.315 coreutils.texi
--- doc/coreutils.texi  27 Feb 2006 10:47:23 -  1.315
+++ doc/coreutils.texi  6 Mar 2006 07:15:27 -
@@ -7003,7 +7003,8 @@ argument(s).  (No spaces around any comm
 Access the output file using the flags specified by the @var{flag}
 argument(s).  (No spaces around any comma(s).)
 
-Flags:

+Here are the flags.  Not every flag is supported on every operating
+system.
 
 @table @samp
 
@@ -7019,6 +7020,13 @@ contents of the file.  This flag makes s

 @cindex direct I/O
 Use direct I/O for data, avoiding the buffer cache.
 
[EMAIL PROTECTED] directory

[EMAIL PROTECTED] directory
[EMAIL PROTECTED] directory I/O
+
+Fail unless the file is a directory.  Most operating systems do not
+allow I/O to a directory, so this flag has limited utility.
+
 @item dsync
 @opindex dsync
 @cindex synchronized data reads
@@ -7043,11 +7051,6 @@ Use non-blocking I/O.
 @cindex access time
 Do not update the file's access time.
 
[EMAIL PROTECTED] nofollow

[EMAIL PROTECTED] nofollow
[EMAIL PROTECTED] symbolic links, following
-Do not follow symbolic links.
-
 @item noctty
 @opindex noctty
 @cindex controlling terminal
@@ -7056,6 +7059,16 @@ This has no effect when the file is not 
 On many hosts (e.g., @acronym{GNU}/Linux hosts), this option has no effect

 at all.
 
[EMAIL PROTECTED] nofollow

[EMAIL PROTECTED] nofollow
[EMAIL PROTECTED] symbolic links, following
+Do not follow symbolic links.
+
[EMAIL PROTECTED] nolinks
[EMAIL PROTECTED] nolinks
[EMAIL PROTECTED] hard links
+Fail if the file has multiple hard links.
+
 @item binary
 @opindex binary
 @cindex binary I/O
Index: src/dd.c
===
RCS file: /fetish/cu/src/dd.c,v
retrieving revision 1.190
diff -p -u -r1.190 dd.c
--- src/dd.c7 Dec 2005 21:12:12 -   1.190
+++ src/dd.c6 Mar 2006 07:15:27 -
@@ -263,10 +263,12 @@ static struct symbol_value const flags[]
   {"append", O_APPEND},
   {"binary", O_BINARY},
   {"direct", O_DIRECT},
+  {"directory",  O_DIRECTORY},
   {"dsync",  O_DSYNC},
   {"noatime",O_NOATIME},
   {"noctty", O_NOCTTY},
   {"nofollow",   O_NOFOLLOW},
+  {"nolinks",O_NOLINKS},
   {"nonblock",   O_NONBLOCK},
   {"sync",   O_SYNC},
   {"text",   O_TEXT},
@@ -460,6 +462,8 @@ Each FLAG symbol may be:\n\
 "), stdout);
   if (O_DIRECT)
fputs (_("  directuse direct I/O for data\n"), stdout);
+  if (O_DIRECTORY)
+   fputs (_("  directory fail unless a directory\n"), stdout);
   if (O_DSYNC)
fputs (_("  dsync use synchronized I/O for data\n"), stdout);
   if (O_SYNC)
@@ -468,11 +472,13 @@ Each FLAG symbol may be:\n\
fputs (_("  nonblock  use non-blocking I/O\n"), stdout);
   if (O_NOATIME)
fputs (_("  noatime   do not update access time\n"), stdout);
-  if (O_NOFOLLOW)
-   fputs (_("  nofollow  do not follow symlinks\n"), stdout);
   if (O_NOCTTY)
fputs (_("  nocttydo not assign controlling terminal from file\n"),
   stdout);
+  if (O_NOFOLLOW)
+   fputs (_("  nofollow  do not follow symlinks\n"), stdout);
+  if (O_NOLINKS)
+   fputs (_("  nolinks   fail if multiply-linked\n"), stdout);
   if (O_BINARY)
fputs (_("  binaryuse binary I/O for data\n"), stdout);
   if (O_TEXT)
Index: src/system.h
===
RCS file: /fetish/cu/src/system.h,v
retrieving revision 1.143
diff -p -u -r1.143 system.h
--- src/system.h26 Feb 2006 10:03:17 -  1.143
+++ src/system.h6 Mar 2006 07:15:27 -
@@ -193,6 +193,10 @@ initialize_exit_failure (int status)
 # define O_NOFOLLOW 0
 #endif
 
+#if !defined O_NOLINKS

+# define O_NOLINKS 0
+#endif
+
 #if !defined O_RSYNC
 # define O_RSYNC 0
 #endif
  


___
Bug-coreutils mailing list
Bug-coreutils@gnu.org
http://lists.gnu.org/mailman/listinfo/bug-coreutils


Re: dd new iflag= oflag= flags directory, nolinks

2006-03-21 Thread Phillip Susi
What is atomic about having dd do this?  open() with O_DIRECTORY to test 
for existence of a directory is exactly what test does isn't it?  If 
your goal is to test for the existence of a directory then test is what 
you want to use, not dd.  The purpose of dd is to copy/convert data 
between devices, not test if files or directories exist, so I don't 
think this patch is very appropriate. 


Paul Eggert wrote:

You can open a directory without writing to it.  Something like this:

   $ mkdir foo
   $ dd if=foo iflag=directory count=0
   0+0 records in
   0+0 records out
   0 bytes (0 B) copied, 2e-05 seconds, 0 B/s

You can think of this as a way to do a "test -d foo && test -r foo"
atomically, without race conditions.  Admittedly this is somewhat
twisted, but the new documentation does say that iflag=directory is of
"limited utility"

  


___
Bug-coreutils mailing list
Bug-coreutils@gnu.org
http://lists.gnu.org/mailman/listinfo/bug-coreutils


Re: dd new iflag= oflag= flags directory, nolinks

2006-03-21 Thread Paul Eggert
Phillip Susi <[EMAIL PROTECTED]> writes:

> What is atomic about having dd do this?  open() with O_DIRECTORY to test for
> existence of a directory is exactly what test does isn't it?

No, because "test -d foo && test -r foo" is _two_ invocations of
"test", not one.  A race condition is therefore possible.  The race
condition is not possible with dd if=foo iflag=directory count=0.

Admittedly this usage is unusual.  The main arguments for it are
(1) "dd" supports all the other O_* flags, so why not O_DIRECTORY? and
(2) I ran into a situation where I could use O_DIRECTORY.
(1) is far more important than (2).


___
Bug-coreutils mailing list
Bug-coreutils@gnu.org
http://lists.gnu.org/mailman/listinfo/bug-coreutils


Re: dd new iflag= oflag= flags directory, nolinks

2006-03-21 Thread Phillip Susi

Paul Eggert wrote:

No, because "test -d foo && test -r foo" is _two_ invocations of
"test", not one.  A race condition is therefore possible.  The race
condition is not possible with dd if=foo iflag=directory count=0.

  


Ok, so this allows you to atomically test if the named object is both a 
directory and is readable, but why bother?  It's a bit silly to worry 
about a race between the two tests when you still have a race between 
the dd-test and whatever it is the script actually does with the 
directory, such as try to list the files in it.  Practically, 
eliminating the one pedantic race condition doesn't solve any problems 
because you've still got a dozen others. 




Admittedly this usage is unusual.  The main arguments for it are
(1) "dd" supports all the other O_* flags, so why not O_DIRECTORY? and
(2) I ran into a situation where I could use O_DIRECTORY.
(1) is far more important than (2).


The purpose of dd is to transfer data.  Since O_DIRECTORY excludes 
transfering data, its use goes against the grain of dd, and since it 
doesn't actually accomplish anything useful either, I don't think it 
should be done.  It just adds complexity for no good reason.



___
Bug-coreutils mailing list
Bug-coreutils@gnu.org
http://lists.gnu.org/mailman/listinfo/bug-coreutils


Re: dd new iflag= oflag= flags directory, nolinks

2006-03-21 Thread Olivier Delhomme
Le Mon, 06 Mar 2006 18:20:12 -0500, Phillip Susi disait :

> I'm confused.  You can't open() and write() to a directory, so how does 
> it make any sense to ask dd to set O_DIRECTORY?

So do I ...I never used open() with a directory, but why shouldn't it
be possible ?

I looked to the man 2 open page and I saw the following which confuses
me more :

 O_DIRECTORY
  If  pathname  is not a directory, cause the open to
fail.  This flag is Linux-specific, and was added in kernel version
2.1.126, to avoid denial-of- service problems if opendir(3) is called
on a FIFO or tape device, but should not be used outside of the
implementation of opendir.


So if this flag is linux specific does it mean that dd iflag=directory
won't run on other unices ?

Thanks,

Olivier.


> Paul Eggert wrote:
> > I wanted to use dd iflag=directory (to test whether a file is a
> > directory, atomically), and noticed that dd didn't have it.  The use
> > was a fairly obscure one (just testing the O_DIRECTORY flag) but I
> > figured dd should support all the flags.  I noticed also that dd
> > doesn't support the Solaris 10 O_NOLINKS option.  So I installed this:
> >
> > 2006-03-05  Paul Eggert  <[EMAIL PROTECTED]>
> >
> > * doc/coreutils.texi (dd invocation): New flags directory, nolinks.
> > Alphabetize nofollow.
> > * src/dd.c (flags, usage): New flags directory, nolinks.
> > * src/system.h (O_NOLINKS): Define to 0 if not already defined.
> >
> > Index: doc/coreutils.texi
> > ===
> > RCS file: /fetish/cu/doc/coreutils.texi,v
> > retrieving revision 1.315
> > diff -p -u -r1.315 coreutils.texi
> > --- doc/coreutils.texi  27 Feb 2006 10:47:23 -  1.315
> > +++ doc/coreutils.texi  6 Mar 2006 07:15:27 -
> > @@ -7003,7 +7003,8 @@ argument(s).  (No spaces around any comm
> >  Access the output file using the flags specified by the @var{flag}
> >  argument(s).  (No spaces around any comma(s).)
> >  
> > -Flags:
> > +Here are the flags.  Not every flag is supported on every operating
> > +system.
> >  
> >  @table @samp
> >  
> > @@ -7019,6 +7020,13 @@ contents of the file.  This flag makes s
> >  @cindex direct I/O
> >  Use direct I/O for data, avoiding the buffer cache.
> >  
> > [EMAIL PROTECTED] directory
> > [EMAIL PROTECTED] directory
> > [EMAIL PROTECTED] directory I/O
> > +
> > +Fail unless the file is a directory.  Most operating systems do not
> > +allow I/O to a directory, so this flag has limited utility.
> > +
> >  @item dsync
> >  @opindex dsync
> >  @cindex synchronized data reads
> > @@ -7043,11 +7051,6 @@ Use non-blocking I/O.
> >  @cindex access time
> >  Do not update the file's access time.
> >  
> > [EMAIL PROTECTED] nofollow
> > [EMAIL PROTECTED] nofollow
> > [EMAIL PROTECTED] symbolic links, following
> > -Do not follow symbolic links.
> > -
> >  @item noctty
> >  @opindex noctty
> >  @cindex controlling terminal
> > @@ -7056,6 +7059,16 @@ This has no effect when the file is not 
> >  On many hosts (e.g., @acronym{GNU}/Linux hosts), this option has no effect
> >  at all.
> >  
> > [EMAIL PROTECTED] nofollow
> > [EMAIL PROTECTED] nofollow
> > [EMAIL PROTECTED] symbolic links, following
> > +Do not follow symbolic links.
> > +
> > [EMAIL PROTECTED] nolinks
> > [EMAIL PROTECTED] nolinks
> > [EMAIL PROTECTED] hard links
> > +Fail if the file has multiple hard links.
> > +
> >  @item binary
> >  @opindex binary
> >  @cindex binary I/O
> > Index: src/dd.c
> > ===
> > RCS file: /fetish/cu/src/dd.c,v
> > retrieving revision 1.190
> > diff -p -u -r1.190 dd.c
> > --- src/dd.c7 Dec 2005 21:12:12 -   1.190
> > +++ src/dd.c6 Mar 2006 07:15:27 -
> > @@ -263,10 +263,12 @@ static struct symbol_value const flags[]
> >{"append",   O_APPEND},
> >{"binary",   O_BINARY},
> >{"direct",   O_DIRECT},
> > +  {"directory",O_DIRECTORY},
> >{"dsync",O_DSYNC},
> >{"noatime",  O_NOATIME},
> >{"noctty",   O_NOCTTY},
> >{"nofollow", O_NOFOLLOW},
> > +  {"nolinks",  O_NOLINKS},
> >{"nonblock", O_NONBLOCK},
> >{"sync", O_SYNC},
> >{"text", O_TEXT},
> > @@ -460,6 +462,8 @@ Each FLAG symbol may be:\n\
> >  "), stdout);
> >if (O_DIRECT)
> > fputs (_("  directuse direct I/O for data\n"), stdout);
> > +  if (O_DIRECTORY)
> > +   fputs (_("  directory fail unless a directory\n"), stdout);
> >if (O_DSYNC)
> > fputs (_("  dsync use synchronized I/O for data\n"), stdout);
> >if (O_SYNC)
> > @@ -468,11 +472,13 @@ Each FLAG symbol may be:\n\
> > fputs (_("  nonblock  use non-blocking I/O\n"), stdout);
> >if (O_NOATIME)
> > fputs (_("  noatime   do not update access time\n"), stdout);
> > -  if (O_NOFOLLOW)
> > -   fputs (_("  nofollow  do not follow symlinks\n"), stdout);
> >if (O_NOCTTY)
> > fputs (_("  noctty 

Re: dd new iflag= oflag= flags directory, nolinks

2006-03-22 Thread Paul Eggert
Olivier Delhomme <[EMAIL PROTECTED]> writes:

> So if this flag is linux specific does it mean that dd iflag=directory
> won't run on other unices ?

Yes, that's right.  It's just like "dd iflag=noatime".  The general
rule is that dd issues a runtime diagnostic and immediately fails if
you try to use a flag that isn't supported on the current platform.

The issue is more complicated than "linux specific".  For example,
iflag=noatime is supported by some Linux kernels but not others.
And iflag=nolinks works on SunOS 5.10 and later, but not on any Linux
kernel that I know of (yet).


___
Bug-coreutils mailing list
Bug-coreutils@gnu.org
http://lists.gnu.org/mailman/listinfo/bug-coreutils


Re: dd new iflag= oflag= flags directory, nolinks

2006-03-27 Thread Eric Blake
-BEGIN PGP SIGNED MESSAGE-
Hash: SHA1

According to Olivier Delhomme on 3/8/2006 12:45 PM:
> Le Mon, 06 Mar 2006 18:20:12 -0500, Phillip Susi disait :
> 
>> I'm confused.  You can't open() and write() to a directory, so how does 
>> it make any sense to ask dd to set O_DIRECTORY?
> 
> So do I ...I never used open() with a directory, but why shouldn't it
> be possible ?

It's possible to open directories read-only, but then you can't read()
that file descriptor.  Beyond atomic existance checks, about all that can
be usefully done with a directory fd is using fdopendir() on it (as a
replacement to opendir, especially useful when using openat() and
friends).  But I still think Paul's patch was worthwhile, from the
completeness point of view - dd now supports every O_* flag possible, even
if there is not much use for it.

> 
> I looked to the man 2 open page and I saw the following which confuses
> me more :
> 
>  O_DIRECTORY
>   If  pathname  is not a directory, cause the open to
> fail.  This flag is Linux-specific, and was added in kernel version
> 2.1.126, to avoid denial-of- service problems if opendir(3) is called
> on a FIFO or tape device, but should not be used outside of the
> implementation of opendir.
> 
> 
> So if this flag is linux specific does it mean that dd iflag=directory
> won't run on other unices ?

The dd code is conditionally compiled so that platforms not supporting the
various O_* flags do not accept that particular flag, nor document it in
the --help output.  Just as you can't use dd iflag=directory on Solaris,
you can't use dd iflag=nolinks on Linux.

- --
Life is short - so eat dessert first!

Eric Blake [EMAIL PROTECTED]
-BEGIN PGP SIGNATURE-
Version: GnuPG v1.4.2.1 (Cygwin)
Comment: Public key at home.comcast.net/~ericblake/eblake.gpg
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFEINGr84KuGfSFAYARAkLPAJ96BqO/5D5Rw1I+jpb0rHjxCye/0wCgmYif
2QJGGeJsO4C7xXRLVVc3uZk=
=J0WG
-END PGP SIGNATURE-


___
Bug-coreutils mailing list
Bug-coreutils@gnu.org
http://lists.gnu.org/mailman/listinfo/bug-coreutils


Re: dd new iflag= oflag= flags directory, nolinks

2006-03-27 Thread Paul Eggert
Phillip Susi <[EMAIL PROTECTED]> writes:

> You can't open() and write() to a directory, so how does it make
> any sense to ask dd to set O_DIRECTORY?

You can open a directory without writing to it.  Something like this:

   $ mkdir foo
   $ dd if=foo iflag=directory count=0
   0+0 records in
   0+0 records out
   0 bytes (0 B) copied, 2e-05 seconds, 0 B/s

You can think of this as a way to do a "test -d foo && test -r foo"
atomically, without race conditions.  Admittedly this is somewhat
twisted, but the new documentation does say that iflag=directory is of
"limited utility"


___
Bug-coreutils mailing list
Bug-coreutils@gnu.org
http://lists.gnu.org/mailman/listinfo/bug-coreutils


Re: dd new iflag= oflag= flags directory, nolinks

2006-03-27 Thread Paul Eggert
Phillip Susi <[EMAIL PROTECTED]> writes:

> Ok, so this allows you to atomically test if the named object is both a
> directory and is readable, but why bother?

You might want to bother if you want to test some filesystem code
using a shell script.  That's what I was doing.  I wanted to make sure
that O_DIRECTORY worked, even with a symbolic link to a directory.  I
couldn't do that with the shell and standard utilites, until I added
iflag=directory.

> The purpose of dd is to transfer data.

No, dd has other purposes.  For example, you can use dd to reposition
standard input without reading it.  There's an example of this in the
coreutils manual.

The original purpose of the shell was to provide a thin layer over
operating system services.  The idea was that there was a simple
scriptable interface to pretty much anything you could do with a
system call.  This change fits within that tradition.  (Obviously the
tradition is not always upheld, but that's a different matter.)

(One could also argue that the original purpose of 'dd' was to mimic
the DD directive of OS/360 JCL
, and the
'directory' flag is also well within this tradition.  :-)


Anyway, your email caused me to look again at the 'dd' source code
and test cases and NEWS, and I installed these further improvements.
Thanks.

2006-03-08  Paul Eggert  <[EMAIL PROTECTED]>

* NEWS: Document dd's new 'directory' and 'nolinks' flags.
* src/dd.c (set_fd_flags): Handle file-creation flags on file
descriptors, rather than ignoring them.
* tests/dd/misc: Add test cases for append, nofollow, directory,
and nolinks flags.  Simplify redirection to /dev/null in some cases.

Index: NEWS
===
RCS file: /fetish/cu/NEWS,v
retrieving revision 1.361
diff -p -u -r1.361 NEWS
--- NEWS27 Feb 2006 10:47:56 -  1.361
+++ NEWS8 Mar 2006 18:55:23 -
@@ -71,9 +71,18 @@ GNU coreutils NEWS  
 
 ** New features
 
-  dd's new iflag=noatime option causes it to read a file without
-  updating its access time, on hosts that support this (currently only
-  Linux kernels, version 2.6.8 and later).
+  New dd iflag= and oflag= flags:
+
+'directory' causes dd to fail unless the file is a directory, on
+hosts that support this (e.g., Linux kernels, version 2.1.126 and
+later).  This has limited utility but is present for completeness.
+
+'noatime' causes dd to read a file without updating its access
+time, on hosts that support this (e.g., Linux kernels, version
+2.6.8 and later).
+
+'nolinks' causes dd to fail if the file has multiple hard links,
+on hosts that support this (e.g., Solaris 10 and later).
 
   rm now accepts the -I (--interactive=once) option.  This new option
   prompts once if rm is invoked recursively or if more than three
Index: src/dd.c
===
RCS file: /fetish/cu/src/dd.c,v
retrieving revision 1.191
diff -p -u -r1.191 dd.c
--- src/dd.c6 Mar 2006 07:20:19 -   1.191
+++ src/dd.c8 Mar 2006 18:55:24 -
@@ -1325,12 +1325,44 @@ copy_with_unblock (char const *buf, size
 static void
 set_fd_flags (int fd, int add_flags, char const *name)
 {
+  /* Ignore file creation flags that are no-ops on file descriptors.  */
+  add_flags &= ~ (O_NOCTTY | O_NOFOLLOW);
+
   if (add_flags)
 {
   int old_flags = fcntl (fd, F_GETFL);
   int new_flags = old_flags | add_flags;
-  if (old_flags < 0
- || (new_flags != old_flags && fcntl (fd, F_SETFL, new_flags) == -1))
+  bool ok = true;
+  if (old_flags < 0)
+   ok = false;
+  else if (old_flags != new_flags)
+   {
+ if (new_flags & (O_DIRECTORY | O_NOLINKS))
+   {
+ /* NEW_FLAGS contains at least one file creation flag that
+requires some checking of the open file descriptor.  */
+ struct stat st;
+ if (fstat (fd, &st) != 0)
+   ok = false;
+ else if ((new_flags & O_DIRECTORY) && ! S_ISDIR (st.st_mode))
+   {
+ errno = ENOTDIR;
+ ok = false;
+   }
+ else if ((new_flags & O_NOLINKS) && 1 < st.st_nlink)
+   {
+ errno = EMLINK;
+ ok = false;
+   }
+ new_flags &= ~ (O_DIRECTORY | O_NOLINKS);
+   }
+
+ if (ok && old_flags != new_flags
+ && fcntl (fd, F_SETFL, new_flags) == -1)
+   ok = false;
+   }
+
+  if (!ok)
error (EXIT_FAILURE, errno, _("setting flags for %s"), quote (name));
 }
 }
Index: tests/dd/misc
===
RCS file: /fetish/cu/tests/dd/misc,v
retrieving revision 1.5
diff -p -u -r1.5 misc
--- tests/dd/misc   8 Mar 2006 18:21:54 -   1.5