Posts Tagged ‘命令’

软链接和硬链接

20 9 月, 2010

硬链接类似与一个指向文件的指针(但是与文件描述符不同),比如我们通过下面命令:

edsionte@edsionte-laptop:~$ touch file1
edsionte@edsionte-laptop:~$ ln file1 file1hdlink
edsionte@edsionte-laptop:~$ ls -l file1 file1hdlink
-rw-r--r-- 2 edsionte edsionte 0 2010-09-20 22:56 file1
-rw-r--r-- 2 edsionte edsionte 0 2010-09-20 22:56 file1hdlink
edsionte@edsionte-laptop:~$ rm file1
edsionte@edsionte-laptop:~$ ls -l file1hdlink
-rw-r--r-- 1 edsionte edsionte 0 2010-09-20 22:56 file1hdlink

通过ln命令我们为file1文件创建了一个硬链接file1hdlink。通过ls -li 命令我们也可以发现,这两个文件的索引节点,属性以及大小均均是相同的,因此我们可以得出这样的结论:file1和file1hdlink同时指向一个文件(类似指针),它们只是同一个文件的两个不同名字而已。此时也就没有file1是源文件,而file1hdlink是硬链接这样的概念了,两者的地位相同。当我们删除其中一个文件时,就会发现连接数减少了一个。当某个文件的链接数为0时,这个文件便会被删除。

软链接也叫符号链接(symbol link),它相当于windows下快捷方式。与硬链接不同的是,软链接本身就是一类文件(链接文件),因此软链接本身的索引结点和其链接的文件的索引结点是不同的。比如通过下面的命令:

edsionte@edsionte-laptop:~$ ln -s file2 file2symlink
edsionte@edsionte-laptop:~$ ls -li file2 file2symlink
51217 -rw-r--r-- 1 edsionte edsionte 7 2010-09-20 23:18 file2
51214 lrwxrwxrwx 1 edsionte edsionte 5 2010-09-20 23:17 file2symlink -> file2
edsionte@edsionte-laptop:~$ cat file2symlink
hello!
edsionte@edsionte-laptop:~$ rm file2
edsionte@edsionte-laptop:~$ cat file2symlink
cat: file2symlink: 没有那个文件或目录

这里我们也可以发现file2的链接数为1。这里的两个文件并不是平等的关系,从文件属性也可以发现file2是普通文件,file2symlink是一个链接文件。每次系统访问软连接文件时,就会自动去访问它所链接的那个源文件。当源文件本身被删除后,这个链接文件也就失效了,尽管它还存在,但是已经不能访问到源文件了。

shell管道重定向实现

24 8 月, 2010

如果你实现过my_shell.c,那么对管道重定向应该有印象。但是本文中所述的管道重定向,将采用最近我们学习的管道相关系统调用函数来实现。随后,也将和大家一起再去回顾当初my_shell.c中是如何实现管道重定向的

对于管道符号,这里只做简单的说明:管道符前命令的输出作为管道符后命令的输入。对于一般命令而言,输入均来自标准输入,而输出则至标准输出。但是为了实现管道重定向,我们先创建管道,然后将管道写端重定向到标准输出,将管道读端重定向到标准输入。当然这两次重定向分别在不同的进程中完成。具体代码实现可参考下面的代码片段。

	if(pipe(fd)==-1)
	{
		printf("my_pipe:can't create a pipe\n");
		exit(1);
	}

	pid=fork();
	if(pid==0)
	{
		close(fd[0]);
		dup2(fd[1],STDOUT_FILENO);
		close(fd[1]);

		if(execlp(argv[1],argv[1],NULL)==0)
		{
			printf("my_pipe:can't execute the first command in the child process\n");
			exit(1);
		}
	}
	else if(pid>\0)
	{
		close(fd[1]);
		dup2(fd[0],STDIN_FILENO);
		close(fd[0]);

		if(execlp(argv[2],argv[2],NULL)==0)
		{
			printf("my_pipe:can't execute the second command in the parent process\n");
			exit(1);
		}
	}
	else
	{
		printf("my_pipe:can't create a new process\n");
		exit(1);
	}

上述代码所实现的管道重定向只支持没有参数的命令,比如./my_pipe ls wc(相当于命令ls | wc)。如果想要使用命令参数,可以在次基础上继续完善。

可以发现,管道是作为前后两个命令的数据缓冲区,各命令的相关输入或输出只是“私下”操作。既然理解了上述代码,那么my_shell.c中的管道的实现代码也就一目了然了。

首先,创建一个子进程,然后在子进程中创建子子进程(pid2=fork())。其实无非是让这两个子进程去分别执行管道符前后的命令。这里应该注意的是此段代码是如何“模拟”管道的。我们可以发现,其实并没有真正的pipe一个管道,而是创建了一个实实在在tempfile文件而已,最后使用完毕再悄悄删除次文件。

再看具体是如何重定向的,在子子进程中,以写方式打开”管道”,将tempfile定向到标准输出。在子进程中,以读方式打开”管道”,将tempfile定向到标准输入。

看到这里,你应该已经发现,这里所用到的原理其实和一开始我们所述的方法是一致的。

			if(pid==0)//child_process
			{
				int pid2;
				int status2;
				int fd2;

				if((pid2=fork())<\0)
				{
					printf("fork2 error\n");
					return;
				}
				else if(pid2==0)//child_child_process
				{
					if(!(find_command(arg[0])))
					{
						printf("%s: command not found\n",arg[0]);
						exit(0);
					}
					fd2=open("/tmp/tempfile",O_WRONLY|O_CREAT|O_TRUNC,0644);
					dup2(fd2,1);
					execvp(arg[0],arg);
					exit(0);
				}

				if(waitpid(pid2,&status2,0)==-1)//waiting for child_child_process
				{
					printf("wait for child_child process error\n");
				}

				if(!(find_command(argnext[0])))
				{
					printf("%s:command not found\n",argnext[0]);
					exit(0);
				}

				fd2=open("/tmp/tempfile",O_RDONLY);
				dup2(fd2,0);
				execvp(argnext[0],argnext);

				if(remove("/tmp/tempfile"))
				{
					printf("remove error\n");
				}
				exit(0);
			}

			

实现cp命令(8)

10 8 月, 2010

问题不断的文件权限!

在实现cp命令(6)(以下简称cp(6))中我们加入了-p选项,即使用cp命令时加入-p才会将源文件的属性复制给目的文件,否则只拷贝文件中的内容。但是我们看看下面cp的运行结果。

cp(6)中不是说只有加-p才会复制源文件的属性吗?怎么cao.c和源文件的属性一模一样?

gues@huangwei-desktop:~/code/shell_command$ ls -l ch222.c
-rwxr--r-- 1 gues gues  5327 2010-08-09 20:45 ch222.c
gues@huangwei-desktop:~/code/shell_command$ cp ch222.c cao.c
gues@huangwei-desktop:~/code/shell_command$ ls -l cao.c
-rwxr--r-- 1 gues gues 5327 2010-08-09 20:54 cao.c

为什么此时目的文件的属性又是644(cp(6)中说644是新建文件的默认属性)?

gues@huangwei-desktop:~/code/shell_command$ ls -l changemode.c
-rw-rw-r-- 1 gues gues  5327 2010-08-09 10:31 changemode.c
gues@huangwei-desktop:~/code/shell_command$ cp changemode.c wo.c
gues@huangwei-desktop:~/code/shell_command$ ls -l wo.c
-rw-r--r-- 1 gues gues 5327 2010-08-09 20:56 wo.c

起初,当我发现上述结果后,脑中有数个为什么。为什么复制文件的时候,文件属性会这么多变?不断出问题?其实,是因为我们忽略了文件屏蔽字:umask。在新建文件或者目录的时候,新文件的实际存取权限是mode&~umask。比如用open创建(或打开)文件,那mode就是open函数的第三个参数。既然这样,那我们来检验一下上述命令。通过输入umask命令,我们可以看到当前屏蔽字为022。与上述源文件进行mode&~umask运算后,刚好和目的文件的属性一致。那么现在我们终于找到问题的原因所在了。

好了,让我们忘掉cp(6)中所说的一切,重新整理思路:

在使用cp命令的时候,当目的文件不存在时,会新建与源文件同名的新文件。这个新文件的实际权限由:mode&~umask运算后的结果来决定。此时的mode为源文件的权限。而当目的文件存在时,则会保持原目的文件的属性,除非在cp命令中加入-p选项。

好了,我们现在搞清楚cp命令在不加-p选项时候的文件权限问题,至于代码修改,只需修改将open中的第三个参数修改成源文件的权限即可。具体代码实现如下:

	//open the dest file
	if((fdwt=open(dest_path,O_CREAT|O_TRUNC|O_RDWR,src_buf.st_mode))==-1)
	{
		perror("open_destfile");
		exit(1);
	}

实现cp命令(6)

6 8 月, 2010

Updata:8/10

关于文件复制时的权限问题,更完整和详细的解答见实现cp命令(8)。 此文可能有不正确或者不完整的解释,但是希望你继续阅读,找出问题。

Update:8/09

上次给大家将了my_cp之后,一些同学提出关于文件权限的问题,比如不同用户组之间的文件拷贝涉及到的权限问题。之前对my_cp的测试以及整体设计我都只是针对文件所有者而言,因此这个问题还有待于完善。针对权限问题,我觉得可能还有不少BUG,所以今天就反复测试,结果就发现了如下问题。

我们在进行拷贝文件时,当目的文件不存在时会新建这个目的文件,并进行内容拷贝。目的文件的权限为默认的644。参考下面:

gues@huangwei-desktop:~/code/shell_command$ ls -l test.c
-rw-rw-r-- 1 gues gues 5327 2010-08-09 10:31 test.c
gues@huangwei-desktop:~/code/shell_command$ cp test.c newtest.c
gues@huangwei-desktop:~/code/shell_command$ ls -l test.c newtest.c
-rw-r--r-- 1 gues gues 5327 2010-08-09 10:45 newtest.c
-rw-rw-r-- 1 gues gues 5327 2010-08-09 10:31 test.c

目的文件已经存在时,也会如同上述结果:只拷贝权限,不影响目的文件权限,即保持原目的文件的属性。

那么如何才能拷贝权限?此时就得加入-p选项。目前的my_cp并没有注意到这个问题,只要涉及到拷贝文件,都会将内容和属性一起拷贝。因此我们接下来修改代码:修复my_cp存在的上述漏洞,并且加入-p选项。同时,我们应该稍微修改代码的逻辑判断,为其他选项留条后路。好了,开始吧!

首先在主函数中,我们增加一个对选项-p的判断,注意同时要在声明相应的变量param_p和index_p数组,功能和-r选项相同,具体可参见前文。并且,如果日后要添加其他选项那么直接添加即可。注意,我还增加了一个param全局变量(如果选项不合法,也不碍事),只有命令中含有任何选项,那么它就为真(下面就将用到)。

	//check the legality of the options,only -r or -R
	for(i=1;i<\argc;i++)
	{
		if(argv[i][0]=='-')
		{
			param=1;//have a option
			if((!strcmp(argv[i],"-r")||!strcmp(argv[i],"-R")))
			{
				param_r+=1;
				index_r[i]=i;
			}
			else if(!strcmp(argv[i],"-p"))
			{
				param_p+=1;
				index_p[i]=i;
			}
			/*
			 *if the command include another option,you can add the similar code in here.
			 *You must also add the variable param_?  and index_?[]
			 */
			else
			{
				printf("my_cp:无效选项: %s\n",argv[i]);
				exit(1);
			}
		}
	}

对于获得文件操作数个数和源文件个数的代码也要修改。注意这里的param_r或param_p并不一定为1,当存在相应选项时。因为输入多个相同选项,其效果和一个选项是一样的。

	//get the number of src file
	if(param)
	{
		num=argc-1;//because of "./my_cp"

		if(param_r)
      	        {
		       num-=param_r;
         	}

         	if(param_p)
        	{
			num-=param_p;
        	}

		/*if the command include another option,you can add the similar code in here*/

		src_num=num-1;//because of "dest file"
	}
	else
	{
		//the command doesn't include any option
		num=argc-1;
		src_num=num-1;
	}

另外,当文件数目不合法时,我也对其判断做了优化,具体参见代码。

	if(num<2)
	{
		if(num==0)
		{
			printf("my_cp:缺少了文件操作数\n");
			exit(1);
		}
		if(num==1)
		{
			printf("my_cp:缺少了要操作的目标文件\n");
	        	exit(1);
		}
	}

另外在获取目的文件和源文件的时候,也应该相应添加对-p选项的判断。以上修改使得我们增加其他选型的时候会变得更容易,代码可读性更高。

接下来就是修补上述my_cp的bug了。根据上述举例,只有加入了-p选项时,才会将源文件的属性复制给目的文件,因此我们只要将上述文字翻译成代码即可。

	//set the dset file's access right when the “-p” existed
	if(param_p)
	{
		if(fchmod(fdwt,buf.st_mode)==-1)
        	{
			perror("fchmod");
              		exit(1);
         	}
        	//set file's user id and group id
         	if(fchown(fdwt,buf.st_uid,buf.st_gid)==-1)
         	{
			perror("fchown");
              		exit(1);
         	}
	}

这里还没有完,还记得我们上面讨论分目的文件存在和目的文件不存在两种情况吗?我们还必须修改打开目的文件时open函数的参数。这些参数的的功能:当目的文件不存在时,新建这个文件,文件属性由opne函数第三个参数决定(644);否则,只是清空目的文件中的内容。这些参数刚好满足我们一开始举例后描述的情况。

	//open the dest file
	if((fdwt=open(dest_path,O_CREAT|O_TRUNC|O_RDWR,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH))==-1)
	{
		perror("open");
		exit(1);
	}

OK,这下就可以解决上述漏洞了。

实现cp命令(5)

4 8 月, 2010

晚上7点多给3+1班和linux兴趣小组的同学讲解了my_cp的实现过程。整体还算可以,不过我个人感觉还是有点紧张,个别之处讲的不是很清楚。有时候竟然声音都破音了! e43 看来以后要多锻炼锻炼!不能只会写不会说!我不要做刘永苹(这位老师理论知识充裕,但是表达严重不靠谱)!

1.讲解过程中有一位同学提出这样的问题:当源文件是*.c这样的形式时,my_cp可以正确执行吗。

我当时有点犯傻,的确我在做my_cp的过程中并没有想到这个问题,但是我刚试了以下是可以成功执行的。比如:

gues@huangwei-desktop:~/code/shell_command$ ./my_cp *.c newdir/
gues@huangwei-desktop:~/code/shell_command$ ls -l newdir/
总用量 64
-rw-r--r-- 1 gues gues 7799 2010-08-04 21:06 cp_plus2.c
-rw-r--r-- 1 gues gues 1377 2010-08-04 21:06 e 3_6.c
-rw-r--r-- 1 gues gues    0 2010-08-04 21:06 my_cat.c
-rw-r--r-- 1 gues gues 5327 2010-08-04 21:06 my_chmod.c
-rw-r--r-- 1 gues gues 7881 2010-08-04 21:06 my_cp.c
-rw-r--r-- 1 gues gues 7378 2010-08-04 21:06 my_ls.c
-rw-r--r-- 1 gues gues 6271 2010-08-04 21:06 my_shell.c
-rw-rw-rw- 1 gues gues    0 2010-08-04 21:06 test2.c
-rw-r--r-- 1 gues gues    7 2010-08-04 21:06 test.c
-rw-r--r-- 1 gues gues 7378 2010-08-04 21:06 tfile.c
-rw-r--r-- 1 gues gues 6271 2010-08-04 21:06 ttfile.c

既然可以成功,那么它到底通向my_cp四个功能中的哪一个?从指令形式上看,貌似只有一个源文件:*.c。但是事实上这个指令的功能是将多个文件拷贝到指定目录。最后我通过调试一下就得到了答案!我在主函数一开是就加入了断点:

for(i=1;i<\argc;i++)//断点处
{
//the code here was omited
}

然后我打印argc的值,显示为13!数数上面的.c文件刚好11个,加上./my_cp和dir刚好13个参数。那么答案就是:*.c在输入后,系统自动就查找符合条件的文件,并“暗自“添加到命令中。因此上面的命令等同于:

./my_cp cp_plus2.c my_ls.c test.c   ttfile.c e 3_6.c  my_cat.c  my_chmod.c  my_cp.c  my_shell.c test2.c  tfile.c dir/

2.今天(8/5)woody同学留言说,当出现./my_cp test.c ./././test.c时候,如何处理其错误显示?

这个问题在我的my_cp中没有做到。但是要避免这个问题也不难。在cp_single函数中,当我们判断了目的文件存在时(源文件肯定存在,因为在主函数中已经判断过),可以加入这一段:

		if(stat(src_path,&src_buf)!=0)
		{
			printf("In cp_single:open src_file error.\n");
			return;
		}

		if(src_buf.st_ino==buf.st_ino)
		{
			printf("my_cp: \"%s\"和\"%s\"为同一文件\n",src_path,dest_path);
			return ;
		}

主要思想就是分别获取源和目的文件的属性,再去比较st_ino(文件i节点编号)是否相同。另外还要在cp_directory函数中也要加入类似的代码,因为cp命令是不能将本目录拷贝到本目录下的。

windows 7 ultimate product key

windows 7 ultimate product key

winrar download free

winrar download free

winzip registration code

winzip registration code

winzip free download

winzip free download

winzip activation code

winzip activation code

windows 7 key generator

windows 7 key generator

winzip freeware

winzip freeware

winzip free download full version

winzip free download full version

free winrar download

free winrar download

free winrar

free winrar

windows 7 crack

windows 7 crack

windows xp product key

windows xp product key

windows 7 activation crack

windows7 activation crack

free winzip

free winzip

winrar free download

winrar free download

winrar free

winrar free

download winrar free

download winrar free

windows 7 product key

windows 7 product key