文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>实现cp命令(6)

实现cp命令(6)

时间:2010-08-09  来源:edsionte

Update: 8/9

上次给大家将了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,这下就可以解决上述漏洞了。

排行榜 更多 +
辰域智控app

辰域智控app

系统工具 下载
网医联盟app

网医联盟app

运动健身 下载
汇丰汇选App

汇丰汇选App

金融理财 下载