废话少说,直接看代码:
#include <unistd.h> #include <sys/types.h> #include <errno.h> #include <stdio.h> #include <string.h> #include <linux/limits.h> #define OPEN_MAX 1024 int mydup2(int filedes, int filedes2) { int open_fds[OPEN_MAX]; int open_count = 0; int new_fds; int i; errno = 0; // test wether filedes is open and a valid file descriptor if((open_fds[open_count++] = dup(filedes)) == -1) return -1; // test wether filedes2 is a valid file descriptor if(filedes2 < 0 || filedes2 > OPEN_MAX) { errno = EBADF; return -1; } // if equal, return directly if(filedes == filedes2) { return filedes; } // test wether filedes2 is open, and close it if it is open if((open_fds[open_count++] = dup(filedes2)) >= 0) { if(close(filedes2) == -1) { return -1; } } // dup until the return file descriptor equals to filedes2 new_fds = dup(filedes); open_fds[open_count++] = new_fds; while(new_fds != -1 && new_fds != filedes2) { open_fds[open_count++] = new_fds; new_fds = dup(filedes); } // close the des open by dup unless the last one for(i = 0; i < open_count - 1; ++i) { close(open_fds[i]); } return new_fds; } void test_mydup2(int (*fun_dup2)(int,int)) { // test case int old_fds[] = {0, 0, 2, 0, -1, 10, -1, 65536}; int new_fds[] = {0, 2, 2, 30, 2, 20, 65536, 65536}; int count = sizeof(old_fds)/sizeof(int); int ret; int i; // begin test for(i = 0; i < count; i++) { printf("dup2(%d, %d) : ", old_fds[i], new_fds[i]); ret = fun_dup2(old_fds[i], new_fds[i]); if(-1 == ret) { printf("%s\n", strerror(errno)); } else if(ret == new_fds[i]) { printf("success.\n"); if(ret != 0 && ret != 1 && ret != 2) close(ret); } else { printf("failed, not equal.\n"); } } // test: dup stdout to 20, and print a string by 20 printf("dup(1, 20), write(20, \"A test\\n\", 7) : "); fflush(stdout); // i don't know why fsync(1) not work here fun_dup2(1, 20); write(20, "A test\n", 7); printf("\n"); close(20); } int main() { // test my dup2 printf("********* my dup2 ***********\n"); test_mydup2(mydup2); // test standard dup2 for a contrast printf("********standard dup2********\n"); test_mydup2(dup2); return 0; }