CS50 Recover runs and recovers all files except the first one - cs50

My question is regarding the Recover assignment as part of CS50.
The code is running (finally) and it produces 50 JPEG files, and most of them are the correct images, except the first file is not an image, therefore it doesn't pass check50.
I have spent a long time trying to figure out what the problem is but I cannot pinpoint it so I am hoping someone might be able to help me out so I can move on.
Thanks in advance! Here is my code:
int main(int argc, char *argv[])
{
// ensure proper usage
if (argc != 2)
{
fprintf(stderr, "Usage: Name of Memory Card File\n");
return 1;
}
char *readfile = argv[1];
// open memory card file
FILE *card_ptr = fopen(readfile, "r");
if (card_ptr == NULL)
{
fprintf(stderr, "Could not open %s.\n", readfile);
return 2;
}
//Declare a buffer to read into
unsigned char *buffer = malloc(512);
//to check if we have already found a file
bool (jpgAlreadyNew) = false;
//declare counter for the number of files found and a file pointer
int filenumber = 0;
FILE *new_jpg_ptr = NULL;
char filename[8];
//read in bytes until reach EOF
while (fread(buffer, 1, 512, card_ptr) != 0x00)
{
//if we reach the header pattern of bytes
if (buffer [0] == 0xff && buffer [1] == 0xd8 && buffer [2] == 0xff && (buffer [3] & 0xf0) == 0xe0)
{
//if there is not already a JPEG file found
if (!jpgAlreadyNew)
{
//change the bool value
(jpgAlreadyNew) = true;
//open new file
sprintf(filename, "%03i.jpg", filenumber);
new_jpg_ptr = fopen(filename, "w");
if (new_jpg_ptr == NULL)
{
return 3;
}
//add to counter of files found
filenumber++;
//write files from buffer into new img file
fwrite(buffer, 1, 512, new_jpg_ptr);
}
//if there is already a JPEG file found
if (jpgAlreadyNew)
{
//close the previous file which would now be complete
fclose(new_jpg_ptr);
//open new file
sprintf(filename, "%03i.jpg", filenumber);
new_jpg_ptr = fopen(filename, "w");
if (new_jpg_ptr == NULL)
{
return 4;
}
//add to counter of files found
filenumber++;
//write files from buffer into new img file
fwrite(buffer, 1, 512, new_jpg_ptr);
}
}
// else if we do not see pattern of header bytes
else
{
//if already found a jpg file which is open then write the bytes to that file
if (jpgAlreadyNew)
{
fwrite(buffer, 1, 512, new_jpg_ptr);
}
//if no file found yet, discard and move on
if (!jpgAlreadyNew)
{
continue;
}
}
}
//free memory
free (buffer);
//close pointers and end program successfully
fclose(card_ptr);
fclose(new_jpg_ptr);
return 0;
}

Let's walk through the program starting with finding the first jpeg signature:
This if (!jpgAlreadyNew) evaluates to true, so it enters the if block; the first thing it does is (jpgAlreadyNew) = true;. When it is done creating the file and writing the first block, what happens next? This if (jpgAlreadyNew). Which also evaluates to true. So it closes 000.jpg and moves along.
Since jpgAlreadyNew is a boolean, an if {} else {} construct would suffice.

Related

RECOVER Pset_4 CS50 - Images recovered are incomplete

So I'm doing the CS50 pset4 recover task (where you need to search for jpg files on a memory card and whenever you find one- you open a new file and write the jpg found to the new file). I have written the code in a slightly different manner then what is told in the course but I think(hope) my logic is right. I am able to recover all 50 images but the images are incomplete and distorted. Also for some reason the 050th image is not opening. Here is my code
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
typedef uint8_t BYTE; //defining a byte = 8 bits or 8 0's or 1's
int main(int argc, char *argv[]) {
//assigning variables
int BLOCK_SIZE = 512;
BYTE buffer[BLOCK_SIZE];
int i = 0;
char* nf = malloc(sizeof(int)*3);
//checking to see a file name is given
if (argc != 2)
{
printf("Usage: ./recover IMAGE\n");
return 1;
}
//opening said file
FILE *rfile = fopen(argv[1], "r");
if(rfile == NULL)
{
printf("File '%s' does not exist\n", argv[1]);
return 1;
}
//opening a copy
FILE *c = fopen(argv[1], "r");
if(c == NULL)
{
printf("File '%s' does not exist\n", argv[1]);
return 1;
}
//checking 512 bytes again and again for orginal
while (fread (buffer, 1, BLOCK_SIZE, rfile) == BLOCK_SIZE)
{
fseek(c, ftell(rfile) , SEEK_SET); //fread (buffer, 1, BLOCK_SIZE, c);
sprintf(nf, "%03i.jpg", i); //000, 001, 002
//opening a file to write in
FILE *img = fopen(nf, "w");
if(img == NULL)
{
return 1;
}
//Is it a jpeg!?
if (buffer[0]==0xff && buffer[1]==0xd8 && buffer[2]==0xff && (buffer[3] & 0xf0) == 0xe0)
{
//writing the img in a file called img
fwrite(buffer, 512, 1, img);
fwrite(c, BLOCK_SIZE, 2048, img);
i++; //making sure a new file is opened next time
}
fclose(img);
}
fclose(c);
fclose(rfile);
free(nf); }

Recover Jpeg files from raw data

I need to recover jpeg files from a memory card (raw data). I have done the code below but I am getting a seg fault which i cannot identify the source. Just to summarize, I´ve done a loop to read 512bytes chunks and look for specific jpeg header. If it is the first jpeg, the programa will open a file and keep writing to it. If jpeg is not the first, close previous image and keep writing to it.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
int main(int argc, char *argv[])
{
// Check usage
if (argc != 2)
{
printf("Usage: ./recover image\n");
return 1;
}
// Open file
FILE *file = fopen(argv[1], "r");
if (!file)
{
fprintf(stderr, "Could not open %s.\n", argv[1]);
return 1;
}
// open array to store the chunks with enough memory
unsigned char buffer [512];
// variables jpeg count
int img_count = 0;
// open filename img to write to
char filename[8];
FILE *img = NULL;
// create loop to read 512 chunks
while (fread(buffer, 512, 1, file) > 0)
{
if (buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3] & 0xf0) == 0xe0)
{
// if theres already a jpeg open
if (img_count > 0)
{
fclose(img);
sprintf(filename, "%i03.jpg", img_count);
img = fopen(filename, "w");
img_count++;
} // first jpeg img count == 0
else if (img_count == 0)
{
sprintf(filename, "%i03.jpg", img_count);
img = fopen(filename, "w");
img_count++;
}
}
//if this is not a new jpeg header, just write to img
if (img_count > 0)
{
fwrite(buffer, 512, 1, img);
}
else
{
continue;
}
}
fclose(img);
fclose(file);
return 0;
}
Found it...typo i had "%i03.jpg" instead of %03i.jpg"

C - Writing multi-lined txt in memory

I'm working in PUTTY, using C. I have a .txt file with the data of multiple users. For example, a line looks like: "SSNumber, Name, PhoneNumber, Class, Age(...)". There's only one line per user. I want to write it in a shared memory location with malloc. But I'll have to change one of the fields later on. How can I do this? Do I need to read it line by line, anyway? It's very confusing.
Thanks!
Is this enough?
if (fp != NULL) {
/* Vai ao fim do ficheiro. */
if (fseek(fp, 0L, SEEK_END) == 0) {
long bufsize = ftell(fp);
if (bufsize == -1) { /* Error */ }
source = malloc(sizeof(char) * (bufsize + 1));
if (fseek(fp, 0L, SEEK_SET) == 0) { /* Error */ }
size_t newLen = fread(source, sizeof(char), bufsize, fp);
if (newLen == 0) {
fputs("Error reading file", stderr);
} else {
source[++newLen] = '\0'; /* Just to be safe. */
}
}
fclose(fp);
}

FFMPEG - How to save audio stream detached from video to file whithout transcoding

I try to use fwrite() to save audio stream. But, generated file can not be opened.
At the same time, I also try to use av_frame_write() to write packet. But, it can not write.
Please help me with this problem. How to write audio stream without transcoding....
/* open the input file with generic avformat function */
err = avformat_open_input(input_format_context, filename, NULL, NULL);
if (err < 0) {
return err;
}
/* If not enough info to get the stream parameters, we decode the
first frames to get it. (used in mpeg case for example) */
ret = avformat_find_stream_info(*input_format_context, 0);
if (ret < 0) {
av_log(NULL, AV_LOG_FATAL, "%s: could not find codec parameters\n", filename);
return ret;
}
/* dump the file content */
av_dump_format(*input_format_context, 0, filename, 0);
for (size_t i = 0; i < (*input_format_context)->nb_streams; i++) {
AVStream *st = (*input_format_context)->streams[i];
if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
FILE *file = NULL;
file = fopen("C:\\Users\\MyPC\\Downloads\\test.aac", "wb");
AVPacket reading_packet;
av_init_packet(&reading_packet);
while (av_read_frame(*input_format_context, &reading_packet) == 0) {
if (reading_packet.stream_index == (int) i) {
fwrite(reading_packet.data, 1, reading_packet.size, file);
}
av_free_packet(&reading_packet);
}
fclose(file);
return 0;
}
}
aac file require that frames have ADTS headers. If the file you are reading from does not use use ADTS frames (mp4 for example) you will need to manually create these headers, or use a bitstream filter. Also your code does not check to see if the codec is AAC.

AssetManager and native code

I have a config.txt file. The file is not compressed during the apk build using the nocompress extension="txt" option. Then I'm openning in my java code asset manager and passing it to the native function. Finally I'm opening a File* using the below code.
The problem is that when calling fgets(line, 32, file) - where line is char * - the content of line is not what is the first line of the file.
AAssetManager* mgr = AAssetManager_fromJava(env, assetManager);
if(NULL == mgr) return -1;
AAsset* asset = AAssetManager_open(mgr, "config.txt", AASSET_MODE_UNKNOWN);
if (NULL == asset) {
return -1;
}
off_t start, length;
int fd = AAsset_openFileDescriptor(asset, &start, &length);
if (fd < 0)
return -1;
FILE * file = fdopen(fd, "r");
As you can see in https://code.google.com/p/java-ide-droid/source/browse/trunk/jni/aapt/jni/Package.cpp (search for "static const char* kNoCompressExt" ) txt is not in the exclude list and may be compressed!
Actually this should lead to fd beeing smaller than zero.

Resources