mkdir() - creates inode for directory file, writes . and .. entries in
block allocated to file, and adds an antry in the parent node with the name
rmdir() - does reverse, and if directory is not in use, inode and data
blocks are freed
unlink() - used by rm(1); removes an entry from a directory
and decrements the link count
link() - used by ln(1); makes a new link with a specified
name to an inode (but not to directories)
rename() - used by mv; typically uses link() and unlink()
chdir() - used by cd; changes the current directory of a
process (i.e., the inode number)
pwd
How would you write pwd?
Full implementation is beyond the class; answer in Molay chapter 4
Multiple File Systems
Move UNIX file systems are made up of multiple disks (and often
multiple partitions per disk).
Yet all appear within a single, unified, logical tree.
Each partition has its own file and directory tree (and thus its own
inodes, etc.)
We can attach one partition to another by 'mounting' one to another
A mount takes the place of an existing directory
link() and rename() will fail when attempting to link across
filesystems
Modern versions of mv will resort to copying and unlinking
Symbolic links (generated by ln -s can span filesystems and
can point to anything (including directories)
Solution to HW#5 -- #2.4
The FILE structure used by fopen(), getc(), fclose(), etc.
Difficult to find for some versions of UNIX.
struct __FILE_TAG in stdio_impl.h for Solaris for C
Some (older) UNIXes might still have struct FILE defined explicitly,
but not all modern ones.
Solution to HW#5 -- #2.5
Saving kernel buffers to disk...
void sync(void): schedules writes for all information in
memory that should be on disk, including modified super blocks, modified
inodes, and delayed block I/O.
int fsync(int fildes), int fdatasync(int fildes): writes all modified data and attributes
of the file descriptor fildes to a storage device before returning.
int fflush(FILE *stream): causes any unwritten data for that
stream to be written to the file.
int ioctl(int fildes, int command, ... /*arg*/): can flush streams
int msync(void *addr, size_t len, int flags): writes all
modified copies of pages over the range [addr, addr + len) to
the underlying hardware. (Only useful with mmap().)
open(2) with O_SYNC, O_DSYNC, etc. options: write operations do not complete until data is written to underlying hardware.
Solution to HW#5 -- #2.9
lseek() beyond end of file. What happens when you read() or write() to locations well beyond the end?
For read(): No data transfer will occur past the current end-of-file.
If the starting position is at or after the end-of-file, 0
will be returned.
For write(): will complete. Creates "holes" in files. Difference in 'logical' size and actual number of bytes written to disk. Bytes in "holes" are 0s.
Try using od -c file to see contents.
Solution to HW#5 -- #3.8
The execute bit for directories controls use of the directory -- you need execute permissions to cd to the directory, or to access a file in it or a subdirectory of it.
It is also required to view all info about contents (but not just filename).
In contrast, read permissions are only needed to view the contents, but not to execute (cd or access to files or subdirectories).
Thus, you can set your home directory to be unreadable (but still executable) by others, and so those who know the names of publicly readable files/directories will still have access (e.g., web home pages).
Solution to HW#5 -- #3.21
Write a version of cp() that preserves file access time on original, and replicates file access and modification on the copy.