System Programming Chapter 4 Files and Directories 1

advertisement

System Programming

Chapter 4

Files and Directories

1

Fun Projects

• Communicating intimacy vs. communicating verbal messages

• Lovers’ cups, drinking interfaces

(MIT media Lab)

• Emotional (Crying) Décor (NYU)

• Interactive Pillow (TII, Sweden)

• Hand holding (Cornell)

2

More Fun Project

• Do you feel confused in the classroom?

• Do you feel bored in the classroom?

• Do you feel ignored in the classroom?

• Do you feel unfairness that only the speaker has control of the slides?

• Now … you can express frustration with the Active Slides!

3

Files and Directories

• Objectives

– Additional Features of the File System

– Properties of a File.

• Three major functions:

#include <sys/types.h>

#include <sys/stat.h> int stat(const char *pathname, struct stat *buf); int fstat(int filedes, struct stat *buf); int lstat(const char *pathname, struct stat *buf);

4

Files and Directories

• Differences on stat(), fstat(), lstat():

– lstat() returns info regarding the symbolic link, instead of the referenced file, if it happens.

struct stat { mode_t st_mode; /* type & mode */ ino_t st_ino; /* i-node number */ dev_t st_dev; /* device no (filesystem) */ dev_t st_rdev; /* device no for special file */ nlink_t st_nlink; /* # of links */ uid_t st_uid; gid_t st_gid; off_t st_size; /* sizes in byes */ time_t st_atime; /* last access time */ time_t st_mtime; /* last modification time */ time_t st_ctime; /* time for last status change */ long st_blk_size; /* best I/O block size */ long st_blocks; /* number of 512-byte blocks allocated */

};

5

File Types

• Encoded in st_mode

• Regular Files: text, binary, etc.

• Directory Files: Only Kernel can update these files –

{ (filename, pointer) }.

• Character Special Files, e.g., tty, audio, etc.

• Block Special Files, e.g., disks, etc.

• FIFO – named pipes

• Sockets – not POSIX.1 or SVR4

– SVR4 uses library of socket functions, instead. 4.3+BSD has a file type of socket.

• Symbolic Links – not POSIX.1 or SVR4

6

File Type Macro in <sys/stats.h>

S_ISREG() // regular file

S_ISDIR()

S_ISCHR()

S_ISBLK()

S_ISFIFO()

S_ISLNK()

S_ISSOCK()

7

#include "apue.h"

{

Int main(int argc, char *argv[]) int struct stat char buf;

*ptr; i; for (i = 1; i < argc; i++) { printf("%s: ", argv[i]); if (lstat(argv[i], &buf) < 0) { err_ret("lstat error"); continue;

} if (S_ISREG(buf.st_mode)) ptr = "regular "; else if (S_ISDIR(buf.st_mode)) ptr = "directory";

Figure 4.3

} else if (S_ISCHR(buf.st_mode)) ptr = "character special"; if (S_ISBLK(buf.st_mode)) ptr = "block special"; else if (S_ISFIFO(buf.st_mode)) ptr = "fifo"; else if (S_ISLNK(buf.st_mode)) ptr = "symbolic link"; else if (S_ISSOCK(buf.st_mode)) ptr = "socket"; else ptr = "** unknown mode **"; printf("%s\n", ptr);

} exit(0);

8

File Access Permissions

• All files have access permissions

– st_mode mask – owner, group, other

#define S_IRWXU 00700 /* read, write, execute: owner */

#define S_IRUSR 00400 /* read permission: owner */

#define S_IWUSR 00200 /* write permission: owner */

#define S_IXUSR 00100 /* execute permission: owner */

#define S_IRWXG 00070 /* read, write, execute: group */

#define S_IRGRP 00040 /* read permission: group */

#define S_IWGRP 00020 /* write permission: group */

#define S_IXGRP 00010 /* execute permission: group */

#define S_IRWXO 00007 /* read, write, execute: other */

#define S_IROTH 00004 /* read permission: other */

#define S_IWOTH 00002 /* write permission: other */

#define S_IXOTH 00001 /* execute permission: other */

9

File Operations vs. Access Permissions

• File Operations: read, write, execute, etc.

• File Access Permissions: who (process) can perform what operations

• Directory file

– X – pass through the dir (search bit), e.g., /usr/dict/words.

– R – list of files under the dir.

– W – update the dir, e.g., delete or create a file.

• Regular file

– X – execute a file (which must be a regular file)

– R – O_RDONLY or O_RDWR

– W – O_WRONLY, O_RDWR, or O_TRUNC

• What are the needed file access permissions?

– ls /home/professor/hchu

– cd /home/professor/hchu

– rm /home/professor/hchu/foo

– cat /home/professor/hchu/foo

– echo 123 >> /home/professor/hchu/foo

10

Process IDs

• How to check if a process can perform an operation on file access permissions?

– File access test: check (process IDs, file APs, OP)

• A process can have more than one ID.

– Real user/group ID // who we really are, e.g., hchu

– Effective user/group ID // used for file access

// permission checks

– Supplementary group IDs

– Saved set-user/group-ID // saved by exec function

11

Access Permissions & UID/GID

• File Access Test – each time a process creates/opens/deletes a file

– If the effective UID == 0  superuser!

– If the effective UID == UID of the file

• Check appropriate access permissions!

– If the effective GID == GID of the file

• Check appropriate access permissions!

– Check appropriate access permissions for others!

• Related Commands: chmod & umask

12

hchu@linux1:/> ls -l /etc/shadow

-rw-r----- 1 root shadow 843 2006-03-07 10:01 /etc/shadow hchu@linux1:/> cat /etc/shadow hchu@linux1:/> ls -al .

drwxr-xr-x 22 root root 4096 2006-01-20 13:33 ./ drwxr-xr-x 22 root root 4096 2006-01-20 13:33 ../ drwxr-xr-x 2 root root 4096 2006-03-13 18:23 bin/ hchu@linux1:/> cd bin hchu@linux1:/usr/include> which passwd

/usr/bin/passwd hchu@linux1:/usr/include> ls -l /usr/bin/passwd

-rwsr-xr-x 1 root root 28224 2006-02-22 14:05 /usr/bin/passwd hchu@linux1:/usr/include> rm /usr/bin/passwd hchu@linux1:/usr/include> passwd

13

Set-User-ID/Set-Group-ID

• st_mode: st_uid/st_gid

– Setting user/group ID of the owner.

• How can a user change his/her password without having the write permission to /etc/passwd and /etc/shadow?

-rw-r--r--

-r--------

1 root root 1746 2/21 13:00 /etc/passwd

1 root root 1142 2/21 13:01 /etc/shadow

• A process can have more than one ID.

– Real user/group ID

– Effective user/group ID

– Supplementary group IDs

– Saved set-user/group-ID

14

Ownership of a New File

• Rules:

– UID of a file = the effective UID of the creating process

– GID of a file – options under POSIX

1.

GID of the file = the effective GID of the process

2.

GID of the file = the GID of the residing dir

– 4.3BSD and Mac OS X do (2).

– SVR4 needs to set the set-group-ID bit of the residing dir

(mkdir)!

15

Function – access

• Test a file accessibility before accessing it.

#include <unistd.h> int access(const char *pathname, int mode);

– R_OK // test for read permission

– W_OK

– X_OK

– F_OK

– Check the real UID/GID!

16

Figure 4.8 Program

#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 exit(0); printf("open for reading OK\n");

>ls -l fig4.8.exe

-rwxr-xr-x 1 hchu users 9487 2006-

03-21 19:53 fig4.8.exe

>fig4.8.exe fig4.8.exe

read access OK open for reading OK

>ls -l /etc/shadow

-rw-r----- 1 root shadow 843 2006-

03-07 10:01 /etc/shadow

>fig4.8.exe /etc/shadow access error for /etc/shadow:

Permission denied open error for /etc/shadow:

Permission denied

17

Function – umask

• Set file mode creation mask (default file permissions)

#include <sys/types.h>

#include <sys/stat.h> mode_t umask(mode_t cmask);

– Any bits that are on in the cmask are turned off in the file’s mode

• cmask = bitwise-OR file access permissions (e.g., S_I[RWX]USR)

• Examples: cmask = S_IRWXO, cmask = S_IWOTH | S_IWGRP

– The mask goes with the process only.

• Inheritance from the parent!

18

Figure 4.9 Program

#include "apue.h"

#include <fcntl.h>

#define RWRWRW

(S_IRUSR|S_IWUSR|S_IRGRP|S_IW

GRP|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) exit(0); err_sys("creat error for bar");

>umask

22

>fig4.9.exe

>ls -al foo bar

-rw------- 1 hchu users 0 2006-03-21 20:14 bar

-rw-rw-rw- 1 hchu users 0 2006-03-21

20:14 foo

>umask

22

19

Function – chmod & fchmod

• Change file access permissions for an existing file.

#include <sys/types.h>

#include <sys/stat.h> int chmod(const char *pathname, mode_t mode); int fchmod(int filedes, mode_t mode);

– fchmod() is not in POSIX.1, but in SVR4/4.3+BSD

– Callers must be a superuser or effective UID = file UID.

– Mode = bitwise-OR S_I[RWX]USR, S_ISVTX (sticky bit), S_IS[UG]ID, etc (Fig 4.6).

20

Figure 4.10 Program

}

#include "apue.h"

{

Int main(void) struct stat statbuf;

/* turn on set-group-ID and turn off group-execute */ if (stat("foo", &statbuf) < 0) err_sys("stat error for foo"); if ( chmod("foo", (statbuf.st_mode &

~S_IXGRP) | S_ISGID) < 0) err_sys("chmod error for foo");

/* set absolute mode to "rw-r--r--" */ if ( chmod("bar", S_IRUSR | S_IWUSR |

S_IRGRP | S_IROTH) < 0) err_sys("chmod error for bar"); exit(0);

>ls -al foo bar

-rw------- 1 hchu users 0 2006-03-21

20:14 bar

-rw-rw-rw- 1 hchu users 0 2006-03-21

20:14 foo

>fig4.12.exe

>ls -al foo bar

-rw-r--r-- 1 hchu users 0 2006-03-21

20:14 bar

-rw-rwSrw- 1 hchu users 0 2006-03-

21 20:14 foo

// what is strange here?

21

Function – chmod & fchmod

• set-group-ID

– If the GID of a newly created file is not equal to the effective GID of the creating process (or one of the supplementary GID’s), or the process is not a superuser, clear the set-group-ID bit!

– Clear up set-user/group-ID bits if a non-superuser process writes to a set-uid/gid file.

22

Function – chmod & fchmod

• Sticky Bit (S_ISVTX) – saved-text bit

– For frequently executed binaries

– Not POSIX.1 – by SVR4 & 4.3+BSD

– Only superusers can set it!

– S_ISVTX executable file

• Used to save a copy of a S_ISVTX executable in the swap area to speed up the execution next time.

– S_ISVTX directory file, e.g., /tmp

• Remove/rename its file only if w permission of the dir is set, and the process is belonging to superusers/owner of the file/dir

23

Function – chown, fchown, lchown

• Change the user/group ID of a file

#include <sys/types.h>

#include <unistd.h> int chown(const char *pathname, uid_t owner, gid_t, grp); int fchown(int filedes, uid_t owner, gid_t, grp); int lchown(const char *pathname, uid_t owner, gid_t, grp);

– lchown() is unique to SVR4. Under non-SVR4 systems, if the pathname to chown() is a symbolic link, only the ownership of the symbolic link is changed.

– -1 for owner or grp if no change is wanted

.

• Why would one want to give away file ownership?

24

Function – chown, fchown, lchown

• _POSIX_CHOWN_RESTRICTED is in effect (check pathconf())

– Superuser  the UID of the file can be changed!

– The GID of the file can be changed if

• the process owns the file, and

• Parameter owner = UID of the file & Parameter grp = the process

GID or is in supplementary GID’s

• set-user/group-ID bits would be cleared if chown is called by nonsuper users.

25

File Size

• File Sizes – st_size

– Regular files – 0~max (off_t)

– Directory files – multiples of 16/512

– Symbolic links – pathname length

– /* a pipe’s file size for SVR4 */

• File Holes

– st_blocks vs st_size (st_blksize)

– Commands:

• “ls –l file.hole” == “wc –c file.hole”

• du –s file.hole  actual size

• cat file.hole > file.hole.copy

26

Functions – truncate & ftruncate

# include <sys/types.h>

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

– Not POSIX.1

– SVR4 creates a hole if length > fsize.

– 4.3+BSD only truncates files.

– Portability?

27

System Programming

Chapter 4

朱浩華教授 / 施吉昇教授

臺灣大學資訊工程系

28

Administration Misc. (4/12)

• The mid-term will be held on April 26, 2006 in class.

It will cover Chapter 1 to 6.

• MP2 is out today and due on April 28, 2006 (Friday).

• Some of your email address on website have been deleted due to a bug for the web site. Please visit the site to update your email address.

29

Playing with Shadow

(Tokyo University)

30

Filesystem

• A disk can be divided into logical partitions.

• Each partition has a filesystem.

• Each filesystem contains a list of inodes (i-list) as well as the actual directory- and data blocks

• Every inode has a link count (st_nlink): it shows how many “things” point to this inode. Only if this link count is 0 are the data blocks freed. Each name

<-> inode association is called a hard link.

inode contains most of information found in the stat structure.

inode number in a directory entry must point to an inode on the same file system (no hardlinks across filesystems)

• To move a file within a single filesystem, we can just ”move” the directory entry (actually done by creating a new entry, and deleting the old one).

31

BSD UNIX File System (UFS)

32

BSD UNIX File System (UFS)

Figure 4.14 (hard links)

33

Filesystem – 4.4BSD i-node

mode owner timestamp size block ref-count data data data

• 4KB block size

• 12 direct pointers

• 48KB

• 1 single indirect

• 4-byte block ptr

• 1K * 4KB = 4MB

• >> 4GB for the largest file!

(offset = 32 bits, 4G=2 32 ) direct blocks data single indirect double indirect

… data

… data

… data

… data triple indirect

… data

* “Operating system concept”, Silberschatz and Galvin, Addison Wesley, pp. 380.

34

BSD UNIX File System (UFS)

(> mkdir testdir ; link count, leaf vs. intermediate dirs)

35

Hard Link v.s. Soft Link

• Hard Link

– Cannot link to different mounted file system.

– is a different name for the same set of data blocks.

– Only superuser can create a link to a directory.

• Soft Link (or Symbolic link)

– Can be a directory or file

– Is a pointer to a set of data blocks.

– File type is S_IFLINK

• What’s the difference on their i-nodes?

36

/usr/joe foo

/usr/sue bar

/usr/joe foo

/usr/sue bar

Hard vs. Soft Links

File i-node:

#Reference = 2

File i-node:

#Reference = 1

File i-node:

#Reference = 1 data block:

“/usr/joe/foo”

• Hard Link

– Each directory entry creates a hard link of a filename to the i-node that describes the file’s contents.

– Normally require that link & file on the same file system

• Symbolic Link (Soft Link)

– It is implemented as a file that contains a pathname.

– Filesize = pathname length

– Example: Shortcut on

Windows

– Get around with filesystem limitation & linking dirs

37

/usr/joe foo

/usr/sue bar

/usr/joe foo

/usr/sue bar

Hard vs. Soft Links

File i-node:

Reference = 2

• Problems with links

– Infinite loops

– Dangling pointers

– Unable to remove

File i-node:

Reference = 1

File i-node:

Reference = 1 data block:

“/usr/joe/foo”

38

Symbolic Links: infinite loops

a foo testdir

> mkdir foo

> touch foo/a

> ln –s ../foo foo/testdir

> ls –l foo

> ls –R

• List subdirectories recursively foo foo/a foo/testdir foo/testdir/?

39

BSD UNIX File System (UFS)

(> mv testdir testdir2 -> only update inode)

40

Functions – link, unlink, rename, remove

#include <unistd.h> int link(const char *existingpath, const char *newpath); int unlink(const char *pathname);

– Atomic action for link – hard link

• POSIX.1 allows linking across filesystems

• Only superusers could create a link to a dir

– Error if newpath exists

– Unlink – WX right at the residing dir

• Remove the dir entry & delete the file if link count reaches zero and no one still opens the file (Remark: sticky bit & dir rights).

41

Functions – link, unlink, rename, remove

• Program 4.16 – Page 110

– Open & unlink a file

#include "apue.h"

#include <fcntl.h>

}

{ int main(void) if (open("tempfile", O_RDWR) < 0) err_sys("open error"); if (unlink("tempfile") < 0) err_sys("unlink error"); printf("file unlinked\n"); sleep(15); printf("done\n"); exit(0);

42

Functions – link, unlink, rename, remove

• Unlink a file

– Sticky bits set for a residing dir, we must have the write permission for the directory and either owner of the file, the dir, or super users.

– If pathname is a symbolic link, unlink references the symbolic link.

43

Functions – link, unlink, rename, remove

#include <stdio.h> int remove(const char *pathname); int rename(const char *oldname, const char *newname);

– remove = rmdir if pathname is a dir. (ANSI C)

– Rename – ANSI C

• File: both files, newname is removed first, WX permission for both residing directories

• Directory: both dir, newname must be empty, newname could not contain oldname.

– > rename /usr/foo /usr/foo/testdir ???

44

Symbolic Links

#include <unistd.h>

int symlink(const char *actualpath, const char

*sympath); int readlink(const char *pathname, char *buf, int bufsize);

– actualpath does not need to exist!

• They do not need to be in the same file system.

– readlink is an action consisting of open, read, and close – not null terminated.

45

File Times

• Three Time Fields:

Field Description st_atime last-access-time st_mtime last-modification-time st_ctime last-i-node-change-time

Example

Read

Write chmod, chown ls-option

-u default

-c

• Changing the access permissions, user ID, link count, etc, only affects the inode!

• ctime is modified automatically! (stat, access)

• Example: reading/writing a file only affects the file, instead of the residing dir (Fig4.13).

46

File Times

#include <sys/types.h>

#include <utime.h> struct utimbuf { time_t actime;

} time_t modtime;

int utime(const char *pathname, const struct utimbuf

*times);

– time values are in seconds since the Epoch

– times = null  set as the current time

• Effective UID = file UID or W right to the file

– times != null  set as requested

• Effective UID = (file UID or superuser) and W right to the file.

– Program 4.21

47

#include "apue.h"

#include <fcntl.h>

#include <utime.h>

}

{

Int main(int argc, char *argv[]) int struct stat struct utimbuf timebuf; statbuf; i, fd; for (i = 1; i < argc; i++) { if (stat(argv[i], &statbuf) < 0) { current times */

/* fetch err_ret("%s: stat error", argv[i]); continue;

} if ((fd = open(argv[i], O_RDWR | O_TRUNC))

< 0) { /* truncate */ err_ret("%s: open error", argv[i]); continue;

} close(fd); timebuf.actime = statbuf.st_atime;

} timebuf.modtime = statbuf.st_mtime; if (utime(argv[i], &timebuf) < 0) {

/* reset times */ err_ret("%s: utime error", argv[i]); continue;

} exit(0);

• Change: atime, mtime, ctime?

> ls -l changemod

-rw-r--r-- 1 hchu professor 0 Apr 12 00:35 changemod

> ls -lu changemod

-rw-r--r-- 1 hchu professor 0 Apr 12 00:36 changemod

> date

Wed Apr 12 00:40:55 CST 2006

> ./fig4.21.exe changemod

> ls -l changemod

-rw-r--r-- 1 hchu professor 0 Apr 12 00:35 changemod

> ls -lu changemod

-rw-r--r-- 1 hchu professor 0 Apr 12 00:36 changemod

> ls -lc changemod

-rw-r--r-- 1 hchu professor 0 Apr 12 00:41 changemod

48

Functions – mkdir and rmdir

#include <sys/types.h>

#include <sys/stat.h>

int mkdir(const char *pathname, mode_t mode);

– umask, UID/GID setup (Sec 4.6)

– From 4.2BSD & SVR3 (SVR4 – inheritance of the S_ISGID bit)

#include <unistd.h>

int rmdir(const char *pathname);

– An empty dir is deleted.

– Link count reaches zero, and no one still opens the dir.

49

Functions – opendir, readdir, rewinddir, closedir

#include <sys/types.h>

#include <dirent.h>

DIR *opendir(const char *pathname); struct dirent *readdir(DIR *dp); void rewinddir(DIR *dp); int closedir(DIR *dp);

– Only the kernel can write to a dir!!!

– WX for creating/deleting a file!

– Implementation-dependent!

50

Functions – opendir, readdir, rewinddir, closedir

• dirent struct is very implementation-dependent, e.g.,

struct dirent { ino_t d_ino; /* not in POSIX.1 */ char d_name[NAME_MAX+1];

} /* fpathconf() */

• Program 4.22: traverse a file hierarchy and count # of files for each file type

51

#include "apue.h"

#include <dirent.h>

#include <limits.h>

/* function type that is called for each filename */ typedef int struct stat *, int);

Myfunc(const char *, const static Myfunc myfunc; static int static int myftw(char *, Myfunc *); dopath(Myfunc *); static long nreg, ndir, nblk, nchr, nfifo, nslink, nsock, ntot;

{ int main(int argc, char *argv[]) int ret; if (argc != 2) err_quit("usage: ftw <starting-pathname>"); ret = myftw(argv[1], myfunc); does it all */

/* ntot = nreg + ndir + nblk + nchr + nfifo + nslink + nsock; if (ntot == 0) ntot = 1;

0; print 0 for all counts */

/* avoid divide by printf("regular files = %7ld, %5.2f %%\n", nreg, nreg*100.0/ntot); printf("directories = %7ld, %5.2f %%\n", ndir, ndir*100.0/ntot); printf("block special = %7ld, %5.2f

%%\n", nblk, nblk*100.0/ntot); printf("char special = %7ld, %5.2f

%%\n", nchr, nchr*100.0/ntot); printf("FIFOs = %7ld, %5.2f

%%\n", nfifo, nfifo*100.0/ntot); printf("symbolic links = %7ld, %5.2f

%%\n", nslink, nslink*100.0/ntot); printf("sockets = %7ld, %5.2f

%%\n", nsock, nsock*100.0/ntot);

} exit(ret);

52

/*

* Descend through the hierarchy, starting at "pathname".

* The caller's func() is called for every file.

*/

#define FTW_F 1 file other than directory */

#define FTW_D directory */

2

#define FTW_DNR 3 directory that can't be read */

#define FTW_NS file that we can't stat */

4

/*

/*

/*

/* static char *fullpath; pathname for every file */

/* contains full

}

{ static int

/* we return whatever func() returns */ myftw(char *pathname, Myfunc *func) int len; fullpath = path_alloc(&len);

PATH_MAX+1 bytes */

/* malloc's for

({Prog pathalloc}) */ strncpy(fullpath, pathname, len);

*/ fullpath[len-1] = 0;

/* buffer overrun */

/*

/* protect against return(dopath(func));

53

/*

* Descend through the hierarchy, starting at "fullpath".

* If "fullpath" is anything other than a directory, we lstat() it,

* call func(), and return. For a directory, we call ourself

* recursively for each name in the directory.

{

*/ static int

/* we return whatever func() returns */ dopath(Myfunc* func) struct stat struct dirent *dirp; statbuf;

DIR

*dp; int char *ptr; ret; if (lstat(fullpath, &statbuf) < 0) /* stat error */ return(func(fullpath, &statbuf, FTW_NS)); if (S_ISDIR(statbuf.st_mode) == 0) /* not a directory

*/ return(func(fullpath, &statbuf, FTW_F));

/*

* It's a directory. First call func() for the directory,

* then process each filename in the directory.

*/ if ((ret = func(fullpath, &statbuf, FTW_D)) != 0) return(ret);

} ptr = fullpath + strlen(fullpath); /* point to end of fullpath */

*ptr++ = '/';

*ptr = 0; if ((dp = opendir(fullpath)) == NULL) can't read directory */ return(func(fullpath, &statbuf,

FTW_DNR));

/* while ((dirp = readdir(dp)) != NULL) { if (strcmp(dirp->d_name, ".") == 0 || strcmp(dirp->d_name, "..") == 0) continue;

/* ignore dot and dot-dot */ strcpy(ptr, dirp->d_name); append name after slash */

/* if ((ret = dopath(func)) != 0)

/* recursive */ break; /* time to leave

}

*/ ptr[-1] = 0; slash onwards */

/* erase everything from if (closedir(dp) < 0) fullpath); err_ret("can't close directory %s", return(ret);

54

{ static int myfunc(const char *pathname, const struct stat

*statptr, int type) switch (type) { case FTW_F: switch (statptr->st_mode & S_IFMT) { case S_IFREG: break; nreg++; nblk++; case S_IFBLK: break; case S_IFCHR: break; nchr++; nfifo++; case S_IFIFO: break; case S_IFLNK: break; case S_IFSOCK: break; nslink++; nsock++; case S_IFDIR: err_dump("for S_IFDIR for

%s",

} pathname); directories should have type = FTW_D */

} break; case FTW_D: ndir++; break; case FTW_DNR: err_ret("can't read directory %s", pathname); break; case FTW_NS: err_ret("stat error for %s", pathname); break;

/*

} default: err_dump("unknown type %d for pathname %s", type, pathname); return(0);

55

Functions – chdir, fchdir, getcwd

#include <unistd.h> int chdir(const char *pathname); int fchdir(int filedes);

– Every process has its own current working directory

– Per-process attribute – working dir!

– chdir must be built into shells (pwd)!

– The kernel only maintains the i-node number and dev ID for the current working directory!

• Program 4.23

56

#include "apue.h"

}

{ int main(void) if (chdir("/tmp") < 0) err_sys("chdir failed"); printf("chdir to /tmp succeeded\n"); exit(0);

> pwd

?

/usr/lib

> mycd

>chdir to /tmp succeeded

> pwd

57

Functions – chdir, fchdir, getcwd

#include <unistd.h>

char *getcwd(char *buf, size_t size);

– The buffer must be large enough, or an error returns!

– chdir follows symbolic links, and getcwd has not idea of symbolic links!

• Program 4.24

– getcwd

58

Special Device Files

• Device Number – dev_t

– Major and minor numbers: 8 bit each under 4.3+BSD

– macro definition <sysmacros.h> @ntucsa

#define L_BITSMINOR 18 /* # of SVR4 minor device bits */

#define L_MAXMAJ 0x3fff /* SVR4 max major value */

#define major(x) (int)((unsigned)((x)>>O_BITSMINOR) & O_MAXMAJ)

• Program 4.25

– st_dev vs st_rdev

59

Major Number vs. Minor Number

Driver

Controller 1

Major #1

USB Controller

Controller 2

Major #2

Controller 3

Major #3

Device 1

Minor #1

USB KB

Device 2

Minor #2

USB Cam

Device 1

Minor #1

Device 2

Minor #2

Device 1

Minor #1

Device 2

Minor #2

60

}

#include "apue.h"

#ifdef SOLARIS

#include <sys/mkdev.h>

#endif

{ int main(int argc, char *argv[]) int struct stat buf; i; for (i = 1; i < argc; i++) { printf("%s: ", argv[i]);

} if (stat(argv[i], &buf) < 0) { err_ret("stat error"); continue;

} exit(0); printf("dev = %d/%d", major(buf.st_dev), minor(buf.st_dev)); if (S_ISCHR(buf.st_mode) || S_ISBLK(buf.st_mode)) { printf(" (%s) rdev = %d/%d",

(S_ISCHR(buf.st_mode)) ? "character" : "block", major(buf.st_rdev), minor(buf.st_rdev));

} printf("\n");

61

Download