Download presentation
Presentation is loading. Please wait.
1
檔案及目錄
2
認識檔案的基本屬性
3
檔案的基本屬性 (ls -alh) -rw shiwulo shiwulo 2.5K Jan 28 09:59 .ICEauthority drwx shiwulo shiwulo 4.0K Dec 29 12:44 .local -rw-rw-r-- 1 shiwulo shiwulo 0 Jan 28 10:15 ltrace_dropbox drwxr-xr-x 2 shiwulo shiwulo 4.0K Dec 29 12:44 Music drwxr-xr-x 2 shiwulo shiwulo 4.0K Dec 29 12:44 .parallels drwxr-xr-x 2 shiwulo shiwulo 4.0K Dec 29 12:44 Pictures -rw-r--r-- 1 shiwulo shiwulo 675 Dec 29 05:41 .profile drwxr-xr-x 2 shiwulo shiwulo 4.0K Dec 29 12:44 Public lrwxrwxrwx 1 shiwulo shiwulo 57 Feb 23 09:44 sp -> /home/shiwulo/Desktop/Parallels Shared Folders/Dropbox/sp
4
為什麼要用“ls -alh”而不是“ls”
檔名使用「.」開頭的視為隱藏檔 「.」代表當前的目錄 「..」代表上一層目錄 課堂小作業:回到上一層目錄 l:代表印出多一點的訊息 h:將檔案大小以人類易懂的方式顯示,例如:1000會印成1K
5
檔案的基本屬性 紅色的第1個字代表目錄(d)或檔案(-)
-rw-r--r-- 2 shiwulo shiwulo 8.8K Dec 29 05:41 examples.desktop -rw-r--r-- 1 shiwulo shiwulo 675 Dec 29 05:41 .profile 紅色的第1個字代表目錄(d)或檔案(-) 2-9總共九個字,代表各種人(擁有者、群組、其他人)的讀寫的權利,rwx分別代表執行、讀取、寫入 因此- rw- r-- r-- ,代表「這是檔案」「擁有者可讀寫」「群組可以讀」「其他人可以讀」
6
檔案的基本屬性 -rw-r--r-- 2 shiwulo shiwulo 8.8K Dec 29 05:41 examples.desktop -rw-r--r-- 1 shiwulo shiwulo 675 Dec 29 05:41 .profile 2與1分別代表有多少「連結」(有一點像是Windows的捷徑)連到這個檔案(後面會介紹Linux的「捷徑」) 第一個shiwulo代表「擁有者」是shiwulo,第二個shiwulo代表這個檔案的「群組」是shiwulo
7
檔案的基本屬性 -rw-r--r-- 2 shiwulo shiwulo 8.8K Dec 29 05:41 examples.desktop -rw-r--r-- 1 shiwulo shiwulo 675 Dec 29 05:41 .profile 「8.8K」「675」分別代表檔案大小 「 Dec 29 05:41 」及「 Dec 29 05:41 」是上一次的「存取時間」 「 examples.desktop 」及「 .profile 」則是檔名,請注意當檔名的第一個字母是小數點「.」時,該檔案是隱藏檔,如果「ls」所下的指令未包含「a」,就不會顯示隱藏檔
8
rwx在目錄上的權限含義 在傳統UNIX系統上,目錄是一個「特別的檔案」,這個檔案記錄 了「其他檔案的檔名、屬性」及「對應的檔案分配表(inode)」 「r」代表可以可以讀取該目錄,例如:印出該目錄的內容 「w」代表可以修改這個目錄,例如:「新增、刪除、更名、移 動」一個檔案 「x」代表可以進入該目錄
9
檔案的特殊屬性
10
process有三個id effective user id (euid) real user id (ruid)
2017/4/12 process有三個id euid effective user id (euid) 真正用來判斷權限的id real user id (ruid) 該process的owner的user id saved-user-id 當euid改變時,將舊的euid存放在saved-user-id uid suid executable file (set-uid)
11
set-uid #include <unistd.h> int setuid(uid_t uid);
int setgid(gid_t gid); 將euid設定為uid,如果設定正確回傳0,失敗回傳-1,失敗的原 因紀錄在errno
12
lab: 製造一個超級ls 複製/bin/ls cp /bin/ls ./sls 變更擁有者為super user
sudo chown root sls 加入set user id bit sudo chmod +s ./sls 測試 ./sls /root 「可以讀取該目錄」 ./sls /lost+found 「可以讀取該目錄」 ls /root 「沒有『set-uid』的ls,無法讀取該目錄」 課堂作業:仿造「sls」的做法,製造一個能讀取任何檔案的「超級less」
13
2017/4/12 Changing UIDs and GIDs 如果是超級使用者(super user, root)呼叫setuid(uid)那麼real user ID, effective user ID和saved-user-ID都會等於uid。 因此super user可以變身為任何人,但是一旦變身以後,就無法變身回去了 如果是一般使用者(normal user)那麼呼叫setuid(uid)以後 uid必須等於real user ID或saved-user-id,否則會產生錯誤 setuid會將effective user ID設定為real user ID或saved-user-id
14
課堂小作業 寫一隻程式,可以變成任何人 提示:system(“bin/bash”); 提示:記得要對你的執行檔設定set-uid權限
15
change sudo chown root ./change sudo +s ./change adduser guest1
#include <stdlib.h> #include <unistd.h> #include <stdio.h> int main(int argc, char**argv) { int uid; sscanf(argv[1], "%d", &uid); setuid(0); setuid(uid); system("/bin/bash"); return 0; } sudo chown root ./change sudo +s ./change adduser guest1 /*假設guest 1的user ID是1001 ./change 1001
16
setreuid and setregid #include <unistd.h>
2017/4/12 setreuid and setregid #include <unistd.h> int setreuid(uid_t ruid, uid_t euid); int setregid(gid_t rgid, gid_t egid); 設定real user ID和effective user ID。這個函數通常用來交換(swap) real user ID 和effective user ID?讓set-uid的程式暫時性的切換到real uid。正確回傳0,否則回傳-1。
17
seteuid #include <unistd.h> int seteuid(uid_t uid);
2017/4/12 seteuid #include <unistd.h> int seteuid(uid_t uid); int setegid(gid_t gid); 只改變effective user ID。錯誤回傳-1否則回傳0
18
getuid() #include <unistd.h> #include <sys/types.h>
uid_t getuid(void); uid_t geteuid(void);
19
getresuid() #define _GNU_SOURCE #include <unistd.h>
int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid); 拿到real user ID、effective user ID及saved-user-ID,錯誤回傳-1否則回傳0
20
sticky bit 設定一個目錄,該目錄只有目錄擁有者、檔案擁有者或超級使用者 (super user,root)可以刪除檔案。
通常使用於暫存目錄,例如:/tmp 指令chmod +t
21
sticky bit $ mkdir tmp $ chmod +t ./tmp $ ls -alh drwxrwxr-t 2 shiwulo shiwulo 4.0K Mar 20 06:29 tmp
22
硬連結及軟連結
23
關於hard link hard link是讓目錄結構內,多個項目(可能是檔案,也可能是目 錄)指向另一個項目(檔案或目錄)『在Linux中只可連向檔案』 hard link所指向的新路徑與就路徑必須存在於同一個partition 只有當hard link的數量變成0時,該檔案才會被真正的刪除 -rw-r--r-- 2 shiwulo shiwulo 8.8K Dec 29 05:41 examples.desktop 一個檔案的多個hard link可以各自擁有自己的權限,因此透過hard link可以讓一個檔案擁有多個不同權限(後面我們會介紹更一般 化的方法)
24
關於soft link 是一個特別的檔案(類似於Windows的捷徑)連向某個檔案或目 錄
softlink可以跨過不同的partition softlink可以指向一個不存在的東西 softlink不會影響link的數量 -rw-r--r-- 2 shiwulo shiwulo 8.8K Dec 29 05:41 examples.desktop 在這個例子中,無論創建了多少softlink都不會改變「2」
25
hard link Linux指令:ln(hard link),ln -s (soft link)
#include <unistd.h> /*hard link*/ int link(const char *oldpath, const char *newpath); /*soft link*/ int symlink(const char *oldpath, const char *newpath);
26
link 撰寫一支程式,可以建立hard link及soft link
例子,建立hard link:link -s source target 例子,建立soft link :link source target
27
link #include <stdio.h> } else { #include <unistd.h>
ret = link(argv[2], argv[3]); #include <errno.h> if (ret != 0) perror("hard link"); int main(int argc, char **argv) } { return 0; int ret; printf("%d \n", argc); if (argc == 4) {/*softlink*/ ret = symlink(argv[1], argv[2]); printf("%s, %s\n", argv[2], argv[3]); if (ret != 0) perror("soft link:");
28
執行結果 $ ex ex_ $ ln -s ex ex__ $ ls ex* -alh -rw-r--r-- 3 shiwulo shiwulo 8.8K Dec 29 05:41 ex -rw-r--r-- 3 shiwulo shiwulo 8.8K Dec 29 05:41 ex_ lrwxrwxrwx 1 shiwulo shiwulo 2 Mar 12 11:37 ex__ -> ex
29
操作目錄及檔案屬性
30
mkdir Linux指令:mkdir #include <sys/stat.h>
#include <sys/types.h> int mkdir(const char *pathname, mode_t mode); 製造一個目錄於pathname,目錄權限是mode & ~umask &0777
31
rmdir Linux指令:rmdir #include <unistd.h>
int rmdir(const char *pathname); 刪除目錄pathname
32
chdir Linux指令:cd #include <unistd.h>
int chdir(const char *path); int fchdir(int fd); 改變目前的工作目錄
33
課堂作業 將目前的「工作目錄」更改為path或者fd所指向的目錄
在Linux中,cd是內建指令(internal,因此無法使用strace觀看 cd如何實作) 可以使用system(“bash”);
34
mycd #include <unistd.h> #include <stdlib.h>
int main(int argc, char**argv) { chdir(argv[1]); system("bash"); return 0; }
35
getcwd Linux指令:pwd #include <unistd.h>
char *getcwd(char *buf, size_t size); getcwd會將目前的「絕對路徑」寫入到buf,這個buf大小為size, 如果buf太小,那麼Linux就無法將路徑完整地寫出到buf
36
課堂小作業 寫一隻程式mypwd可以印出現在的工作目錄
37
條列目錄裡所有的物件
38
列出目錄裡所有的東西 Linux指令:ls #include <dirent.h>
DIR *opendir(const char *pathname); struct dirent *readdir(DIR *dp); int closedir(DIR *dp);
39
dirent結構 在這個資料結構中,最常用到的是d_name,可以藉由d_name及 stat()拿到這個檔案的所有屬性
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 */ }; 在這個資料結構中,最常用到的是d_name,可以藉由d_name及 stat()拿到這個檔案的所有屬性
40
dir #include <stdio.h> #include <dirent.h> }
int main(int argc, char **argv) closedir(dir); { return 0; DIR* dir; struct dirent* ent; dir = opendir(argv[1]); ent = readdir(dir); while(ent!=NULL) { printf("%s\n", ent- >d_name);
41
執行結果 $ ./dir ./ . .. chmod chmod.c dir dir.c dir2 dir2.c dir3 dir3.c link.c lnk
42
利用stat讀取檔案屬性
43
更進階版的dir 目前的dir程式只能列印出檔案名稱,但無法知道這個檔案的屬性 如果要知道檔案的屬性,必須使用下一頁所列的三個函數
44
更進階版的dir #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); stat會將資料寫入buf,lstat會檢視「soft link」本身,而fstat的傳入值是file descriptor 下一頁說明struct stat
45
struct stat struct stat {
dev_t st_dev; /* ID of device containing file */ ino_t st_ino; /* inode number */ mode_t st_mode; /* protection */ nlink_t st_nlink; /* number of hard links */ uid_t st_uid; /* user ID of owner */ gid_t st_gid; /* group ID of owner */ dev_t st_rdev; /* device ID (if special file) */ off_t st_size; /* total size, in bytes */ blksize_t st_blksize; /* blocksize for filesystem I/O */ blkcnt_t st_blocks; /* number of 512B blocks allocated */ time_t st_atime; /* time of last access */ time_t st_mtime; /* time of last modification */ time_t st_ctime; /* time of last status change */ };
46
struct stat常用的欄位說明 struct stat { mode_t st_mode; /* 檔案類型及檔案權限*/
nlink_t st_nlink; /* 多少hard link指到這個檔案*/ uid_t st_uid; /* owner的ID */ gid_t st_gid; /* group的ID */ dev_t st_rdev; /* device ID (if special file) */ off_t st_size; /* total size, in bytes */ time_t st_atime; /* 最後存取時間*/ time_t st_mtime; /* 上次修改時間 */ time_t st_ctime; /* 修改這個資料結構(meta-data)的時間 */ };
47
dir2 #include <stdio.h> #include <dirent.h>
#include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h>
48
dir2 #include <time.h> int main(int argc, char **argv) {
DIR* dir; struct dirent* ent; char* curDir = "./"; char pathname[512]; struct stat buf; int perm;
49
dir2 char *time; dir = opendir(argv[1]); ent = readdir(dir);
while(ent!=NULL) { strcpy(pathname, curDir); strcat(pathname, ent->d_name); stat(pathname, &buf); perm = (buf.st_mode & \ (S_IRWXU | S_IRWXG | S_IRWXO));
50
dir2 time = ctime(&buf.st_atime); time[strlen(time)-1] = 0;
printf("%o %d %d %8d %s %s\n",\ perm, buf.st_uid, buf.st_gid,\ (int)buf.st_size, time, ent->d_name); ent = readdir(dir); } closedir(dir); return 0;
51
執行結果 $ ./dir2 ./ Sat Mar 12 06:42: Fri Mar 11 16:35: Fri Mar 11 17:10: chmod Fri Mar 11 13:52: chmod.c Sat Mar 12 06:42: dir Fri Mar 11 17:05: dir.c Sat Mar 12 06:42: dir Sat Mar 12 06:36: dir2.c Fri Mar 11 17:10: link.c Fri Mar 11 17:10: lnk
52
更進階版的dir 目前dir的輸出結果已經很像ls -al 但使用者名稱和群組名稱都是數字,而非有意義的字串 使用下列二個函數
#include <pwd.h> struct passwd *getpwuid(uid_t uid); #include <grp.h> struct group *getgrgid(gid_t gid);
53
dir3 將輸出函數換成新的輸出函數 printf("%o %d %d %8d %s %s\n", perm,\
buf.st_uid, buf.st_gid,\ (int)buf.st_size, time, ent->d_name); printf("%o %s %s %8d %s %s\n", perm, \ getpwuid(buf.st_uid)->pw_name, getgrgid(buf.st_gid)->gr_name,\
54
執行結果 $ ./dir3 ./ 755 shiwulo shiwulo 408 Sat Mar 12 07:02: shiwulo shiwulo 680 Fri Mar 11 16:35: shiwulo shiwulo 8663 Sat Mar 12 06:59: chmod 664 shiwulo shiwulo 305 Fri Mar 11 13:52: chmod.c 775 shiwulo shiwulo 8709 Sat Mar 12 06:59: dir 664 shiwulo shiwulo 261 Fri Mar 11 17:05: dir.c 775 shiwulo shiwulo 9092 Sat Mar 12 06:59: dir2 664 shiwulo shiwulo 762 Sat Mar 12 06:59: dir2.c 775 shiwulo shiwulo 9200 Sat Mar 12 07:02: dir3 664 shiwulo shiwulo 831 Sat Mar 12 07:02: dir3.c 664 shiwulo shiwulo 298 Sat Mar 12 06:59: link.c 664 shiwulo shiwulo 298 Sat Mar 12 06:59: lnk
55
檔案的操作
56
檔案權限的遮罩umask Linux指令:umask #include <sys/types.h>
#include <sys/stat.h> mode_t umask(mode_t mask); 使用umask可以設定「檔案遮罩」,所有新建立的檔案或者檔案權限 的修改都會受到這個檔案遮罩的影響。umask的回傳值是「舊的 umask的設定值」 例如:使用umask將檔案遮罩設定為「002」,那麼新建立的檔案的 「其他人」就一定不會有「寫入權限」
57
課堂小作業 寫一支程式,該程式會在螢幕上印出目前umask的設定,並且不 會改變umask的設定值
58
unlink Linux指令:rm #include <stdio.h>
int remove(const char *pathname); 刪除pathname,在Linux中由於一個檔案可能被多個「路徑名」參照,因此 「刪除pathname」的實際功能是讓「參照數」少1,如果參照數變為0,系 統就會真正刪除這個檔案/資料夾(資料夾的參考數都為1) 要特別注意的是,如果正好有一個程式打開(open)了這個檔案,除非這個程 式關閉(close)了這個檔案,否則這個檔案會以「隱形的方式」存在於檔案系 統
59
課堂小作業 寫一隻小程式,可以移除某個檔案或者資料夾,例如: myrm /path/something
60
rename() Linux指令:rm #include <stdio.h>
int rename(const char *old, const char *new); 將old名字改成new。這個函數在我的Linux上的man 3找不到,但 經過測試,這個函數可用
61
rename #include <stdio.h> int main(int argc, char **argv) {
rename(argv[1], argv[2]); return 0; }
62
結果 $ ./rename tmp ../tmp $ cd .. $ ls tmp tmp
63
chmod, chgrp, chowner Linux指令: chgrp, chown, chmod
#include <sys/types.h> #include <unistd.h> int chown(const char *path, uid_t owner, gid_t group); #include <sys/stat.h> int chmod(const char *path, mode_t mode); int fchmodat(int fd, const char *path, mode_t mode, int flag); 課堂作業:自行用man這個指令查看這三個函數的用途
64
修改權限 Linux指令:chmod #include <sys/stat.h>
int chmod(const char *path, mode_t mode); int fchmod(int fd, mode_t mode);
65
課堂作業 撰寫一支程式,可以改變檔案權限
66
chmod #include <stdio.h> #include <sys/stat.h>
int main(int argc, char **argv) { int perm; int owner, grp, others; sscanf(argv[2], "%1d%1d%1d", &owner, &grp, &others); printf("permission = %d %d %d\n", owner, grp, others); perm = owner<<6 | grp<<3 | others; chmod(argv[1], (mode_t)perm); return 0; }
67
執行結果 $./chmod link.c 777 permission = $ ls -alh link.c -rwxrwxrwx 1 shiwulo shiwulo 298 Mar 11 14:23 link.c
68
設定檔案的擴充權限
69
檔案的擴充屬性 傳統Unix只有三種屬性,分別是:owner、group、others,但有 時候人員很複雜,需要做個細緻的規範 例如:
老師可以針對作業進行任何修改 助教:可以讀取任何作業 學生:可以修改作業 其他人:沒有權限 以上一個例子而言,權限就有四種,超出傳統Unix的權限
70
getfacl, setfacl getfacl(acl:access control list)讀取一個檔案或目錄的擴充屬性
71
getfacl $ getfacl examples.desktop /*對,就是這麼簡單,getfacl後面將路徑名*/ # file: examples.desktop /*檔名*/ # owner: shiwulo /*檔案擁有者*/ # group: shiwulo /*群組*/ user::rw- /*UNIX預設屬性rwx rwx rwx*/ group::r-- other::r--
72
setfacl setfacl -m u:guest1:rx ./tmp setfacl -m g:guest1:rx ./tmp
-m代表修改(modify)權限 u:[使用者名稱]:[權限] 檔名 setfacl -m g:guest1:rx ./tmp g:[群組名稱]:[權限] 檔名
73
執行結果 $setfacl -m u:guest1:rw ./tmp $getfacl ./tmp # file: tmp # owner: shiwulo # group: shiwulo user::rw- /*沒有使用者(::)代表擁有者(owner) user:guest1:rw- group::rw- mask::rw- other::r--
74
執行結果 $setfacl -m g:guest1:rw ./tmp $ getfacl ./tmp # file: tmp # owner: shiwulo # group: shiwulo user::rw- user:guest1:rw- group::rw- group:guest1:rw- /*增加了新的群組guset1,權限為可讀寫*/ mask::rw- other::r--
75
ls一下 $ls -lh drwxrwxr-x 6 shiwulo shiwulo 4.0K Feb 1 12:25 _sp drwxr-xr-x 2 shiwulo shiwulo 4.0K Dec 29 12:44 Templates -rw-rw-r--+ 1 shiwulo shiwulo 0 Mar 15 08:14 tmp /*檔案屬性多了+代表這一個檔案有擴充屬性,要用getfacl才可以看到完整的屬性*/ drwxr-xr-x 2 shiwulo shiwulo 4.0K Dec 29 12:44 Videos
76
getxattr #include <sys/types.h> #include <attr/xattr.h>
ssize_t getxattr(const char *path, const char *name, void *value, size_t size); ssize_t lgetxattr(const char *path, const char *name, ssize_t fgetxattr(int fd, const char *name, 課堂作業:上網查詢這三個函數的用法
77
setxattr #include <sys/types.h> #include <sys/xattr.h>
int setxattr(const char *path, const char *name, const void *value, size_t size, int flags); int lsetxattr(const char *path, const char *name, int fsetxattr(int fd, const char *name, 課堂作業:上網查詢這三個函數的用法
78
監聽資料夾內的變動
79
inotify int inotify_init(void)
初始化一個inofiry的監聽,回傳值是file descript int inotify_add_watch(int fd, const char* pathname, int mask) 使用fd對一個檔案或者目錄(pathname)進行一些(mask)監聽 int inotify_rm_watch(int fd, int wd) 移除inotify的一個監聽 設定好要監聽的物件(如:目錄、檔案)後,就可以用read來查 看監聽的結果
80
inotify.c #include <sys/inotify.h> #include <stdio.h>
#include <dirent.h> #include <unistd.h> #include <stdlib.h> #define BUF_LEN (10 * (sizeof(struct inotify_event) + NAME_MAX + 1)) int main(int argc, char **argv) { int fd;
81
inotify.c int num; char* p; struct inotify_event* event;
char buf[BUF_LEN]; int ret; fd = inotify_init(); if (fd < 0) { perror("error"); exit (-1); }
82
inotify.c ret=inotify_add_watch(fd, argv[1], IN_ALL_EVENTS);
if (ret < 0) { perror("error"); exit (-1); } while(1) { num = read(fd, buf, BUF_LEN); if (num < 0) { perror("Error"); exit(-1);
83
inotify.c for (p = buf; p < buf + num; ) {
event = (struct inotify_event *) p; printf("mask = %d\n", event->mask); if (event->mask & IN_ACCESS) puts("in access"); if (event->mask & IN_CREATE) puts("IN_CREATE "); if (event->mask & IN_DELETE) puts("IN_DELETE "); p+=sizeof(struct inotify_event) + event->len; }
84
結果 $./inotify ./tmp mask = mask = in access mask = in access mask = mask = 256IN_CREA
85
課堂作業 攔截一個目錄裡面的所有物件,必須使用遞迴,以包含子目錄
Similar presentations