Unit 3 - Notes
CSE325
Unit 3: File system management
Introduction to File System Calls
File system calls provide the interface between a running program (process) in User Space and the Operating System Kernel. In Linux/Unix systems, almost everything is treated as a file. To manipulate files, the kernel provides a set of system calls.
Unlike standard library functions (like fopen, fprintf in C), system calls work directly with File Descriptors (FDs) rather than FILE* streams. These calls are unbuffered and closer to the hardware, offering lower-level control over file I/O.

1. File Descriptors
Before diving into specific calls, it is essential to understand the File Descriptor.
- Definition: A non-negative integer representing an open file.
- Standard FDs:
0: Standard Input (stdin)1: Standard Output (stdout)2: Standard Error (stderr)
- Assignment: When a new file is opened, the OS assigns the lowest available integer (usually starts at 3 for user files).

2. The open() System Call
The open() system call is used to establish a connection between a file and a file descriptor. It can open an existing file or create a new one.
Syntax
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
Arguments
- pathname: The relative or absolute path to the file.
- flags: Determines how the file is opened. Common flags (combined using bitwise OR
|):O_RDONLY: Open for reading only.O_WRONLY: Open for writing only.O_RDWR: Open for reading and writing.O_CREAT: Create the file if it doesn't exist.O_EXCL: Used withO_CREAT; fails if file already exists.O_TRUNC: If file exists, truncate size to 0 (delete contents).O_APPEND: Append data to the end of the file.
- mode: (Required only when creating a file). Specifies permissions (e.g.,
0644- Read/Write for owner, Read for group/others).
Return Value
- Success: Returns the new file descriptor (a non-negative integer).
- Failure: Returns
-1and sets the global variableerrno.
Example
int fd = open("data.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (fd < 0) {
perror("Error opening file");
}
3. The close() System Call
The close() system call dissociates a file descriptor from the corresponding file, releasing resources.
Syntax
#include <unistd.h>
int close(int fd);
Arguments
- fd: The file descriptor to close.
Return Value
- 0: Success.
- -1: Error (e.g., invalid FD).
Importance
Failing to close files can lead to a "resource leak." The OS has a limit on the number of files a process can keep open simultaneously.
4. The read() System Call
The read() system call attempts to read a specified number of bytes from the file into a buffer.
Syntax
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
Arguments
- fd: File descriptor to read from.
- buf: Pointer to the memory buffer where data will be stored.
- count: Maximum number of bytes to read.
Return Value
- > 0: Number of bytes actually read.
- 0: End of File (EOF) reached.
- -1: Error.
Note on ssize_t
ssize_t is a signed integer type used to handle the -1 error return. size_t is unsigned.
5. The write() System Call
The write() system call writes data from a buffer to the file associated with the file descriptor.
Syntax
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
Arguments
- fd: File descriptor to write to.
- buf: Pointer to the data to be written.
- count: Number of bytes to write.
Return Value
- > 0: Number of bytes actually written.
- -1: Error (e.g., disk full, file opened read-only).

6. The lseek() System Call
lseek stands for "long seek". It repositions the read/write file offset (the "cursor" position inside the file).
Syntax
#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);
Arguments
- fd: File descriptor.
- offset: Number of bytes to move the pointer (can be negative).
- whence: The reference point for the offset.
SEEK_SET: The beginning of the file.SEEK_CUR: The current position of the file pointer.SEEK_END: The end of the file.
Return Value
- Success: Returns the new offset location in bytes from the beginning of the file.
- Failure: Returns
-1.
Common Uses
lseek(fd, 0, SEEK_SET): Rewind to the start.lseek(fd, 0, SEEK_END): Move to the end (useful for appending or finding file size).lseek(fd, -10, SEEK_CUR): Move backward 10 bytes.

Comprehensive Example: Implementing all calls
This C program creates a file, writes to it, uses lseek to reset the cursor, reads the content back, and prints it to the standard output.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#define FILENAME "example_file.txt"
#define BUFFER_SIZE 100
int main() {
int fd;
char write_buf[] = "Operating Systems Lab - Unit 3: File Management.";
char read_buf[BUFFER_SIZE];
ssize_t bytes_read, bytes_written;
// 1. OPEN (Create and Write)
// O_TRUNC clears file if it exists so we start fresh
fd = open(FILENAME, O_RDWR | O_CREAT | O_TRUNC, 0644);
if (fd < 0) {
perror("Open failed");
exit(1);
}
printf("File opened with FD: %d\n", fd);
// 2. WRITE
// Write the contents of write_buf to the file
bytes_written = write(fd, write_buf, strlen(write_buf));
if (bytes_written < 0) {
perror("Write failed");
close(fd);
exit(1);
}
printf("Written %ld bytes to file.\n", bytes_written);
// 3. LSEEK
// After writing, the cursor is at the end. Move it back to start to read.
if (lseek(fd, 0, SEEK_SET) < 0) {
perror("Lseek failed");
close(fd);
exit(1);
}
printf("Cursor reset to beginning of file.\n");
// 4. READ
// Read from the file into read_buf
bytes_read = read(fd, read_buf, BUFFER_SIZE - 1); // Leave space for null terminator
if (bytes_read < 0) {
perror("Read failed");
close(fd);
exit(1);
}
// Null terminate the buffer to print it as a string
read_buf[bytes_read] = '\0';
printf("Read from file: \"%s\"\n", read_buf);
// 5. CLOSE
if (close(fd) < 0) {
perror("Close failed");
exit(1);
}
printf("File closed successfully.\n");
return 0;
}
Explanation of the Code Flow
open: Createsexample_file.txtwith read/write permissions (0644).write: Writes the string literal into the file. The file offset moves forward as data is written.lseek: Because the offset is at the end of the written data, we must move it back to0(SEEK_SET) to read what we just wrote.read: Reads the data from the disk into theread_bufmemory.close: Releases the file descriptorfdso it can be reused by the system.