APUE练习题3.2——write your own dup2

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。

废话少说,直接看代码:


#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;
}

代码中有注释,如有疑问,欢迎留言。

你可能感兴趣的:(linux,unix,dup2,apue)