目錄表

Files and Directories

0x00 Outline


0x01 Introduction

File Name

Path Name

Directory


0x02 File Information

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

Common File Information

File Types


0x03 File Permissions

這邊可以先參考 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 */
a.out
#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 */

0x04 File Systems Files

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

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

0x05 Directory Operations

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

0x06 Device Special Files

每個系統檔案都有他的 major/minor device numbers,編碼後儲存在 system type 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


0x07 參考資料