/*
* Copyright 2011 Steven Gribble
*
* This file is the solution to an exercise problem posed during
* one of the UW CSE 333 lectures (333exercises).
*
* 333exercises is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 333exercises is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with 333exercises. If not, see .
*/
// Lecture 6 exercise 2
//
// Write a program that:
// - loops forever; in each loop, it:
// - prompts the user to input a filename
// - reads from stdin to receive a filename
// - opens and reads the file, and prints its contents to stdout, in
// the format shown on the right
//
// Since we use readline() in this program, we need to link against
// libreadline.a. On linux, you can compile/link with this command:
//
// gcc -Wall -g -o exercise2 exercise2.c -lreadline
#include
#include
#include
#include
#include
#include
#include
void HexdumpFile(unsigned char *buffer, int len);
unsigned char *ReadFile(char *fname, int *retlen);
int main(int argc, char **argv) {
char *nextfilename;
// Loop and read the next filename.
while (1) {
unsigned char *fcontent;
int retlen;
nextfilename = readline("Enter a filename: ");
if (nextfilename == NULL)
break;
// Read in the file.
fcontent = ReadFile(nextfilename, &retlen);
if (fcontent == NULL) {
fprintf(stderr, "Couldn't read file '%s': ", nextfilename);
perror(NULL);
exit(EXIT_FAILURE);
}
// Dump the content to stdout.
HexdumpFile(fcontent, retlen);
free(fcontent);
free(nextfilename);
}
return EXIT_SUCCESS;
}
// Slurps the file into memory, or returns NULL.
#define READSIZE 1000
unsigned char *ReadFile(char *fname, int *retlen) {
unsigned char *buf = NULL;
FILE *f;
int readlen, count = 0;
// Open up the file.
f = fopen(fname, "rb");
if (f == NULL)
return NULL;
// Slurp in the file, READSIZE bytes at a time.
buf = (unsigned char *) realloc(buf, READSIZE);
assert(buf != NULL);
while ((readlen = fread(buf+count, 1, READSIZE, f)) > 0) {
count += readlen;
buf = (unsigned char *) realloc(buf, count + READSIZE);
assert(buf != NULL);
}
// Did we break because of an error?
if (ferror(f)) {
// Yes, so clean up and arrange to return NULL.
free(buf);
buf = NULL;
count = 0;
}
fclose(f);
*retlen = count;
return buf;
}
void HexdumpFile(unsigned char *buffer, int buflen) {
int count = 0;
int bytesleft = buflen;
// Loop in 16 byte chunks.
while (bytesleft > 0) {
int nextcount = (bytesleft >= 16) ? 16 : bytesleft;
int i;
// print the length prefix
fprintf(stdout, "%07x", count);
// print the content body
for (i = 0; i < nextcount; i++) {
fprintf(stdout, " %02x", buffer[count + i]);
}
fprintf(stdout, "\n");
count += nextcount;
bytesleft -= nextcount;
}
}