Saturday, December 13, 2014

System calls for Files

System call OPEN

Opening
or creating a file can be done using the system call open. The syntax is:

#include
<sys/types.h>

#include
<sys/stat.h>

#include <fcntl.h>

int open(const char *path,

int flags,... /* mode_t mod */);

This
function returns the file descriptor or in case of an error -1. The number of
arguments that this function can have is two or three. The third argument is
used only when creating a new file. When we want to open an existing file only two
arguments are used. The function returns the smallest available file
descriptor. This can be used in the following system calls: read, write, lseek and close. The effective UID or the
effective GID of the process that executes the call has to have read/write
rights, based on the value of the argument flags.
The file pointer is places on the first byte in the file. The argument flags is formed by a bitwise OR
operation made on the constants defined in the fcntl.h header.

System call CREATE:

A
new file can be created by:

#include
<sys/types.h>

#include
<sys/stat.h>

#include
<fcntl.h>

int creat(const char *path, mode_t mod);

The
function returns the file descriptor or in case of an error it returns the
value -1. This call is equivalent with:

open(path, O_WRONLY |
O_CREAT | O_TRUNC, mod);

The
argument path specifies the name of
the file, while mod defines the
access rights. If the created file doesn’t exist, a new i-node is allocated and
a link is made to this file from the directory it was created in. The owner of
the process that executes the call - given by the effective UID and the
effective GUID - must have writing permission in the directory. The open file
will have the access rights that were specified in the second argument (see umask, too). The call returns the
smallest file descriptor available. The file is opened for writing and its
initial size is 0. The access time and the modification time are updated in the
i-node. If the file exists (permission to search the directory is needed), it
looses its contents and it will be opened for writing. The ownership and the access
permissions won’t be modified. The second argument is ignored.

System call READ

When
we want to read a certain number of bytes starting from the current position in
a file, we use the read call. The
syntax is:

#include
<unistd.h>

ssize_t read(int
fd, void* buf, size_t noct);

The
function returns the number of bytes read, 0 for end of file (EOF) and -1 in
case an error occurred. It reads noct
bytes from the open file referred by the fd descriptor and it puts it into a buffer buf. The pointer (current position) is
incremented automatically after a reading that certain amount of bytes. The
process that executes a read operation waits until the system puts the data from
the disk into the buffer.

System call WRITE

For
writing a certain number of bytes into a file starting from the current
position we use the write call. Its
syntax is:

#include
<unistd.h>

ssize_t write(int fd, const
void* buf, size_t noct);

The
function returns the number of bytes written and the value -1 in case of an
error. It writes noct bytes from the
buffer buf into the file that has as
its descriptor fd.
It is interesting to note that the actual writing onto the disk is delayed.
This is done at the initiative of the root, without informing the user when it
is done. If the process that did the call or an other process reads the data
that haven’t been written on the disk yet, the system reads all this data out
from the cache buffers. The delayed writing is faster, but it has three
disadvantages:

a)a disk error or a system error may cause loosing all
the data

b)a process that had the initiative of a write operation
cannot be informed in case a writing error occurred

c)the physical order of the write operations cannot be
controlled.

To
eliminate these disadvantages, in some cases the O_SYNC is used. But as this
slows down the system and considering the reliability of today’s systems it is
better to use the mechanism which includes using cache buffers.

System call CLOSE

For
closing a file and thus eliminating the assigned descriptor we use the system
call close.

#include
<unistd.h>

int
close(int fd);

The
function returns 0 in case of success and -1 in case of an error. At the
termination of a process an open file is closed anyway.

System call LINK

To
link an existing file to another directory (or to the same directory) link can
be used. To make such a link in fact means to set a new name or a path to an
existing file. The link system call creates a hard link.
Creating symbolic links can be done using symlink system call.
The syntax of link is:

#include <unistd.h>

int link(const char* oldpath, const char* newpath);

int symlink(const char* oldpath, const char* newpath);

The
function returns 0 in case of success and -1 in case of an error. The argument oldpath has to be a path to an existing
file. Only the root has the right to set a link to a directory.

System call UNLINK

To
delete a link (a path) in a directory we can use the unlink system call. Its syntax is:

#include <unistd.h>

int unlink(const char* path);

The
function returns 0 in case of success and -1 otherwise. The function decrements
the hard link counter in the i-node and deletes the
appropriate directory entry for the file whose link was deleted. If the number of
links of a file becomes 0 then the space occupied by the file and its i-node
will be freed. Only the root can delete a directory.

System calls STAT, LSTAT and FSTAT

In
order to obtain more details about a file the following system calls can be
used: stat, lstat or fstat.

#include <sys/types.h>

#include <sys/stat.h>

int stat(const char* path, struct
stat* buf);

int lstat(const char* path, struct
stat* buf);

int fstat(int
df, struct stat* buf);

These
three functions return 0 in case of success and -1 in case of an error. The
first two gets as input parameter a name of a file and completes the structure
of the buffer with additional information read from its i-node. The fstat function is similar, but it works
for files that were already opened and for which the file descriptor is known.
The difference between stat and lstat is that in case of a symbolic link,
function stat returns information
about the linked (refered) file, while lstat
returns information about the symbolic link file.

System call CHMOD

To
modify the access rights for an existing file we use:

#include <sys/types.h>

#include <sys/stat.h>

int chmod(const char* path, mode_t
mod);

The
function returns 0 in case of a success and -1 otherwise. The chmod call modifies the access rights of
the file specified by the path
depending on the access rights specified by the mod argument. To be able to modify the access rights the effective
UID of the process has to be identical to the owner of the file or the process
must have root rights.

The
mod argument can be specified by one
of the symbolic constants defined in the sys/stat.h
header.

System call CHOWN

This
system call is used to modify the owner (UID) and the group (GID) that a
certain file belongs to. The syntax of the function is:

#include <sys/types.h>

#include <unistd.h>

int chown(const char* path, uid_t owner, gid_t grp);

The
function returns 0 in case of success and -1 in case of an error. Calling this
function will change the owner and the group of the file specified by the argument
path to the values specified by the
arguments owner and grp. None of the users can change the
owner of any file (even of his/her own files), except the root user, but they can change the GID for
their own files to that of any group they belong to.

mount() attaches the filesystem specified by
source (which is often a device name, but can also be a directory name
or a dummy) to the directory specified by
target.
umount() and
umount2() remove the attachment of the (topmost) filesystem mounted on
target.