0% found this document useful (0 votes)
4 views

ospp-chap05-part3

Uploaded by

asjeevannavar
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views

ospp-chap05-part3

Uploaded by

asjeevannavar
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 9

File Management

Chapter 5 – Part 03

Differences between a Stream Pointer and a File Descriptor

Kernel Support for Files

What happens when you open a file? (Also refer to figure below)
1. The kernel will search the process descriptor table and look for the first unused entry. If
an entry is found, that entry will be designated to reference the file .The index of the entry
will be returned to the process as the file descriptor of the opened file.

2. The kernel will scan the file table in its kernel space to find an unused entry that can be
assigned to reference the file. If an unused entry is found the following events will occur:
 The process file descriptor table entry will be set to point to this file table entry.
 The file table entry will be set to point to the inode table entry, where the inode
record of the file is stored.
 The file table entry will contain the current file pointer of the open file. This is an
offset from the beginning of the file where the next read or write will occur.
 The file table entry will contain an open mode that specifies that the file opened is
for read only, write only or read and write etc. This should be specified in open
function call.
 The reference count (rc) in the file table entry is set to 1. Reference count is used to
keep track of how many file descriptors from any process are referring the entry.
 The reference count of the in-memory inode of the file is increased by 1. This count
specifies how many file table entries are pointing to that inode.
 If either (1) or (2) fails, the open system call returns -1 (failure/error)

What happens when you close a file?


1. The kernel sets the corresponding file descriptor table entry to be unused.
2. It decrements the (reference count) rc in the corresponding file table entry by 1, if rc not
equal to 0 go to step 6.
3. The file table entry is marked as unused.
4. The rc in the corresponding file inode table entry is decremented by 1, if rc value not
equal to 0 go to step 6.
5. If the hard link count of the inode is not zero, it returns to the caller with a success
status otherwise it marks the inode table entry as unused and de-allocates all the
physical disk storage of the file.
6. It returns to the process with a 0 (success) status.

Usually the reference count (rc) in the file table entry is 1, if we wish to increase the rc in the
file table entry, this can be done using fork, dup, dup2 system call. When an open system
call is succeeded, its return value will be an integer (file descriptor). Whenever the process
wants to read or write data from the file, it should use the file descriptor as one of its
argument.
File APIs

1. open
#include <sys/stat.h>
#include <fcntl.h>

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


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

The return value of open() is a file descriptor, a small, nonnegative integer that is used in
subsequent system calls (read(), write(), lseek(), fcntl(), etc.) to refer to the open file. The
file descriptor returned by a successful call will be the lowest-numbered file descriptor not
currently open for the process.

This is used to establish a connection between a process and a file i.e. it is used to open
an existing file for data transfer function or else it may be also be used to create a new
file. The returned value of the open system call is the file descriptor (row number of
the file table), which contains the inode information.

Arguments:
 The first argument is the name of the file to be created or opened. This may be
an absolute pathname or relative pathname. If the given pathname is symbolic
link, the open function will resolve the symbolic link reference to a non -
symbolic link file to which it refers.
 The second argument is access modes, which is an integer value that specifies
how actually the file should beaccessed by the calling process.
 The third argument is used only when a new file is being created. The symbolic
constants used in mode are given in table below:
Generally the access modes are specified in <fcntl.h>. Various access modes are:
O_RDONLY - open for reading file only
O_WRONLY - open for writing file only
O_RDWR - opens for reading and writing file.

There are other access modes, which are termed as access modifier flags, and one or
more of the following can be specified by bitwise-ORing them with one of the above access
mode flags to alter the access mechanism of the file.

 O_APPEND
o Append data to the end of file.
 O_CREAT
o Create the file if it doesn’t exist
 O_EXCL
o Generate an error if O_CREAT is also specified and the file already exists.
 O_TRUNC
o If file exists discard the file content and set the file size to zero bytes.
 O_NONBLOCK
o Specify subsequent read or write on the file should be non-blocking.
 O_NOCTTY
o Specify not to use terminal device file as the calling process control terminal.

2. creat
#include <sys/stat.h>
#include <fcntl.h>
int creat(const char *pathname, mode_t mode);

It is used to create new regular files Returns: file descriptor opened for write-only if OK, -1
on error.

Arguments:
 The first argument pathname specifies name of the file to be created.
 The second argument mode_t, specifies permission of a file to be accessed by owner
group and others.

Note that open() can open device special files, but creat() cannot create them; we need to
use mknod() instead.

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

read() attempts to read up to count bytes from file descriptor fd into the buffer starting
at buf. If count is zero, read() returns zero and has no other results. If count is greater than
SSIZE_MAX, the result is unspecified. The size_t data type is defined in the <sys/types.h>
header and should be the same as unsigned int.

Arguments:
 The first argument is an integer, fdesc that refers to an opened file.
 The second argument, buf is the address of a buffer holding any data read.
 The third argument specifies how many bytes of data are to be read from the file.

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

write() writes up to count bytes to the file referenced by the file descriptor fd from the
buffer starting at buf. POSIX requires that a read() which can be proved to occur after
a write() has returned returns the new data. On success, the number of bytes written are
returned (zero indicates nothing was written). On error, -1 is returned, and errno is set
appropriately.

Arguments:
 The first argument, fdesc is an integer that refers to an opened file.
 The second argument, buf is the address of a buffer that contains data to be written.
 The third argument, size specifies how many bytes of data are in the buf argument

5. close
#include<unistd.h>
int close(int fdesc);

The close system call is used to terminate the connection to a file from a process. If
successful, close returns 0 and if unsuccessful, close returns –1. The argument fdesc refers
to an opened file. Close function frees the unused file descriptors so that they can be reused
to reference other files. This is important because a process may open up to OPEN_MAX
files at any time and the close function allows a process to reuse file descriptors to access
more than OPEN_MAX files in the course of its execution.

The close function de-allocates system resources like file table entry and memory buffer
allocated to hold the read/write.

6. fcntl
#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd, int cmd, ... /* arg */ );

fcntl() performs one of the operations described below on the open file descriptor fd. The
operation is determined by cmd. fcntl() can take an optional third argument. Whether or
not this argument is required is determined by cmd. The required argument type is
indicated in parentheses after each cmd name (in most cases, the required type is int, and
we identify the argument using the name arg), or void is specified if the argument is not
required.

Arguments:
 The first argument is the file descriptor.
 The second argument cmd specifies what operation has to be performed.
 The third argument is dependent on the actual cmd value.

The possible cmd values are defined in <fcntl.h> header and are below:
cmd value Use
F_GETFL Returns the access control flags of a file descriptor fdesc
F_SETFL Sets or clears access control flags that are specified in the third argument
to fcntl. The allowed access control flags are O_APPEND & O_NONBLOCK
F_GETFD Returns the close-on-exec flag of a file referenced by fdesc. If a return
value is zero, the flag is off; otherwise on.
F_SETFD Sets or clears the close-on-exec flag of a fdesc. The third argument to
fcntl is an integer value, which is 0 to clear the flag, or 1 to set the flag
F_DUPFD Duplicates file descriptor fdesc with another file descriptor. The third
argument to fcntl is an integer value which specifies that the duplicated
file descriptor must be greater than or equal to that value. The return
value of fcntl is the duplicated file descriptor

The fcntl function is useful in changing the access control flag of a file descriptor. For
example: after a file is opened for blocking read-write access and the process needs to
change the access to non-blocking and in write-append mode, it can call:
int cur_flags=fcntl(fdesc, F_GETFL);
int rc=fcntl(fdesc, F_SETFL, cur_flag | O_APPEND | O_NONBLOCK);

7. lseek
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);

lseek() repositions the file offset of the open file description associated with the file
descriptor fd to the argument offset according to the directive whence as follows:
SEEK_SET: The file offset is set to offset bytes.
SEEK_CUR: The file offset is set to its current location plus offset bytes.
SEEK_END: The file offset is set to the size of the file plus offset bytes.

lseek() allows the file offset to be set beyond the end of the file (but this does not change
the size of the file). If data is later written at this point, subsequent reads of the data in the
gap (a "hole") return null bytes ('\0') until data is actually written into the gap.
8. link
#include <unistd.h>
int link(const char *cur_link, const char *new_link);

The link function creates a new link for the existing file.If successful, the link function
returns 0. If unsuccessful, link returns –1. The first argument cur_link, is the pathname of
existing file. The second argument new_link is a new pathname to be assigned to the same
file. If this call succeeds, the hard link count will be increased by 1.

9. unlink
#include <unistd.h>
int unlink(const char * cur_link);

The unlink function deletes a link of an existing file. This function decreases the hard link
count attributes of the named file, and removes the file name entry of the link from
directory file. A file is removed from the file system when its hard link count is zero and no
process has any file descriptor referencing that file.

If successful, the unlink function returns 0. If unsuccessful, unlink returns –1. The argument
cur_link is a path name that references an existing file.

10. stat, fstat


#include<sys/stat.h> #include<unistd.h>
int stat(const char *pathname, struct stat *statv);
int fstat(const int fdesc, struct stat *statv);

The stat and fstat function retrieves the file attributes of a given file. The only difference
between stat and fstat is that the first argument of a stat is a file pathname, where as the
first argument of fstat is file descriptor. The second argument to stat and fstat is the
address of a struct stat-typed variable which is defined in the <sys/stat.h> header. Its
declaration is as follows:
struct stat {
dev_t st_dev; /* file system ID */
ino_t st_ino; /* file inode number */
mode_t st_mode; /* contains file type and permission */
nlink_t st_nlink; /* hard link count */
uid_t st_uid; /* file user ID */
gid_t st_gid; /* file group ID */
dev_t st_rdev; /*contains major and minor device#*/
off_t st_size; /* file size in bytes */
time_t st_atime; /* last access time */
time_t st_mtime; /* last modification time */
time_t st_ctime; /* last status change time */
};
11. File Locking
#include<fcntl.h>
int fcntl(int fdesc, int cmd_flag, );

The first argument specifies the file descriptor. The second argument cmd_flag specifies
what operation has to be performed.

If fcntl is used for file locking then it can values as

F_SETLK - sets a file lock, do not block if this cannot succeed immediately.
F_SETLKW - sets a file lock and blocks the process until the lock is acquired.
F_GETLK - queries as to which process locked a specified region of file.

For file locking purpose, the third argument to fctnl is an address of a struct flock type
variable.

This variable specifies a region of a file where lock is to be set, unset or queried.

struct flock
{
short l_type; /* what lock to be set or to unlock file */
short l_whence; /* Reference address for the next field */
off_t l_start ; /*offset from the l_whence reference addr*/
off_t l_len ; /*how many bytes in the locked region */
pid_t l_pid ; /*pid of a process which has locked the file */
};

The l_type field specifies the lock type to be set or unset. The possible values, which are
defined in the <fcntl.h> header, and their uses are
F_RDLCK - Set a read lock on a specified region
F_WRLCK - Set a write lock on a specified region
F_UNLCK - Unlock a specified region

The l_whence, l_start & l_len define a region of a file to be locked or unlocked. The possible
values of l_whence and their uses are

SEEK_CUR - The l_start value is added to current file pointer address


SEEK_SET - The l_start value is added to byte 0 of the file
SEEK_END - The l_start value is added to the end of the file
Program:
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>

int main()
{
char buf[20];
int fd1, fd2;
fd1 = creat("file.txt", O_RDWR);
write(fd1, "abcdefghij", 10);
close(fd1);

fd2 = open("file.txt", O_RDWR, S_IXUSR | S_IRWXG | S_IRWXO);


read(fd2, buf, 10);
printf("read data is %s\n", buf);

lseek(fd2, 5, SEEK_SET);
char c[10];
read(fd2, c, 2);

int val, accmode;


val = fcntl(fd2, F_GETFL, 0);

accmode = val & O_ACCMODE;


if( accmode == O_RDONLY )
printf( "read only\n");
else if(accmode == O_WRONLY )
printf( "write only\n" );
else if( accmode == O_RDWR )
printf( "read write\n" );

close(fd2);

struct stat info;


if (stat("file.txt", &info) != 0)
perror("stat() error");
else {
printf("stat() returned the following information\n:");
printf(" inode: %d\n", (int) info.st_ino);
printf(" dev id: %d\n", (int) info.st_dev);
printf(" mode: %08x\n", info.st_mode);
printf(" links: %d\n", info.st_nlink);
printf(" uid: %d\n", (int) info.st_uid);
printf(" gid: %d\n", (int) info.st_gid);
}
return 0;
}

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy