欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

apue读书笔记-Ch04(2)

程序员文章站 2022-07-14 20:19:07
...
# 4.9 `chmod, fchmod fchmodat` Functions
#include <sys/stat.h>
int chmod(const char *pathname, mode_t mode);
int fchmod(int fd, mode_t mode);
int fchmodat(int fd, const char *pathname, mode_t mode, int flag);
JunrdeMacBook-Pro:ch04 junr$ ls -l foo bar
-rw-r--r--  1 junr  staff  0  8 14 16:10 bar
-rw-r--r--  1 junr  staff  0  8 14 16:10 foo
#include "apue.h"
int main(void)
{
    struct stat statbuf;

    if(stat("foo", &statbuf) < 0)
        err_sys("stat error for foo");
    // execute by group
    // set-group-ID on execution
    if(chmod("foo", (statbuf.st_mode & ~S_IXGRP) | S_ISGID) < 0)
        err_sys("chmod error for foo");

    if(chmod("bar", S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) < 0)
        err_sys("chmod error for bar");

    exit(0);
}
编译运行后:
JunrdeMacBook-Pro:ch04 junr$ ./a.out
JunrdeMacBook-Pro:ch04 junr$ ls -l foo bar
-rw-r--r--  1 junr  staff  0  8 14 16:10 bar
-rw-r-Sr--  1 junr  staff  0  8 14 16:10 foo
Note that the ls command lists the group-execute permission as S to signify that the set-group-ID bit is set without the group-execute bit being set.
set-user-ID: SUID 当文件的该位有设置时,表示当该文件被执行时,程序具有文件所有者的权限而不是执行者的权限。 这样说有点绕,举个例子就是说passwd这个命令,它的所有者是root,并且它的set-user-id有设置,所以执行passwd命令后,passwd进程具有root权限,也才能改密码,毕竟普通用户没有修改/etc/passwd文件的权限。然而,并不能该别人的密码,因为st_uid还是我,并不是root。 当文件的set-user-ID位被设置时,通过ls -l命令查看,在许可权限部分,用户的x被替换成s ls -l /usr/include/passwd -rwsr-xr-x 1 root root 41284 9月 13 2012 /usr/bin/passwd set-group-ID: SGID 和set-user-id同理,不过具有的是所有组的权限. 当文件的set-group-ID位被设置时,在许可权限部分,组用户的x被替换成s sticky: sticky位对于文件和目录有不同的用途。 对于文件而言,sticky位告诉内核即使没有人在使用这个程序,也要把它放在交换空间中,放在交换空间里的文件被内存调用的时候要比放在磁盘上快。不过有虚拟技术后,这个用的很少了。 对于目录而言,sticky位使得存放在这个目录下的文件只能被创建者删除,别人不能够删除。 当文件的sticky位被设置时,通过ls -l命令查看,在许可权限部分,其他用户的x被替换成t 设置方法类似 : chmod 4777 filename 4 代表SUID 2 代表SGID 1 代表sticky

We’ll see in Section 4.19 that the chmod function updates only the time that the i-node was last changed. By default, the ls -l lists the time when the contents of the file were last modified.

4.10 Sticky Bit

4.11 chown, fchown, fchownat, lchown Functions

#include <unistd.h>
int chown(const char *pathname, uid_t owner, gid_t group);
int fchown(int fd, uid_t owner, gid_t group);
int fchownat(int fd, const char *pathname, uid_t owner, gid_t group, int flag);
int lchown(const char *pathname, uid_t owner, gid_t group);

4.12 File Size

The st_size member of the stat structure contains the size of the file in bytes. This field is meaningful only for regular files, directories, and symbolic links.

Most contemporary UNIX systems provide the fields st_blksize and st_blocks. The first is the preferred block size for I/O for the file, and the latter is the actual number of 512-byte blocks that are allocated. Recall from Section 3.9 that we encountered the minimum amount of time required to read a file when we used st_blksize for the read operations. The standard I/O library, which we describe in Chapter 5, also tries to read or write st_blksize bytes at a time, for efficiency.

Holes in a File

Holes are created by seeking past the current end of file and writing some data.

NAME
     du -- display disk usage statistics
-a或-all 显示目录中个别文件的大小。 
-b或-bytes 显示目录或文件大小时,以byte为单位。 
-c或--total 除了显示个别目录或文件的大小外,同时也显示所有目录或文件的总和。
-k或--kilobytes 以KB(1024bytes)为单位输出。 
-m或--megabytes 以MB为单位输出。 
-s或--summarize 仅显示总计,只列出最后加总的值。 
-h或--human-readable 以KMG为单位,提高信息的可读性。 
-x或--one-file-xystem 以一开始处理时的文件系统为准,若遇上其它不同的文件系统目录则略过。 
-L<符号链接>或--dereference<符号链接> 显示选项中所指定符号链接的源文件大小。 
-S或--separate-dirs 显示个别目录的大小时,并不含其子目录的大小。 
-X<文件>或--exclude-from=<文件> 在<文件>指定目录或文件。 
--exclude=<目录或文件> 略过指定的目录或文件。 
-D或--dereference-args 显示指定符号链接的源文件大小。 
-H或--si 与-h参数相同,但是KMG是以1000为换算单位。 
-l或--count-links 重复计算硬件链接的文件。

来自: http://man.linuxde.net/du
wc命令用来计算数字。利用wc指令我们可以计算文件的Byte数、字数或是列数,若不指定文件名称,或是所给予的文件名为“-”,则wc指令会从标准输入设备读取数据。

wc(选项)(参数)

-c或--bytes或——chars:只显示Bytes数; 
-l或——lines:只显示列数; 
-w或——words:只显示字数。

来自: http://man.linuxde.net/wc

4.13 File Truncation

#include <unistd.h>
int truncate(const char *pathname, off_t length); 
int ftruncate(int fd, off_t length);

4.14 File Systems

To appreciate the concept of links to a file, we need a conceptual understanding of the structure of the UNIX file system. Understanding the difference between an i-node and a directory entry that points to an i-node is also useful.

我们可以将一个disk drive分为多个区块,每个区块包含一个文件系统。 i-nodes是一个固定长度的entries,它包含了大多数关于文件的信息。
apue读书笔记-Ch04(2)

If we examine the i-node and data block portion of a cylinder group in more detail, we could have the arrangement shown in Figure 4.14.
apue读书笔记-Ch04(2)

  • 有两个directory entries指向了同一个i-node entry。每个i-node有个link count,它记录了指向它的directory entries的个数。只有link count等于0,文件才被删除。This is why the function that removes a directory entry is called unlink, not delete.
  • 另一种link:symnbolic link 文件的内容–data blocks–存储了symbolic link指向的文件文件名。
    In the following example, the filename in the directory entry is the three-character string lib and the 7 bytes of data in the file are usr/lib:

    lrwxrwxrwx 1 root 7 Sep 25 07:14 lib -> usr/lib

    The file type in the i-node would be S_IFLNK so that the system knows that this is a symbolic link.

  • i-node 包含了关于文件的所有信息。而directory entry包含了两个信息:filename,i-node number。

  • 当重命名一个文件时(不改变文件系统),只需要add a new directory entry that points to the existing i-node and then unlink the old directory entry

Assume that we make a new directory in the working directory, as in

mkdir testdir

apue读书笔记-Ch04(2)

4.15 link, linkat, unlink, unlinkat, remove Functions

As we saw in the previous section, a file can have multiple directory entries pointing to its i-node. We can use either the link function or the linkat function to create a link to an existing file.

#include <unistd.h>
int link(const char *existingpath, const char *newpath);
int linkat(int efd, const char *existingpath, int nfd, const char *newpath, int flag);
#include <unistd.h>
int unlink(const char *pathname);
int unlinkat(int fd, const char *pathname, int flag);

Only when the link count reaches 0 can the contents of the file be deleted.

4.16

#include <stdio.h>
int rename(const char *oldname, const char *newname);
int renameat(int oldfd, const char *oldname, int newfd, const char *newname);
  • If oldname specifies a file that is not a directory, then we are renaming a file or a symbolic link. In this case, if newname exists, it cannot refer to a directory. If newname exists and is not a directory, it is removed, and oldname is renamed to newname.
  • If oldname specifies a directory, then we are renaming a directory. If newname exists, it must refer to a directory, and that directory must be empty. (When we say that a directory is empty, we mean that the only entries in the directory are dot and dot-dot.)

4.17 Symbolic Links

http://wzgl08.blog.51cto.com/668144/308987

4.19 File Times