Great Deal! Get Instant $10 FREE in Account on First Order + 10% Cashback on Every Order Order Now

I have pasted the question below

1 answer below »
Workshop D
Operating Systems Programming – COMP 3015
1 Introduction
In this workshop you will investigate file I/O and file copy operations.
2 Specification
Following on from the demonstration program cp1.c presented in the lecture, we will make a series of modifi-
cations to the program.
Firstly, what happens when thecp1.cprogram is asked to copy a file onto itself, i.e. cp1 input input?
Is this what you expect? Modify the program to do something more sensible! As a hint, two files are the same if
they are on the same device and have the same i-node number (which stat() can give you), simply comparing
the names is not enough.
Secondly, a real copy program will assign the same file permissions to the destination as were on the source,
modify your answer to the last part to do this.
Thirdly, real copy programs allow the second argument to be a directory, i.e. you specify a directory for the
second part and a copy of the source is placed in that directory with the same name as the source. Modify the
answer to the last part to include this functionality. You should allocate the space for the new name dynamically.
Fourthly, your program should rename the original version of the destination file to filename.bak (i.e. add
an additional extension of .bak) if the destination file exists, or if the destination is a directory that a file with the
same name exists in the directory.
1
3 Sample Code
3.1 cp1.c
* cp1.c -- simple copy program example
* Dr Evan Crawford ( XXXXXXXXXX)
* COMP 30015 Operating Systems Programming
* Practical Case Study D
* This sample file was adapted from:
* Molay, B XXXXXXXXXXcp1.c. In Understanding unix/linux programming.
* Source Code, Prentice Hall.
*
#include #include #include #define BUFFERSIZE 4096
#define COPYMODE 0644
void oops(char *, char *);
int main(int ac, char *av[])
{
int in_fd;
int out_fd;
int n_chars;
char buf[BUFFERSIZE];
if (ac != 3)
{
fprintf(stde
, "usage: %s source destination\n", *av);
exit(1);
}
if ((in_fd = open(av[1], O_RDONLY)) == -1)
{
oops("Cannot open ", av[1]);
}
if ((out_fd = creat(av[2], COPYMODE)) == -1)
{
oops("Cannot creat", av[2]);
}
while ((n_chars = read(in_fd, buf, BUFFERSIZE)) > 0)
{
if (write(out_fd, buf, n_chars) != n_chars)
{
oops("Write e
or to ", av[2]);
}
}
2
if (n_chars == -1)
{
oops("Read e
or from ", av[1]);
}
if (close(in_fd) == -1 || close(out_fd) == -1)
{
oops("E
or closing files", "");
}
eturn 0;
}
void oops(char *s1, char *s2)
{
fprintf(stde
, "E
or: %s ", s1);
pe
or(s2);
exit(1);
}
3
4 Supplementary Materials
The material on the following pages is an extract of the linux system documentation and may prove useful in
implementing this Workshop. These manual pages are taken from the Linux man-pages Project available at:
http:
www.kernel.org/doc/man-pages/.
4
http:
www.kernel.org/doc/man-pages
OPEN(2) Linux Programmer’s Manual OPEN(2)
NAME
open, openat, creat − open and possibly create a file
SYNOPSIS
#include int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
int creat(const char * pathname, mode_t mode);
int openat(int dirfd , const char *pathname, int flags);
int openat(int dirfd , const char *pathname, int flags, mode_t mode);
* Documented separately, in openat2(2): *
int openat2(int dirfd , const char *pathname,
const struct open_how *how, size_t size);
Feature Test Macro Requirements for glibc (see feature_test_macros(7)):
openat():
Since glibc 2.10:
_POSIX_C_SOURCE >= 200809L
Before glibc 2.10:
_ATFILE_SOURCE
DESCRIPTION
The open() system call opens the file specified by pathname. If the specified file does not exist, it may op-
tionally (if O_CREAT is specified in flags) be created by open().
The return value of open() is a file descriptor, a small, nonnegative integer that is an index to an entry in the
process’s table of open file descriptors. The file descriptor is used in subsequent system calls (read(2),
write(2), lseek(2), fcntl(2), etc.) to refer to the open file. The file descriptor returned by a successful call
will be the lowest-numbered file descriptor not cu
ently open for the process.
By default, the new file descriptor is set to remain open across an execve(2) (i.e., the FD_CLOEXEC file
descriptor flag described in fcntl(2) is initially disabled); the O_CLOEXEC flag, described below, can be
used to change this default. The file offset is set to the beginning of the file (see lseek(2)).
A call to open() creates a new open file description, an entry in the system-wide table of open files. The
open file description records the file offset and the file status flags (see below). A file descriptor is a refer-
ence to an open file description; this reference is unaffected if pathname is subsequently removed or modi-
fied to refer to a different file. For further details on open file descriptions, see NOTES.
The argument flags must include one of the following access modes: O_RDONLY, O_WRONLY, o
O_RDWR. These request opening the file read-only, write-only, or read/write, respectively.
In addition, zero or more file creation flags and file status flags can be bitwise-or’d in flags. The file cre-
ation flags are O_CLOEXEC, O_CREAT, O_DIRECTORY, O_EXCL, O_NOCTTY, O_NOFOL-
LOW, O_TMPFILE, and O_TRUNC. The file status flags are all of the remaining flags listed below.
The distinction between these two groups of flags is that the file creation flags affect the semantics of the
open operation itself, while the file status flags affect the semantics of subsequent I/O operations. The file
status flags can be retrieved and (in some cases) modified; see fcntl(2) for details.
The full list of file creation flags and file status flags is as follows:
O_APPEND
The file is opened in append mode. Before each write(2), the file offset is positioned at the end of
the file, as if with lseek(2). The modification of the file offset and the write operation are per-
formed as a single atomic step.
O_APPEND may lead to co
upted files on NFS filesystems if more than one process appends
data to a file at once. This is because NFS does not support appending to a file, so the client kernel
has to simulate it, which can’t be done without a race condition.
Linux XXXXXXXXXX
OPEN(2) Linux Programmer’s Manual OPEN(2)
O_ASYNC
Enable signal-driven I/O: generate a signal (SIGIO by default, but this can be changed via fc-
ntl(2)) when input or output becomes possible on this file descriptor. This feature is available only
for terminals, pseudoterminals, sockets, and (since Linux 2.6) pipes and FIFOs. See fcntl(2) fo
further details. See also BUGS, below.
O_CLOEXEC (since Linux 2.6.23)
Enable the close-on-exec flag for the new file descriptor. Specifying this flag permits a program to
avoid additional fcntl(2) F_SETFD operations to set the FD_CLOEXEC flag.
Note that the use of this flag is essential in some multithreaded programs, because using a separate
fcntl(2) F_SETFD operation to set the FD_CLOEXEC flag does not suffice to avoid race condi-
tions where one thread opens a file descriptor and attempts to set its close-on-exec flag using fc-
ntl(2) at the same time as another thread does a fork(2) plus execve(2). Depending on the order of
execution, the race may lead to the file descriptor returned by open() being unintentionally leaked
to the program executed by the child process created by fork(2). (This kind of race is in principle
possible for any system call that creates a file descriptor whose close-on-exec flag should be set,
and various other Linux system calls provide an equivalent of the O_CLOEXEC flag to deal with
this problem.)
O_CREAT
If pathname does not exist, create it as a regular file.
The owner (user ID) of the new file is set to the effective user ID of the process.
The group ownership (group ID) of the new file is set either to the effective group ID of the
process (System V semantics) or to the group ID of the parent directory (BSD semantics). On
Linux, the behavior depends on whether the set-group-ID mode bit is set on the parent directory: if
that bit is set, then BSD semantics apply; otherwise, System V semantics apply. For some filesys-
tems, the behavior also depends on the bsdgroups and sysvgroups mount options described in
mount(8).
The mode argument specifies the file mode bits to be applied when a new file is created. If neithe
O_CREAT nor O_TMPFILE is specified in flags, then mode is ignored (and can thus be speci-
fied as 0, or simply omitted). The mode argument must be supplied if O_CREAT or O_TMP-
FILE is specified in flags; if it is not supplied, some a
itrary bytes from the stack will be applied
as the file mode.
The effective mode is modified by the process’s umask in the usual way: in the absence of a de-
fault ACL, the mode of the created file is (mode & ~umask).
Note that mode applies only to future accesses of the newly created file; the open() call that cre-
ates a read-only file may well return a read/write file descriptor.
The following symbolic constants are provided for mode:
S_IRWXU
00700 user (file owner) has read, write, and execute permission
S_IRUSR
00400 user has read permission
S_IWUSR
00200 user has write permission
S_IXUSR
00100 user has execute permission
S_IRWXG
00070 group has read, write, and execute permission
Linux XXXXXXXXXX
OPEN(2) Linux Programmer’s Manual OPEN(2)
S_IRGRP
00040 group has read permission
S_IWGRP
00020 group has write permission
S_IXGRP
00010 group has execute permission
S_IRWXO
00007 others have read, write, and execute permission
S_IROTH
00004 others have read permission
S_IWOTH
00002 others have write permission
S_IXOTH
00001 others have execute permission
According to POSIX, the effect when other bits are set in mode is unspecified. On Linux, the fol-
lowing bits are also honored in mode:
S_ISUID XXXXXXXXXXset-user-ID bit
S_ISGID XXXXXXXXXXset-group-ID bit (see inode(7)).
S_ISVTX
XXXXXXXXXXsticky bit (see inode(7)).
O_DIRECT (since Linux 2.4.10)
Try to minimize cache effects of the I/O to and from this file. In general this will degrade perfor-
mance, but it is useful in special situations, such as when applications do their own caching. File
I/O is done directly to/from user-space buffers. The O_DIRECT flag on its own makes an effort
to transfer data synchronously, but does not give the guarantees of the O_SYNC flag that data and
necessary metadata are transfe
ed. To guarantee synchronous I/O, O_SYNC must be used in ad-
dition to O_DIRECT. See NOTES below for further discussion.
A semantically similar (but deprecated) interface for block devices is described in raw(8).
O_DIRECTORY
If pathname is not a directory, cause the open to fail. This flag was added in kernel version
2.1.126, to avoid denial-of-service problems if opendir(3) is called on a FIFO or tape device.
O_DSYNC
Write operations on the file will complete according to the requirements of synchronized
Answered 2 days After May 21, 2022

Solution

Pawan answered on May 22 2022
107 Votes
SOLUTION.PDF

Answer To This Question Is Available To Download

Related Questions & Answers

More Questions »

Submit New Assignment

Copy and Paste Your Assignment Here