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.

 System call mount /Umount:

#include <sys/mount.h> 

int mount(const char *source, const char *target, 
          const char *filesystemtype, unsigned long mountflags, 
          const void *data); 

int umount(const char *target);
int umount2(const char *target, int flags);

Description:
 
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.




 

No comments:

Post a Comment