Operating systems

Files and directories

Prashanth L.A.

2023-11-08

Lecture 40

Basic Abstraction: FILE (regular file)

Basic Abstraction: DIRECTORY (special type of file)

FILE DESCRIPTOR

Example Directory Tree

File creation

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <assert.h>

int
main(int argc, char *argv[])
{
    int rc = creat("file1", S_IRWXU); //open("file1",O_CREAT,S_IRWXU);
    assert(rc >= 0);
    return 0;
}
int fd = open(``foo'', O_CREAT | O_WRONLY | O_TRUNC);

Per-process management of FDs

struct proc {
  ...
  struct file *ofile[NOFILE]; // Open files
... 
};

OFT

struct file { // simple version
  int type;   // e.g., FILE, PIPE
  int ref_cnt; 
  int mode;   // e.g., READABLE, WRITEABLE
  int offset; // current offset

  struct inode *inode;
  // or pointer to pipe, etc.
}

Reading and Writing Files

prompt> echo hello > foo
prompt> cat foo
hello
prompt>

strace for tracing system calls made

prompt> strace cat foo
…
open(“foo”, O_RDONLY|O_LARGEFILE)   = 3
read(3, “hello\n”, 4096)    = 6
write(1, “hello\n”, 6)      = 6 
hello
read(3, “”, 4096)           = 0 
close(3)                = 0
…
prompt>

Non-sequential read/write

Updating offset

Implicit Explicit
Reading N bytes, makes the current offset N Use lseek(int fildes, off_t offset, int whence)
whence meaning
SEEK_SET the offset is set to offset bytes.
SEEK_CUR the offset is set to its current location plus offset bytes
SEEK_END the offset is set to the size of the file plus offset bytes

Examples of seeking

Opens a \(300\) byte file and read it again and again..


Open the same file twice and issue a read to each of them

fds 3 and 4 refer to Open file table (OFT) entries 10 and 11


use lseek() to reposition the current offset before reading

fsync()

Example

int fd = open"foo", O_CREAT | O_WRONLY | O_TRUNC;
assert(fd > -1);
int rc = write(fd, buffer, size);
assert(rc == size);
rc = fsync(fd);
assert(rc == 0);

Renaming Files

prompt> mv foo bar  // mv uses the system call rename

Vim may save files like this

int fint fd = open("foo.txt.tmp", O_WRONLY|O_CREAT|O_TRUNC);
write(fd, buffer, size); // write out new version of file
fsync(fd);
close(fd);
rename("foo.txt.tmp", "foo.txt");

What info should a file system store about a file?

Other file info

Get file info using stat

struct stat {
dev_t st_dev;   /* ID of device containing file */
ino_t st_ino;   /* inode number */
mode_t st_mode;     /* protection */
nlink_t st_nlink;   /* number of hard links */
uid_t st_uid;   /* user ID of owner */
gid_t st_gid;   /* group ID of owner */
dev_t st_rdev;  /* device ID if special file */
off_t st_size;  /* total size, in bytes */
blksize_t st_blksize; /* blocksize for filesystem I/O */
blkcnt_t st_blocks;     /* number of blocks allocated */
time_t st_atime;    /* time of last access */
time_t st_mtime;    /* time of last modification */
time_t st_ctime;    /* time of last status change */
};

Usage

prompt> echo hello > file
prompt> stat file
File: ‘file’
Size: 6 Blocks: 8 IO Block: 4096 regular file
Device: 811h/2065d Inode: 67158084 Links: 1
Access: 0640/-rw-r----- Uid: 30686/ root Gid: 30686/ remzi
Access: 2011-05-03 15:50:20.157594748 -0500
Modify: 2011-05-03 15:50:20.157594748 -0500
Change: 2011-05-03 15:50:20.157594748 -0500

Removing Files

prompt> strace rm foo
…
unlink“foo”     = 0 // return 0 upon success
…
prompt>

Why unlink and not remove/delete?

Directories

prompt> strace mkdir foo
…
mkdir“foo”, 0777        = 0
prompt>
prompt> ls –a
./  ../
prompt> ls -al
total 8
drwxr-x---  2 remzi remzi    6 Apr 30 16:17 ./
drwxr-x--- 26 remzi remzi 4096 Apr 30 16:17 ../

Reading Directories

int main(int argc, char *argv[]) {
  DIR *dp = opendir(".");       // open current directory
  assert(dp != NULL);
  struct dirent *d;
  while ((d = readdir(dp)) != NULL) {
      printf("%lu %s\n", (unsigned long) d->d_ino, d->d_name);
  }
  closedir(dp);
  return 0;
}

Directory entry

struct dirent {
  char      d_name[256];    /* filename */
  ino_t     d_ino;      /* inode number */
  off_t     d_off;      /* offset to the next direct */
  unsigned short    d_reclen;       /* length of this record */
  unsigned char d_type;     /* type of file */
}

Delete directories using rmdir (need the dir to be empty)

Making and Mounting a File System

prompt> mount –t ext3 /dev/sda1 /home/users
prompt> ls /home/users
a b
/dev/sda1 on / type ext3 rw
proc on /proc type proc rw
sysfs on /sys type sysfs rw
/dev/sda5 on /tmp type ext3 rw
/dev/sda7 on /var/vice/cache type ext3 rw
tmpfs on /dev/shm type tmpfs rw
AFS on /afs type afs rw