07 - File I-O

Class: CSCE-313


Notes:

Outline:

Unix I/O

Background

Applications running in the system are addresses space abstractions called processes.

Processes need to talk to the outside world, and they do so via privileged interfaces (system calls)

In this module we will focus on the UNIX I/O interface.

Notes:

Example:
Look at your hard disk:

ls -l /dev/sda

What if we cat this file?

cat /dev/sda

Unix Files

A Unix file is a sequence of bytes

B0,B1,,Bk,,Bm1

Most I/O devices (networks, disks, terminals) are represented as files.

Even the kernel is represented as a file:

All I/O is performed by reading and writing files

Notes:

/dev/pts/0

Write into this device

echo "Hello World" > /dev/pts/0
Hello World

You can also cat /dev/mem, which is the physical bytes of your memory

cat /dev/mem

A /proc filesystem does not need system calls, you can read and write to this filesystem

cat /proc/uptime

Common Unix File Types

Notes:

Generally all UNIX systems have a dictionary:

cat /usr/share/dict/words

But can you do?

cat /usr/share/dict

Output:

cat: /usr/share/dict: Is a directory

Now what if we do:

cat /*

Character device example

ls - l 'tty'
c-...

Block device example

ls -l /dev/sda
b-..

Socket device example

nc -lU sock
ls -l
s-..

struct dirent (man 3 readdir)

struct dirent {
	ino_t d_ino;       // file # of entry
	uint16_t d_reclen; // len of rec
	uint8_t d_type;    // file type
	uint8_t d_namlen;  // len of d_name
	char d name[255 + 1];
};

Notes:

ls example:

ls -li

Lets say you have:

/
  foo/
	fib
	fab

Common operations (system calls)

Basic Unix I/O operations (system calls)

00 - TAMU Brain/6th Semester (Spring 26)/CSCE-313/Lecture/Visual Aids/image-18.png282

Opening Files

Opening a file informs the kernel that we are ready to access that file.

int fd = open("/etc/hosts", O_RDONLY);
if (fd < 0) {
    perror("open");
    exit(1);
}

Notes:

Each process created by a Unix shell [generally] begins with three open file descriptors associated with the terminal:

On success, open returns the smallest available fd value, e.g., in the picture below fd=3 ( 02 are occupied)

int fd = open("/etc/hosts", O_RDONLY);
if (fd < 0) {
    perror("open");
    exit(1);
}

Closing Files

Closing a file informs the kernel that we are finished accessing that file

if((retval = close(fd)) < 0) {
    perror("close");
    exit(1);
}

The kernel responds by

When a process terminates for any reason, the kernel performs the equivalent of close on all open files

Notes:

Creating a File

So far, we have only opened files for reading. The file must have existed beforehand. To create a file, we call open() with a flag set to O_CREAT and mode specifying appropriate permissions.

int open(const char *pathname, int flags, mode_t mode)

Consult the man page for more details. Here are some common use cases.

Notes:

Files on Disk

Pasted image 20260223140237.png250
Pasted image 20260223140307.png250

Notes:

The stat structure

Pasted image 20260223141159.png500

Notes:

Making a link of a file

ln mybomb mybomb2
> ls -li
total 16
55675409 -rw-r--r--  1 macc  staff  582 Jan 21 16:55 2
55674416 -rw-r--r--  1 macc  staff  582 Jan 21 16:55 file
64037704 -rw-r--r--  2 macc  staff    0 Feb 23 14:15 mybomb
64037704 -rw-r--r--  2 macc  staff    0 Feb 23 14:15 mybomb2

Look at your user:

> id
uid=501(macc) gid=20(staff) groups=20(staff),101(access_bpf),12(everyone),61(localaccounts),79(_appserverusr),80(admin),81(_appserveradm),33(_appstore),98(_lpadmin),100(_lpoperator),204(_developer),250(_analyticsusers),395(com.apple.access_ftp),398(com.apple.access_screensharing),399(com.apple.access_ssh),400(com.apple.access_remote_ae),701(com.apple.sharepoint.group.1)

st_mode bits

Pasted image 20260223142053.png

Notes:

Example:

> ll
total 16
-rw-r--r--  1 macc  staff   582B Jan 21 16:55 2
-rw-r--r--  1 macc  staff   582B Jan 21 16:55 file
-rw-r--r--  2 macc  staff     0B Feb 23 14:15 mybomb
-rw-r--r--  2 macc  staff     0B Feb 23 14:15 mybomb2
drwxr-xr-x  6 macc  staff   192B Feb 17 15:14 pa1-report

Example:

> stat -x mybomb
  File: "mybomb"
  Size: 0            FileType: Regular File
  Mode: (0644/-rw-r--r--)         Uid: (  501/    macc)  Gid: (   20/   staff)
Device: 1,16   Inode: 64037704    Links: 2
Access: Mon Feb 23 14:15:25 2026
Modify: Mon Feb 23 14:15:25 2026
Change: Mon Feb 23 14:15:31 2026
 Birth: Mon Feb 23 14:15:25 2026

Creating a File

int open(const char *pathname, int flags, mode_t mode);

The following two items specifies permissions of a file:

Types of Access Types of Users
- Read (R) - User/Owner (U)
- Write (W) - Group (G)
- Execute (X) - Others (O)

Notes

Creating a File

int open(const char *pathname, int flags, mode_t mode);

To create a file only for yourself. (umask bits cleared.)

int main() {
    int fd = open("test.txt", O_WRONLY|O_CREAT|O_TRUNC, S_IRWXU);
    if(fd < 0) {
        perror("Cannot create file "); exit(0);
    }
    cout << "File created successfully" << endl;
}
prompt> ls -l
total 36
-rwxrwxr-x 1 osboxes osboxes 17424 Sep 7 15:23 a.out
-rw-rw-r-- 1 osboxes osboxes 256 Sep 214:21 exec1.cpp
-rw-rw-r-- 1 osboxes osboxes 313 Sep 715:23 fileio1.cpp
-rw-rw-r-- 1 osboxes osboxes 288 Sep 123:08 fork1.cpp
-rw-rw-r-- 1 osboxes osboxes 496 Sep 214:01 fork2.cpp
-rwx----1 osboxes osboxes 0 Sep 715:23 test.txt

Note:

File mode bits (man 7 inode)

Pasted image 20260223143629.png400

Creating a File (2)

int open(const char *pathname, int flags, mode_t mode);

However, keep in mind that you cannot just directly put 700 for permission because 700 in decimal is not the same as 700 in octet. You can write 0700 though, because that represents octal number.

int main () {
    int fd = open ("test.txt", O_WRONLY|O_CREAT|O_TRUNC,700); // this is incorrect
    if (fd < 0) {
        perror ("Cannot create file "); exit(0);
    }
    cout << "File created successfully" << endl;
}
prompt> ls -l
total 36
-rwxrwxr-x 1 osboxes osboxes 17424 Sep 7 15:22 a.out
-rw-rw-r-- 1 osboxes osboxes 256 Sep 214:21 exec1.cpp
-rw-rw-r-- 1 osboxes osboxes 309 Sep 7 15:22 fileio1.cpp
-rw-rw-r-- 1 osboxes osboxes 288 Sep 123:08 fork1.cpp
-rw-rw-r-- 1 osboxes osboxes 496 Sep 2 14:01 fork2.cpp
--w-rwxr-- 1 osboxes osboxes 0 Sep 715:22 test.txt

Notes:


Interesting questions from last class: See filesystems.html


Mount a remote filesystem:

ls gcloud

Steps:

  1. First it enumerates the current directory

    • All its saying is: "if you want to find the metadata for this object: go to this inode"
    • In this example we retrieve the inode for /home
      ls -l / bat
      
  2. Enumerate the next component of your file name

    • Find the next inode that you want
      ls -l /home
      
    • And so on

The r bit

~ ls -ld tmp
dr--r-xr-x 27 sandeep.kumar staff 864 Feb 24 18:50 tmp

~ /bin/ls tmp
[files...]

~ ls tmp/gforms.txt
Is: tmp/gforms.txt: Permission denied

Notes:

The w bit

~ ls -ld tmp
dr-xr-xr-x 26 sandeep.kumar staff 832 Feb 24 20:45 tmp

~ ls -l tmp/foo.gpg
-rw-r--r--@ 1 sandeep.kumar staff 99 Nov 25 18:28 tmp/foo.gpg

~ rm tmp/foo.gpg
rm: tmp/foo.gpg: Permission denied

Notes:

The x bit

~ ls -ld tmp
d--xr-xr-x 27 sandeep.kumar staff 864 Feb 24 18:50 tmp

~ ls tmp
Failed to read cwd.

~ ls tmp/gforms.txt
tmp/gforms.txt

~ vi tmp/gforms.txt
works

Notes:

Example:

bat fixpath

The open system call (Chapter 3 of APUE)

#include <fcntl.h>
int open(const char *pathname, int oflag, ... /* mode_t mode */);

oflag must be one (and only one) of:

and may be OR'd with any of these:

Notes:

The close system call

#include <unistd.h>
int close(int fd); // returns: 0 if OK , -1 on error

Notes:

The read system call

#include <unistd.h>
ssize_t read(int fd, void *buf, size_t num);

Reading Files

Reading a file copies bytes from the current file position to memory, and then updates file position.

char buf[512];
int fd = open(filename, O_RDONLY);
int nbytes;
/* Then read upto 512 bytes from file fd */
if ((nbytes = read(fd, buf, sizeof(buf))) < 0) {
    perror("read");
    exit(1);
}

Returns number of bytes read from file fd into buf

Example:

Reading files: example

What's the output of the following program that reads a file with contents "foobar"

char buf[2];
int fd = open(filename, O_RDONLY);
int nbytes = read(fd, buf, sizeof(buf)); // buf = ?
nbytes = read(fd, buf, sizeof(buf)); // buf = ?

Notes:

The write system call

#include <unistd.h>
ssize_t write(int fd, void *buf, size_t num);

Notes:

Writing files

Writing file copies bytes from memory to the current file position, and then updates current file position.

char buf[512];
int nbytes; /* number of bytes written*/
int fd = open(filename, O_WRONLY|O_CREAT, 0700);
/* Then write up to 512 bytes from buf to file fd */
if ((nbytes = write(fd, buf, sizeof(buf)) < 0) {
    perror("write");
    exit(1);
}

Returns number of bytes written from buf to file fd

Writing files: example

What would be the content of the file after executing the following program?

char buf[] = {'a', 'b'}; // what if char *buf = “ab”
int fd;                  // file descriptor

/* Open the file fd ... */
/* Then write up to 2 bytes from buf to file fd */
write(fd, buf, sizeof(buf)); //file = ?
write(fd, buf, sizeof(buf)); //file = ?

Final file content:

abab

File Representation: Three Tables

Descriptor Table

File Table

v-node Table

How the Unix kernel represents open files?

Pasted image 20260227141630.png600

Notes:

File Sharing

Two distinct DTs sharing the same disk file through two distinct open FT entries

00 - TAMU Brain/6th Semester (Spring 26)/CSCE-313/Lecture/Visual Aids/image-19.png603