File Name
.
: 表示當前目錄..
: 表示上層目錄Path Name
Directory
chdir
指令改變/etc/passwd
檔案中stat, fstat, lstat Functions
#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); /* Returns: 0 if OK, -1 on error */ 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 file system 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 */ };
stat
和 lstat
基本上相似,主要差別在 stat
會跟隨 symbolic link 顯示檔案資訊,lstat
則不跟隨 symbolic link,而是顯示 symbolic link 本身資訊fstat
則是在參數部分使用 file description,不同於 stat
和 lstat
使用路徑,fstat
可以取得開啟中的檔案資訊Common File Information
File Types
這邊可以先參考 SUID & SGID in UNIX 這篇
#include <sys/types.h> #include <unistd.h> int setuid(uid_t uid); int setgid(gid_t gid); /* Return 0 if OK, -1 if error */
程式在執行時可以透過 setuid
, setgid
function 來改變 euid, egid
File Access Permissions
File access test precedence
符合四項中的其中一項即有存取權限
Ownership of New Files and Directories
access Function
#include <unistd.h> int access(const char *pathname, int mode); /* Return 0 if OK, -1 on error */
#include "apue.h" #include <fcntl.h> int main(int argc, char *argv[]) { if (argc != 2) err_quit("usage: a.out <pathname>"); if (access(argv[1], R_OK) < 0) err_ret("access error for %s", argv[1]); else printf("read access OK\n"); if (open(argv[1], O_RDONLY) < 0) err_ret("open error for %s", argv[1]); else printf("open for reading OK\n"); exit(0); }
$ ls -l a.out -rwxrwxr-x 1 sar 15945 Nov 30 12:10 a.out $ ./a.out a.out read access OK open for reading OK $ ls -l /etc/shadow -r-------- 1 root 1315 Jul 17 2002 /etc/shadow $ ./a.out /etc/shadow access error for /etc/shadow: Permission denied open error for /etc/shadow: Permission denied $ sudo su - become superuser Password: enter superuser password # chown root a.out change file's user ID to root # chmod u+s a.out and turn on set-user-ID bit # ls -l a.out check owner and SUID bit -rwsrwxr-x 1 root 15945 Nov 30 12:10 a.out # exit go back to normal user $ ./a.out /etc/shadow access error for /etc/shadow: Permission denied open for reading OK
umask Function
#include <sys/types.h> #include <sys/stat.h> mode_t umask(mode_t mask); /* previous file mode creation mask */
#define RWRWRW (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) int main(void) { umask(0); if (creat("foo", RWRWRW) < 0) err_sys("creat error for foo"); umask(S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); if (creat("bar", RWRWRW) < 0) err_sys("creat error for bar"); }
$ umask // first print the current file mode creation mask 002 $ ./a.out $ ls -l foo bar -rw------- 1 sar 0 Dec 7 21:20 bar -rw-rw-rw- 1 sar 0 Dec 7 21:20 foo $ umask // see if the file mode creation mask changed 002
Set File Modes and Ownerships
#include <sys/stat.h> int chmod(const char *path, mode_t mode); int fchmod(int fd, mode_t mode);
#include <unistd.h> int chown(const char *path, uid_t owner, gid_t group); int fchown(int fd, uid_t owner, gid_t group); int lchown(const char *path, uid_t owner, gid_t group); /* Return 0 if OK, -1 on error */
Cylinder Group's i-nodes and Data Blocks
i-node 可被多個 entry 指到
建立資料夾前的 i-node 示意圖:
建立資料夾後的 i-node 示意圖:
Reference Counts
#include <unistd.h> int link(const char *oldpath, const char *newpath); int unlink(const char *pathname); /* Returns: 0 if OK, -1 on error */ #include <stdio.h> int remove(const char *pathname); int rename(const char *oldpath, const char *newpath); /* Returns: 0 if OK, -1 on error */
Relevant Commands
ls -l
: long listing format, check the reference countls -ls
: show file sizes in 1KB blocksls -li
: show i-node numbersSymbolic links
#include <unistd.h> int symlink(const char *actualpath, const char *sympath); /* Returns: 0 if OK, -1 on error */ ssize_t readlink(const char *path, char *buf, size_t bufsiz); /* Returns: number of bytes placed in the buffer, -1 on error */
File Times
Field | Description | Example | ls(1) option |
---|---|---|---|
st_atime | last access time | read | -u |
st_mtime | last modification time (file content) | write | default |
st_ctime | last change time (i-node) | chmod, chown | -c |
utime Function
#include <sys/types.h> #include <utime.h> int utime(const char *filename, const struct utimbuf *times); /* Returns: 0 if OK, -1 on error */ struct utimbuf { time_t actime; /* access time */ time_t modtime; /* modification time */ }; #include <sys/time.h> int utimes(const char *filename, const struct timeval times[2]); /* Returns: 0 if OK, -1 on error */ struct timeval { long tv_sec; /* seconds */ long tv_usec; /* microseconds */ };
mkdir and rmdir function
#include <sys/stat.h> #include <sys/types.h> int mkdir(const char *pathname, mode_t mode); /* Returns: 0 if OK, -1 on error */ #include <unistd.h> int rmdir(const char *pathname); /* Returns: 0 if OK, -1 on error */
Reading Directories
資料夾的 access 權限:
#include <sys/types.h> #include <dirent.h> DIR *opendir(const char *name); /* Returns: pointer to the directory if OK, NULL on error */ DIR *fdopendir(int fd);
#include <dirent.h> struct dirent *readdir(DIR *dirp); /* Returns: pointer to a dirent structure if OK, NULL on reaching EOF or error */ struct dirent { ino_t d_ino; /* inode number */ off_t d_off; /* offset to the next dirent */ unsigned short d_reclen; /* length of this record */ unsigned char d_type; /* type of file */ char d_name[256]; /* filename */ };
#include <sys/types.h> #include <dirent.h> int closedir(DIR *dirp); /* Returns: 0 if OK, -1 on error */
Seek in an Opened Directory
#include <sys/types.h> #include <dirent.h> void rewinddir(DIR *dirp); /* Returns: current location of the opened dir */ long telldir(DIR *dirp); /* Returns: current location of the opened dir */ void seekdir(DIR *dirp, long offset);
chdir, fchdir, getcwd
Every process has a current working directory
#include <unistd.h> int chdir(const char *path); /* Returns: 0 if OK, 1 on error */ int fchdir(int fildes); /* Returns: 0 if OK, 1 on error */ #include <unistd.h> char *getcwd(char *buf, size_t size); /* Returns: buf if OK, NULL on error */
每個系統檔案都有他的 major/minor device numbers,編碼後儲存在 system type dev_t
major(dev_t)
minor(dev_t)
在前面的 struct stat 中有 st_dev 和 the st_rdev 有什麼差別?
int main(int argc, char *argv[]) { int i; struct stat buf; for (i = 1; i < argc; i++) { printf("%s: ", argv[i]); if (stat(argv[i], &buf) < 0) { err_ret("stat error"); continue; } printf("dev=%d/%d", major(buf.st_dev), minor(buf.st_dev)); if (S_ISCHR(buf.st_mode) || S_ISBLK(buf.st_mode)) // 是 character 或是 block { printf(" (%s) rdev = %d/%d", (S_ISCHR(buf.st_mode)) ? "character" : "block", major(buf.st_rdev), minor(buf.st_rdev)); } printf("\n"); } exit(0); }
$ ./fig4.25-devrdev / /dev /home/chuang /dev/tty0 /dev/sda2 /: dev = 8/2 /dev: dev = 0/14 /home/chuang: dev = 8/2 /dev/tty0: dev = 0/14 (character) rdev = 4/0 /dev/sda2: dev = 0/14 (block) rdev = 8/2
Common Device Special Files