Por que o OS X 'instala' erros na entrada redirecionada quando a mesma versão de 'install' no linux funciona bem?

7

Eu gostaria de usar o comando install para criar um novo arquivo executável com conteúdo pré-preenchido (por exemplo, com o comando pwd único).

Então eu estendi este exemplo que cria um novo arquivo executável vazio:

install -b -m 755 /dev/null newfile

para este:

install -m755 <(echo pwd) newfile

ou:

echo pwd | install -m755 /dev/stdin newfile

Onde espero criar um novo arquivo executável newfile a ser criado com o conteúdo pwd dentro.

Funciona no Linux, no entanto, no OS X ele falha com o seguinte erro:

  • 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

Por que isso não funciona no Unix, mas funciona no Linux? Eu estou sentindo falta de alguma coisa? Existe alguma maneira de contornar o aviso acima usando uma sintaxe diferente ( sem criando um arquivo em comandos separados e usando chmod depois disso?)

Em ambos os ambientes (Linux e SO X), tenho a mesma versão de install :

$ install --version
install (GNU coreutils) 8.23
    
por kenorb 12.10.2015 / 23:37

1 resposta

1

A instalação do BSD encontrada nos sistemas OpenBSD contém este trecho de código (de src/usr.bin/xinstall/xinstall.c ):

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

Isso emite o erro

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

quando é descoberto que /dev/df/4 não é um arquivo normal. (Há uma verificação anterior separada para /dev/null )

Isso foi bem direto.

O GNU install tem este código ( 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);

O código que emite o erro vem de src/copy.c :

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

(algumas linhas foram omitidas)

  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));

Isso é em copy_reg() , que copia um arquivo normal. A macro SAME_INODE é avaliada como falsa porque os inodes diferem nas duas stat structs *src_sb e src_open_sb . O *src_sb vem de uma chamada stat() ou lstat() no nome do arquivo de origem e src_open_sb de fstat() como visto acima, em um descritor recém aberto.

Eu posso ver por que abrir um novo descritor de arquivo e comparar seu inode com o do descritor de arquivo dado pelo shell ( /dev/fd/4 no meu caso) irá falhar, mas infelizmente não posso colocá-lo em palavras definitivas.

    
por 23.07.2016 / 13:46