5

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;
}
mydreamadsl
  • 568
  • 4
  • 16
  • 25

2 Answers2

5

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+.

Mike Nakis
  • 56,297
  • 11
  • 110
  • 142
  • so lseek(source,-1,SEEK_END)? – mydreamadsl Jan 03 '12 at 17:30
  • 1
    Then you should care about buffering. Why don't you handle your file several kilobytes at a time? – Basile Starynkevitch Jan 03 '12 at 17:33
  • 1
    lseek(source,-1,SEEK_END) is in the right direction, but that will not work, either. You should use lseek(source,n,SEEK_END), inside a for loop, where n varies starting from -1, while <= -file_size. – Mike Nakis Jan 03 '12 at 17:34
  • yes i can use buf[100] at time, but i want to understand hot lseek works. I would be glad if you could assist me. So I have 3 file descriptors source, dest and buf, reading source, putting read position to the end but what to write in while loop? – mydreamadsl Jan 03 '12 at 17:35
  • 2
    @BasileStarynkevitch let him get it to work correctly the slow-as-molasses way, and then he may worry about making it more efficient. "Premature optimization is the root of all evil". – Mike Nakis Jan 03 '12 at 17:36
  • 1
    You put the read position where it needs to be, read one byte, and write it to the output file, then move the read position back by 1, and repeat. Until the beginning of the source file. – Mike Nakis Jan 03 '12 at 17:36
  • so, is this line correct ? while ((n=read(source,&buf,1))!=0) how can i loop lseek and increment counter? – mydreamadsl Jan 03 '12 at 17:40
  • Nope, you should actually assert that you always read 1 byte. For as long as you are reading within the file, reading 1 byte should always succeed. – Mike Nakis Jan 03 '12 at 17:42
  • 1
    for( int i = 0; i < file_size; i++ ) { lseek(source,file_size - 1 - i,SEEK_END); ... } – Mike Nakis Jan 03 '12 at 17:43
  • file_size should be initialized to -1? – mydreamadsl Jan 03 '12 at 17:45
  • 1
    No, you need to somehow find the file size. Look at the functions available in fcntl for a function which returns the file size. Hint: lseek can be used to find the file size. – Mike Nakis Jan 03 '12 at 17:47
  • StackOverflow is the place for everything: http://stackoverflow.com/questions/8236/how-do-you-determine-the-size-of-a-file-in-c – Mike Nakis Jan 03 '12 at 17:55
  • Actually, forget that q&a that I pointed you to. Just use lseek to calculate the length of the file, since you are already using int file handles. – Mike Nakis Jan 03 '12 at 17:59
  • @MikeNakis By popular words, "Nevermind that the O(x) is actually [a] pretty large O." :) – jørgensen Jan 03 '12 at 19:11
  • MikeNakis, can you edit your answer and add my recent code to your answer, so we can accept it and rate you (:. I will remove mine Thanks for help – mydreamadsl Jan 03 '12 at 19:25
0

lseek(source, (off_t) i, SEEK_SET); should probably be lseek(source, (off_t) i - 1, SEEK_SET);