From 3aad46748a719d8b75ccc4bb024e6e39e1cc850c Mon Sep 17 00:00:00 2001 From: Isaac Shoebottom Date: Mon, 4 Dec 2023 18:39:21 -0400 Subject: [PATCH] Add an implementation, still just trying to read --- .../.idea/runConfigurations/Assignment9.xml | 7 + Assignment9/.idea/runConfigurations/Test1.xml | 7 + Assignment9/.idea/runConfigurations/Test2.xml | 7 + Assignment9/.idea/runConfigurations/Test3.xml | 7 + Assignment9/.idea/runConfigurations/Test4.xml | 7 + Assignment9/CMakeLists.txt | 4 +- .../documentation/EndiannessAndHomework9.c | 68 ++++++++ Assignment9/src/main.c | 38 ++++- Assignment9/src/png.c | 146 ++++++++++++++++++ Assignment9/src/png.h | 74 +++++++++ 10 files changed, 363 insertions(+), 2 deletions(-) create mode 100644 Assignment9/.idea/runConfigurations/Assignment9.xml create mode 100644 Assignment9/.idea/runConfigurations/Test1.xml create mode 100644 Assignment9/.idea/runConfigurations/Test2.xml create mode 100644 Assignment9/.idea/runConfigurations/Test3.xml create mode 100644 Assignment9/.idea/runConfigurations/Test4.xml create mode 100644 Assignment9/documentation/EndiannessAndHomework9.c create mode 100644 Assignment9/src/png.c create mode 100644 Assignment9/src/png.h diff --git a/Assignment9/.idea/runConfigurations/Assignment9.xml b/Assignment9/.idea/runConfigurations/Assignment9.xml new file mode 100644 index 0000000..2d993cf --- /dev/null +++ b/Assignment9/.idea/runConfigurations/Assignment9.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/Assignment9/.idea/runConfigurations/Test1.xml b/Assignment9/.idea/runConfigurations/Test1.xml new file mode 100644 index 0000000..4fc2a99 --- /dev/null +++ b/Assignment9/.idea/runConfigurations/Test1.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/Assignment9/.idea/runConfigurations/Test2.xml b/Assignment9/.idea/runConfigurations/Test2.xml new file mode 100644 index 0000000..3ccca8d --- /dev/null +++ b/Assignment9/.idea/runConfigurations/Test2.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/Assignment9/.idea/runConfigurations/Test3.xml b/Assignment9/.idea/runConfigurations/Test3.xml new file mode 100644 index 0000000..6f0a61c --- /dev/null +++ b/Assignment9/.idea/runConfigurations/Test3.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/Assignment9/.idea/runConfigurations/Test4.xml b/Assignment9/.idea/runConfigurations/Test4.xml new file mode 100644 index 0000000..e4a356b --- /dev/null +++ b/Assignment9/.idea/runConfigurations/Test4.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/Assignment9/CMakeLists.txt b/Assignment9/CMakeLists.txt index 163ccd2..ffc1a9a 100644 --- a/Assignment9/CMakeLists.txt +++ b/Assignment9/CMakeLists.txt @@ -1,4 +1,6 @@ cmake_minimum_required(VERSION 3.20) project(Assignment9 C) set(CMAKE_C_STANDARD 99) -add_executable(Assignment9 src/main.c) \ No newline at end of file +add_executable(Assignment9 src/main.c + src/png.c + src/png.h) \ No newline at end of file diff --git a/Assignment9/documentation/EndiannessAndHomework9.c b/Assignment9/documentation/EndiannessAndHomework9.c new file mode 100644 index 0000000..ae29c0d --- /dev/null +++ b/Assignment9/documentation/EndiannessAndHomework9.c @@ -0,0 +1,68 @@ +#include +#include +#include +// FILE format is: 'header', then 2023 skipped bytes, then the number of interest +#define OURINT 1426915328 +#define OFFSETTODATA 2023 + +int writeToFile(){ + + FILE* fp = fopen("toReadLater.txt","w+"); + char c = 'h'; + fwrite(&c, sizeof(char), 1, fp); + c = 'e'; + fwrite(&c, sizeof(char), 1, fp); + c = 'a'; + fwrite(&c, sizeof(char), 1, fp); + c = 'd'; + fwrite(&c, sizeof(char), 1, fp); + c = 'e'; + fwrite(&c, sizeof(char), 1, fp); + c = 'r'; + fwrite(&c, sizeof(char), 1, fp); + unsigned int buf = OFFSETTODATA; + fwrite(&buf, sizeof(int), 1, fp); + fseek(fp, OFFSETTODATA, SEEK_CUR); + + buf = OURINT; + fwrite(&buf, sizeof(int), 1, fp); + fclose(fp); +} + +int readFromFile(){ + FILE *fp = fopen("toReadLater.txt", "r+"); + fseek(fp, 6 , SEEK_SET); + int skip = 0; + fread(&skip, sizeof(int), 1, fp); + // NOTE, in HW, the size of the section is a value in + // Big-Endian format, it will actually need conversion + fseek(fp, skip, SEEK_CUR); + unsigned int qBe = 0; + unsigned int qLe = 0; + int i; + unsigned char *c = (char *)(&qBe); + unsigned char *d = (char *)(&qLe); + for (i = 0; i < 4; i++) + { + c[i] = getc(fp); + printf("Byte %i: %i %x\n",i, c[i], c[i]); + } + + for (i = 0; i < 4; i++) + { + d[4-i-1] = c[i]; + } + + printf("Translated using swapping the bytes order: %i\n", qLe); + qLe = ntohl(qBe); + printf("Translated using ntohl: %i\n", qLe); + fclose(fp); +} +int main (int argc, char** argv){ + unsigned int wantToRead; + writeToFile(); + printf("Sizeof (int) is:%li\n", sizeof(unsigned int)); + readFromFile(); + + return 0; +} \ No newline at end of file diff --git a/Assignment9/src/main.c b/Assignment9/src/main.c index d65e213..bd1ed8a 100644 --- a/Assignment9/src/main.c +++ b/Assignment9/src/main.c @@ -1,3 +1,39 @@ +#include +#include +#include +#include +#include +#include "png.h" + int main(int argc, char *argv[]) { - return 0; + if (argc != 2) { + printf("Usage: %s \n", argv[0]); + exit(1); + } + if (strlen(argv[1]) > PATH_MAX) { + printf("Path too long\n"); + exit(1); + } + char *path = argv[1]; + + char* png_buffer = load_file(get_fd(path)); + if (!is_png(png_buffer)) { + printf("It's not a PNG file\n"); + exit(1); + } else { + printf("It's a PNG file\n"); + } + png_chunk **chunks = get_png_chunks(png_buffer); + int size = get_number_of_chunks(chunks); + for (int i = 0; i < size; i++) { + // Check if header is IDAT or IEND + bool is_idat = memcmp(chunks[i]->type, "IDAT", 4) == 0; + bool is_iend = memcmp(chunks[i]->type, "IEND", 4) == 0; + if (is_idat || is_iend) { + printf("Found %s chunk\n", chunks[i]->type); + } else { + printf("Found unknown: %s\n", chunks[i]->type); + } + printf("Chunk size is:%d\n", chunks[i]->length); + } } \ No newline at end of file diff --git a/Assignment9/src/png.c b/Assignment9/src/png.c new file mode 100644 index 0000000..ebb4eaa --- /dev/null +++ b/Assignment9/src/png.c @@ -0,0 +1,146 @@ +/* + * Copyright Notice + * ---------------- + * Copyright © 1998, 1999 by: Glenn Randers-Pehrson + * This specification is a modification of the PNG 1.0 specification. It is being + * provided by the copyright holder under the provisions of the 1996 MIT copyright and license: + * Copyright © 1996 by: Massachusetts Institute of Technology (MIT) + * This W3C specification is being provided by the copyright holders under + * the following license. By obtaining, using and/or copying this specification, you + * agree that you have read, understood, and will comply with the following terms + * and conditions: + * Permission to use, copy, and distribute this specification for any purpose + * and without fee or royalty is hereby granted, provided that the full text of + * this NOTICE appears on ALL copies of the specification or portions thereof, + * including modifications, that you make. + * THIS SPECIFICATION IS PROVIDED ”AS IS,” AND COPYRIGHT HOLD-ERS + * MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR + * IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, COPYRIGHT + * HOLDERS MAKE NO REPRESENTATIONS OR WARRANTIES OF MER-CHANTABILITY + * OR FITNESS FOR ANY PARTICULAR PURPOSE OR + * THAT THE USE OF THE SPECIFICATION WILL NOT INFRINGE ANY + * THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER + * RIGHTS. COPYRIGHT HOLDERS WILL BEAR NO LIABILITY FOR ANY + * USE OF THIS SPECIFICATION. + * The name and trademarks of copyright holders may NOT be used in + * ad-vertising or publicity pertaining to the specification without specific, written + * prior permission. Title to copyright in this specification and any associated + * documentation will at all times remain with copyright holders. + */ + +#include +#include +#include +#include +#include +#include "png.h" + +int get_fd(char *path) { + FILE *fp = fopen(path, "rb"); + if (fp == NULL) { + perror("fopen"); + exit(1); + } + int fd = fileno(fp); + if (fd == -1) { + perror("fileno"); + exit(1); + } + return fd; +} + +FILE *get_fp(int fd) { + FILE *fp = fdopen(fd, "rb"); + if (fp == NULL) { + perror("fdopen"); + exit(1); + } + return fp; +} + +char *load_file(int fd) { + FILE *fp = get_fp(fd); + fseek(fp, 0, SEEK_END); + long size = ftell(fp); + rewind(fp); + char *buffer = malloc(size); + if (buffer == NULL) { + perror("malloc"); + exit(1); + } + fread(buffer, 1, size, fp); + // Iterate over buffer and convert from network byte order to host byte order + //for (int i = 0; i < size; i += 4) { + // uint32_t *ptr = (uint32_t *)(buffer + i); + // *ptr = ntohl(*ptr); + //} + fclose(fp); + return buffer; +} + +int is_png(char *buffer) { + return memcmp(buffer, PNG_SIGNATURE, PNG_SIGNATURE_SIZE) == 0; +} + +png_chunk *get_png_chunk(char *buffer, int offset) { + png_chunk *chunk = malloc(sizeof(png_chunk)); + if (chunk == NULL) { + perror("malloc"); + exit(1); + } + memcpy(&chunk->length, buffer + offset + 0, 4); + chunk->length = ntohl(chunk->length); + memcpy(&chunk->type, buffer + offset + 4, 4); + chunk->data = malloc(chunk->length); + if (chunk->data == NULL) { + perror("malloc"); + exit(1); + } + memcpy(chunk->data, buffer + offset + 8, chunk->length); + memcpy(&chunk->crc, buffer + offset + 8 + chunk->length, 4); + return chunk; +} + +png_chunk **get_png_chunks(char *buffer) { + png_chunk **chunks = malloc(sizeof(png_chunk *)); + if (chunks == NULL) { + perror("malloc"); + exit(1); + } + int offset = PNG_SIGNATURE_SIZE; + int i = 0; + while (1) { + chunks[i] = get_png_chunk(buffer, offset); + offset += chunks[i]->length; + if (memcmp(chunks[i]->type, "IEND", 4) == 0) { + break; + } + i++; + chunks = realloc(chunks, sizeof(png_chunk *) * (i + 1)); + if (chunks == NULL) { + perror("realloc"); + exit(1); + } + } + return chunks; +} + +int is_chunk_valid(png_chunk *chunk) { + uint32_t crc = htonl(chunk->crc); + //uint32_t calculated_crc = crc32(0, chunk->type, 4); + //calculated_crc = crc32(calculated_crc, chunk->data, chunk->length); + //return crc == calculated_crc; + return 1; +} + +int is_chunk_critical(png_chunk *chunk) { + return chunk->type[0] >= 'A' && chunk->type[0] <= 'Z'; +} + +int get_number_of_chunks(png_chunk **chunks) { + int i = 0; + while (chunks[i] != NULL) { + i++; + } + return i; +} diff --git a/Assignment9/src/png.h b/Assignment9/src/png.h new file mode 100644 index 0000000..4a68df5 --- /dev/null +++ b/Assignment9/src/png.h @@ -0,0 +1,74 @@ +/* + * Copyright Notice + * ---------------- + * Copyright © 1998, 1999 by: Glenn Randers-Pehrson + * This specification is a modification of the PNG 1.0 specification. It is being + * provided by the copyright holder under the provisions of the 1996 MIT copyright and license: + * Copyright © 1996 by: Massachusetts Institute of Technology (MIT) + * This W3C specification is being provided by the copyright holders under + * the following license. By obtaining, using and/or copying this specification, you + * agree that you have read, understood, and will comply with the following terms + * and conditions: + * Permission to use, copy, and distribute this specification for any purpose + * and without fee or royalty is hereby granted, provided that the full text of + * this NOTICE appears on ALL copies of the specification or portions thereof, + * including modifications, that you make. + * THIS SPECIFICATION IS PROVIDED ”AS IS,” AND COPYRIGHT HOLD-ERS + * MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR + * IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, COPYRIGHT + * HOLDERS MAKE NO REPRESENTATIONS OR WARRANTIES OF MER-CHANTABILITY + * OR FITNESS FOR ANY PARTICULAR PURPOSE OR + * THAT THE USE OF THE SPECIFICATION WILL NOT INFRINGE ANY + * THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER + * RIGHTS. COPYRIGHT HOLDERS WILL BEAR NO LIABILITY FOR ANY + * USE OF THIS SPECIFICATION. + * The name and trademarks of copyright holders may NOT be used in + * ad-vertising or publicity pertaining to the specification without specific, written + * prior permission. Title to copyright in this specification and any associated + * documentation will at all times remain with copyright holders. + */ + +#pragma once + +#include +#include +#include +#include +#include + +// http://www.libpng.org/pub/png/spec/1.2/PNG-Rationale.html#R.PNG-file-signature +#define PNG_SIGNATURE "\211PNG\r\n\032\n" +#define PNG_SIGNATURE_SIZE 8 +typedef struct png_chunk { + uint32_t length; + char type[4]; + char *data; + uint32_t crc; +} png_chunk; + +// Get file descriptor from path +int get_fd(char *path); + +// Get FILE* from file descriptor +FILE *get_fp(int fd); + +// Store file in heap memory +char *load_file(int fd); + +// Check if file is a PNG +int is_png(char *buffer); + +// Get PNG chunk +png_chunk *get_png_chunk(char *buffer, int offset); + +// Get all PNG chunks +png_chunk **get_png_chunks(char *buffer); + +// Get number of chunks +int get_number_of_chunks(png_chunk **chunks); + +// Check if chunk is critical +int is_chunk_critical(png_chunk *chunk); + +// Is chunk valid? +int is_chunk_valid(png_chunk *chunk); \ No newline at end of file