-1
#include <stdio.h> //for printf
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include  <stdio.h>
//#define STDOUT_FILENO 1
// define STDERR_FILENO 2
int main(){
    // mode_t mode = S_IROTH | S_IRUSR | S_IWUSR;
    mode_t mode = S_IRUSR | S_IWUSR;
    
    close(1);
    int fildes = open("hello_world.txt", O_CREAT | O_TRUNC | O_RDWR, mode);
    printf("Hi! My Name is \n" );
    close(fildes);
    return 0;
}

From what I learned, "Hi! My Name is" should be printed to "hello_world.txt". It works well in Linux virtual machine which my professor provided. But in my machine (I'm using remote WSL in vscode), "hello_world.txt" is empty. Can I fix this problem?

rici
  • 234,347
  • 28
  • 237
  • 341
jun
  • 133
  • 1
  • 3
  • 1
    Printf always prints to stdout if you want to print to a file you should use [fprintf](https://www.tutorialspoint.com/c_standard_library/c_function_fprintf.htm) or [dprintf](https://linux.die.net/man/3/dprintf) – Samuel Aug 23 '21 at 16:07
  • 2
    If you close the underlying file descriptor before you flush the file, then this is what you should expect to happen. Try `fflush` before `close` – William Pursell Aug 23 '21 at 16:16
  • You never print to your new `fildes`. By default, each process has file descriptors 0, 1, and 2 for stdin, stdout, and stderr, respectively. `open` creates a new file descriptor (not guarenteed to be 1 just because you closed fd 1; you can print `fildes` to see). You need to set stdout to your new file descriptor for this to work as-is, such as `dup2(1, fildes)`. Alternatively, you can print directly to a file descriptor with `dprintf`. – h0r53 Aug 23 '21 at 16:18

1 Answers1

3

printf does not necessarily write anything. Typically, it buffers data and defers writes until the buffers are full. stdout is automatically flushed when the process exits, but you've closed the file descriptor before that happens, so the write fails. Try fflush(stdout) before you close the underlying file descriptor. (This assumes that the hacky open actually gives you the underlying file descriptor of stdout. That should happen and in most cases will, but it certainly is not guaranteed. You should use freopen if you want to do this reliably.)

William Pursell
  • 204,365
  • 48
  • 270
  • 300
  • You're saying that because the earlier code closes file handle 1, the subsequent open will reuse that same (STDOUT) handle. Ouch, that's grim. – jarmod Aug 23 '21 at 16:23
  • *That should happen and in most cases will, but it certainly is not guaranteed* [It is guaranteed](https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/functions/V2_chap02.html#tag_15_14): "All functions that open one or more file descriptors shall, unless specified otherwise, atomically allocate the lowest numbered available (that is, not already open in the calling process) file descriptor at the time of each allocation." – Andrew Henle Aug 23 '21 at 16:23
  • @jarmod *You're saying that because the earlier code closes file handle 1, the subsequent open will, in some cases, reuse that same handle. Ouch, that's grim.* That's the required behavior under POSIX. See my previous comment. – Andrew Henle Aug 23 '21 at 16:24
  • I believe the not guaranteed part comes from the idea that FD 1 may still contain buffered data when `open` is called, causing it to not be available for reassignment – h0r53 Aug 23 '21 at 16:24
  • @h0r53 File descriptors don't have buffered data. – Andrew Henle Aug 23 '21 at 16:25
  • 1
    @h0r53: In your comment, you wrote: `"Sure, the FILE* pointed to by the descriptor."` -- This sentence implies something that is not true. A descriptor does not point to a `FILE *`. Rather, the opposite is true. A `FILE *` points to a structure which contains a file descriptor. See this question for further information: [What's the difference between a file descriptor and file pointer?](https://stackoverflow.com/q/2423628/12149471) – Andreas Wenzel Aug 23 '21 at 16:33
  • I meant the file table entry corresponding to the file descriptor, but yes, wrong terminology – h0r53 Aug 23 '21 at 16:40