3therk1ll
3therk1ll

Reputation: 2421

Read n bytes from file and get integer value

I'm working on a coding challenge where I have to read n bytes from an encoded file and perform some operations with them. I am trying to get the integer value of the bytes to use as a seed for srand().

I'm not sure I'm doing this properly. I am passing in 4 and file pointer to read_n_bytes() in which I am reading 4 bytes from the file and writing them to a location in memory set aside with malloc(). Then returning the malloc() address as a char pointer as seed and attempting to access the bytes with &seed.

The rest of my operation isn't working here.

Am I going about this the right way?

char* seed;

int main() {
    FILE * fp;

    fp = fopen("flag.enc", "rb");

    // extract seed from flag
    seed = read_n_bytes(4, fp);

    srand(&seed);
}

char* read_n_bytes(int b, FILE * fp) {
    char * buffer;
    buffer = malloc(b);
    fread(buffer, 1, b, fp);
    return buffer;
}

Upvotes: 0

Views: 278

Answers (2)

Fe2O3
Fe2O3

Reputation: 8344

Below, I presume that the exercise involves a lot of integer values in the file, and the int values returned from calls to rand(). (Else, why worry about seeding with a constant value loaded from a file???)

Use main() to "set up" and "tear down" the information you will work with. "Contain" the exercise to a separate function.

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

// A function defined (before use) is a function declared!
exercise( int arr[], size_t nElem ) {
    // whatever is the rest of the challenge
    // arr[0] is first int (seed is not included )
    // work with arr[0] to arr[ nElem - 1 ]
}

int main() {
    char *fname = "flag.enc"; // prominent and re-usable

    // attempt to open to read (binary mode)
    FILE *fp = fopen( fname, "rb" );
    if( fp == NULL ) {
        fprintf( stderr, "Cannot open '%s'\n", fname ); // see?
        exit( EXIT_FAILURE );
    }

    // measure the file (presuming reasonable size)
    fseek( fp, 0, SEEK_END ); 
    size_t fsize = ftell( fp );
    fseek( fp, 0, SEEK_SET ); // rewind

    /* Make BIG presumption that the data in the file is all integers */
    /* 'seed' is unsigned, but 'rand()' will return signed integers */
    size_t nInts = fsize / sizeof( int );

    int *buf = malloc( nInts * sizeof *buf );
    if( buf == NULL ) {
        fprintf( stderr, "malloc failed. wanted %zu bytes\n", fsize );
        fclose( fp );
        exit( EXIT_FAILURE );
    }

    size_t nread = fread( buf, sizeof *buf, nInts, fp );
    fclose(fp); // no longer needed

    if( nread != nInts ) {
        fprintf( stderr, "read %zu ints, not %zu (full file)\n", nread, nInts );
        exit( EXIT_FAILURE );
    }

    srand( (unsigned int)buf[0] );

    exercise( buf + 1, nInts - 1 ); // work with data that is loaded

    free( buf );

    return 0;
}

Upvotes: 1

Remy Lebeau
Remy Lebeau

Reputation: 595377

srand() wants an integer, not a char** pointer that you are trying to give it. You would have to typecast and dereference the pointer to access the integer value, eg:

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

char* read_n_bytes(size_t b, FILE *fp);

int main() {
    FILE *fp = fopen("flag.enc", "rb");
    if (fp == NULL) {
        // error handling...
    }

    // extract seed from flag
    uint32_t *seed = (uint32_t*) read_n_bytes(sizeof(uint32_t), fp);
    if (seed == NULL) {
        // error handling...
    }

    srand(*seed);

    free(seed);
    fclose(fp);
}

char* read_n_bytes(size_t b, FILE *fp) {
    char *buffer = malloc(b);
    if (buffer) {
        if (fread(buffer, b, 1, fp) != 1) {
            free(buffer);
            buffer = NULL;
        }
    }
    return buffer;
}

Alternatively, get rid of malloc() and let fread() read directly into an integer variable, eg:

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

int read_n_bytes(void *buf, size_t b, FILE *fp);

int main() {
    FILE *fp = fopen("flag.enc", "rb");
    if (fp == NULL) {
        // error handling...
    }

    // extract seed from flag
    uint32_t seed;
    if (read_n_bytes(&seed, sizeof(seed), fp) < 0) {
        // error handling...
    }

    srand(seed);

    fclose(fp);
}

int read_n_bytes(void *buf, size_t b, FILE *fp) {
    return (fread(buf, b, 1, fp) != 1) ? -1 : 0;
}

Upvotes: 1

Related Questions