Open-Source Internship opportunity by OpenGenus for programmers. Apply now.
In this article at OpenGenus, we shall learn the basics of I/O syscalls, file descriptors and modes.
FILE DESCRIPTORS
A file descriptor uniquely identifies an open file of the process. Some file descriptor values are reserved for system uses.
fd | purpose |
---|---|
0 | Standard input |
1 | Standard output |
2 | Standard error |
>3 | User created file descriptors using the syscalls mentioned below |
PERMISSIONS/MODE
Every file in unix has permissions, that is, which all users can read(r)/write(w)/execute(x) the file. These are often represented using octal numbers: In 0abc, a corresponds to the permissions of the owner, b corresponds to the permissions of the group, c corresponds to the permissions of others.
Number | Ref |
---|---|
0 | --- |
1 | --x |
2 | -w- |
3 | -wx |
4 | r-- |
5 | r-x |
6 | rw- |
7 | rwx |
For example, if the permissions of a file is 0600, then only the owner can read and write, but not execute the file. Other users cannot read, write or execute the file.
SYSCALLS
System call are those that the services of the operating system to the user programs via Application Program Interface(API). The different I/O syscalls used here, include:
1. creat()
Usage
int creat(char *filename, mode_t mode)
Purpose
Creates an empty file at path filename
with permissions mode
and returns the file descriptor that points to that file in the file table entry. In case of any error, it returns -1.
Sample usage
int new_file = creat("new_file.txt",0600);
Here, a new file with file name "new_file.txt"
is created with the permissions 0600
. The variable new_file
contains the file descriptor
2. open()
Usage
int open (const char* Path, int flags [, int mode ]);
Purpose
Open the file at path Path
with the flags flags
and permissions mode
and returns the file descriptor that points to that file in the file table entry. In case of any error, it returns -1.
The different flags available include
Flag | Purpose |
---|---|
O_RDONLY | read only |
O_WRONLY | write only |
O_RDWR | read and write |
O_CREAT | create file if it doesn’t exist |
O_EXCL | prevent creation if it already exists |
__O_LARGEFILE | used for opening large files(>1GB) |
O_TRUNC | Truncate the contents of the file, if the file already exists |
Sample usage
1) Open a file for writing
int dest_file = open("./output.txt", O_CREAT | O_RDWR | __O_LARGEFILE | O_TRUNC, 0600);
2) Open a file for reading
int source_file = open("./input.txt", O_RDONLY | __O_LARGEFILE);
3. close()
Usage
int close (int filedes);
Purpose
Close the file. It returns 0 once the file is closed successfully and -1 in case of any error.
Sample usage
close(dest_file);
4. read()
Usage
ssize_t read(int fd, void *buf, size_t count);
Purpose
Read data upto count
bytes from a file whose file descriptor is fd
and store the results in buf
pointer. It returns the number of bytes read. In case of any error, it returns -1.
Sample usage
char *c = (char *)malloc(1000);
int chk = read(source_file, c, 1000);
5. write()
Usage
ssize_t write(int fd, const void *buf, size_t count);
Purpose
Read data upto count
bytes from the memory location pointed by buf
to a file whose file descriptor is fd
. It returns the number of bytes read. In case of any error, it returns -1.
Sample usage
char *c = (char *)malloc(1000);
int chk=write(dest_file, c, 1000);
6. lseek()
Usage
off_t lseek(int fd, off_t offset, int whence);
Purpose
repositions the file offset of the file descriptor fd
to offset
bytes with respect to whence
directive:
- SEEK_SET: set file offtset to
offset
bytes from the beginning of the file - SEEK_CUR: set file offtset to
offset
bytes + current location - SEEK_END: set file offtset to
offset
bytes + size of file
It returns the new location of the file offset of the file descriptor
Sample usage
1) Get the current location of the file descriptor
int current_location = lseek(source_file, 0, SEEK_CUR);
2) Move the file descriptor to the start of the file
lseek(source_file, 0, SEEK_SET);
3) Move the file descriptor to the end of the file
lseek(source_file, -1, SEEK_END);
4) Get the length of the file
off_t fileLength = lseek(source_file, 0, SEEK_END);
7. stat()
Usage
int stat(const char *path, struct stat *buf);
Purpose
Store properties of a file at path
in buf
. It returns 0 in case of success and -1 in case of failure
Sample usage
struct stat buffer;
stat(output_file_path, &buffer);
8. fflush()
Usage
fflush(FILE *ostream);
Purpose
Clear (or flush) the output buffer and move the buffered data to the output stream.
Sample usage
fflush(stdout);
EXAMPLE
These I/O system calls can be used to
- reverse the contents of a file
- check if a file is a reverse of the other
- display the permissions of a file
- make a shell (similar to bash) using only sys calls
With this article at OpenGenus, you must have got the complete idea of different I/O syscalls, file descriptors and modes in C programming language. Enjoy.