+ All Categories
Transcript
Page 1: System Programming

1

System Programming

Chapter 4Files and Directories

Page 2: System Programming

2

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)

Page 3: System Programming

3

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!

Page 4: System Programming

4

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);

Page 5: System Programming

5

Files and Directories

• Differences on stat(), fstat(), lstat():– lstat() returns info regarding the symbolic link, instead of the referen

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

};

Page 6: System Programming

6

File Types

• Encoded in st_mode• Regular Files: text, binary, etc.• Directory Files: Only Kernel can update these files – { (f

ilename, 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

Page 7: System Programming

7

File Type Macro in <sys/stats.h>

S_ISREG() // regular file

S_ISDIR()

S_ISCHR()

S_ISBLK()

S_ISFIFO()

S_ISLNK()

S_ISSOCK()

Page 8: System Programming

8

Figure 4.3#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 (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";

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";

elseptr = "** unknown mode **";

printf("%s\n", ptr);}exit(0);

}

Page 9: System Programming

9

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

Page 10: System Programming

10

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

Page 11: System Programming

11

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

Page 12: System Programming

12

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

Page 13: System Programming

13

hchu@linux1:/> ls -l /etc/shadow-rw-r----- 1 root shadow 843 2006-03-07 10:01 /etc/shadowhchu@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

Page 14: System Programming

14

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?

• A process can have more than one ID. – Real user/group ID– Effective user/group ID– Supplementary group IDs– Saved set-user/group-ID

-rw-r--r-- 1 root root 1746 2/21 13:00 /etc/passwd-r-------- 1 root root 1142 2/21 13:01 /etc/shadow

Page 15: System Programming

15

Ownership of a New File

• Rules:– UID of a file = the effective UID of the creating pro

cess– GID of a file – options under POSIX

1. GID of the file = the effective GID of the process2. 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)!

Page 16: System Programming

16

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!

Page 17: System Programming

17

Figure 4.8 Program#include "apue.h"#include <fcntl.h>

intmain(int argc, char *argv[]){

if (argc != 2)err_quit("usage: a.out <pathna

me>");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 fig4.8.exe-rwxr-xr-x 1 hchu users 9487 200

6-03-21 19:53 fig4.8.exe>fig4.8.exe fig4.8.exeread access OKopen for reading OK>ls -l /etc/shadow-rw-r----- 1 root shadow 843 200

6-03-07 10:01 /etc/shadow>fig4.8.exe /etc/shadowaccess error for /etc/shadow: Pe

rmission deniedopen error for /etc/shadow: Per

mission denied

Page 18: System Programming

18

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!

Page 19: System Programming

19

Figure 4.9 Program

#include "apue.h"#include <fcntl.h>

#define RWRWRW (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)

intmain(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");exit(0);

}

>umask22>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>umask22

Page 20: System Programming

20

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[U

G]ID, etc (Fig 4.6).

Page 21: System Programming

21

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-2

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

3-21 20:14 foo>fig4.12.exe>ls -al foo bar-rw-r--r-- 1 hchu users 0 2006-03-2

1 20:14 bar-rw-rwSrw- 1 hchu users 0 2006-0

3-21 20:14 foo

// what is strange here?

Page 22: System Programming

22

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.

Page 23: System Programming

23

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 se

t, and the process is belonging to superusers/owner of the file/dir

Page 24: System Programming

24

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?

Page 25: System Programming

25

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 pr

ocess GID or is in supplementary GID’s• set-user/group-ID bits would be cleared if chown is called b

y non-super users.

Page 26: System Programming

26

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

Page 27: System Programming

27

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?

Page 28: System Programming

28

System ProgrammingChapter 4

朱浩華教授 / 施吉昇教授臺灣大學資訊工程系

Page 29: System Programming

29

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.

Page 30: System Programming

30

Playing with Shadow(Tokyo University)

Page 31: System Programming

31

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 actu

al directory- and data blocks• Every inode has a link count (st_nlink): it shows how many “thin

gs” 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” th

e directory entry (actually done by creating a new entry, and deleting the old one).

Page 32: System Programming

32

BSD UNIX File System (UFS)

Page 33: System Programming

33

BSD UNIX File System (UFS)Figure 4.14 (hard links)

Page 34: System Programming

34

Filesystem – 4.4BSD i-node

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

mode

owner

timestamp

size block

ref-count

triple indirect

double indirect

single indirect

direct blocks

data

data

data

data

data

data…

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=232)

Page 35: System Programming

35

BSD UNIX File System (UFS)(> mkdir testdir ; link count, leaf vs. intermediate dirs)

Page 36: System Programming

36

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?

Page 37: System Programming

37

Hard vs. Soft Links• 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 li

mitation & linking dirs

foo

bar

/usr/joe

/usr/sueFile i-node:

#Reference = 2

foo

bar

/usr/sue

File i-node:#Reference = 1

/usr/joe

File i-node:#Reference = 1

data block:“ /usr/joe/foo”

Page 38: System Programming

38

Hard vs. Soft Links• Problems with links

– Infinite loops– Dangling pointers– Unable to remove

foo

bar

/usr/joe

/usr/sueFile i-node:

Reference = 2

foo

bar

/usr/sue

File i-node:Reference = 1

/usr/joe

File i-node:Reference = 1

data block:“ /usr/joe/foo”

Page 39: System Programming

39

Symbolic Links: infinite loops

> mkdir foo> touch foo/a> ln –s ../foo foo/testdir> ls –l foo> ls –R • List subdirectories recursive

ly

foofoo/afoo/testdirfoo/testdir/?

foo

a testdir

Page 40: System Programming

40

BSD UNIX File System (UFS)(> mv testdir testdir2 -> only update inode)

Page 41: System Programming

41

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).

Page 42: System Programming

42

Functions – link, unlink, rename, remove

• Program 4.16 – Page 110– Open & unlink a file

#include "apue.h"#include <fcntl.h>

intmain(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);

}

Page 43: System Programming

43

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.

Page 44: System Programming

44

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 ???

Page 45: System Programming

45

Symbolic Links

#include <unistd.h>int symlink(const char *actualpath, const char *s

ympath);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 c

lose – not null terminated.

Page 46: System Programming

46

File Times

• Three Time Fields:

• Changing the access permissions, user ID, link count, etc, only affects the i-node!

• ctime is modified automatically! (stat, access)• Example: reading/writing a file only affects the file, instead of th

e residing dir (Fig4.13).

Field Description Example ls-optionst_atime last-access-time Read -u

st_mtime last-modification-time Write default

st_ctime last-i-node-change-time chmod, chown -c

Page 47: System Programming

47

File Times

#include <sys/types.h>#include <utime.h>int utime(const char *pathname, const struct uti

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

struct utimbuf { time_t actime; time_t modtime; }

Page 48: System Programming

48

#include "apue.h"#include <fcntl.h>#include <utime.h>

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

int i, fd;struct stat statbuf;struct utimbuf timebuf;

for (i = 1; i < argc; i++) {if (stat(argv[i], &statbuf) < 0) { /* fetch curr

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

> dateWed 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

Page 49: System Programming

49

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_ISGI

D bit)#include <unistd.h>int rmdir(const char *pathname);

– An empty dir is deleted.– Link count reaches zero, and no one still opens the di

r.

Page 50: System Programming

50

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!

Page 51: System Programming

51

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

Page 52: System Programming

52

#include "apue.h"#include <dirent.h>#include <limits.h>

/* function type that is called for each filename */typedef int Myfunc(const char *, const

struct stat *, int);

static Myfunc myfunc;static int myftw(char *, Myfunc *);static int dopath(Myfunc *);

static long nreg, ndir, nblk, nchr, nfifo, nslink, nsock, ntot;

intmain(int argc, char *argv[]){

int ret;

if (argc != 2)err_quit("usage: ftw <starting-pathnam

e>");

ret = myftw(argv[1], myfunc); /* does it all */

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

ntot = 1; /* avoid divide by 0; print 0 for all counts */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);}

Page 53: System Programming

53

/* * Descend through the hierarchy, starting at "pathnam

e". * The caller's func() is called for every file. */#define FTW_F 1

/* file other than directory */#define FTW_D 2

/* directory */#define FTW_DNR 3

/* directory that can't be read */#define FTW_NS 4

/* file that we can't stat */

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

static int/* we return whatever fu

nc() returns */myftw(char *pathname, Myfunc *func){

int len;fullpath = path_alloc(&len); /* malloc's for PATH_MAX+1 bytes */

/* ({Prog pathalloc}) */strncpy(fullpath, pathname, len); /* protect against */fullpath[len-1] = 0;

/* buffer overrun */

return(dopath(func));}

Page 54: System Programming

54

/* * Descend through the hierarchy, starting at "fullpath". * If "fullpath" is anything other than a directory, we lsta

t() 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 statbuf;struct dirent *dirp;DIR

*dp;int

ret;char *ptr;

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; /* erase everything from slash onwards */

if (closedir(dp) < 0)err_ret("can't close directory %s", fu

llpath);

return(ret);}

Page 55: System Programming

55

static intmyfunc(const char *pathname, const struct st

at *statptr, int type){

switch (type) {case FTW_F:

switch (statptr->st_mode & S_IFMT) {

case S_IFREG: nreg++;break;

case S_IFBLK: nblk++;break;

case S_IFCHR: nchr++;break;

case S_IFIFO: nfifo++;break;case S_IFLNK: nslink++;break;case S_IFSOCK: nsock++;break;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", pat

hname);break;

default:err_dump("unknown type %d f

or pathname %s", type, pathname);}

return(0);}

Page 56: System Programming

56

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 t

he current working directory!• Program 4.23

Page 57: System Programming

57

#include "apue.h"

intmain(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?

Page 58: System Programming

58

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

Page 59: System Programming

59

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

Page 60: System Programming

60

Major Number vs. Minor Number

Driver

Controller 1Major #1

Controller 2Major #2

Controller 3Major #3

Device 1Minor #1

Device 2Minor #2

Device 1Minor #1

Device 2Minor #2

Device 1Minor #1

Device 2Minor #2

USB Controller

USB KB USB Cam

Page 61: System Programming

61

#include "apue.h"#ifdef SOLARIS#include <sys/mkdev.h>#endif

intmain(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)) {printf(" (%s) rdev = %d/%d",

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

}printf("\n");

}

exit(0);}


Top Related