1

I was playing with very simple encryption/decryption algorithm like this;

#include <stdio.h>
#include <stdlib.h>

#define BUFFESIZE 1024

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

    int keylen = 0;
    char *key = argv[1];
    char *buffer = NULL;
    size_t buffersize = 0;
    size_t nbytes = 0;
    size_t nread;
    int i = 0;
    while(*key++ != 0) keylen++;
    key = argv[1];

    do {
        buffersize+=BUFFESIZE;
        buffer = realloc(buffer, buffersize);
        nread = fread(buffer+nbytes, 1, BUFFESIZE, stdin);
        nbytes+=nread;
    } while (nread > 0);

    for(i=0; i<nbytes; i++) {
        putchar(buffer[i] ^ key[i % keylen]);
    }
    return 0;
}

Encyption key is the first command-line argument to the program. I expect that this should get me originial file when encrypted/decrypted with same key. However, I sometimes get only small amount of the file back if I encrypt/decrypt it. My guess is that algorithm adds EOF control character in the middle of file.

How can I get around this problem?

I compiled this using MinGW gcc 4.8.1 on windows XP. If you're interested, you can find a sample input file demonstrating the problem in the edit history of this question.

5
  • Your code works fine for me (on Linux / GCC). What OS and compiler are you using? Also, it would help if you could paste in a short example of a file and a key that demonstrate the problem. Commented Feb 28, 2015 at 12:04
  • 2
    In any case, you might want to try setting stdin and stdout to binary mode. Commented Feb 28, 2015 at 12:07
  • I'm guessing that the ciphertext has a 00 valued byte in it and that the rest isn't read. Commented Feb 28, 2015 at 12:41
  • @Maarten: Actually, nulls are not a problem for fread(). Apparently, however, on WIndows in text mode, the Ctrl-Z character (0x1A) is. Commented Mar 1, 2015 at 15:38
  • @IlmariKaronen Ugh, that's another entry in my Windows weirdness table inside my head. Growing and growing, hopefully I can put it into {any folder at all}/NUL someday. Commented Mar 1, 2015 at 15:44

1 Answer 1

2

Well, your code works for me on Linux (compiled with GCC 4.8.2), even using your sample input and key. This suggests that the issue is specific to Windows — most likely, that it's caused by stdin and stdout being in text mode by default. (On Linux and other Unix-ish systems, there's usually no difference between text mode and binary mode, so such issues do not show up there.)

To fix it, you will need to set stdin and stdout to binary mode. The standard way of doing this, as of C99, would be:

freopen(NULL, "rb", stdin);
freopen(NULL, "wb", stdout);

but alas, according to the answers in the thread I linked to above, the Windows C library does not support this C99 feature, so you'll need to fall back on the non-standard _setmode() instead:

_setmode(_fileno(stdin), _O_BINARY);
_setmode(_fileno(stdout), _O_BINARY);

If you want to remain portable, you could always use some conditional code, e.g. like this (warning: not actually tested on Windows!):

#if __STDC_VERSION__ >= 199901L
  #define binmode(fh, w) freopen(NULL, ((w) ? "wb" : "rb"), (fh)) /* C99 */
#elif _MSC_VER >= 1200
  #include <io.h>
  #include <fcntl.h>
  #define binmode(fh, w) _setmode(_fileno(fh), _O_BINARY) /* MSVC 6.0+ */
#elif defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
  #define binmode(fh, w) /* Unix-ish, just do nothing */
#else
  #error Not sure how to define binmode() on this platform
#endif

binmode(stdin, 0);
binmode(stdout, 1);

Or, of course, you could just sidestep the whole issue by opening your own input and output files (in binary mode) instead of using stdin and stdout.

Sign up to request clarification or add additional context in comments.

1 Comment

I opened my own input and output files. I thought it was a simpler solution. And it works too.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.