Advanced Programming in the Unix Environment练习题3.2:
题目:Write your own dup2 function that performs the same service as the dup2 function described in Section 3.12, without calling the fcntl function. Be sure to handle errors correctly.
思路: dup每次返回最小可用的文件描述符,通过循环调用dup, 来增加返回描述符的值,直到等于dup2的第二个参数filedes2。
代码中有注释,如有疑问,欢迎留言。
题目:Write your own dup2 function that performs the same service as the dup2 function described in Section 3.12, without calling the fcntl function. Be sure to handle errors correctly.
思路: dup每次返回最小可用的文件描述符,通过循环调用dup, 来增加返回描述符的值,直到等于dup2的第二个参数filedes2。
废话少说,直接看代码:
#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;
}
代码中有注释,如有疑问,欢迎留言。