Apue Chapter 4 習題答案

Q1. 用stat 函數替換圖4-3程序中的lstat 函數,如若命令行參數之一是符號鏈接,會發生什麼變化?

改之前:

[root@clstore3 ~]# ./lstat /etc/passwd /etc /dev/log /dev/tty /dev/sr0 /dev/cdrom

/etc/passwd: regular

/etc: directory

/dev/log: socket

/dev/tty: character special

/dev/sr0: block special

/dev/cdrom: symbolic link

可以看出,lstat 把/dev/cdrom 當着軟鏈接去看。

現在我們把程序lstat 改爲stat 之後,允許結果如下,可以看stat查看的是符號鏈接所引用的文件的信息。  

結論:lstat 函數類似於stat,但當命名的文件是一個符號鏈接時,lstat返回該符號鏈接的有關信息,而不是有該符號鏈接引用的文件的信息。 

[root@clstore3 ~]# ./stat /etc/passwd /etc /dev/log /dev/tty /dev/sr0 /dev/cdrom

/etc/passwd: regular

/etc: directory

/dev/log: socket

/dev/tty: character special

/dev/sr0: block special

/dev/cdrom: block special


#include "apue.h"

int

main(int argc, char *argv[])

{

  int i;

  struct stat buf;

  char *ptr;


for ( i = 1; i < argc; i++) {

  printf("%s: ", argv[i]);

 if (stat(argv[i], &buf) < 0){   /* this need to change lstat from stae*/ 

   err_ret("lstat error");

   continue;

}

 if ( S_ISREG(buf.st_mode))

     ptr = "regular";

 else if ( S_ISDIR(buf.st_mode))

     ptr = "directory";

 else if ( S_ISCHR(buf.st_mode))

     ptr = "character special";

 else if ( S_ISBLK(buf.st_mode))

     ptr = "block special";

 else if ( S_ISFIFO(buf.st_mode))

     ptr = "fifo special";

 else if ( S_ISLNK(buf.st_mode))

     ptr = "symbolic link";

 else if ( S_ISSOCK(buf.st_mode))

     ptr = "socket";

 else

     ptr = "** unknow mode **";

 printf("%s\n", ptr);

}

 exit(0);

}


Q2.

如果文件模式創建屏蔽字是777(八進制),結果會怎樣?用shell 的umask 命令驗證該結果。 

[root@clstore3 ~]# umask

0022

改爲777後

[root@clstore3 ~]# umask 777

[root@clstore3 ~]# umask

0777

創建一個test3文件子後,只有root可以看,也不可以更改了。 

[root@clstore3 ~]# vim test3.txt

[root@clstore3 ~]# ls -al test3.txt

----------. 1 root root 12 Nov 13 10:44 test3.txt


Q3.關閉一個你所有擁有的用戶的讀權限,將導致拒絕你訪問你自己的文件,對此進行驗證。

[root@clstore3 ~]# chmod 640 /home/zhangb/Makefile

[root@clstore3 ~]# ls -al /home/zhangb/Makefile

-rw-r-----. 1 root root 18709 May 22 17:32 /home/zhangb/Makefile

切換到用戶zhangb,由於用戶zhangb沒有該文件的讀權限,所以不能查看該文件。 

[root@clstore3 ~]# su - zhangb

522868 $ ls -al Makefile

-rw-r-----. 1 root root 18709 May 22 17:32 Makefile

522868 $ less Makefile

Makefile: Permission denied

522868 $ whoami

522868


Q4,創建文件foo 和bar後,運行圖4-9的程序,將發生什麼情況?

什麼都沒有發生, 權限爲沒有任何改變。 

[root@clstore3 ~]# touch foo bar

[root@clstore3 ~]# ls -al foo bar

-rw-r--r--. 1 root root 0 Nov 13 11:34 bar

-rw-r--r--. 1 root root 0 Nov 13 11:34 foo

[root@clstore3 ~]# ./create_foobar

[root@clstore3 ~]# ls -al foo bar

-rw-r--r--. 1 root root 0 Nov 13 11:34 bar

-rw-r--r--. 1 root root 0 Nov 13 11:34 foo


###############################################################

[root@clstore3 ~]# cat create_foobar.c

#include "apue.h"

#include <fcntl.h>

#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("create error for foo");

 umask ( S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);

if (creat("bar", RWRWRW) < 0 )

   err_sys("create error for bar");

  exit(0);

}


Q4.5 4.12節中講到一個普通文件的大小可以是0,同時我們又知道st_size字段是爲目錄或符號鏈接定義的,那麼目錄和符號鏈接的長度可否爲0?

A:對於普通文件,其文件長度可以是0,在開始讀寫這種文件是,將得到文件(end-of-file)指示。

對於目錄,文件長度通常是一個(16or512)的整倍數。 

符號鏈接-文件長度是在文件名中的實際字節數。

[root@clstore3 /]# ls -al /dev/cdrom

lrwxrwxrwx. 1 root root 3 May 29 21:55 /dev/cdrom -> sr0

[root@clstore3 var]# ls -al mail

lrwxrwxrwx. 1 root root 10 Sep 15  2014 mail -> spool/mail


Q4.6,編寫一個類似cp1的程序,它複製包含空洞的文件,但不將字節0寫到輸入文件中去.

 

[root@clstore3 ~]# od -c file.hole

0000000   a   b   c   d   e   f   g   h   i   j  \0  \0  \0  \0  \0  \0

0000020  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0

*

0040000   A   B   C   D   E   F   G   H   I   J

0040012


[root@clstore3 ~]# od -c file.out

0000000   a   b   c   d   e   f   g   h   i   j   A   B   C   D   E   F

0000020   G   H   I   J

0000024


程序代碼部分

#include <stdio.h>

#include <stdlib.h>

/* this program is to copy a file ( ignore the hole part if there is a hole in it

 * zhangbo  2015/11/13 */


int main ()

{

  int c;

  FILE *in, *out;

  in = fopen("file.hole","r");

 out = fopen("file.out","w");

     c = fgetc(in);

   while ( c != EOF )

   {

    /* this is to copy the file, if encounter file with a hole in it '\0', do nothing,

      *  otherwise, copy the content to file.out*/

       if ( c != '\0')

        fputc(c,out);

        c = fgetc(in);

    }

        exit(0);

}


apue Note in output from the ls command in section 4.12 that the file core and core.copy have different access permission. If the umask value didn’t change between the creation of these two files. explain how the difference could have occurred. ? 


Q4.8 when running program 4.5 we check the available disk space with the df(1) command. why didn’t we use the du(1) command. 


du command reports that the amount of disk space used by the file. 512-byte blocks. 

Df displays the amount of disk space available on the file system containing each file name argument. 


Q4.9 In figure 4.20, we show the unlink function as modifying the changed-status time of the file itself. How can this happen?

The modification time indicates when the contents of the file were last modified. 

The changed-status time indicates when the i-node of the file was last modified. 

some operations the affect the i-node without changing the actual contents of the files:

 change the file access permissions/user ID, and change the number of links and so on. 

The unlink function changes the i-node contents of the file and it is for changed-status time. 

test1 are the hard link to test.txt,我們可以看到在unlink test1.txt 後,test.txt 的changed-status time 變成了16:59, 證明unlink 更改了i-node裏的信息link減1,導致最後的changed-status 變成了最新的

zhangbodeMacBook-Pro:script zhangbo$ ls -lc test*

-rw-r--r--  3 zhangbo  staff  12 11 16 16:49 test.txt

-rw-r--r--  3 zhangbo  staff  12 11 16 16:49 test1.txt

zhangbodeMacBook-Pro:script zhangbo$ ./a.out

file unlinked

done

zhangbodeMacBook-Pro:script zhangbo$ ls -lc test*

-rw-r--r--  2 zhangbo  staff  12 11 16 16:59 test.txt

 Three time fields are maintained for each file, Their purpose is summarized in the below. 

  st_atime    last-access time of tile                    read                  -u (ls option ls -u )

  st-mtime    last-modification time of file date    write 

  st-ctim       last-change time of i-node status    chmod,chown   -c 


Q4.10 in Section 4.22 how does the system’s limit on the number of open files effect the mighty function?

Opendir 打開一個目錄後,遞歸調用dopath函數。假設opendir使用一個文件描述符,並且只有在處理完目錄後才調用closedir釋放描述符,這就意味這每次將一級就要使用另外一個描述符。所以進程可以打開的最大描述符數就限制了我們可以遍歷的文件系統的深度。 


Q4.11 In section 4.22, our version of ftw never changes its directory, Modify this routine so that each time it encounters a directory, it uses the chdir function to change to that directory. allowing it to use the filename and not the pathname for each call to stat. When all the entries in the directory have been processed, execute chdir(“..”) compare the time used by this version and the version int the next. 

每次到要做兩次chdir,這樣會耗費系統的資源,感覺耗時。 


Q4.12. Each process also have a root directory that is used for resolution of absolute phonemes. 

this root directory can be changed with the chroot function. Look up the description for this function in your manuals when might this function be useful?

chroot 函數被英特網文件傳輸協議(FTP)程序用於輔助安全性,系統中咩有賬戶的用戶(匿名用戶)放在一個單獨的目錄下,利用chroot將目錄當着新的根目錄,就可以阻止用戶訪問此目錄之外的文件。 

chroot也可以在另一臺機器上構造一個文件系統結構的副本,然後修改此副本更改原來的文件系統,這可以用於測試新軟件包的安裝(標準答案)


Q4.13 how can you set only one of the two time values with the utimes functions?

utimes 太老了,搞不定,就用了個utime.跟它差不多,功能是一樣的。

utime 的結構是

struct utimbuf

  {

    __time_t actime;            /* Access time.  */

    __time_t modtime;           /* Modification time.  */

  };


[root@clstore3 ~]# vim file.out

[root@clstore3 ~]# ls -al file.out

-rw-r--r--. 1 root root 13 Nov 18 18:25 file.out

[root@clstore3 ~]# ls -lu file.out

-rw-r--r--. 1 root root 13 Nov 18 18:25 file.out

[root@clstore3 ~]# ./a.out

運行後的時間,access time 時間沒有變化,但mod 時間變了,

[root@clstore3 ~]# ls -al file.out

-rw-r--r--. 1 root root 13 Nov 15 18:25 file.out

[root@clstore3 ~]# ls -lu file.out

-rw-r--r--. 1 root root 13 Nov 18 18:25 file.out


# cat zap.c   -- 該程序來源於 http://m.blog.csdn.net/blog/zhoulaowu/14158137

#include <utime.h>

#include <sys/stat.h>

#include <stdio.h>

#include <stdlib.h>

int

main(int argc, char *argv[])

{

        int                             i, fd;

        struct stat     statbuf;

        char pathname[] = "/root/file.out";

      struct utimbuf ubuf;

        /*struct timespec       times[2];*/

          struct timespec times[2];


         if (stat(pathname, &statbuf) == -1) {

              printf("stat error for %s\n", argv[i]);

            } else

            {

              ubuf.modtime = statbuf.st_mtime - 30000;

              ubuf.actime = statbuf.st_atime ;



                if ( utime(pathname, &ubuf) == -1 )

                printf("utime error for %s\n", pathname);



        }

        exit(0);

}



Q4.14. some versions of the finger command output “new mail received …” and “unread since …” where …are the corresponding time and dates. How can the program determine these two times and dates

查看最後一次 access 時間 of a file. 

Q4.15. Examine the archive formats used by the clio and tar commands. ( these descriptions are usually found in section 5 of the Unix programmer’s manual)how many of the three possible time values are saved for each file? when a file is restored, what value do you think the access time is set to. and why?

mtime and atime for tar. 

tar 在抽取文件是,默認不改變文件的modify time,用戶的 access time 被修改。 

[root@clstore3 test1]# tar -xf tar.tat

[root@clstore3 test1]# ls -l   ---可以查看用戶的modify 時間,沒有被修改。 

total 12

-rw-r--r--. 1 root root     0 Nov 19 15:51 blues   --mtime 沒有被修改。 

-rw-r--r--. 1 root root     0 Nov 19 15:51 folk

-rw-r--r--. 1 root root     0 Nov 19 15:51 jazz

-rw-r--r--. 1 root root 10240 Nov 19 17:35 tar.tat

[root@clstore3 test1]# ls -u

blues  folk  jazz  tar.tat

[root@clstore3 test1]# ls -lu

total 12

-rw-r--r--. 1 root root     0 Nov 19 17:39 blues  --atime 被修改爲文件的抽取時間。

-rw-r--r--. 1 root root     0 Nov 19 17:39 folk

-rw-r--r--. 1 root root     0 Nov 19 17:39 jazz

-rw-r--r--. 1 root root 10240 Nov 19 17:35 tar.tat

[root@clstore3 test1]# date

Thu Nov 19 17:39:59 CST 2015


同樣的抽取是+M參數後,mtime and atime 都被改到被抽取的時間,可以看到mtime and atime 和現在的時間是一直的。

[root@clstore3 test1]# tar -mxf tar.tat

[root@clstore3 test1]# ls -al

total 20

drwxr-xr-x. 2 root root  4096 Nov 19 17:45 .

drwxr-xr-x. 4 root root  4096 Nov 19 17:28 ..

-rw-r--r--. 1 root root     0 Nov 19 17:45 blues

-rw-r--r--. 1 root root     0 Nov 19 17:45 folk

-rw-r--r--. 1 root root     0 Nov 19 17:45 jazz

-rw-r--r--. 1 root root 10240 Nov 19 17:35 tar.tat

[root@clstore3 test1]# ls -lu

total 12

-rw-r--r--. 1 root root     0 Nov 19 17:45 blues

-rw-r--r--. 1 root root     0 Nov 19 17:45 folk

-rw-r--r--. 1 root root     0 Nov 19 17:45 jazz

-rw-r--r--. 1 root root 10240 Nov 19 17:35 tar.tat

[root@clstore3 test1]# date

Thu Nov 19 17:45:14 CST 2015



Q4.16. Does the unix system have a fundamental limitation on the depth of a directory tree? To find our, write a program that creates a directory and then changes to that directory in a loop. Make certain that the length of the absolute pathname of the of the leaf of the directory is greater than your system’s PATH_MAX limit. Can you call getcwd to fetch the directory’s pathname? how do the standard UNIX system tools deal with this long pathname?

總體上說文件深度的應該是有限制的,但不同的系統限制也不同。 

我的機器在到203多的時候就不能顯示了,就說結果太大了。mac and linux 大概路徑長度爲1052個字符,然後就不行了。  但是mac 還是可以mkdir而且成功的。 unix 下就直接到203的時候不行了.

Linux and mac os pathname ~= 1052 字符 

mac os 可以繼續創建文件夾,但linux 就不可以了。 

 new current directory is:Result too large

current directory level: 8667

mkdir successed.

 new current directory is:Result too large

current directory level: 8668

mkdir successed.

 new current directory is:Result too large

current directory level: 8669

mkdir successed.


[root@clstore3 ~]# tail test.txt  | sed -n '5,7p' 

current directory level: 203

mkdir successed.

 new current directory is:/root/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test/test

[root@clstore3 ~]# tail test.txt  | sed -n '10p' | wc -c

1052


程序源碼

#include <sys/stat.h>

#include <unistd.h>

#include <limits.h>

#include <sys/stat.h>

#include <stdlib.h>

#include <string.h>

#include <stdio.h>

int main( int argc, char *argv[])

{

char path[1000];

char file[1000];

argv[1] = "test";

char *d ;

    char *s = "/view";

int i;

getwd(path);

printf("current directory is: %s\n", path);

    for ( i = 1; i <= 10000; i++){

printf("current directory level: %d\n", i);

  if ( mkdir(argv[1], S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH) < 0)

  {

  printf("mkdir failed\n");

  return 2;

  }

  if(chdir(argv[1]) < 0 )

  {

  printf("chdir failed \n");

  return 2;

  }

  getwd(path);

  /*strcpy(path, argv[1]);*/

  printf("mkdir successed.\n new current directory is:%s\n",path);

  }

  return 0;

}



Can you archive the directory using either tar or clio?

4.17. In section 3.16, we describe the /dev/fd feature. for any user to be able to access these files. their permissions must be rw-rw-rw. some programs that create an output file delete the file first, in case in already exists. ignoring the return code:

   unlink(path);

 if (( fd = create(path, FILE_MODE)) < 0 ) 

    erro_sys(…);

what happens if path is /dev/fd/1 ?

系統直接拒絕我unlink 

zhangbodeMacBook-Pro:script zhangbo$ ./a.out

unlink error: Permission denied

zhangbodeMacBook-Pro:script zhangbo$ ls -al /dev/fd

total 0

crw--w----   1 zhangbo  tty     16,   3 11 21 14:21 0

crw--w----   1 zhangbo  tty     16,   3 11 21 14:21 1

crw--w----   1 zhangbo  tty     16,   3 11 21 14:21 2

zhangbodeMacBook-Pro:script zhangbo$ cat delete_fd.c 

#include <apue.h>

#include <fcntl.h>

#include <unistd.h>

#include <stdio.h>

char *path;

int fd;

int main(void)

{

path="/dev/fd/1";

if (unlink(path) < 0 )

    err_sys("unlink error");

/*if ((fd = creat(path, FILE_MODE)) < 0 )

 err_sys("hello this is error");*/

}

我手工去rm 1 的時候被拒絕,官方解釋是/dev 這個目錄下面的寫權限被關閉了,但我感覺感覺不是的,

我到/dev 下面去刪點別(/dev/fd and /dev/zero )的東西也可以。在測試機器上做的centos 6.2重啓過後又好了看來linux 還是有很強大的自我恢復功能的。  

懇請看官有好的解釋通知俺一聲。 

[root@client2 ~]# ls -al /dev/fd

lrwxrwxrwx. 1 root root 13 10月 21 08:40 /dev/fd -> /proc/self/fd

[root@client2 ~]# ls -al /dev/fd/

總用量 0

dr-x------. 2 root root  0 11月 21 01:29 .

dr-xr-xr-x. 8 root root  0 11月 21 01:29 ..

lrwx------. 1 root root 64 11月 21 01:29 0 -> /dev/pts/3

lrwx------. 1 root root 64 11月 21 01:29 1 -> /dev/pts/3

lrwx------. 1 root root 64 11月 21 01:29 2 -> /dev/pts/3

lr-x------. 1 root root 64 11月 21 01:29 3 -> /proc/53116/fd

[root@client2 ~]# ls -al /proc/self/fd

總用量 0

dr-x------. 2 root root  0 11月 21 01:29 .

dr-xr-xr-x. 8 root root  0 11月 21 01:29 ..

lrwx------. 1 root root 64 11月 21 01:29 0 -> /dev/pts/3

lrwx------. 1 root root 64 11月 21 01:29 1 -> /dev/pts/3

lrwx------. 1 root root 64 11月 21 01:29 2 -> /dev/pts/3

lr-x------. 1 root root 64 11月 21 01:29 3 -> /proc/53129/fd

zhangbodeMacBook-Pro:script zhangbo$ ./a.out

unlink error: Permission denied

zhangbodeMacBook-Pro:script zhangbo$ ls -al /dev/fd

total 0

crw--w----   1 zhangbo  tty     16,   3 11 21 14:21 0

crw--w----   1 zhangbo  tty     16,   3 11 21 14:21 1

crw--w----   1 zhangbo  tty     16,   3 11 21 14:21 2


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章