---
# System prepended metadata

title: Ch03 File I/O
tags: [APUE, C basics]

---

# Ch03 File I/O 
>###### tags: `APUE` `C basics`

>致謝
>W. Richard Stevens
>Advanced Programming in the UNIX Environment III 
>github:XutongLi
>https://github.com/XutongLi/Learning-Notes 
>大木實驗室
>https://www.bilibili.com/s/video/BV1NJ411x7Mq



## dup and dup2

An existing file descriptor is duplicated by either of the following functions:
```c= 
#include <unistd.h>
int dup(int fd);
int dup2(int fd, int fd2);

//Both return: new file descriptor if OK, −1 on error
```

The new file descriptor returned by dup is guaranteed to be the lowest-numbered available file descriptor. With dup2, we specify the value of the new descriptor with the
 fd2 argument.

The new file descriptor that is returned as the value of the functions shares the same file table entry as the fd argument. They share the same file status flags — read, write and so on — and the same current file offset.

```c=
    newfd = dup(1); //the next available descriptor is 3
```
![](https://i.imgur.com/9Evpjhw.png)



Another way to duplicate a descriptor is with the fcntl function.
```c= 
    fcntl(fd, F_DUPFD, 0); //equivalent to dup(fd);
```


**code**
>reference 
>台部落
>https://www.twblogs.net/a/5b90b0882b71771c618680b8

```c= 
#include <stdio.h>
#include <stdlib.h>

#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>

int main(void)
{
    int fd_temp = open("temp", O_RDWR | O_CREAT | O_TRUNC, S_IRWXU | S_IRWXG );
    int fd_save_stdout;
    dup2(1, fd_save_stdout); //save the fd of stdout
    dup2(fd_temp, 1);        //1 and fd point to "temp.txt"
    
    if(setvbuf(stdout, NULL, _IOLBF, 0) < 0){
        perror("setvbuf\n");
        exit(EXIT_FAILURE);
    }

    printf("hahaha\n");        
    dup2(fd_save_stdout, 1);   //recover
    printf("dup dup dup\n");   //output to terminal
    close(fd_save_stdout);

    return 0;
}
```
The program will put "hahaha" into the file -- temp; then print "dup dup dup" on the terminal.
After calling dup2, the file is no longer line buffered, but the same as the file operation -- fully buffered is used. We must use setvbuf() to guarantee the program works as we expected, or we could use fflush() instead.

```c= 
    int fd_save_stdout;
    dup2(1, fd_save_stdout); //save the fd of stdout
    dup2(fd_temp, 1);        //1 and fd point to "temp.txt"
    fflush(stdout);
    printf("hahaha\n");
```