Skip to content

Latest commit

 

History

History

15-file-attributes

Chapter 15: File Attributes

Exercise 15-1

Question

Section 15.4 contained several statement about the permissions required for various file-system operations. Use shell commands or write programs to verify or answer the following:

a) Removing all owner permissions from a file denies the file owner access, even though group and other do have access. b) On a directory with read permission but not execute permission, the names of files in the directory can be listed, but the files themselves can't be accessed, regardless of the permissions on them. c) What permissions are required on the parent directory and the file itself in order to create a new file, open a file for reading, open a file for writing, and delete a file? What permissions are required on the source and target directory to rename a file? If the target file of a rename operation already exists, what permissions are required on that file? How does setting the sticky permission bit (chmod +t) of a directory affect renaming and deletion operations.

Answer

Part A

  $ ./ex1atest.sh 
  ----rwxrwx 1 posborne posborne 4 Dec 29 16:18 test/ex1a_testfile.txt
  cat: test/ex1a_testfile.txt: Permission denied

Part B

  $ ./ex1btest.sh
  ls: cannot access test/b: Permission denied
  ls: cannot access test/a: Permission denied
  ls: cannot access test/..: Permission denied
  ls: cannot access test/.: Permission denied
  total 0
  d????????? ? ? ? ?            ? .
  d????????? ? ? ? ?            ? ..
  -????????? ? ? ? ?            ? a
  -????????? ? ? ? ?            ? b
  cat: test/a: Permission denied
  cat: test/b: Permission denied

Part C

$ ./ex1ctest.sh 
== +rwx, - ==
   create: PASS
   read:   PASS
   write:  PASS
   delete: PASS
   delt:   PASS
== +rw, -x ==
   create: ----
   read:   PASS
   write:  ----
   delete: ----
   delt:   ----
== +rx, -w ==
   create: ----
   read:   PASS
   write:  PASS
   delete: ----
   delt:   ----
== +xw, -r ==
   create: PASS
   read:   PASS
   write:  PASS
   delete: PASS
   delt:   PASS
== +x, -rw ==
   create: ----
   read:   PASS
   write:  PASS
   delete: ----
   delt:   ----
== +w, -rx ==
   create: ----
   read:   PASS
   write:  ----
   delete: ----
   delt:   ----
== +r, -wx ==
   create: ----
   read:   PASS
   write:  ----
   delete: ----
   delt:   ----
== Rename Tests ==
   rx -> xt:		----
   rx -> r:		----
   rx -> rt:		----
   rx -> rwt:		----
   rx -> wt:		----
   rx -> w:		----
   rx -> rwx:		----
   rx -> xwt:		----
   rx -> rw:		----
   rx -> rxt:		----
   rx -> xw:		----
   rx -> x:		----
   rx -> rwxt:		----
   xt -> r:		----
   xt -> rt:		----
   xt -> rwt:		----
   xt -> wt:		----
   xt -> w:		----
   xt -> rwx:		----
   xt -> xwt:		----
   xt -> rw:		----
   xt -> rxt:		----
   xt -> xw:		----
   xt -> x:		----
   xt -> rwxt:		----
   r -> rt:		----
   r -> rwt:		----
   r -> wt:		----
   r -> w:		----
   r -> rwx:		----
   r -> xwt:		----
   r -> rw:		----
   r -> rxt:		----
   r -> xw:		----
   r -> x:		----
   r -> rwxt:		----
   rt -> rwt:		----
   rt -> wt:		----
   rt -> w:		----
   rt -> rwx:		----
   rt -> xwt:		----
   rt -> rw:		----
   rt -> rxt:		----
   rt -> xw:		----
   rt -> x:		----
   rt -> rwxt:		----
   rwt -> wt:		----
   rwt -> w:		----
   rwt -> rwx:		----
   rwt -> xwt:		----
   rwt -> rw:		----
   rwt -> rxt:		----
   rwt -> xw:		----
   rwt -> x:		----
   rwt -> rwxt:		----
   wt -> w:		----
   wt -> rwx:		----
   wt -> xwt:		----
   wt -> rw:		----
   wt -> rxt:		----
   wt -> xw:		----
   wt -> x:		----
   wt -> rwxt:		----
   w -> rwx:		----
   w -> xwt:		----
   w -> rw:		----
   w -> rxt:		----
   w -> xw:		----
   w -> x:		----
   w -> rwxt:		----
   rwx -> xwt:		PASS
   rwx -> rw:		----
   rwx -> rxt:		----
   rwx -> xw:		PASS
   rwx -> x:		----
   rwx -> rwxt:		PASS
   xwt -> rw:		----
   xwt -> rxt:		----
   xwt -> xw:		----
   xwt -> x:		----
   xwt -> rwxt:		----
   rw -> rxt:		----
   rw -> xw:		----
   rw -> x:		----
   rw -> rwxt:		----
   rxt -> xw:		----
   rxt -> x:		----
   rxt -> rwxt:		----
   xw -> x:		----
   xw -> rwxt:		PASS
   x -> rwxt:		----

Exercise 15-2

Question

Do you expect any of a file's three timestamps to be changed by the stat() system call? If not, explain why?

Answer

A file's three timestamps are

  • st_atime: Time of last file access
  • st_mtime: Time of last file modification
  • st_ctime: Time of last status change

Accessing a file's metadata via stat() seems unlikely to change any of these entries. stat() just access information in the inode, not in the file itself.

This is confirmed by the results of exercise2_stattest.c:

  == Initial Stat ==
  st_atime: 1356847530
  st_mtime: 1356847529
  st_ctime: 1356847529

  ... Waiting 2 seconds ...

  == After First stat() call ==
  st_atime: 1356847530
  st_mtime: 1356847529
  st_ctime: 1356847529

Exercise 15-3

Question

On a system running Linux 2.6, modify the program in Listing 15-1 (t_stat.c) so that the file timestamps are displayed with nanosecond accuracy.

Answer See exercise3_tstat.c.

$ ./prog_tstat ch15-exercises.txt
File type:                regular file
Device containing i-node: major=8   minor=21
I-node number:            15610057
Mode:                     100664
Number of (hard) links:   1
Ownership:                UID=1000   GID=1000
File size:                6263 bytes
Optimal I/O block size:   4096 bytes
512B blocks allocated:    16
Last file access:         Sat Dec 29 23:49:57.702632926 2012
Last file modification:   Sun Dec 30 00:06:25.882630582 2012
Last status change:       Sun Dec 30 00:06:25.882630582 2012

Exercise 15-4

Question

The access() system call checks permissions using the process's real user and group IDs. Write a corresponding function that performs the checks according to the process's effective user and group IDs.

Answer

TODO: easiest way probably involves temporarily setting the real user id and real group id to the effective for a period of time.

Exercise 15-5

Question

As noted in Section 15.4.6, umask() always sets the process umask and, at the same time, returns a copy of the old umask. How can we obtain a copy of the current process umask while leaving it unchanged?

Answer

This can be done by calling umask() twice. That is:

mode_t my_umask;
my_umask = umask(0); /* clear temporarily */
umask(my_umask); /* set it back */

Exercise 15-6

Question

The chmod a+rX file command enables read permission for all categories of user, and likewise enables execute permission for all categories of user if the file is a directory or execute permission is enabled for any of the user categories for file, as demonstrated in the following example:

(...)

Write a program that uses stat() and chmod() to perform the equivalent of chmod a+rX

Answer

See exercsise6_chmod.c.

Example:

  $ ls -ld testex6/*
  dr--------   2 posborne       posborne     4096 Dec 30 20:43 testex6/dir/
  -r--------   1 posborne       posborne        0 Dec 30 20:43 testex6/file
  -r-x------   1 posborne       posborne        0 Dec 30 20:43 testex6/prog
  $ ./prog_chmod testex6/*
  $ ls -ld testex6/*
  dr-xr-xr-x   2 posborne       posborne     4096 Dec 30 20:43 testex6/dir/
  -r-xr-x--x   1 posborne       posborne        0 Dec 30 20:43 testex6/file
  -r-xr-x--x   1 posborne       posborne        0 Dec 30 20:43 testex6/prog

Exercise 15-7

Question

Write a simple version of the chattr(1) command, which modifies file i-node flags. See the chattr(1) man page for details of the chattr command-line interface. (You don't need to implement the -R, -V, and -v options.)

Answer

See chattr.c for an implementation.

  $ touch test.txt
  $ lsattr test.txt
  -------------e- test.txt
  $ ./prog_chattr +suActe test.txt
  $ lsattr test.txt
  su-----Ac--t-e- test.txt
  $./prog_chattr -suA test.txt
  $ lsattr test.txt
  --------c--t-e- test.txt
  $ ./prog_chattr =e test.txt
  $ lsattr test.txt
  -------------e- test.txt