30

The strings command behaves weirdly, apparently it doesn't stop writing to a file even if drive run out of space. Or perhaps I'm missing something?

I run the following:

# strings /dev/urandom > random.txt

this was keep running and didn't stop even after filling the disk (a regular usb flash).

then to be quicker I created a ramdisk and tried again the same command. it also didn't stop.

I understand that urandom isn't a regular file and also strings's output is redirected, however in both cases above, the cat command reported the error when there was no more space.

# cat /dev/urandom > random.txt
cat: write error: No space left on device
  1. Is this normal behavior of strings? If so, why?
  2. Where is the data written after there's no more space left?
  • 1
    What was the indication that your first command had actually filled up the disk? – Kusalananda Mar 6 at 7:33
  • 1
    @Kusalananda It was reported by df. I was monitoring it from another virtual terminal using watch df -h – user174174 Mar 6 at 7:40
  • 2
    @Kusalananda: you can test this easily with strace strings /dev/urandom > /dev/full – Peter Cordes Mar 6 at 9:39
  • 2
    @mosvy OpenBSD uses that same strings implementation from GNU binutils. I was referring to the strace command. – Kusalananda Mar 6 at 19:48
  • 2
    @Kusalananda OK, because the "BSD toolchain" replacement of strings(1) doesn't check for the return value of putchar() either – mosvy Mar 6 at 20:15
63

If GNU cat can't write out what it read, it will exit with an error:

/* Write this block out.  */

{
  /* The following is ok, since we know that 0 < n_read.  */
  size_t n = n_read;
  if (full_write (STDOUT_FILENO, buf, n) != n)
    die (EXIT_FAILURE, errno, _("write error"));
}

GNU strings, on the other hand, doesn't care whether it managed to write successfully:

while (1)
  {
    c = get_char (stream, &address, &magiccount, &magic);
    if (c == EOF)
      break;
    if (! STRING_ISGRAPHIC (c))
      {
        unget_part_char (c, &address, &magiccount, &magic);
        break;
      }
    putchar (c);
  }

So all those writes fail, but strings continues merrily along, until it reaches end of input, which will be never.

$ strace -e write strings /dev/urandom > foo/bar
write(1, "7[\\Z\n]juKw\nl [1\nTc9g\n0&}x(x\n/y^7"..., 4096) = 4096
write(1, "\nXaki%\ndHB0\n?5:Q\n6bX-\np!E[\n'&=7\n"..., 4096) = 4096
write(1, "%M6s\n=4C.%\n&7)n\nQ_%J\ncT+\";\nK*<%\n"..., 4096) = 4096
write(1, "&d<\nj~g0\nm]=o\na=^0\n%s]2W\nM7C%\nUK"..., 4096) = -1 ENOSPC (No space left on device)
write(1, "~\nd3qQ\n^^u1#\na#5\\\n^=\t\"b\n*91_\n ]o"..., 4096) = -1 ENOSPC (No space left on device)
write(1, "L\n6QO1x\na,yE\nk>\",@Z\nyM.ur\n~z\tF\nr"..., 4096) = -1 ENOSPC (No space left on device)
write(1, "\n61]R\nyg9C\nfLVu\n<Ez:\n.tV-c\nw_'>e"..., 4096) = -1 ENOSPC (No space left on device)
write(1, "\nCj)a\nT]X:uA\n_KH\"B\nRfQ4G\n3re\t\n&s"..., 4096) = -1 ENOSPC (No space left on device)
write(1, "j\nk7@%\n9E?^N\nJ#8V\n*]i,\nXDxh?\nr_1"..., 4096) = -1 ENOSPC (No space left on device)
write(1, "ia\tI\nQ)Zw\nnV0J\nE3-W \n@0-N2v\nK{15"..., 4096) = -1 ENOSPC (No space left on device)
write(1, "\nZ~*g\n)FQn\nUY:G\ndRbN\nn..F\nvF{,\n+"..., 4096) = -1 ENOSPC (No space left on device)
...
  • 19
    Nice analysis. I'd say that should be considered a bug in strings. – kasperd Mar 6 at 15:01
  • 3
    Anyone planning to report the bug? – Nate Eldredge Mar 7 at 16:52

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.