Transcript Slide Set 8

Kernel Directory Interface
Directories
operating
systems
Recall that in Unix your hard drive is organized
into a hierarchical system of directories and files.
Root
B
A
B
A
B
C
B
C
C
B
C
C
C
C
operating
systems
Directories
All of the directory functions are defined in the
header file dirent.h
A pointer to a DIR structure is used to manipulate
directory information, much as a FILE structure is
used to manipulate files.
operating
systems
Opening a Directory
#include <dirent.h>
#include <sys/types.h>
DIR *opendir (const char *name);
If the open succeeds, a pointer to
a directory structure is returned.
Otherwise a NULL pointer is returned.
see the man page for opendir!
operating
systems
Reading from a Directory
#include <dirent.h>
#include <sys/types.h>
struct dirent *readdir (DIR *dirp);
readdir reads the next entry from the directory
and returns a pointer to a dirent structure.
see the man page for readdir!
operating
systems
The dirent structure
On OS/X The dirent structure is defined as
(see dirent man page)
types defined
in <sys/types.h>
struct dirent
{
u_int32_t d_fileno;
u_int16_t d_reclen;
u_int8_t d_type;
u_int8_t d_namlen;
char d_name[255 + 1];
};
//
//
//
//
//
files inode number
length of this record
file type
length of name string
name
This is the only field guaranteed by Posix
operating
systems
dirent File Types
DT_UNKNOWN
DT_FIFO
DT_CHR
DT_DIR
DT_BLK
DT_REG
DT_LNK
DT_SOCK
DT_WHT
0
1
2
4
6
8
10
12
14
operating
systems
What Else Can You Do
with a Directory?
telldir( )
returns the current location in the
directory stream
seekdir( )
sets the position in the directory
stream
rewinddir( )
sets the position to the beginning
of the directory stream
closedir( )
closes a directory
operating
systems
Look at an Example
The ls Command
links
$ ls -al
total 104
owner group size last modified
name
drwxr-xr-x 25 debryro staff 850 Aug 3 14:50 .
drwxr-xr-x 13 debryro staff 442 Jun 15 13:09 3060
drwxr-xr-x 2 debryro staff
68 Jun 15 13:08 CNS3060
-rw-r--r-1 debryro staff
36 Jun 14 14:09 afile
-rw-r--r-2 debryro staff
16 Jun 14 15:08 file-a
-rw-r--r-2 debryro staff
16 Jun 14 15:08 file-b
lrwxr-xr-x 1 debryro staff
6 Jun 14 15:11 file-c -> file-a
-r-xr-xr-x
1 debryro staff 1809 Jun 14 11:34 monthly
drwxr-xr-x 4 debryro staff 136 Aug 1 14:59 more
file type
permissions
Where does ls get its
information?
operating
systems
file attributes are returned in a stat structure. The
header file <sys/stat.h> declares all of the symbols used
in this structure. File attributes are returned in the
following three functions:
int stat (const char *filename, struct stat *buf);
returns 0 when successful
-1 when fails
when the file is a symbolic link, lstat returns information about the
link, while stat returns information about the file the link points to!
int lstat (const char *filename, struct stat *buf);
int fstat (int filedes, struct stat *buf);
fstat returns information about a file that
is already open.
stat structure
operating
systems
(os/X)
struct stat {
dev_t
st_dev;
/* ID of device containing file */
ino_t
st_ino;
/* File serial number */
mode_t
st_mode;
/* Mode of file */
nlink_t
st_nlink;
/* Number of hard links */
uid_t
st_uid;
/* User ID of the file */
gid_t
st_gid;
/* Group ID of the file */
dev_t
st_rdev;
/* Device ID */
time_t
st_atime;
/* Time of last access */
long
st_atimensec;
/* nsec of last access */
time_t
st_mtime;
/* Last data modification time */
long
st_mtimensec;
/* last data modification nsec */
time_t
st_ctime;
/* Time of last status change */
long
st_ctimensec;
/* nsec of last status change */
off_t
st_size;
/* file size, in bytes */
blkcnt_t
st_blocks;
/* blocks allocated for file */
blksize_t
st_blksize;
/* optimal blocksize for I/O */
__uint32_t
st_flags;
/* user defined flags for file */
__uint32_t
st_gen;
/* file generation number */
__int32_t
st_lspare;
/* RESERVED: DO NOT USE! */
__int64_t
st_qspare[2]; /* RESERVED: DO NOT USE! */
};
see /usr/include/sys.stat.h
operating
systems
Reading st_mode bits
Use the following macros to test the file type
int S_ISDIR (mode_t m); // returns non-zero if a directory
int S_ISCHR (mode_t m); // returns non-zero if a char device
int S_ISBLK (mode_t m); // returns non-zero if a block device
int S_ISREG (mode_t m); // returns non-zero if a regular file
int S_ISFIFO (mode_t m); // returns non-zero if a pipe
int S_ISLNK (mode_t m) returns non-zero if a symbolic link
int S_ISSOCK (mode_t m); // returns non-zero if a socket
Example usage:
if (S_ISREG(buf.st_mode) )
printf(“regular file”);
operating
systems
Use these masks for the permission bits
S_IRUSR
read bit for file owner
S_IWUSR
write bit for file owner
S_IXUSR
execute but for file owner
S_IRGRP
S_IWGRP
S_IXGRP
S_IROTH
S_IWOTH
S_IXOTH
read bit for group
write bit for group
execute bit for group
read bit for other
write bit for other
execute bit for other
Example:
if ( buf.st_mode & S_IRUSR)
printf (“user read bit is on”);
operating
systems
Look at Some Examples
operating
systems
File Ownership
Every process has six or more IDs associated with it.
a real user id
a real group id
These identify who we really are.
They are taken from the password
file when we log in. These are properties
of the file.
an effective user id When we execute a program, the
an effective group id effective user id is usually the same
as the real user id and the effective
group id is usually the same as the real
group id. These are properties of the
Example: if the file owner is root,
and the set-user-ID bit is set, then
process.
while that file is running, it has root
privileges (example – passwd)
Test the set-User-ID bit with
the constant S_ISUID
It is possible to set a flag that says
“when this file is executed, set the
effective user ID of the process to be
the owner of the file.
operating
systems
Some File Access Permission
Rules
Whenever we want to open any type of file by name, we must
have execute permissions in each directory mentioned in the
path to the file, including the current directory. Read
permission on a directory only means that you can
read the directory – obtaining a list of file names in the
directory.
We cannot create a new file in a directory unless we have both
write and execute permissions for the directory.
To delete a file we need both write and execute permissions in
the directory. Note that you do not need read and write
permissions for the file!
operating
systems
File access tests
The kernel performs the following access tests each time
a process opens, creates, or deletes a file:
If the effective user ID of the process is 0, access is allowed.
If the effective user ID of the process equals the owner ID of
the file, access is allowed if the appropriate permission bit is set.
If the effective group ID of the process equals the group ID of
The file, access is allowed if the appropriate permission bit is set.
If the appropriate other permission bit is set access is allowed.
operating
systems
Changing File Permissions
#include <sys/types.h>
#include <sys/stat.h>
int chmod (const char *pathname, mode_t mode);
int fchmod(int fd, mode_t mode);
If (chmod(“foo”, S_IRUSR | S_IWUSR | S_IXUSR) < 0)
// error code …
operating
systems
Changing File Ownership
#include <sys/stat.h>
#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 lchown (const char *pathname, uid_t owner, gid_t group);
Changes the owner of the symbolic link, not
The owner of the file linked to.
Normally, only the file owner can
change ownership of the file.
operating
systems
Time Values
Field
Description
Example ls option
st_atime
st_mtime
st_ctime
last access time of file
last modification time
last change time (inode)
read
write
chmod
-u
default
-c
operating
systems
Unix Time Functions
A digression …
operating
systems
The basic Linux (and Unix) time service counts the number
of seconds that have passed since January 1, 1970 (UTC).
These seconds are normally stored in a variable whose type
is time_t.
This is called calendar time.
operating
systems
We can get calendar time by using the call
time_t time (time_t *tptr);
returns the time, and stores the value here if the argument
is non-null.
string
formatted string
asctime
broken down time
mktime
struct tm
localtime
ctime
strftime
gmtime
operating
systems
time_t calendar time
time
kernel
takes time zone into account
struct tm
operating
systems
Broken down time
struct tm
{
int tm_sec;
int tm_min;
int tm_hour;
int tm_mday;
int tm_mon;
int tm_year;
int tm_wday;
int tm_yday;
int tm_isdst
};
allows leap seconds
// seconds after the minute [0-61]
// minutes after the hour [0-59]
// hours after midnight [0-23]
// day of the month [1-31]
// month of the year [0-11]
// years since 1900
// day of the week [0-6]
// days since Jan 1 [0-365]
// daylight savings flag [pos, 0, neg]
operating
systems
Converting time_t to tm
#include <time.h>
struct tm *gmtime (const time_t *tptr);
broken down time is in UTC
struct tm *localtime (const time_t *tptr);
broken down time is in local time, given time zone and daylight savings
operating
systems
Converting tm to time_t
time_t mktime (struct tm *tptr);
operating
systems
generating time strings
char *asctime (const struct tm *tmptr);
char *ctime (const time_t *tptr);
Takes time zone into account
both generate a 26 character string of the form
Tue Sep 26 16:49:05 2002\n\0
operating
systems
Generating a formatted
string
size_t strftime (char *tbuf, size_t maxsize, const char *format,
const struct tm *tptr);
a broken down time
the buffer to store the
string in, and its max size
returns the size of the formatted string if successful
0 if fails
the format string
– works like printf
Format Description
Example
%a
%A
%b
%B
%c
%d
%H
%I
%j
%m
%M
%p
%S
%U
%w
%W
%x
%X
%y
%Y
%Z
Tue
Tuesday
Jan
January
Tue Jan 14 19:40:05 2002
14
19
07
014
01
40
PM
05
02
5
07
01/14/02
19:40:04
02
2002
MST
abbreviated weekday name
full weekday name
abbreviated month name
full month name
date and time
day of the month [00-31]
hour of 24 hour day [00-23]
hour of 24 hour day [00-12]
day of the year [001-366]
month [01-12]
minute [00-59]
am or pm
second [00-61]
Sunday week number [00-53]
weekday [0=Sunday – 6]
Monday week number [00-53]
date
time
year without century[00-99]
year with century
time zone name
operating
systems
Getting the Directory
Name
#include <unistd.h>
extern char *getcwd (char *buf, size_t size);
size is max size of the path name that can be returned.
operating
systems
Project #2
du command
du command with no arguments
Your du command should use the current working directory.
Print out the number of bytes in the directory entry itself.
For each file in the directory, print out the size of the file
in bytes, followed by the file name.
For each sub-directory in the directory, print out the
number of bytes in the directory entry, then open the
directory and repeat this process for each entry in that
sub-directory. Repeat this recursively until everything in
the directory has been handled.
operating
systems
Project #2
du command
du command with a filename
print out the size of the file in bytes, followed
by the file name.
operating
systems
Project #2
du command
du command with a directory name
Print out the number of bytes in the directory entry itself.
For each file in the directory, print out the size of
the file in bytes, followed by the file name.
For each sub-directory in the directory, print out the number
of bytes in the directory entry, then open the directory and
repeat this process for each entry in that sub-directory.
Continue to repeat this recursively until everything in the
directory has been handled.
operating
systems
Project #2
du command
Hints
To get the full pathname of the current directory,
use the getcwd( ) function.
Use the d_type field in the dirent structure to get
the type of file (a regular file or a directory)
Use the d_name field in the dirent structure to get
the name of the file
Read chapter 3 in Molay for more ideas.