2017-2018-1 20155330 《信息安全系统设计基础》加分项目--实现mypwd

2017-2018-1 20155330 《信息安全系统设计基础》加分项目--实现mypwd

pwd命令

  • 命令功能:查看”当前工作目录“的完整路径。
    1071510-20171119145502499-914565794.png
  • 通过man命令查看pwd的相关信息
    1071510-20171119145658015-1296814924.png

    mypwd的实现

    研究pwd实现需要的系统调用(man -k; grep),写出伪代码

  • 通过man -k directory | grep 2查看相关系统调用。可以发现getcwd()函数是实现该功能的相关函数。
    1071510-20171119150308218-747882979.png
  • 通过man 2 getcwd查看函数结构。
    1071510-20171119150652952-1712826115.png
  • 利用getcwd()函数简单实现的伪代码

设置一个char型数组(或指针)用于保存当前绝对路径内容;
调用系统函数`getcwd()`获取当前路径并保存在之前的数组中;
if(返回指针==NULL)
    错误;
else
    打印当前路径;
  • 代码
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#define MAX 2048

int main()
{
    char buf[MAX],*a=getcwd(buf,sizeof(buf));
    if(a==NULL)
        printf("Error!");
    else
        printf("%s\n",a);
    return 0;
}

运行结果:1071510-20171119151829734-1125963908.png

  • 通过man -k directory | grep 3查看相关库函数。
    1071510-20171119152749062-924890337.png
  • 通过之前查看的getcwd函数可知getcwd函数与getwd函数基本相同。现在查看opendir()函数和readdir()函数。
    • opendir()函数
      1071510-20171119153126499-1420314649.png
    • readdir()函数
      1071510-20171119153218437-620158128.png
  • readdir()函数中的结构体
struct dirent {
           ino_t          d_ino;       /* inode number */
           off_t          d_off;       /* not an offset; see NOTES */
           unsigned short d_reclen;    /* length of this record */
           unsigned char  d_type;      /* type of file; not supported
                                          by all filesystem types */
           char           d_name[256]; /* filename */
       };

可以知道显示文件名需要与之对应的i-node

  • 获得i-node可用stat函数,需要注意的是,在使用帮助文档查看stat函数时,应使用命令man 2 stat1071510-20171119161123140-633625234.png
  • 代码实现查看inode功能
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
       {
           struct stat sb;

           if (argc != 2) {
               fprintf(stderr, "Usage: %s <pathname>\n", argv[0]);
               exit(EXIT_FAILURE);
           }

           if (stat(argv[1], &sb) == -1) {
               perror("stat");
               exit(EXIT_FAILURE);
           }

           printf("File type:                ");

           switch (sb.st_mode & S_IFMT) {
           case S_IFBLK:  printf("block device\n");            break;
           case S_IFCHR:  printf("character device\n");        break;
           case S_IFDIR:  printf("directory\n");               break;
           case S_IFIFO:  printf("FIFO/pipe\n");               break;
           case S_IFLNK:  printf("symlink\n");                 break;
           case S_IFREG:  printf("regular file\n");            break;
           case S_IFSOCK: printf("socket\n");                  break;
           default:       printf("unknown?\n");                break;
           }

           printf("I-node number:            %ld\n", (long) sb.st_ino);

           printf("Mode:                     %lo (octal)\n",
                   (unsigned long) sb.st_mode);

           printf("Link count:               %ld\n", (long) sb.st_nlink);
           printf("Ownership:                UID=%ld   GID=%ld\n",
                   (long) sb.st_uid, (long) sb.st_gid);

           printf("Preferred I/O block size: %ld bytes\n",
                   (long) sb.st_blksize);
           printf("File size:                %lld bytes\n",
                   (long long) sb.st_size);
           printf("Blocks allocated:         %lld\n",
                   (long long) sb.st_blocks);

           printf("Last status change:       %s", ctime(&sb.st_ctime));
           printf("Last file access:         %s", ctime(&sb.st_atime));
           printf("Last file modification:   %s", ctime(&sb.st_mtime));

           exit(EXIT_SUCCESS);
       }
  • 运行结果1071510-20171119162210265-1459587293.png
  • 综合以上信息得到伪代码
设置一个char型数组(或指针)用于保存当前绝对路径内容,无符号数用于记录绝对路径的深度;
while(1)
{
    分别获取"."(当前目录)和".."(当前目录的上一级目录)i-node;
    if("."i-node==".."i-noode)
        输出目录信息;
    else
    {
        切换至父级目录获取i-node
        在父级目录中搜索对应的文件名并记录下来
    }
}
  • 完整代码
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <unistd.h>

//获取文件的inode-number
ino_t get_ino_byname(char *filename)
{
    struct stat file_stat;
    if(0 != stat(filename, &file_stat)) //stat()通过文件名filename获取文件信息,并保存在buf所指的结构体stat中
    {
        perror("stat");
        exit(-1);
    }

    return file_stat.st_ino;
}

//根据inode-number, 在当前目录中查找对应文件名
char *find_name_byino(ino_t ino)
{
    DIR *dp = NULL;
    struct dirent *dptr = NULL;
    char *filename = NULL;
    
    if(NULL == (dp = opendir("."))) //opendir()打开一个目录,在失败的时候返回一个空的指针,成返回DIR结构体
    {
        fprintf(stderr, "Can not open Current Directory\n");
        exit(-1);
    }
    else
    {
        while(NULL != (dptr = readdir(dp))) //readdir()用来读取目录。返回是dirent结构体指针
        {
            if(dptr->d_ino == ino)
            {
                filename = strdup(dptr->d_name); //strdup()将串拷贝到新建的位置处,返回一个指针,指向为复制字符串分配的空间;如果分配空间失败,则返回NULL值.
                break;
            }
        }

        closedir(dp);
    }

    return filename;
}

int main(int argc, char *argv[])
{
    //记录目名的栈
    char *dir_stack[256];
    unsigned current_depth = 0;

    while(1)
    {
        ino_t current_ino = get_ino_byname("."); //通过"."获取当期目录inode
        ino_t parent_ino = get_ino_byname(".."); //通过".."获取当前目录的父目录的inode
        if(current_ino == parent_ino)
            break;               //达到根目录,推出循环

        /*若两个inode不一样*/
        chdir(".."); //更改当前工作目录,变为当前目录的父目录
        dir_stack[current_depth++] = find_name_byino(current_ino); //"文件名"地址存放
    }

    int i = current_depth - 1;
    for(i = current_depth - 1; i >= 0; i--) //打印路径
    {
        fprintf(stdout, "/%s", dir_stack[i]);
    }
    fprintf(stdout, "%s\n", current_depth == 0 ? "/" : "");

    return 0;
}

运行结果:1071510-20171119171418109-895926013.png

转载于:https://www.cnblogs.com/ashin-kl/p/7860382.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值