0

I am trying to implement the caesar cipher with mmap. I think the cipher works so fine but the problem is, the mmap. The idea of it is to update the file, if there was a change. So far it isn't working. I can just read the memory mapped file and print it. But if I make any modificaiton, I get a segmentation fault. Unfortunately, I couldn't solve the problem myself. So, I would appreciate it, if you could help me with it.

Here is the code.

int main (int argc, char *argv[]) {

    if(argc != 5)
       fprintf(stdeer, "usage: ./cipher (encrypt|decrypt) <file name> (casar| vigenere) <key>\n");

    // (encrypt / decrypt) can be found in argv[1]
    // filename in argv[2]
    // encryption method in argv[3]
    // key in argv[4]
    int fd = open(argv[2], O_RDWR, S_IWRITE | S_IREAD);
    if (fd < 0)
        hanle_error("open");

    off_t len = lseek(fd, 0, SEEK_END);
    if (len == (off_t)-1)
        handle_error("lseek");

    unsigned char* data = mmap(0, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); // Add PROT_WRITE
    if (data == MAP_FAILED)
        handle_error("mmap");

    char c = *argv[4];
    int key = 0;

    if(strcmp(argv[3], "caesar") == 0) {
        key = c - 48;
        if(strcmp(argv[1], "decrpyt") == 0)
            key = -key;
        int num = 0;
        for(int size_t i = 0; i < (size_t)len; i++) {
            if(data[i] >= 97 && data[i] <= 122) {
                num = data[i];
                num +=key;
                if(num > 'z') {
                    num -= 26;
                    data[i] = num + '0';
                } else if (num < 'a') {
                    num += 26;
                    data[i] = num + '0';
                } else {
                    data[i] = num + '0';
                }
            } else {
                continue;
            }
        }
    }

    return 0;
}

A possible input can be anything e.g.

SsWd asdas
qwmkfd aw.

The algorithm above should just modify the lower case letters and leave the rest as it is.

I hope someone might be able to help me.

Also, I only implemented the caesar cipher.

EDIT: The seg fault is gone after I added PROT_WRITE. But know I get weird question marks for the modified lower case letters. Does anyone know why?

  • 1
    What do you think that `PROT_READ` means?... – Oliver Charlesworth Jan 21 '14 at 21:14
  • @OliCharlesworth: Well, I must've forgotten. I don't know why, but thanks. But there is an other issue. Now, I get for the modified lower case letters weird question marks. Do you maybe know why? –  Jan 21 '14 at 21:21

1 Answers1

1

If you want to write to the file too, then

unsigned char* data = mmap(0, len, PROT_READ, MAP_SHARED, fd, 0);

should be

unsigned char* data = mmap(0, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

That may not be the only issue, but would explain the seg fault.

The reason is self explanatory!

abligh
  • 24,573
  • 4
  • 47
  • 84
  • Ok, I don't know, how I missed. Thanks for the reminder. But know I get for the modified lower case letters weird question marks. Do you know what it might be causing? –  Jan 21 '14 at 21:17
  • Reading your code, that would depend what the value of `key` is, i.e. what i in argv[4]. If your code isn't meant to do that, I'd guess you've implemented the caesar cipher wrongly. I would work through the code with a lower case character and whatever value you wrote as 'key' and see what it turns out as. However, this is no longer a 'memory mapped file' question - that part has been answered correctly I think! – abligh Jan 21 '14 at 21:23
  • @user2965601 Yes, I guess that is what abligh was trying to communicate. Please accept the answer if this has solved your (mapping) issue. – Maarten Bodewes Jan 29 '14 at 21:01