[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#916562: libc6: fputs(), fputc(), and fwrite() do not fail on write error



Package: libc6
Version: 2.27-8
Severity: normal
Tags: upstream

Dear Maintainer,

If I use fputs(3), fputc(3), or fwrite(3) to write to a file that can
be opened for writing but cannot be written to (e.g /dev/full), the
functions return 1 rather than the expected EOF (or 0 in the case of
fread()). On the other hand, write(2) returns -1 and sets errno to
ENOSPC an expected.

Expected results:
The functions fputs() and fputc() should return EOF and fwrite()
should return 0. All the functions should set errno to ENOSPC (for
/dev/full).

Actual results:
The functions return 1 (an indication of success) and leave errno
unchanged.

Steps to reproduce:
Compile the attached program (the compiler flag `-fno-builtin' does
not change anything, nor does -O0):
$ gcc -o write write.c

Run the program with /dev/full as the output file:
$ ./write hello /dev/full
fputs() returned 1 and errno is 0 (Success).
fputc() returned 104 (h) and errno is 0 (Success).
fwrite() returned 5 (the length of "hello" is 5) and errno is 0 (Success).
write() returned -1 (the length of "hello" is 5) and errno is 28 (No space left on device).

The expected output is:
fputs() returned EOF (-1) and errno is 28 (No space left on device).
fputc() returned EOF (-1) and errno is 28 (No space left on device).
fwrite() returned 0 (the length of "hello" is 5) and errno is 28 (No space left on device).
write() returned -1 (the length of "hello" is 5) and errno is 28 (No space left on device).


-- System Information:
Debian Release: buster/sid
  APT prefers testing
  APT policy: (500, 'testing')
Architecture: amd64 (x86_64)

Kernel: Linux 4.18.0-2-amd64 (SMP w/2 CPU cores)
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8), LANGUAGE=en_US.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Init: systemd (via /run/systemd/system)
LSM: AppArmor: enabled

Versions of packages libc6 depends on:
ii  libgcc1  1:8.2.0-9

libc6 recommends no packages.

Versions of packages libc6 suggests:
ii  debconf [debconf-2.0]  1.5.69
pn  glibc-doc              <none>
ii  libc-l10n              2.27-8
ii  locales                2.27-8

-- debconf information:
* glibc/restart-services: cups cron
  glibc/kernel-too-old:
  glibc/kernel-not-supported:
  glibc/restart-failed:
  glibc/upgrade: true
  glibc/disable-screensaver:
* libraries/restart-without-asking: false
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>

int main(int argc, char **argv) {
  int ret;
  size_t string_len;
  FILE *output_file;
  
  if (argc != 3) {
    fprintf(stderr, "Usage: %s STRING FILE\nWrite STRING to FILE.\n", argv[0]);
    return 1;
  }

  /* Open the file */
  if (!(output_file = fopen(argv[2], "w"))) {
    fprintf(stderr, "%s: could not open %s: %m\n", argv[0], argv[2]);
    return 1;
  }

  /* Now try to write to the file using fputs() */
  errno = 0;
  ret = fputs(argv[1], output_file);
  /* `ret' should be EOF if an error occured (see fputs(3)) */
  printf ("fputs() returned ");
  if (ret == EOF)
    printf("EOF (%d)", ret);
  else
    printf("%d", ret);
  printf(" and errno is %d (%m).\n", errno);

  /* This happens with fputc() too */
  errno = 0;
  ret = fputc(argv[1][0], output_file);
  printf("fputc() returned ");
  if (ret == EOF)
    printf("EOF (%d)", ret);
  else
    printf("%d (%c)", ret, (char)ret);
  printf(" and errno is %d (%m).\n", errno);

  string_len = strlen(argv[1]);

  /* This happens with fwrite() too */
  errno = 0;
  printf("fwrite() returned %lu (the length of \"%s\" is %lu) ",
	 fwrite(argv[1], 1, string_len, output_file), argv[1], string_len);
  printf("and errno is %d (%m).\n", errno);

  /* write() gives us expected results */
  errno = 0;
  printf("write() returned %ld (the length of \"%s\" is %lu) ",
	 write(fileno(output_file), argv[1], string_len), argv[1], string_len);
  printf("and errno is %d (%m).\n", errno);

  return 0;
}

Reply to: