Linux高級環(huán)境編程之5磁盤文件屬性管理

課程目標(biāo)

  1. 編程目標(biāo):
    (a)實(shí)現(xiàn)ls –l全部功能。
    (b)實(shí)現(xiàn)tree工具全部功能篮幢。
  2. 理解文件系統(tǒng)對磁盤文件的管理策略丈积。
  3. 掌握文件屬性獲取與修改的API應(yīng)用鬼悠。
  4. 特殊文件的基本信息。

主要知識點(diǎn)

  1. VFS文件系統(tǒng)以及ext2/3/4文件系統(tǒng)結(jié)構(gòu)捌木。
  2. 文件信息存儲inode以及文件類型油坝,文件屬性的獲取。
  3. 文件屬性的獲取與修改刨裆。
  4. 編程應(yīng)用澈圈。

1—Linux一切都是文件及文件系統(tǒng)

  • 一切皆文件的概念
    Linux一切皆為文件的思想是基于虛擬文件系統(tǒng)(Virtual File System,VFS)實(shí)現(xiàn)帆啃。把底層的硬件實(shí)現(xiàn)全部隱藏瞬女,用戶操作普通文件或者其它的硬件設(shè)備,都基于文件系統(tǒng)的方式努潘,即基本上都可以使用open/read/write/close這些文件操作的系統(tǒng)調(diào)用來訪問诽偷。便于應(yīng)用層的程序開發(fā)。
  • Linux下根據(jù)設(shè)備的屬性將文件分為7類:
文件類型 類別 標(biāo)識符
普通文件 磁盤文件 -
目錄文件 磁盤文件 d
鏈接文件 磁盤文件 l
字符設(shè)備文件 設(shè)備文件 c
塊設(shè)備文件 設(shè)備文件 b
管道文件 進(jìn)程通信文件 p
socket文件 網(wǎng)絡(luò)通信文件 s
  • 磁盤文件系統(tǒng)怎么來管理文件疯坤?

    struct inode結(jié)構(gòu)體存儲了文件的**基本屬性报慕,這個屬性在內(nèi)核中定義。
    在終端中輸入man 2 stat查看stat相關(guān)信息:
       #include <sys/types.h>
       #include <sys/stat.h>
       #include <unistd.h>

       int stat(const char *path, struct stat *buf);
       int fstat(int fd, struct stat *buf);
       int lstat(const char *path, struct stat *buf);
以上三個函數(shù)可以獲取某個文件的詳細(xì)的屬性压怠,
可以通過 strut stat結(jié)構(gòu)體查看

           struct stat {
               dev_t     st_dev;     /* ID of device containing file */
               ino_t     st_ino;     /* inode number */  文件在當(dāng)前文件系統(tǒng)下的唯一編號
               mode_t    st_mode;    /* protection */ 存放的是文件的類型以及權(quán)限
               nlink_t   st_nlink;   /* number of hard links */ 硬鏈接個數(shù)
               uid_t     st_uid;     /* user ID of owner */ 擁有者ID
               gid_t     st_gid;     /* group ID of owner */ 擁有組ID
               dev_t     st_rdev;    /* device ID (if special file) */
               off_t     st_size;    /* total size, in bytes */ 文件的大小
               blksize_t st_blksize; /* blocksize for file system I/O */ 塊的大小
               blkcnt_t  st_blocks;  /* number of 512B blocks allocated */ 塊的個數(shù)
               time_t    st_atime;   /* time of last access */ 最近訪問時(shí)間
               time_t    st_mtime;   /* time of last modification */ 最近修改熟悉的時(shí)間
               time_t    st_ctime;   /* time of last status change */ 最近修改內(nèi)容的時(shí)間
           };

查看文件編號ls -li

2—文件類型及文件模式

mode_t st_mode; /* protection */ 存放的是文件的類型以及權(quán)限

3個bit的權(quán)限修飾位
  • setuid位
  • setgid位
    以上兩個bit被設(shè)置后眠冈,相應(yīng)的執(zhí)行這個文件時(shí),會提升它的執(zhí)行權(quán)限
    /usr/bin/passwd可執(zhí)行文件為例刑峡。用戶的密碼存儲在/etc/passwd/shadow文件中:
delphi@delphi-vm:~/code/test$ ll /etc/shadow
-rw-r----- 1 root shadow 1010 2014-08-26 21:53 /etc/shadow

從以上可以看出洋闽,普通用戶對這個文件沒有寫的權(quán)限,因此突梦,如果用vi編輯器修改肯定是不可以的诫舅。但是,普通用戶可以使用passwd這個命令來修改自己的密碼宫患,也就是修改了/etc/shadow這個文件刊懈。原因時(shí)/usr/bin/passwd這個可執(zhí)行文件被設(shè)置了setuid

delphi@delphi-vm:~/code/test$ ll /usr/bin/passwd
-rwsr-xr-x 1 root root 37100 2011-02-15 06:12 /usr/bin/passwd*

當(dāng)普通用戶執(zhí)行這個程序時(shí)娃闲,因?yàn)樵O(shè)置了setuid位虚汛,相應(yīng)的這個進(jìn)程對文件的訪問權(quán)限上升到該可執(zhí)行文件擁有者的權(quán)限,在這個地方就是普通用戶執(zhí)行時(shí)皇帮,對文件的讀寫的權(quán)限被提升為這個文件的擁有者root的權(quán)限卷哩,而root用戶對/etc/shadow文件有寫的權(quán)限,因此属拾,可以修改密碼成功将谊。

  • 粘貼位:在早期計(jì)算機(jī)冷溶,如果一個可執(zhí)行文件被設(shè)置此位,期望這個可執(zhí)行文件常駐內(nèi)存尊浓,提高運(yùn)行的速率

3—磁盤文件屬性讀取與修改編程

1. 權(quán)限的修改

man 2 chmod

       #include <sys/stat.h>

       int chmod(const char *path, mode_t mode);
       int fchmod(int fd, mode_t mode);

man 2 umask

mode_t umask(mode_t mask);//修改和獲取當(dāng)前的umask值逞频。默認(rèn)0022

源碼中對于權(quán)限的宏定義

#define S_IRWXU 00700      //擁有者讀寫執(zhí)行的權(quán)限
#define S_IRUSR 00400       //擁有者讀的權(quán)限
#define S_IWUSR 00200      //擁有者寫的權(quán)限
#define S_IXUSR 00100       //擁有者執(zhí)行的權(quán)限

#define S_IRWXG 00070
#define S_IRGRP 00040
#define S_IWGRP 00020
#define S_IXGRP 00010

#define S_IRWXO 00007
#define S_IROTH 00004
#define S_IWOTH 00002
#define S_IXOTH 00001

新創(chuàng)建的文件的權(quán)限
如果使用以下權(quán)限新創(chuàng)建文件

S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH
(octal 0666) when creating a new file, the permissions on the resultingfile will be:
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH
(because 0666 & ~022 = 0644; i.e., rw-r--r--).

最終這個文件的權(quán)限:0666& ~022 = 0644,而~022就是umask值

  • 默認(rèn)新創(chuàng)建文件的權(quán)限:0666&~umask
  • 默認(rèn)新創(chuàng)建的目錄的權(quán)限:0777&~umask

2.用戶的信息

uid_t     st_uid;     /* user ID of owner */ 擁有者ID
gid_t     st_gid;     /* group ID of owner */ 擁有組ID

/etc/passwd存儲的是用戶的ID以及相關(guān)信息栋齿。
/etc/group存儲的是組的ID以及相關(guān)信息苗胀。
通過 stat返回的是用戶的ID,要獲取它的用戶名瓦堵,實(shí)際是讀取對應(yīng)的文件基协。

       #include <sys/types.h>
       #include <pwd.h>

       struct passwd *getpwnam(const char *name);
       struct passwd *getpwuid(uid_t uid);

返回的是一個struct passwd指針:
           struct passwd {
               char   *pw_name;       /* username */
               char   *pw_passwd;     /* user password */
               uid_t   pw_uid;        /* user ID */
               gid_t   pw_gid;        /* group ID */
               char   *pw_gecos;      /* real name */
               char   *pw_dir;        /* home directory */
               char   *pw_shell;      /* shell program */
           };
       #include <sys/types.h>
       #include <grp.h>

       struct group *getgrnam(const char *name);
       struct group *getgrgid(gid_t gid);
返回一個 struct group指針:
           struct group {
               char   *gr_name;       /* group name */
               char   *gr_passwd;     /* group password */
               gid_t   gr_gid;        /* group ID */
               char  **gr_mem;        /* group members */
           };

3. 相關(guān)時(shí)間

struct stat中時(shí)間分為以下三種:

time_t    st_atime;   /* time of last access */ 最近訪問時(shí)間
time_t    st_mtime;   /* time of last modification */ 最近修改熟悉的時(shí)間
time_t    st_ctime;   /* time of last status change */ 最近修改內(nèi)容的時(shí)間

查找man 2 utime

#include <sys/types.h>
#include <utime.h>

int utime(const char *filename, const struct utimbuf *times);

struct utimbuf {
     time_t actime;       /* access time */
     time_t modtime;      /* modification time */
};

struct timeval {
     long tv_sec;        /* seconds */
     long tv_usec;       /* microseconds */
};

4. 文件大小

文件的大小:可以把一個文件截短或擴(kuò)展

  • 截?cái)啵?code>truncate
       #include <unistd.h>
       #include <sys/types.h>

       int truncate(const char *path, off_t length);
       int ftruncate(int fd, off_t length);

如果length小于當(dāng)前文件大小菇用,截短堡掏;如果大于,依賴于系統(tǒng)刨疼,有些系統(tǒng)會擴(kuò)展泉唁。

5. 鏈接問題

  • 硬鏈接:用ln -d來創(chuàng)建,實(shí)際上時(shí)增加某個為你教案的屬性中硬鏈接數(shù)值揩慕。
    編程中用link()函數(shù)實(shí)現(xiàn)
創(chuàng)建硬鏈接
NAME
       link - make a new name for a file (為文件創(chuàng)建一個新名字即為硬鏈接)

SYNOPSIS
       #include <unistd.h>

       int link(const char *oldpath, const char *newpath);

========================
刪除硬鏈接
NAME
       unlink - delete a name and possibly the file it refers to

SYNOPSIS
       #include <unistd.h>

       int unlink(const char *pathname);
僅僅是將某個文件的硬鏈接數(shù)自動減1亭畜,
有時(shí)候用來刪除文件是因?yàn)槲募]有
創(chuàng)建硬鏈接時(shí),硬鏈接數(shù)為1迎卤,而減去1
變?yōu)?拴鸵,從而刪除文件。
  • 符號鏈接:類似于windows的快解方式類似蜗搔,創(chuàng)建了一個新文件劲藐,只是不分配新數(shù)據(jù)空間,符號鏈接文件的大小為源文件路徑字符串長度樟凄。
    在控制臺中創(chuàng)建符號鏈接:
delphi@delphi-vm:~/code/test$ ln -s copy copy.lk
delphi@delphi-vm:~/code/test$ ll copy copy.lk
-rwxrw-r-- 1 delphi delphi 1000 2018-08-07 12:20 copy*
lrwxrwxrwx 1 delphi delphi    4 2018-08-07 15:36 copy.lk -> copy*

在編程中創(chuàng)建符號鏈接:

創(chuàng)建符號鏈接:
NAME
       symlink - make a new name for a file

SYNOPSIS
       #include <unistd.h>

       int symlink(const char *oldpath, const char *newpath);

讀取符號鏈接:
NAME
       readlink - read value of a symbolic link

SYNOPSIS
       #include <unistd.h>

       ssize_t readlink(const char *path, char *buf, size_t bufsiz);
默認(rèn)情況下聘芜,讀取符號鏈接的內(nèi)容和屬性時(shí)得到源文件的信息,
因此缝龄,針對符號鏈接有專門的函數(shù):
stat ==> lstat
chmod ==> lchmod

6. 編程實(shí)現(xiàn)ls -l

  1. 參數(shù)列表問題
    ls -l后面可以跟一個或者多個文件和目錄汰现。要解決這個問題可以使用命令行參數(shù)解析的工具getopt/getopt_long
    另外叔壤,遍歷非-l其他參數(shù)瞎饲,有可能是目錄,有可能是文件炼绘,是目錄則讀取目錄下所有的子文件及子目錄信息嗅战;如果是普通文件,列出文件信息俺亮;如果沒有指定參數(shù)驮捍,則列出當(dāng)前目錄下的文件信息形庭。
    怎么來判斷文件是文件還是目錄呢?**lstat()函數(shù)能夠獲取給定的路徑類型厌漂。

  2. 信息的問題

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市斟珊,隨后出現(xiàn)的幾起案子苇倡,更是在濱河造成了極大的恐慌,老刑警劉巖囤踩,帶你破解...
    沈念sama閱讀 222,000評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件旨椒,死亡現(xiàn)場離奇詭異,居然都是意外死亡堵漱,警方通過查閱死者的電腦和手機(jī)综慎,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來勤庐,“玉大人示惊,你說我怎么就攤上這事∮淞” “怎么了米罚?”我有些...
    開封第一講書人閱讀 168,561評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長丈探。 經(jīng)常有香客問我录择,道長,這世上最難降的妖魔是什么碗降? 我笑而不...
    開封第一講書人閱讀 59,782評論 1 298
  • 正文 為了忘掉前任隘竭,我火速辦了婚禮,結(jié)果婚禮上讼渊,老公的妹妹穿的比我還像新娘动看。我一直安慰自己,他們只是感情好爪幻,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,798評論 6 397
  • 文/花漫 我一把揭開白布弧圆。 她就那樣靜靜地躺著,像睡著了一般笔咽。 火紅的嫁衣襯著肌膚如雪搔预。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,394評論 1 310
  • 那天叶组,我揣著相機(jī)與錄音拯田,去河邊找鬼。 笑死甩十,一個胖子當(dāng)著我的面吹牛船庇,可吹牛的內(nèi)容都是我干的吭产。 我是一名探鬼主播,決...
    沈念sama閱讀 40,952評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼鸭轮,長吁一口氣:“原來是場噩夢啊……” “哼臣淤!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起窃爷,我...
    開封第一講書人閱讀 39,852評論 0 276
  • 序言:老撾萬榮一對情侶失蹤邑蒋,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后按厘,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體医吊,經(jīng)...
    沈念sama閱讀 46,409評論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,483評論 3 341
  • 正文 我和宋清朗相戀三年逮京,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了卿堂。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,615評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡懒棉,死狀恐怖草描,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情策严,我是刑警寧澤陶珠,帶...
    沈念sama閱讀 36,303評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站享钞,受9級特大地震影響揍诽,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜栗竖,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,979評論 3 334
  • 文/蒙蒙 一暑脆、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧狐肢,春花似錦添吗、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,470評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至僵腺,卻和暖如春鲤孵,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背辰如。 一陣腳步聲響...
    開封第一講書人閱讀 33,571評論 1 272
  • 我被黑心中介騙來泰國打工普监, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 49,041評論 3 377
  • 正文 我出身青樓凯正,卻偏偏與公主長得像毙玻,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子廊散,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,630評論 2 359

推薦閱讀更多精彩內(nèi)容