7

I would like to use install command in order to create a new executable file with pre-populated content (e.g. with single pwd command in it).

So I've extended this example which creates a new empty executable file:

install -b -m 755 /dev/null newfile

into this one:

install -m755 <(echo pwd) newfile

or:

echo pwd | install -m755 /dev/stdin newfile

Where I expect to create a new newfile executable file to be created with content pwd inside.

It works on Linux, however on OS X it fails with the following error:

  • BSD install (/usr/bin/install)

    install: /dev/fd/63: Inappropriate file type or format

  • GNU install (/usr/local/opt/coreutils/libexec/gnubin/install)

    install: skipping file /dev/fd/63, as it was replaced while being copied

Why this doesn't work on Unix, but it works on Linux? I'm missing anything? Is there any way to bypass the above warning by using different syntax (without creating a file in separate commands and using chmod after that)?


On both environments (Linux & OS X) I've the same version of install:

$ install --version
install (GNU coreutils) 8.23
  • 1
    I just tried the syntax install -m755 <(echo pwd) newfile on a centOS 7 machine, and it worked correctly. using the syntax install -m755 <(echo pwd)> newfile produced the error you are receiving though. I realize this doesn't implicitly help you, but it does show that your premise is sound at least. It should be working – Gravy Oct 13 '15 at 3:36
  • 2
    If you use zsh, you may try the =(cmd) syntax instead of <(cmd). From the man: "If =(...) is used instead of <(...), then the file passed as an argument will be the name of a temporary file containing the output of the list process. This may be used instead of the < form for a program that expects to lseek (see lseek(2)) on the input file." Otherwise mkfifo is your best bet. – Michaël Nov 17 '15 at 16:09
  • 1
    @kenorb I'm don't know if you've come across this in you're own research into the problem, but your error message seems to have been widespread amongst Cygwin users, most often using cp. This is just one example: permalink.gmane.org/gmane.os.cygwin/129935 – py4on Mar 9 '16 at 20:48
  • 2
    @py4on How this is related to OS X kernel? This happens on Mac for both install versions. – kenorb Mar 9 '16 at 21:23
  • 2
    Unless they share the same bug with some similar code. – kenorb Mar 9 '16 at 21:34
1

The BSD install found on OpenBSD systems has this piece of code in it (from src/usr.bin/xinstall/xinstall.c):

if (!S_ISREG(to_sb.st_mode))
    errc(1, EFTYPE, "%s", to_name);

This emits the error

install: /dev/fd/4: Inappropriate file type or format

when it's discovered that /dev/df/4 is not a regular file. (There's a separate earlier check for /dev/null)

That was fairly straight forward.

GNU install has this code (src/install.c in coreutils):

  /* Allow installing from non-regular files like /dev/null.
     Charles Karney reported that some Sun version of install allows that
     and that sendmail's installation process relies on the behavior.
     However, since !x->recursive, the call to "copy" will fail if FROM
     is a directory.  */

  return copy (from, to, false, x, &copy_into_self, NULL);

The code emitting the error comes from src/copy.c:

  source_desc = open (src_name,
                      (O_RDONLY | O_BINARY
                       | (x->dereference == DEREF_NEVER ? O_NOFOLLOW : 0)));

(a few lines omitted)

  if (fstat (source_desc, &src_open_sb) != 0)
    {
      error (0, errno, _("cannot fstat %s"), quoteaf (src_name));
      return_val = false;
      goto close_src_desc;
    }

  /* Compare the source dev/ino from the open file to the incoming,
     saved ones obtained via a previous call to stat.  */
  if (! SAME_INODE (*src_sb, src_open_sb))
    {
      error (0, 0,
             _("skipping file %s, as it was replaced while being copied"),
             quoteaf (src_name));

This is in copy_reg() which copies a regular file. The SAME_INODE macro evaluates to false because the inodes differ in the two stat structs *src_sb and src_open_sb. The *src_sb comes from a stat() or lstat() call on the source file name and src_open_sb from fstat() as seen above, on a newly open descriptor.

I can kinda see why opening a new file descriptor and comparing its inode to that of the file descriptor given by the shell (/dev/fd/4 in my case) will fail, but I can't put it into definite words unfortunately.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.