1. 程式人生 > >C語言實現linux pwd命令

C語言實現linux pwd命令

實驗內容

通過實現Linux的pwd命令,以理解Linux檔案系統的基本概念一集內部實現,並熟悉Linux系統與檔案系統相關的系統呼叫介面。

知識點:

  • 列表內容
  • Linux pwd命令
  • Linux檔案系統中檔案及目錄的實現方式
  • Linux檔案及目錄系統呼叫介面的使用

pwd命令

pwd命令的用處是輸出當前工作目錄的絕對路徑,可以不帶任何引數直接使用。

1.0版本的pwd

/*
 * 檔名: mypwd1.c
 * 描述:通過系統函式getcwd實現pwd命令
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> int main(void) { char buf[1024]; char *cwd =getcwd(buf, sizeof(buf)); if (NULL == cwd) { perror("Get cerrent working directory fail.\n"); exit(-1); } else { printf("Current working directory is : %s\n", cwd); } return 0; }

雖然這段程式碼實現了pwd的功能,但是卻依然無法為我們解答pwd是如何工作的。

要了解pwd是如何工作的,我們還必須先了解Linux中對於檔案目錄的組織方式開始。

Linux中的檔案

在Linux中的檔案系統中,檔案=N(N>=1)個inode+M(M>=1)個數據塊

資料塊,存放檔案的內容資料,資料塊的數目根據檔案內容大小而定。

inode成為資訊節點,有兩個作用:

  1. 儲存根檔案線管的屬性資訊,如修改時間、所有者、檔案型別和檔案長度,並沒有檔名
  2. 儲存指向檔案內容資料塊的指標資訊。

在一個檔案系統中,一個inode代表一個檔案,並使用一個整數值來表示該inode,成為inode-number

,該值對於一個檔案系統而言是唯一的,即通過該值可以找到其對應的inode。一般情況下,一個檔案只有一個inode資訊來描述它。

下面通過一段程式來獲取某個檔案的inode資訊:

*  檔名:filestat.c
*  描述:列印指定檔名的inode資訊
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

struct stat file_stat;

void print_file_stat(struct stat *fs)
{
    printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
    printf("inode: \t\t\t\t%ld\n", fs->st_ino);
    printf("protection: \t\t\t%o\n", fs->st_mode);
    printf("number of hard links: \t\t%lu\n", fs->st_nlink);
    printf("user ID of owner: \t\t%d\n", fs->st_uid);
    printf("group ID of owner: \t\t%d\n", fs->st_gid);
    printf("file size in bytes: \t\t%ld\n", fs->st_size);
    printf("time of last access: \t\t%s", ctime(&fs->st_atime));
    printf("time of last modification: \t%s", ctime(&fs->st_mtime));
    printf("time of last change: \t\t%s", ctime(&fs->st_ctime));
}   

int main(int argc, char* argv[])
{   

    if (2 != argc) {
        fprintf(stderr, "Usage: %s filename...\n", argv[0]);
        exit(-1);
    }

    if (0 != stat(argv[1], &file_stat)) {
        perror("stat"); 
        exit(-1);
    }

    print_file_stat(&file_stat);

    return 0;
}

Linux中的目錄

在Linux系統中,檔案系統通過目錄“包含”子目錄及檔案的方式,來組織成一個樹狀結構。那麼目錄是如何“包含”其他目錄及檔案的呢?

目錄,在Linux中,其實也是一種檔案,所以它也是由“inode+資料塊”構成的。而氣溫件內容是一個列表,每一個列表記錄“inode-number+filename”。

因此,我們通常所說的目錄a“包含”檔案b,其實現層面上的意思是,目錄a的內容列表裡有一個關於檔案b的列表項,即“b的inode-number+b的filename”。

綜上,Linux中,一個檔案(包括目錄)的檔名,及檔名與inode的對應關係,都是由包含該檔案的目錄所描述的。

下面的例子,掩飾瞭如何列印指定目錄的內容列表:

/*
* 檔名:directorylist.c
* 描述:列印指定目錄的內容列表
*/
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <sys/types.h>

int main(int argc, char *argv[])
{
    if (2 != argc) {
        fprintf(stderr, "Usage: %s directory...\n", argv[0]);
        exit(-1);
    }

    DIR *dp = NULL;
    struct dirent *dptr = NULL;
    if (NULL == (dp = opendir(argv[1]))) {
        fprintf(stderr, "Can not open Input Directory [%s]\n", argv[1]);
        exit(-1);
    } else {
        printf("Directory [%s] Content List: \n", argv[1]);
        while (NULL != (dptr = readdir(dp))) {
            printf("inode-number: %-10ld \t filename: %s\n", dptr->d_ino, dptr->d_name);
        }

        closedir(dp);
    }

    return 0;
}

實現pwd命令

實現思路:
1. 通過特殊的檔名”.”獲取當前目錄的inode-number(假設當前目錄為a)
2. 通過特殊的檔名”..”獲取當前目錄的父級目錄的inode-number
3. 判斷當前目錄和上級目錄的inode-number是否一樣
4. 如果兩個inode-number一樣說明達到根目錄,輸出完整路徑,退出程式
5. 如果兩個inode-number不一樣,切換至父級目錄,根據步驟1獲取的inode-number,在父級目錄中搜索對應的檔名並記錄下來,然後重新回到步驟1

實現程式碼:

/*
* 檔名:mypwd.c
* 描述:實現簡單的pwd命令
*/
#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)) {
        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("."))) {
        fprintf(stderr, "Can not open Current Directory\n");
        exit(-1);
    } else {
        while (NULL != (dptr = readdir(dp))) {
            if (dptr->d_ino == ino) {
                filename = strdup(dptr->d_name);
                break;
            }
        }
        closedir(dp);
    }
    return filename;
}

/*限制最大的目錄深度*/
#define MAX_DIR_DEPTH (256)

int main(int argc, char *argv[])
{
    /*記錄目錄名的棧*/
    char *dir_stack[MAX_DIR_DEPTH];
    unsigned current_depth = 0;

    for(;;) {
        /*1.通過特殊的檔名“.”獲取當前目錄的inode-number*/
        ino_t current_ino = get_ino_byname(".");
        /*2.通過特殊的檔名“..”獲取當前目錄的父級目錄的inode-number*/
        ino_t parent_ino = get_ino_byname("..");

        /*3.判斷當前目錄和上級目錄的inode-number是否一樣*/
        if (current_ino == parent_ino)
            break; /*4.如果兩個inode-number一樣說明到達根目錄*/

        /*5.如果兩個inode-number不一樣*/
        /*切換至父級目錄,根據步驟1獲取的inode-number,在父級目錄中搜索對應的檔名並記錄下來, 重新回到步驟1*/
        chdir("..");
        dir_stack[current_depth++] = find_name_byino(current_ino);
        if (current_depth>=MAX_DIR_DEPTH) { /*路徑名太深*/
             fprintf(stderr, "Directory tree is too deep.\n");
             exit(-1);
        }
    }

    /*輸出完整路徑名*/
    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;
}

參考資料

相關推薦

C語言實現linux pwd命令

實驗內容 通過實現Linux的pwd命令,以理解Linux檔案系統的基本概念一集內部實現,並熟悉Linux系統與檔案系統相關的系統呼叫介面。 知識點: 列表內容 Linux pwd命令 Linux檔案系統中檔案及目錄的實現方式 Linux檔

c語言實現linux下高危函式system (簡易V1.0版本)

system這個函式真的是要慎用,一不小心就會留下漏洞。 下面是用c語言簡易的實現了一下system函式 #include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<err

c語言實現linux下高危函式system (簡易V1.0版本)

system這個函式真的是要慎用,一不小心就會留下漏洞。 下面是用c語言簡易的實現了一下system函式 #include<stdio.h> #include<stdlib.h> #include<unistd.h> #inc

c語言實現檔案拷貝命令

主要知識:main函式引數、檔案讀寫 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h>

C語言實現Linux系統的cp指令

在實現cp指令之前,首先先要了解這樣一個概念,我們平時在寫程式碼時 int main() 這個括號裡省略了3個引數。 int main(int argc,char** argv,char** environ) //argc 表示引數的數量 //argv 是一個字串陣列

linux whoami cp mv mesg 命令 c語言實現

whoami實現 #include<stdio.h>#include<pwd.h>#include<sys/types.h>#include<unistd.h>int main(){ uid_t id; struc

Linux下:用 C 語言實現 ls 命令

這次主要的目的是用 C語言 實現 Linux 系統中的 ls 命令。 在編寫命令之前,需要介紹一下幾個結構體: 第一個 DIR: struct __dirstream { void *__fd; char *__data; in

Linux下的ls命令詳解以及C語言實現

一、眾所周知,ls是linux下最常用的命令之一,使用起來也相當的快捷與方便,ls 命令將每個由 Directory 引數指定的目錄或者每個由 File 引數指定的名稱寫到標準輸出,以及您所要求的和標誌一起的其它資訊。如果不指定 File 或 Directory

linux中用C語言實現ping命令

運用C語言編寫模擬常用網路命令ping命令實現一個基於Linux原始套接字和ICMP協議的ping程式。該程式能用於檢測主機或路由器工作是否正常。 程式中主要的函式 void alarm_handler(int); /*SIGALRM處理程式*/ void int_h

c語言執行linux命令並通過結構體返回每行命令的輸出

打印 linux pop sscanf [] #define ufs pan pipe #include <stdio.h> #include <stdlib.h> #include <unistd.h>

Linux終端程序用c語言實現改變輸出的字的顏色

光標位置 高亮 AI 藍色 屬性 用c語言實現 TE c語言 說明 顏色代碼: 格式: echo "\033[字背景顏色;字體顏色m字符串\033[0m" 例如: echo "\033[41;36m something here \033[0m" 其中41的位置代表

c語言實現cp命令

#include<stdio.h> #include<unistd.h> #include<errno.h> #include<sys/types.h> #include<sys/stat.h> #include<fcntl.

(排序演算法)linux c語言實現選擇排序演算法(氣泡排序的略微改進版)

 快速排序演算法和氣泡排序演算法是差不多的,都是要兩層迴圈,外迴圈是要比較的個數,其實就是元素的個數,內迴圈就是外層那個標記和其他的比較大小, 氣泡排序是相鄰的兩個,兩兩比較,最後交換出一個最大或者最小值, 快速排序是在氣泡排序的基礎上,找出那個最小的或者最大的,但是不是直接交換,

(排序演算法)linux c語言實現快速排序(氣泡排序的改進版)

 快速排序演算法是對氣泡排序演算法的一種改進,氣泡排序是對單個元素的升降,快速排序是對所有元素的升降,不過這個升降是取了某一個標準的前提下,在本文程式碼中,就以a[i],其實就是以最左邊的元素為參考,比較交換之後,將這個參考元素放到分界的地方,即i的位置。 程式碼如下,裡面有比較詳細的

(排序演算法)linux c語言實現二分插入排序演算法(簡化版本的插入排序演算法)

 二分插入演算法是在已經排序好的序列裡插入一個元素,是穩定的演算法,關鍵詞是折中。 比如說我要在12345678910裡插入一個3,那麼我先看看中間的數比3大,還是比3小,要是比3大,我就去後一半,如果是比3小,我就去前一半,現在進入某個一半後,再做如此操作,最後將其他的元素依次往後挪

linux系統C語言實現域名解析功能

版權宣告:本文為遲思堂主人李遲原創文章,版權所有。可隨便任意使用(包括學習研究商用),但由此帶來的成果或後果,概與作者無關。胡亂修改的,不註明出處的,概不負責。 https://blog.csdn.net/subfate/article/details/81776147 背景 後臺專案劃分幾個小

[linux]二叉樹的建立及其遞迴遍歷(C語言實現)

基礎知識 二叉樹的特點: 每一個節點最多有兩棵子樹,所以二叉樹中不存在度大於2的節點,注意,是最多有兩棵,沒有也是可以的 左子樹和右子樹是有順序的,次序不能顛倒,這點可以在哈夫曼編碼中體現, 順序不同編碼方式不同 -即使樹中某個節點中只有一個子樹的花,也要區分它是左子樹還是右子樹

Linux C語言實現帶顏色進度條

Linux 的 bash 命令列直譯器會輸出有顏色的字型 那怎麼做到的呢? print( "\033[字背景顏色;字型顏色m字串\033[0m"); 下面給出一些背景顏色和字型顏色 具體搭配就看你的嘍 字背景顏色範圍:40----49 40:黑 41:深紅

Linux下用c語言實現發送http請求 方式可以Get或者Post例程參考

sockaddr select sleep online 創建 線程終止 index -s lse [1].[代碼] Linux下用c語言實現發送http請求 方式可以Get或者Post 跳至 [1] ? 1 2 3 4 5 6 7 8 9 10 11 12 1

Linux下用c語言實現傳送http請求 方式可以Get或者Post例程參考

[1].[程式碼] Linux下用c語言實現傳送http請求 方式可以Get或者Post 跳至 [1] ? 1 2