i have this code but every time i try to run it it deletes the source file without giving any output, so how can i fix my problem?
note the question is asking me this:
Write a program that takes two file names from the command line, and copies the reverse of the contents of the first file into the second file, assuming that it is able to open the first file for reading and the second one for writing. If it can’t open the first file for reading, it must neither create nor modify (as the case may be) the second file. This program must use the low-level functions
#include<stdlib.h>
#include<stdio.h>
#include<fcntl.h>
#include<string.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<unistd.h>
int main(int argc, char *argv[])
{
int source, dest, n;
char buf;
int filesize;
int i;
if (argc != 3)
{
fprintf(stderr, "usage %s <source> <dest>\n", argv[0]);
exit(-1);
}
at this par i am trying to use the following format: open("outf", O_WRONLY | O_CREAT | O_TRUNC, 0666)
if ((source = open(argv[1],O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0)
{ //read permission for user on source
fprintf(stderr, "can't open source\n");
exit(-1);
}
if ((dest = creat(argv[2], 0666)) < 0)
{ //rwx permission for user on dest
fprintf(stderr, "can't create dest");
exit(-1);
}
filesize = lseek(source, (off_t) 0, SEEK_END); //filesize is lastby +offset
printf("Source file size is %d\n", filesize);
for (i = filesize - 1; i >= 0; i--)
{ //read byte by byte from end
lseek(source, (off_t) i, SEEK_SET);
n = read(source, &buf, 1);
if (n != 1)
{
fprintf(stderr, "can't read 1 byte\n");
exit(-1);
}
n = write(dest, &buf, 1);
if (n != 1)
{
fprintf(stderr, "can't write 1 byte\n");
exit(-1);
}
}
write(STDOUT_FILENO, "DONE\n", 5);
close(source);
close(dest);
return 0;
}
thanks
I am sorry to be rude but did you even read the options you are passing to the first open call? O_CREAT | O_TRUNC?
What do you think those options do? Those options are causing your source file to be deleted.
You need to open your input file with the mode O_RDONLY, i.e. ReaD ONLY not O_WRONLY, i.e. WRite ONLY.
Check this:
int checkstatus(ifstream &in)
{
ios::iostate i;
i = in.rdstate();
if(i & ios::eofbit)
return 0;//cout << "EOF encountered\n";
else if(i & ios::failbit)
return 0;//cout<<"Non-Fatal I/O error\n";
else if(i & ios::badbit)
return 0;//cout<<"Fatal I/O error\n";
return 1;
}
int main()
{
ifstream in;
ofstream o;
in.open("test.txt");
o.open("test1.txt",ios::out);
char c;
in.seekg(0,ios::end);
while(checkstatus(in) != 0)
{
in.seekg(-1,ios::cur);
in.get(c);
in.seekg(-1,ios::cur);
if(checkstatus(in) == 0)
break;
cout<<c;
o.put(c);
}
in.close();
o.close();
return 0;
}
i have made some changes here and it worked very decent but not with very large file!!
#include<stdlib.h>
#include<stdio.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<unistd.h>
int main(int argc, char *argv[])
{
int source, dest, n;
char buf;
int filesize;
int i;
if (argc != 3)
{
fprintf(stderr, "usage %s <source> <dest>\n", argv[0]);
exit(-1);
}
if ((source = open(argv[1], 0666)) < 0)
{ //read permission for user on source
fprintf(stderr, "can't open source\n");
exit(-1);
}
if ((dest = open(argv[2],O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0)
{ //rwx permission for user on dest
fprintf(stderr, "can't create dest");
exit(-1);
}
filesize = lseek(source, (off_t) 0, SEEK_END); //filesize is lastby +offset
printf("Source file size is %d\n", filesize);
for (i = filesize - 1; i >= 0; i--)
{ //read byte by byte from end
lseek(source, (off_t) i, SEEK_SET);
n = read(source, &buf, 1);
if (n != 1)
{
fprintf(stderr, "can't read 1 byte\n");
exit(-1);
}
n = write(dest, &buf, 1);
if (n != 1)
{
fprintf(stderr, "can't write 1 byte\n");
exit(-1);
}
}
write(STDOUT_FILENO, "DONE\n", 5);
close(source);
close(dest);
return 0;
}
do i need to do something with lseek()?
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I would like to read a specified number of bytes from the specified offset value from a file. I pass the offset, a number of bytes, filename as arguments to the file. The code below does not work.Could anyone help me with this? Thanks.
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<error.h>
#include<errno.h>
#include<fcntl.h>
#define buf_size 512
int main(int argc, char *argv[])
{
int bytes;
int offset;
int fd;
int i = 0;
int length = 0;
ssize_t read_bytes;
char *file;
char buf[buf_size];
if (argc != 4)
error(1, 0, "Too many or less than the number of arguments");
file = argv[1];
offset = atoi(argv[2]);
bytes = atoi(argv[3]);
fd = open(file, O_RDONLY);
if (fd == -1)
error(1, errno, "Error while opening the file\n");
while (1) {
read_bytes = read(fd, buf, bytes);
if (read_bytes == -1)
error(1, errno, "Error while reading the file\n");
length += read_bytes;
printf("The length is : %d\n", length);
if (length >= offset) {
for (i = length ; i < bytes; i++)
putchar(buf[i]);
break;
}
}
if (close(fd) == -1)
error(1, 0, "Error while closing the file\n");
}
I have decided to replace some POSIX functions with the ones found in the C standard library due to constraints pointed out by the person who asked the question. This is fairly portable.
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#define buf_size 512
int main(int argc, char *argv[])
{
int bytes;
int offset;
FILE *fd;
int i = 0;
ssize_t read_bytes;
char *file;
char buf[buf_size];
if (argc != 4)
printf("Too many or less than the number of arguments\n");
file = argv[1];
offset = atoi(argv[2]);
bytes = atoi(argv[3]);
fd = fopen(file, "r");
if (fd == NULL)
perror("ERROR");
fseek(fd, offset, SEEK_SET);
read_bytes = fread(buf, 1, bytes, fd);
if (read_bytes == 0) {
if (feof(fd))
printf("ERROR: End of file.\n");
else if (ferror(fd))
printf("ERROR: Unable to read the file.\n");
return 1;
}
for (i = 0; i < bytes; i++)
putchar(buf[i]);
if (fclose(fd) == EOF)
perror("ERROR:");
return 0;
}
I have used the open, close, read, write system calls only for the above-mentioned question.I think it takes care of partial reads, offset > buf_size and bytes > buf_size.Thanks.
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<error.h>
#include<errno.h>
#include<fcntl.h>
#define buf_size 5
int main(int argc, char *argv[])
{
int bytes;
int offset;
int fd;
char *file;
char buf[buf_size];
int rlen = 0;
int len = 0;
int i = 0;
if (argc != 4)
error(1, 0, "Too many or less than the number of arguments");
file = argv[1];
offset = atoi(argv[2]);
bytes = atoi(argv[3]);
fd = open(file, O_RDONLY);
printf("The values of the file descriptor is : %d\n", fd);
if (fd == -1)
error(1, errno, "Error while opening the file\n");
while (1) {
rlen = read(fd, buf, offset);
if (rlen == -1)
error(1, errno, "Error in reading the file\n");
len = len + rlen;
if(len == offset) {
len = 0;
while (1) {
rlen = read(fd, buf, bytes);
if (rlen == -1)
error(1, errno, "Error in reading the file\n");
if (rlen == 0)
return 0;
len = len + rlen;
for (i = 0; i < rlen; i++)
putchar(buf[i]);
if (len == bytes) {
printf("\nSuccess\n");
return 0;
}
bytes = bytes - rlen;
}
}
}
}
I've been trying to find out why my tester is failing, it says that destination and source file don't match. link for testers: https://github.com/ShiraWolf/hwOP.git
Output Requirements & Testing:
It must output one of the following types of messages (precisely and case-sensitive):
Unable to open source file for reading
Unable to open destination file for writing
Unable to write to destination file
Unable to write buffer content to destination file
Unable to read source file
Unable to close source file
Unable to close destination file
File was successfully copied to
Or one of the various arguments parsing errors, as described in the examples above.
My code:
/*
* ex1.c
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define MAX_BUFFER_SIZE 65536
#define DESTINATION_FILE_MODE S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH
extern int opterr, optind;
void exit_with_usage(const char *message) {
fprintf(stderr, "%s\n", message);
fprintf(stderr, "Usage:\n\tex1 [-f] BUFFER_SIZE SOURCE DEST\n");
exit(EXIT_FAILURE);
}
void copy_file(const char *source_file, const char *dest_file, int buffer_size, int force_flag) {
/*
* Copy source_file content to dest_file, buffer_size bytes at a time.
* If force_flag is true, then also overwrite dest_file. Otherwise print error, and exit.
*
* TODO:
* 1. Open source_file for reading
* 2. Open dest_file for writing (Hint: is force_flag true?)
* 3. Loop reading from source and writing to the destination buffer_size bytes each time
* 4. Close source_file and dest_file
*
* ALWAYS check the return values of syscalls for errors!
* If an error was found, use perror(3) to print it with a message, and then exit(EXIT_FAILURE)
*/
int c = 0;
int sourcef = 0;
int destf = 0;
sourcef = open(source_file, O_RDONLY);
if (sourcef == -1) {
perror("Unable to open source file for reading");
exit(EXIT_FAILURE);
}
destf = open(dest_file, O_WRONLY |O_CREAT | O_EXCL, 00700);
if (destf == -1) {
if (force_flag) {
destf = open(dest_file, O_WRONLY, 00700);
if (destf == -1) {
if (close(sourcef) == -1) {
perror("couldn't close source file");
exit(EXIT_FAILURE);
}
perror("Unable to open destination for writing");
exit(EXIT_FAILURE);
}
} else {
perror("Unable to open destination for writing");
exit(EXIT_FAILURE);
}
}
char *buffer = malloc(sizeof(char) * buffer_size);
while ((c = read(sourcef, buffer, buffer_size)) != 0) {
if (c == -1) {
perror("couldn't read from source file");
if (close(sourcef) == -1) {
perror("couldn't close source file after reading has failed");
exit(EXIT_FAILURE);
}
if (close(destf) == -1) {
perror("couldn't close dest file after reading has failed");
exit(EXIT_FAILURE);
}
exit(EXIT_FAILURE);
}
c = write(destf, buffer, buffer_size);
if (c == -1) {
perror("couldn't write to source file");
if (close(sourcef) == -1) {
perror("couldn't close source file after writing has failed");
exit(EXIT_FAILURE);
}
if (close(destf) == -1) {
perror("couldn't close dest file after writing has failed");
exit(EXIT_FAILURE);
}
exit(EXIT_FAILURE);
}
}
free(buffer);
if (close(sourcef) == -1) {
perror("couldn't close source file");
exit(EXIT_FAILURE);
}
if (close(destf) == -1) {
perror("couldn't close dest file");
exit(EXIT_FAILURE);
}
printf("File %s was copied to %s\n", source_file, dest_file);
exit(EXIT_SUCCESS);
}
void parse_arguments (
int argc, char **argv,
char **source_file, char **dest_file, int *buffer_size, int *force_flag) {
/*
* parses command line arguments and set the arguments required for copy_file
*/
int option_character;
opterr = 0; /* Prevent getopt() from printing an error message to stderr */
while ((option_character = getopt(argc, argv, "f")) != -1) {
switch (option_character) {
case 'f':
*force_flag = 1;
break;
default: /* '?' */
exit_with_usage("Unknown option specified");
}
}
if (argc - optind != 3) {
exit_with_usage("Invalid number of arguments");
} else {
*source_file = argv[argc - 2];
*dest_file = argv[argc - 1];
*buffer_size = atoi(argv[argc - 3]);
if (strlen(*source_file) == 0 || strlen(*dest_file) == 0) {
exit_with_usage("Invalid source / destination file name");
} else if (*buffer_size < 1 || *buffer_size > MAX_BUFFER_SIZE) {
exit_with_usage("Invalid buffer size");
}
}
}
int main(int argc, char **argv) {
int force_flag = 0; /* force flag default: false */
char *source_file = NULL;
char *dest_file = NULL;
int buffer_size = MAX_BUFFER_SIZE;
parse_arguments(argc, argv, &source_file, &dest_file, &buffer_size, &force_flag);
copy_file(source_file, dest_file, buffer_size, force_flag);
return EXIT_SUCCESS;
}
Can anybody see where my mistake is?
c = write(destf, buffer, buffer_size); does not use the correct size: you should write c bytes and store the written count into a separate variable nwritten and keep trying to write more bytes until c bytes have been written or write return 0 or -1.
Here is a modified version of the copying loop:
while ((c = read(sourcef, buffer, buffer_size)) != 0) {
if (c == -1) {
perror("Unable to read from source file");
if (close(sourcef) == -1) {
perror("Unable to close source file");
exit(EXIT_FAILURE);
}
if (close(destf) == -1) {
perror("Unable to close destination file");
exit(EXIT_FAILURE);
}
exit(EXIT_FAILURE);
}
int towrite = c;
int pos = 0;
while (towrite > 0) {
int nwritten = write(destf, buffer + pos, towrite);
if (nwritten <= 0) {
perror("Unable to write to destination file");
if (close(sourcef) == -1) {
perror("Unable to close source file");
exit(EXIT_FAILURE);
}
if (close(destf) == -1) {
perror("Unable to close destination file");
exit(EXIT_FAILURE);
}
exit(EXIT_FAILURE);
}
pos += nwritten;
towrite -= nwritten;
}
}
Also note that the other error messages are different from the specification.
I have some problem about to take integer numbers from binary file. My code is:
int main (int argc, char ** argv) {
FILE * fpi, *fpo, *fp;
int i, len;
char buf[50];
if (argc != 3) {
printf ("Syntax: %s filename_input, filename_output", argv[0]);
return (1);
}
len = 0;
if ((fpi = fopen (argv[1], "rt")) == NULL)
perror ("file_input open");
if ((fpo = fopen (argv[2], "wb")) == NULL)
perror ("file_output open %");
while(fscanf(fpi,"%d",&i) != EOF){ //Take the content of file input and put in the file binary
fwrite(&i, sizeof(int), 1, fpo); //I write each number i into file output
}
return (0);
}
Here, given a txt file with for example 5 integer numbers, it generates the corresponding binary file. Then, if I try to fread this binary file is all ok, but if I try to read this binary file with mmap function and I put the content on an array, in the output, as content of array, I have a strange character, a small square with 00 02. The code where I use mmap is:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, char **argv) {
int fd;
int i, n, len;
int *vet;
struct stat stat_buf;
char *paddr;
if (argc != 2) {
printf("Syntax: %s filename", argv[0]);
return (1);
}
if ((fd = open(argv[1], O_RDWR)) == -1) {
perror("open");
}
if (fstat(fd, &stat_buf) == -1) {
perror("fstat");
}
len = stat_buf.st_size;
n = len / sizeof(int);
paddr = mmap((caddr_t) 0, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (paddr == (caddr_t) -1) {
perror("mmap");
}
close(fd);
vet = (int *) paddr;
for (i = 0; i < n; i++) {
printf("%d\n", vet[i]);
}
return (0);
}
The output that it gives me is:
Thank you in advance.
I've got how to copy one file to another from start, but how could i modify the programme to copy it in reverse order? Source file should have read access and destination file read write execute. I have to use file control libraries.
for example
FILE A File B should be
|---------| |----------|
|ABCDEF | |FEDCBA |
|---------| |----------|
*********************UPDATE**********
Thank you, MikeNakis for hints and suggestions
,Sangeeth for your code
I've reworked the code and now it is copy bytes in reverse order printing filesize
here is the code
#include<stdlib.h>
#include<stdio.h>
#include<fcntl.h>
#include<string.h>
#include<sys/stat.h>
#include<unistd.h>
int main(int argc, char *argv[]) {
int source, dest, n;
char buf;
int filesize;
int i;
if (argc != 3) {
fprintf(stderr, "usage %s <source> <dest>", argv[0]);
exit(-1);
}
if ((source = open(argv[1], 0400)) < 0) { //read permission for user on source
fprintf(stderr, "can't open source");
exit(-1);
}
if ((dest = creat(argv[2], 0700)) < 0) { //rwx permission for user on dest
fprintf(stderr, "can't create dest");
exit(-1);
}
filesize = lseek(source, (off_t) 0, SEEK_END); //filesize is lastby +offset
printf("Source file size is %d\n", filesize);
for (i = filesize - 1; i >= 0; i--) { //read byte by byte from end
lseek(source, (off_t) i, SEEK_SET);
n = read(source, &buf, 1);
if (n != 1) {
fprintf(stderr, "can't read 1 byte");
exit(-1);
}
n = write(dest, &buf, 1);
if (n != 1) {
fprintf(stderr, "can't write 1 byte");
exit(-1);
}
}
write(STDOUT_FILENO, "DONE\n", 5);
close(source);
close(dest);
return 0;
}
You just seek to the end and start reading from there. No wonder it won't read anything. You need to seek to the end minus 1 byte, read one byte, write it, then seek to the end minus two bytes, read another byte, and so on.
I presume this is a homework assignment, so your professor should not mind the extreme inefficiency of this approach. (Real-world performance concerns are oh-so un-academic.) If he complains, tell him that in theory, it has the same time complexity as any other algorithm which would perform the same task: O(N). (That's pronounced "big oh of en".) He will give you an A+.
lseek(source, (off_t) i, SEEK_SET); should probably be lseek(source, (off_t) i - 1, SEEK_SET);
This question already has answers here:
How do you determine the size of a file in C?
(15 answers)
Closed 3 years ago.
How can I find out the size of a file I opened with an application written in C ?
I would like to know the size, because I want to put the content of the loaded file into a string, which I allocate using malloc(). Just writing malloc(10000*sizeof(char)); is IMHO a bad idea.
You need to seek to the end of the file and then ask for the position:
fseek(fp, 0L, SEEK_END);
sz = ftell(fp);
You can then seek back, e.g.:
fseek(fp, 0L, SEEK_SET);
or (if seeking to go to the beginning)
rewind(fp);
Using standard library:
Assuming that your implementation meaningfully supports SEEK_END:
fseek(f, 0, SEEK_END); // seek to end of file
size = ftell(f); // get current file pointer
fseek(f, 0, SEEK_SET); // seek back to beginning of file
// proceed with allocating memory and reading the file
Linux/POSIX:
You can use stat (if you know the filename), or fstat (if you have the file descriptor).
Here is an example for stat:
#include <sys/stat.h>
struct stat st;
stat(filename, &st);
size = st.st_size;
Win32:
You can use GetFileSize or GetFileSizeEx.
If you have the file descriptor fstat() returns a stat structure which contain the file size.
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
// fd = fileno(f); //if you have a stream (e.g. from fopen), not a file descriptor.
struct stat buf;
fstat(fd, &buf);
off_t size = buf.st_size;
I ended up just making a short and sweet fsize function(note, no error checking)
int fsize(FILE *fp){
int prev=ftell(fp);
fseek(fp, 0L, SEEK_END);
int sz=ftell(fp);
fseek(fp,prev,SEEK_SET); //go back to where we were
return sz;
}
It's kind of silly that the standard C library doesn't have such a function, but I can see why it'd be difficult as not every "file" has a size(for instance /dev/null)
How to use lseek/fseek/stat/fstat to get filesize ?
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
void
fseek_filesize(const char *filename)
{
FILE *fp = NULL;
long off;
fp = fopen(filename, "r");
if (fp == NULL)
{
printf("failed to fopen %s\n", filename);
exit(EXIT_FAILURE);
}
if (fseek(fp, 0, SEEK_END) == -1)
{
printf("failed to fseek %s\n", filename);
exit(EXIT_FAILURE);
}
off = ftell(fp);
if (off == -1)
{
printf("failed to ftell %s\n", filename);
exit(EXIT_FAILURE);
}
printf("[*] fseek_filesize - file: %s, size: %ld\n", filename, off);
if (fclose(fp) != 0)
{
printf("failed to fclose %s\n", filename);
exit(EXIT_FAILURE);
}
}
void
fstat_filesize(const char *filename)
{
int fd;
struct stat statbuf;
fd = open(filename, O_RDONLY, S_IRUSR | S_IRGRP);
if (fd == -1)
{
printf("failed to open %s\n", filename);
exit(EXIT_FAILURE);
}
if (fstat(fd, &statbuf) == -1)
{
printf("failed to fstat %s\n", filename);
exit(EXIT_FAILURE);
}
printf("[*] fstat_filesize - file: %s, size: %lld\n", filename, statbuf.st_size);
if (close(fd) == -1)
{
printf("failed to fclose %s\n", filename);
exit(EXIT_FAILURE);
}
}
void
stat_filesize(const char *filename)
{
struct stat statbuf;
if (stat(filename, &statbuf) == -1)
{
printf("failed to stat %s\n", filename);
exit(EXIT_FAILURE);
}
printf("[*] stat_filesize - file: %s, size: %lld\n", filename, statbuf.st_size);
}
void
seek_filesize(const char *filename)
{
int fd;
off_t off;
if (filename == NULL)
{
printf("invalid filename\n");
exit(EXIT_FAILURE);
}
fd = open(filename, O_RDONLY, S_IRUSR | S_IRGRP);
if (fd == -1)
{
printf("failed to open %s\n", filename);
exit(EXIT_FAILURE);
}
off = lseek(fd, 0, SEEK_END);
if (off == -1)
{
printf("failed to lseek %s\n", filename);
exit(EXIT_FAILURE);
}
printf("[*] seek_filesize - file: %s, size: %lld\n", filename, (long long) off);
if (close(fd) == -1)
{
printf("failed to close %s\n", filename);
exit(EXIT_FAILURE);
}
}
int
main(int argc, const char *argv[])
{
int i;
if (argc < 2)
{
printf("%s <file1> <file2>...\n", argv[0]);
exit(0);
}
for(i = 1; i < argc; i++)
{
seek_filesize(argv[i]);
stat_filesize(argv[i]);
fstat_filesize(argv[i]);
fseek_filesize(argv[i]);
}
return 0;
}
Have you considered not computing the file size and just growing the array if necessary? Here's an example (with error checking ommitted):
#define CHUNK 1024
/* Read the contents of a file into a buffer. Return the size of the file
* and set buf to point to a buffer allocated with malloc that contains
* the file contents.
*/
int read_file(FILE *fp, char **buf)
{
int n, np;
char *b, *b2;
n = CHUNK;
np = n;
b = malloc(sizeof(char)*n);
while ((r = fread(b, sizeof(char), CHUNK, fp)) > 0) {
n += r;
if (np - n < CHUNK) {
np *= 2; // buffer is too small, the next read could overflow!
b2 = malloc(np*sizeof(char));
memcpy(b2, b, n * sizeof(char));
free(b);
b = b2;
}
}
*buf = b;
return n;
}
This has the advantage of working even for streams in which it is impossible to get the file size (like stdin).
If you're on Linux, seriously consider just using the g_file_get_contents function from glib. It handles all the code for loading a file, allocating memory, and handling errors.
#include <stdio.h>
#define MAXNUMBER 1024
int main()
{
int i;
char a[MAXNUMBER];
FILE *fp = popen("du -b /bin/bash", "r");
while((a[i++] = getc(fp))!= 9)
;
a[i] ='\0';
printf(" a is %s\n", a);
pclose(fp);
return 0;
}
HTH