8

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 
13
  • 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
    CommentedOct 13, 2015 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
    CommentedNov 17, 2015 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
    – toxefa
    CommentedMar 9, 2016 at 20:48
  • 2
    @py4on How this is related to OS X kernel? This happens on Mac for both install versions.
    – kenorb
    CommentedMar 9, 2016 at 21:23
  • 2
    Unless they share the same bug with some similar code.
    – kenorb
    CommentedMar 9, 2016 at 21:34

1 Answer 1

2

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.

    You must log in to answer this question.

    Start asking to get answers

    Find the answer to your question by asking.

    Ask question

    Explore related questions

    See similar questions with these tags.