檔案及目錄.

Slides:



Advertisements
Similar presentations
Linux 环境及 Shell 程序 操作系统实验 1. 二、 Shell 编程与进程通信 常用 shell 命令 文件及文件属性操作 ls 、 cp 、 mv 、 rm ln 、 ln –s 、 chmod 、 groupadd 、 useradd 输入输出操作 echo 、 cat >> 、
Advertisements

Project2: 文件夹同步工具. 任 务 背景 有 2 个文件夹 A 和 B ,经过 之前的同步操作 , 文 件夹 B 中的内容与文件夹 A 中内容完全一致 , 现 在用 户对 A 文件夹中部分文件 进 行了 编辑、 移 动、删 除或者新增的操作 ,请 你的程序根 据文件夹 A 中的内容 变 化.
第1单元 操作系统概论 第一节 绪论 操作系统定义.
行程(process).
第七章 操作系统接口 7.1 联机用户接口 7.2 Shell命令语言 7.3 系统调用 7.4 UNIX系统调用 7.5 图形用户接口.
Linux 的檔案管理.
崑山科技大學資訊傳播系 蔡德明 (鳥哥, VBird)
基于操作系统的编程复习 张玉宏
UNIX系統與資料庫安裝 Why UNIX 常用的工具程式介紹 資料庫的安裝.
第 5 章 文件I/O操作.
Linux 的進階檔案處理.
Confidential Property
Vi 編輯器的練習的說明 因為本課程的實習課是Unix 的工作環境。過去的經驗告訴我,如果你完全未用過Unix 的指令及其 vi 編輯器,你將很難跟上進度,希望學員一定要預先作練習。我們提供了Unix 指令的簡介,以及 vi 編輯器的介紹 ( 請参閱網站中的13&14-unix.pdf 為其講義;13-unix.exe、14-fortran.exe則為其課程錄影.
第8章 字元與字串處理 8-1 C語言的字元檢查函數 8-2 C語言的字串 8-3 字串的輸入與輸出 8-4 指標與字串
第 2 章 上機使用 Unix/Linux 內容: 操作介面 主機連線 登入主機 認識系統環境 使用者常用命令.
第 19 章 檔案系統與 權限設定.
南京天石软件技术有限公司 陈锺 (QQ: Solaris 10 C编程 南京天石软件技术有限公司 陈锺 (QQ:
第4章 鏈結串列(Linked Lists) 4-1 動態記憶體配置-(6) 4-2 鏈結串列的基礎-(7)
台灣大學計算機及資訊網路中心 教學研究組 張傑生
C语言程序设计 第十二章 位运算.
chapter 1-Introduction
计算概论 第二十一讲 文件操作 北京大学信息学院.
Linux 基础与常用命令简介 生物信息学培训班 杭州,2018年1月18日 周银聪.
第七章. 文件系统 (lab5).
第7章 Linux环境编程.
第十一章 文件 文件概述 文件操作 文件操作实例 本章小结 作业: 练习:
第二天 计算机基础技能培训 (一)linux基础知识
Linux server 連線軟體: 主機:kitty.cs.pu.edu.tw 帳號:dar 密碼:n….w.
多进程编程.
STRUCTURE 授課:ANT 日期:2010/5/12.
Function.
程序设计期末复习 黎金宁
程序设计专题一 结构化程序设计与递归函数 主讲教师: 刘新国.
Linux基本操作 程設實習課 ( 2/25 ).
第 20 章 帳號與磁碟空間管理 著作權所有 © 旗標出版股份有限公司.
Chapter 6 Linux 檔案權限與目錄配置 VBird 2005/08/03
作業系統實習課(四) -檔案管理- 實驗室:720A 助教:鄧執中.
THE C PROGRAMMING LANGUAGE
Linux 文件操作——系统调用和标准 IO 库
第9章 文件操作 文件 使用文件的目的 操作系统管理数据的基本单位 存储在外存储器上的数据的集合
实验四 Linux文件目录 一、实验目的 1、了解Linux文件系统与目录操作; 2、了解Linux文件系统目录结构;
实验一、进程控制 一、实验目的 1、加深对进程的理解,进一步认识并发执行的实质; 2、分析进程争用资源现象,学习解决进程互斥的方法;
Struct結構 迴圈
第二章 UNIX系统安装与常用命令.
第六章 shell 程序调试 一. 程序执行状态跟踪 程序: -n 读取命令, 但不执行. 主要用于跟踪程序流程是
Chap5 PHP程式設計進階 授課講師:.
如何有效率的學習Linux 培養組合能力 多用程式, 少寫程式 從錯誤訊息中學習 養成略讀 “各種文件” 加強英文基本閱讀能力 勤作筆記
第三章 UNIX的文件与目录.
C语言环境配置.
第11章 位运算 为了节省内存空间,在系统软件中常将多个标志状态简单地组合在一起,存储到一个字节(或字)中。C语言是为研制系统软件而设计的,所以她提供了实现将标志状态从标志字节中分离出来的位运算功能。 所谓位运算是指,按二进制位进行的运算。 11.1 数值在计算机中的表示 11.2.
杨振伟 清华大学 第一讲:Linux环境下编程(1)
C標準輸出入函數庫 與 作業系統.
第二章 类型、对象、运算符和表达式.
台灣大學計算機及資訊網路中心 教學研究組 張傑生
第6讲 访问控制基本方法 第4章:操作系统基础安全性 第3部分/共5部分.
授课老师:龚涛 信息科学与技术学院 2016年3月 教材:《Visual C++程序员成长攻略》 《C++ Builder程序员成长攻略》
第4章 鏈結串列(Linked Lists) 4-1 動態記憶體配置-(6) 4-2 鏈結串列的基礎-(7)
实验二:添加Linux系统调用及熟悉常见系统调用
作業一: 安裝Linux於btrfs上 中正大學 作業系統實驗室 指導教授:羅習五
杨振伟 清华大学 第一讲:Linux环境下编程(1)
第6章 嵌入式软件开发基础.
Unix指令2.
实验三 Linux文件目录操作 一、目的 二、要求 了解并掌握Linux文件目录结构。 了解Linux文件系统与目录操作:
劉庠宏、林合治編著 國立高雄大學應用數學系 2005年3月1日
第六章 文件系统与文件管理 6.4 Linux文件管理 1、比较MS DOS 与 Linux的目录结构 一、Linux文件系统的树形结构
《操作系统设计与实现》 第5章 文件系统.
《操作系统设计与实现》 Linux系统编程.
Presentation transcript:

檔案及目錄

認識檔案的基本屬性

檔案的基本屬性 (ls -alh) -rw------- 1 shiwulo shiwulo 2.5K Jan 28 09:59 .ICEauthority drwx------ 3 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

為什麼要用“ls -alh”而不是“ls” 檔名使用「.」開頭的視為隱藏檔 「.」代表當前的目錄 「..」代表上一層目錄 課堂小作業:回到上一層目錄 l:代表印出多一點的訊息 h:將檔案大小以人類易懂的方式顯示,例如:1000會印成1K

檔案的基本屬性 紅色的第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-- ,代表「這是檔案」「擁有者可讀寫」「群組可以讀」「其他人可以讀」

檔案的基本屬性 -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

檔案的基本屬性 -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」,就不會顯示隱藏檔

rwx在目錄上的權限含義 在傳統UNIX系統上,目錄是一個「特別的檔案」,這個檔案記錄 了「其他檔案的檔名、屬性」及「對應的檔案分配表(inode)」 「r」代表可以可以讀取該目錄,例如:印出該目錄的內容 「w」代表可以修改這個目錄,例如:「新增、刪除、更名、移 動」一個檔案 「x」代表可以進入該目錄

檔案的特殊屬性

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)

set-uid #include <unistd.h> int setuid(uid_t uid); int setgid(gid_t gid); 將euid設定為uid,如果設定正確回傳0,失敗回傳-1,失敗的原 因紀錄在errno

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」

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

課堂小作業 寫一隻程式,可以變成任何人 提示:system(“bin/bash”); 提示:記得要對你的執行檔設定set-uid權限

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

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。

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

getuid() #include <unistd.h> #include <sys/types.h> uid_t getuid(void); uid_t geteuid(void);

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

sticky bit 設定一個目錄,該目錄只有目錄擁有者、檔案擁有者或超級使用者 (super user,root)可以刪除檔案。 通常使用於暫存目錄,例如:/tmp 指令chmod +t

sticky bit $ mkdir tmp $ chmod +t ./tmp $ ls -alh drwxrwxr-t 2 shiwulo shiwulo 4.0K Mar 20 06:29 tmp

硬連結及軟連結

關於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可以讓一個檔案擁有多個不同權限(後面我們會介紹更一般 化的方法)

關於soft link 是一個特別的檔案(類似於Windows的捷徑)連向某個檔案或目 錄 softlink可以跨過不同的partition softlink可以指向一個不存在的東西 softlink不會影響link的數量 -rw-r--r-- 2 shiwulo shiwulo 8.8K Dec 29 05:41 examples.desktop 在這個例子中,無論創建了多少softlink都不會改變「2」

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);

link 撰寫一支程式,可以建立hard link及soft link 例子,建立hard link:link -s source target 例子,建立soft link :link source target

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:");

執行結果 $ 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

操作目錄及檔案屬性

mkdir Linux指令:mkdir #include <sys/stat.h> #include <sys/types.h> int mkdir(const char *pathname, mode_t mode); 製造一個目錄於pathname,目錄權限是mode & ~umask &0777

rmdir Linux指令:rmdir #include <unistd.h> int rmdir(const char *pathname); 刪除目錄pathname

chdir Linux指令:cd #include <unistd.h> int chdir(const char *path); int fchdir(int fd); 改變目前的工作目錄

課堂作業 將目前的「工作目錄」更改為path或者fd所指向的目錄 在Linux中,cd是內建指令(internal,因此無法使用strace觀看 cd如何實作) 可以使用system(“bash”);

mycd #include <unistd.h> #include <stdlib.h> int main(int argc, char**argv) { chdir(argv[1]); system("bash"); return 0; }

getcwd Linux指令:pwd #include <unistd.h> char *getcwd(char *buf, size_t size); getcwd會將目前的「絕對路徑」寫入到buf,這個buf大小為size, 如果buf太小,那麼Linux就無法將路徑完整地寫出到buf

課堂小作業 寫一隻程式mypwd可以印出現在的工作目錄

條列目錄裡所有的物件

列出目錄裡所有的東西 Linux指令:ls #include <dirent.h> DIR *opendir(const char *pathname); struct dirent *readdir(DIR *dp); int closedir(DIR *dp);

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()拿到這個檔案的所有屬性

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);

執行結果 $ ./dir ./ . .. chmod chmod.c dir dir.c dir2 dir2.c dir3 dir3.c link.c lnk

利用stat讀取檔案屬性

更進階版的dir 目前的dir程式只能列印出檔案名稱,但無法知道這個檔案的屬性 如果要知道檔案的屬性,必須使用下一頁所列的三個函數

更進階版的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

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 */ };

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)的時間 */ };

dir2 #include <stdio.h> #include <dirent.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h>

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;

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));

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;

執行結果 $ ./dir2 ./ 755 1000 1000 340 Sat Mar 12 06:42:29 2016 . 755 1000 1000 680 Fri Mar 11 16:35:03 2016 .. 775 1000 1000 8663 Fri Mar 11 17:10:20 2016 chmod 664 1000 1000 305 Fri Mar 11 13:52:03 2016 chmod.c 775 1000 1000 8709 Sat Mar 12 06:42:25 2016 dir 664 1000 1000 261 Fri Mar 11 17:05:58 2016 dir.c 775 1000 1000 9092 Sat Mar 12 06:42:29 2016 dir2 664 1000 1000 762 Sat Mar 12 06:36:12 2016 dir2.c 664 1000 1000 298 Fri Mar 11 17:10:20 2016 link.c 664 1000 1000 298 Fri Mar 11 17:10:20 2016 lnk

更進階版的dir 目前dir的輸出結果已經很像ls -al 但使用者名稱和群組名稱都是數字,而非有意義的字串 使用下列二個函數 #include <pwd.h> struct passwd *getpwuid(uid_t uid); #include <grp.h> struct group *getgrgid(gid_t gid);

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,\

執行結果 $ ./dir3 ./ 755 shiwulo shiwulo 408 Sat Mar 12 07:02:42 2016 . 755 shiwulo shiwulo 680 Fri Mar 11 16:35:03 2016 .. 775 shiwulo shiwulo 8663 Sat Mar 12 06:59:25 2016 chmod 664 shiwulo shiwulo 305 Fri Mar 11 13:52:03 2016 chmod.c 775 shiwulo shiwulo 8709 Sat Mar 12 06:59:25 2016 dir 664 shiwulo shiwulo 261 Fri Mar 11 17:05:58 2016 dir.c 775 shiwulo shiwulo 9092 Sat Mar 12 06:59:25 2016 dir2 664 shiwulo shiwulo 762 Sat Mar 12 06:59:04 2016 dir2.c 775 shiwulo shiwulo 9200 Sat Mar 12 07:02:42 2016 dir3 664 shiwulo shiwulo 831 Sat Mar 12 07:02:30 2016 dir3.c 664 shiwulo shiwulo 298 Sat Mar 12 06:59:25 2016 link.c 664 shiwulo shiwulo 298 Sat Mar 12 06:59:25 2016 lnk

檔案的操作

檔案權限的遮罩umask Linux指令:umask #include <sys/types.h> #include <sys/stat.h> mode_t umask(mode_t mask); 使用umask可以設定「檔案遮罩」,所有新建立的檔案或者檔案權限 的修改都會受到這個檔案遮罩的影響。umask的回傳值是「舊的 umask的設定值」 例如:使用umask將檔案遮罩設定為「002」,那麼新建立的檔案的 「其他人」就一定不會有「寫入權限」

課堂小作業 寫一支程式,該程式會在螢幕上印出目前umask的設定,並且不 會改變umask的設定值

unlink Linux指令:rm #include <stdio.h> int remove(const char *pathname); 刪除pathname,在Linux中由於一個檔案可能被多個「路徑名」參照,因此 「刪除pathname」的實際功能是讓「參照數」少1,如果參照數變為0,系 統就會真正刪除這個檔案/資料夾(資料夾的參考數都為1) 要特別注意的是,如果正好有一個程式打開(open)了這個檔案,除非這個程 式關閉(close)了這個檔案,否則這個檔案會以「隱形的方式」存在於檔案系 統

課堂小作業 寫一隻小程式,可以移除某個檔案或者資料夾,例如: myrm /path/something

rename() Linux指令:rm #include <stdio.h> int rename(const char *old, const char *new); 將old名字改成new。這個函數在我的Linux上的man 3找不到,但 經過測試,這個函數可用

rename #include <stdio.h> int main(int argc, char **argv) { rename(argv[1], argv[2]); return 0; }

結果 $ ./rename tmp ../tmp $ cd .. $ ls tmp tmp

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這個指令查看這三個函數的用途

修改權限 Linux指令:chmod #include <sys/stat.h> int chmod(const char *path, mode_t mode); int fchmod(int fd, mode_t mode);

課堂作業 撰寫一支程式,可以改變檔案權限

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; }

執行結果 $./chmod link.c 777 permission = 7 7 7 $ ls -alh link.c -rwxrwxrwx 1 shiwulo shiwulo 298 Mar 11 14:23 link.c

設定檔案的擴充權限

檔案的擴充屬性 傳統Unix只有三種屬性,分別是:owner、group、others,但有 時候人員很複雜,需要做個細緻的規範 例如: 老師可以針對作業進行任何修改 助教:可以讀取任何作業 學生:可以修改作業 其他人:沒有權限 以上一個例子而言,權限就有四種,超出傳統Unix的權限

getfacl, setfacl getfacl(acl:access control list)讀取一個檔案或目錄的擴充屬性

getfacl $ getfacl examples.desktop /*對,就是這麼簡單,getfacl後面將路徑名*/ # file: examples.desktop /*檔名*/ # owner: shiwulo /*檔案擁有者*/ # group: shiwulo /*群組*/ user::rw- /*UNIX預設屬性rwx rwx rwx*/ group::r-- other::r--

setfacl setfacl -m u:guest1:rx ./tmp setfacl -m g:guest1:rx ./tmp -m代表修改(modify)權限 u:[使用者名稱]:[權限] 檔名 setfacl -m g:guest1:rx ./tmp g:[群組名稱]:[權限] 檔名

執行結果 $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--

執行結果 $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--

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

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, 課堂作業:上網查詢這三個函數的用法

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, 課堂作業:上網查詢這三個函數的用法

監聽資料夾內的變動

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來查 看監聽的結果

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;

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); }

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);

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; }

結果 $./inotify ./tmp mask = 1073741856mask = 1073741825in access mask = 1073741825in access mask = 1073741840mask = 256IN_CREA

課堂作業 攔截一個目錄裡面的所有物件,必須使用遞迴,以包含子目錄