1- Write a utility like cp(1) that copies a file containing holes, without writi
ID: 3563889 • Letter: 1
Question
1- Write a utility like cp(1) that copies a file containing holes, without writing the bytes of 0 to the output file. Also, add logic that will cause cp to not copy to the target file if it already exists. Add a "-f" option on the commandline that will force the copy even if the file exists.
2- The tee command reads its standard input until end-of-file, writing a copy of the input to standard output and to the file named in its command-line argument. (We show an example of the use of this command when we discuss FIFOs in Section 44.7.) Implement tee using I/O system calls. By default, tee overwrites any existing file with the given name. Implement the –a command-line option (tee –a file), which causes tee to append text to the end of a file if it already exists. (Refer to Appendix B for a description of the getopt() function, which can be used to parse command-line options.)
Explanation / Answer
Please rate:
1- Write a utility like cp(1) that copies a file containing holes, without writing the bytes of 0 to the output file. Also, add logic that will cause cp to not copy to the target file if it already exists. Add a "-f" option on the commandline that will force the copy even if the file exists.
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#ifndef BUF_SIZE /* Allow "cc -D" to override */
#define BUF_SIZE 1024
#endif
void print_usage()
{
printf("Usage: ./prog_cpholes <src> <dst> ");
}
int main(int argc, char *argv[])
{
int inputFd, outputFd, openFlags;
mode_t filePerms;
ssize_t numRead;
char buf[BUF_SIZE];
/* parse argv
* ./prog_cpholes src dst
*/
if (argc != 3 || strcmp(argv[1], "--help") == 0) {
print_usage();
return 1;
}
/* Open input and output files */
openFlags = (O_CREAT | O_WRONLY | O_TRUNC);
filePerms = (S_IRUSR | S_IWUSR | S_IRGRP |
S_IROTH | S_IWOTH);
inputFd = open(argv[1], O_RDONLY);
if (inputFd < 0) {
printf("Failed to open input file: %s ", strerror(errno));
print_usage();
return 1;
}
outputFd = open(argv[2], openFlags, filePerms);
if (outputFd < 0) {
printf("Failed to open output file: %s ", strerror(errno));
print_usage();
return 1;
}
/*
* For copying, we read-and-copy from source to destination
*/
int i, err;
unsigned long holeSize = 0;
while ((numRead = read(inputFd, buf, BUF_SIZE)) > 0) {
for (i = 0; i < numRead; i++) {
if (buf[i] == '') {
holeSize++;
} else if (holeSize > 0) {
lseek(outputFd, holeSize, SEEK_CUR);
write(outputFd, &buf[i], 1);
holeSize = 0;
} else {
write(outputFd, &buf[i], 1);
}
}
}
/* close fds */
close(inputFd);
close(outputFd);
return 0;
}
2- The tee command reads its standard input until end-of-file, writing a copy of the input to standard output and to the file named in its command-line argument. (We show an example of the use of this command when we discuss FIFOs in Section 44.7.) Implement tee using I/O system calls. By default, tee overwrites any existing file with the given name. Implement the –a command-line option (tee –a file), which causes tee to append text to the end of a file if it already exists. (Refer to Appendix B for a description of the getopt() function, which can be used to parse command-line options.)
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
static int append_mode = 0;
int parse_args(int argc, char *argv[])
{
char c;
while ((c = getopt(argc, argv, "a")) != -1) {
switch (c) {
case 'a':
append_mode = 1;
break;
case '?':
if (isprint(optopt))
fprintf(stderr, "Unkonw option `-%c'. ", optopt);
else
fprintf(stderr,
"Unknown option character `\x%x'. ", optopt);
return 1;
default:
abort();
break;
}
}
return 0;
}
int main(int argc, char *argv[])
{
char buf[100];
size_t len;
char *file_mode;
int i;
FILE *files[20];
int num_files;
if (parse_args(argc, argv)) {
return 1;
}
file_mode = (append_mode ? "a" : "w");
num_files = argc - optind;
if (num_files > 0) {
if (files == NULL) {
fprintf(stderr, "Unable to allocate file buffer space ");
return 1;
}
/* go through file arguments and either open for writing
or append based on the -a flag */
for (i = optind; i < argc; i++) {
FILE *pFile = fopen(argv[i], file_mode);
if (pFile == NULL)
{
fprintf(stderr, "Unable to open file %s for mode %s",
argv[i], file_mode);
goto main_cleanup;
}
files[i - optind] = pFile; /* mind the offset */
}
}
FILE *not_stdin = fopen("tee.c", "r");
while ((len = fread(&buf[0], 1, sizeof(buf), not_stdin)) > 0) {
fwrite(&buf[0], 1, len, stdout);
for (i = 0; i < num_files; i++) {
fwrite(&buf[0], 1, len, files[i]);
}
}
main_cleanup:
if (num_files > 0) {
for (i = 0; i < num_files; i++) {
fclose(files[i]);
}
}
return 0;
}
Related Questions
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.