From 2324f0bee4376eb05d576aea0ee99ad8dd0d9763 Mon Sep 17 00:00:00 2001 From: David Stancu Date: Sat, 10 Mar 2018 21:47:33 -0500 Subject: [PATCH 01/18] start laying out structs & some initial api --- Src/File_AppleSingle.h | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 Src/File_AppleSingle.h diff --git a/Src/File_AppleSingle.h b/Src/File_AppleSingle.h new file mode 100644 index 0000000..80eb3f8 --- /dev/null +++ b/Src/File_AppleSingle.h @@ -0,0 +1,22 @@ +/** + * AppleSingle file format support + * + * Author: David Stancu, @mach-kernel, Mar. 2018 + * + */ + +typedef struct as_file_header { + DWORD magic; + DWORD version; + int filler[4]; + WORD num_entries; +} + +typedef struct as_file_entry { + DWORD entry_id; + DWORD offset; + DWORD length; +} + +struct as_file_entry **GetEntries(unsigned char *buf); +unsigned char *GetDataSegment(unsigned char *buf); \ No newline at end of file From 3514855b79a5d2b10d6a2b7af30b0d66272dedfb Mon Sep 17 00:00:00 2001 From: David Stancu Date: Sun, 11 Mar 2018 16:53:54 -0400 Subject: [PATCH 02/18] wip entry types / found place to hook for file reads need to hook file writes then write tape --- Src/Dc_Shared.c | 4 +++- Src/File_AppleSingle.c | 38 ++++++++++++++++++++++++++++++++++++ Src/File_AppleSingle.h | 44 +++++++++++++++++++++++++++++++++++++----- Src/Prodos_Add.c | 19 ++++++++++++++---- 4 files changed, 95 insertions(+), 10 deletions(-) create mode 100644 Src/File_AppleSingle.c diff --git a/Src/Dc_Shared.c b/Src/Dc_Shared.c index 6cad307..5de8e9c 100644 --- a/Src/Dc_Shared.c +++ b/Src/Dc_Shared.c @@ -12,8 +12,9 @@ #include #include "Dc_Shared.h" -#include "os/os.h" #include "Dc_Memory.h" +#include "File_AppleSingle.h" +#include "os/os.h" #ifdef IS_WINDOWS #include @@ -64,6 +65,7 @@ unsigned char *LoadBinaryFile(char *file_path, int *data_length_rtn) /* Renvoi les données et la taille */ *data_length_rtn = nb_read; + return(data); } diff --git a/Src/File_AppleSingle.c b/Src/File_AppleSingle.c new file mode 100644 index 0000000..7257ea3 --- /dev/null +++ b/Src/File_AppleSingle.c @@ -0,0 +1,38 @@ +#include "File_AppleSingle.h" + +const unsigned char AS_MAGIC[] = {0x00, 0x05, 0x16, 0x00}; + +/** + * Is this an AppleSingle file? + * @brief IsAppleSingle + * @param buf + * @return + */ +bool IsAppleSingle(unsigned char *buf) +{ + return memcmp(&buf, &AS_MAGIC, sizeof(AS_MAGIC)); +} + +/** + * Read headers and return a list of as_file_entry pointers + * @brief GetEntries + * @param buf + * @return + */ +struct as_file_entry **GetEntries(unsigned char *buf) +{ + struct as_file_entry **entries = malloc(4 * sizeof(as_file_entry *)); + return entries; +} + +/** + * Parse AppleSingle header and write attributes into prodos_file + * struct + * @brief DecorateProdosFile + * @param current_file + * @param data + */ +void DecorateProdosFile(struct prodos_file *current_file, unsigned char *data) +{ + return; +} diff --git a/Src/File_AppleSingle.h b/Src/File_AppleSingle.h index 80eb3f8..5f73d97 100644 --- a/Src/File_AppleSingle.h +++ b/Src/File_AppleSingle.h @@ -1,22 +1,56 @@ /** * AppleSingle file format support + * RFC 1740: https://tools.ietf.org/html/rfc1740 * * Author: David Stancu, @mach-kernel, Mar. 2018 * */ -typedef struct as_file_header { +#pragma once + +#include +#include +#include +#include + +#include "Dc_Shared.h" +#include "Dc_Prodos.h" + +typedef struct as_file_header +{ DWORD magic; DWORD version; int filler[4]; WORD num_entries; -} +} as_file_header; -typedef struct as_file_entry { +typedef struct as_file_entry +{ DWORD entry_id; DWORD offset; DWORD length; -} +} as_file_entry; + +typedef enum as_entry_types +{ + data_fork = 1, + resource_fork = 2, + real_name = 3, + comment = 4, + icon_bw = 5, + icon_color = 6, + file_dates_info = 8, + finder_info = 9, + mac_file_info = 10, + prodos_file_info = 11, + msdos_file_info = 12, + short_name = 13, + afp_file_info = 14, + directory_id = 15 +} as_entry_types; + +const unsigned char AS_MAGIC[4]; struct as_file_entry **GetEntries(unsigned char *buf); -unsigned char *GetDataSegment(unsigned char *buf); \ No newline at end of file +unsigned char *GetDataSegment(unsigned char *buf); +void DecorateProdosFile(struct prodos_file *current_file, unsigned char *data); diff --git a/Src/Prodos_Add.c b/Src/Prodos_Add.c index 5f6e370..a82ecfb 100644 --- a/Src/Prodos_Add.c +++ b/Src/Prodos_Add.c @@ -18,12 +18,13 @@ #include #include +#include "os/os.h" #include "Dc_Shared.h" #include "Dc_Memory.h" #include "Dc_Prodos.h" -#include "os/os.h" #include "Prodos_Create.h" #include "Prodos_Add.h" +#include "File_AppleSingle.h" static struct prodos_file *LoadFile(char *); static int GetFileInformation(char *,char *,struct prodos_file *); @@ -347,9 +348,19 @@ static struct prodos_file *LoadFile(char *file_path_data) current_file->file_name[i] = toupper(current_file->file_name[i]); /* Proper Case */ current_file->name_case = BuildProdosCase(current_file->file_name_case); - - /*** Chargement des Data ***/ - current_file->data = LoadBinaryFile(file_path_data,¤t_file->data_length); + + // Load data. If an AppleSingle file, parse it. + unsigned char *data = LoadBinaryFile(file_path_data, ¤t_file->data_length); + if (IsAppleSingle(data)) + { + printf(" AppleSingle format detected!"); + DecorateProdosFile(current_file, data); + } + else + { + current_file->data = data; + } + if(current_file->data != NULL && current_file->data_length == 0) { free(current_file->data); From 28b6fb8a36d95c9bb63fc74ab584c851d658e337 Mon Sep 17 00:00:00 2001 From: David Stancu Date: Mon, 12 Mar 2018 20:47:27 -0400 Subject: [PATCH 03/18] make typedefs safer instead of using int and long, LOL ALSO GOT ENDIAND --- Src/Dc_Shared.h | 8 ++++--- Src/File_AppleSingle.c | 48 ++++++++++++++++++++++++++++++++++++++++-- Src/File_AppleSingle.h | 3 ++- 3 files changed, 53 insertions(+), 6 deletions(-) diff --git a/Src/Dc_Shared.h b/Src/Dc_Shared.h index 85ccb83..4d1fef3 100644 --- a/Src/Dc_Shared.h +++ b/Src/Dc_Shared.h @@ -8,9 +8,11 @@ #pragma once -typedef unsigned char BYTE; -typedef unsigned short WORD; -typedef unsigned long DWORD; +#include + +typedef unsigned char BYTE; +typedef uint16_t WORD; +typedef uint32_t DWORD; #define BUFFER_SIZE 2048 diff --git a/Src/File_AppleSingle.c b/Src/File_AppleSingle.c index 7257ea3..935ecdb 100644 --- a/Src/File_AppleSingle.c +++ b/Src/File_AppleSingle.c @@ -13,6 +13,26 @@ bool IsAppleSingle(unsigned char *buf) return memcmp(&buf, &AS_MAGIC, sizeof(AS_MAGIC)); } +/** + * Parse header out of raw data buffer. + * @brief ParseHeader + * @param buf The buffer + * @return + */ +struct as_file_header *ParseHeader(unsigned char *buf) +{ + struct as_file_header *header = malloc(sizeof(as_file_header)); + memcpy(header, buf, sizeof(as_file_header)); + + if (__ORDER_LITTLE_ENDIAN__) { + header->magic = __builtin_bswap32(header->magic); + header->version = __builtin_bswap32(header->version); + header->num_entries = __builtin_bswap16(header->num_entries); + } + + return header; +} + /** * Read headers and return a list of as_file_entry pointers * @brief GetEntries @@ -21,8 +41,31 @@ bool IsAppleSingle(unsigned char *buf) */ struct as_file_entry **GetEntries(unsigned char *buf) { - struct as_file_entry **entries = malloc(4 * sizeof(as_file_entry *)); - return entries; + struct as_file_header *header = ParseHeader(buf); + + if (!header) { + printf(" Invalid AppleSingle file!\n"); + return NULL; + } + + struct as_file_entry **entries = malloc( + header->num_entries * sizeof(as_file_entry *) + ); + + unsigned char *move_buf = buf + sizeof(as_file_header); + + for (int i = 0; i < header->num_entries; ++i) + { + struct as_file_entry *entry = malloc(sizeof(as_file_entry)); + + memcpy(entry, move_buf, sizeof(as_file_entry)); + printf("This entry is %d", __builtin_bswap32(entry->entry_id)); + + entries[i] = entry; + buf += sizeof(as_file_entry); + } + + return entries; } /** @@ -34,5 +77,6 @@ struct as_file_entry **GetEntries(unsigned char *buf) */ void DecorateProdosFile(struct prodos_file *current_file, unsigned char *data) { + GetEntries(data); return; } diff --git a/Src/File_AppleSingle.h b/Src/File_AppleSingle.h index 5f73d97..d765eb1 100644 --- a/Src/File_AppleSingle.h +++ b/Src/File_AppleSingle.h @@ -12,6 +12,7 @@ #include #include #include +#include #include "Dc_Shared.h" #include "Dc_Prodos.h" @@ -20,7 +21,7 @@ typedef struct as_file_header { DWORD magic; DWORD version; - int filler[4]; + DWORD filler[4]; WORD num_entries; } as_file_header; From f699a2c179b1cd49652495535aec51e5ff595bb1 Mon Sep 17 00:00:00 2001 From: David Stancu Date: Tue, 13 Mar 2018 22:40:47 -0400 Subject: [PATCH 04/18] clean up a little bit, add almost ready --- Src/File_AppleSingle.c | 39 +++++++++++++++++++++------------------ Src/File_AppleSingle.h | 2 +- Src/Prodos_Add.c | 2 +- 3 files changed, 23 insertions(+), 20 deletions(-) diff --git a/Src/File_AppleSingle.c b/Src/File_AppleSingle.c index 935ecdb..d53fbe1 100644 --- a/Src/File_AppleSingle.c +++ b/Src/File_AppleSingle.c @@ -16,7 +16,7 @@ bool IsAppleSingle(unsigned char *buf) /** * Parse header out of raw data buffer. * @brief ParseHeader - * @param buf The buffer + * @param buf The buffer * @return */ struct as_file_header *ParseHeader(unsigned char *buf) @@ -39,31 +39,30 @@ struct as_file_header *ParseHeader(unsigned char *buf) * @param buf * @return */ -struct as_file_entry **GetEntries(unsigned char *buf) +struct as_file_entry *GetEntries(unsigned char *buf) { struct as_file_header *header = ParseHeader(buf); - if (!header) { - printf(" Invalid AppleSingle file!\n"); + if (!header) + { + printf(" Invalid AppleSingle file!\n"); return NULL; } - struct as_file_entry **entries = malloc( - header->num_entries * sizeof(as_file_entry *) + struct as_file_entry *entries = malloc( + header->num_entries * sizeof(as_file_entry) ); - unsigned char *move_buf = buf + sizeof(as_file_header); - - for (int i = 0; i < header->num_entries; ++i) - { - struct as_file_entry *entry = malloc(sizeof(as_file_entry)); - - memcpy(entry, move_buf, sizeof(as_file_entry)); - printf("This entry is %d", __builtin_bswap32(entry->entry_id)); + struct as_file_entry *buf_entries = buf + sizeof(as_file_header); + memcpy(entries, buf_entries, header->num_entries * sizeof(as_file_entry)); - entries[i] = entry; - buf += sizeof(as_file_entry); - } + if (__ORDER_LITTLE_ENDIAN__) + for (int i = 0; i < header->num_entries; ++i) + { + entries[i].entry_id = __builtin_bswap32(entries[i].entry_id); + entries[i].offset = __builtin_bswap32(entries[i].offset); + entries[i].length = __builtin_bswap32(entries[i].length); + } return entries; } @@ -77,6 +76,10 @@ struct as_file_entry **GetEntries(unsigned char *buf) */ void DecorateProdosFile(struct prodos_file *current_file, unsigned char *data) { - GetEntries(data); + struct as_file_entry *entries = GetEntries(data); + for (int i = 0; i < 2; ++i) { + printf(" Found entry with ID %04x\n", entries[i].entry_id); + } + return; } diff --git a/Src/File_AppleSingle.h b/Src/File_AppleSingle.h index d765eb1..9703aac 100644 --- a/Src/File_AppleSingle.h +++ b/Src/File_AppleSingle.h @@ -52,6 +52,6 @@ typedef enum as_entry_types const unsigned char AS_MAGIC[4]; -struct as_file_entry **GetEntries(unsigned char *buf); +struct as_file_entry *GetEntries(unsigned char *buf); unsigned char *GetDataSegment(unsigned char *buf); void DecorateProdosFile(struct prodos_file *current_file, unsigned char *data); diff --git a/Src/Prodos_Add.c b/Src/Prodos_Add.c index a82ecfb..896d233 100644 --- a/Src/Prodos_Add.c +++ b/Src/Prodos_Add.c @@ -353,7 +353,7 @@ static struct prodos_file *LoadFile(char *file_path_data) unsigned char *data = LoadBinaryFile(file_path_data, ¤t_file->data_length); if (IsAppleSingle(data)) { - printf(" AppleSingle format detected!"); + printf(" AppleSingle format detected!\n"); DecorateProdosFile(current_file, data); } else From f9b34ec5ad9030f5fb587059df861032f6356d19 Mon Sep 17 00:00:00 2001 From: David Stancu Date: Wed, 14 Mar 2018 21:34:02 -0400 Subject: [PATCH 05/18] add files, needs testing --- Src/File_AppleSingle.c | 119 +++++++++++++++++++++++++++++++++-------- Src/File_AppleSingle.h | 63 +++++++++++++--------- Src/Prodos_Add.c | 4 +- 3 files changed, 137 insertions(+), 49 deletions(-) diff --git a/Src/File_AppleSingle.c b/Src/File_AppleSingle.c index d53fbe1..8f2521a 100644 --- a/Src/File_AppleSingle.c +++ b/Src/File_AppleSingle.c @@ -4,22 +4,22 @@ const unsigned char AS_MAGIC[] = {0x00, 0x05, 0x16, 0x00}; /** * Is this an AppleSingle file? - * @brief IsAppleSingle + * @brief ASIsAppleSingle * @param buf * @return */ -bool IsAppleSingle(unsigned char *buf) +bool ASIsAppleSingle(unsigned char *buf) { - return memcmp(&buf, &AS_MAGIC, sizeof(AS_MAGIC)); + return memcmp(&buf, &AS_MAGIC, sizeof(AS_MAGIC)); } /** * Parse header out of raw data buffer. - * @brief ParseHeader + * @brief ASParseHeader * @param buf The buffer * @return */ -struct as_file_header *ParseHeader(unsigned char *buf) +struct as_file_header *ASParseHeader(unsigned char *buf) { struct as_file_header *header = malloc(sizeof(as_file_header)); memcpy(header, buf, sizeof(as_file_header)); @@ -34,15 +34,33 @@ struct as_file_header *ParseHeader(unsigned char *buf) } /** - * Read headers and return a list of as_file_entry pointers - * @brief GetEntries - * @param buf + * @brief ASParseProdosEntry + * @param entry_buf The entry buffer * @return */ -struct as_file_entry *GetEntries(unsigned char *buf) +struct as_prodos_info *ASParseProdosEntry(unsigned char *entry_buf, DWORD length) { - struct as_file_header *header = ParseHeader(buf); + struct as_prodos_info *prodos_entry = malloc(sizeof(as_prodos_info)); + memcpy(prodos_entry, entry_buf, length); + if (__ORDER_LITTLE_ENDIAN__) + { + prodos_entry->access = __builtin_bswap16(prodos_entry->access); + prodos_entry->filetype = __builtin_bswap16(prodos_entry->filetype); + prodos_entry->auxtype = __builtin_bswap32(prodos_entry->auxtype); + } + + return prodos_entry; +} + +/** + * Read headers and return a list of as_file_entry pointers. + * @brief ASGetEntries + * @param buf + * @return + */ +struct as_file_entry *ASGetEntries(struct as_file_header *header, unsigned char *buf) +{ if (!header) { printf(" Invalid AppleSingle file!\n"); @@ -53,33 +71,88 @@ struct as_file_entry *GetEntries(unsigned char *buf) header->num_entries * sizeof(as_file_entry) ); - struct as_file_entry *buf_entries = buf + sizeof(as_file_header); + struct as_file_entry *buf_entries = buf + 26; memcpy(entries, buf_entries, header->num_entries * sizeof(as_file_entry)); if (__ORDER_LITTLE_ENDIAN__) - for (int i = 0; i < header->num_entries; ++i) - { - entries[i].entry_id = __builtin_bswap32(entries[i].entry_id); - entries[i].offset = __builtin_bswap32(entries[i].offset); - entries[i].length = __builtin_bswap32(entries[i].length); - } + for (int i = 0; i < header->num_entries; ++i) + { + entries[i].entry_id = __builtin_bswap32(entries[i].entry_id); + entries[i].offset = __builtin_bswap32(entries[i].offset); + entries[i].length = __builtin_bswap32(entries[i].length); + } return entries; } +/** + * Grab data from data entry and place in prodos_file. + * @brief ASDecorateDataFork + * @param current_file The current file + * @param data The data + * @param data_fork_entry The data fork entry + */ +void ASDecorateDataFork(struct prodos_file *current_file, unsigned char *data, as_file_entry *data_fork_entry) +{ + if (data_fork_entry->entry_id != data_fork) return; + + unsigned char *data_entry = malloc(data_fork_entry->length); + memcpy(data_entry, data + data_fork_entry->offset, data_fork_entry->length); + current_file->data = data; + + return; +} + +/** + * Read ProDOS metadata struct and place in prodos_file. + * + * @brief ASDecorateProdosFileInfo + * @param current_file The current file + * @param data The data + * @param prodos_entry The prodos entry + */ +void ASDecorateProdosFileInfo(struct prodos_file *current_file, unsigned char *data, as_file_entry *prodos_entry) +{ + if (prodos_entry->entry_id != prodos_file_info) return; + + struct as_prodos_info *info_meta = ASParseProdosEntry( + data + prodos_entry->offset, prodos_entry->length + ); + + if (!info_meta) return; + + current_file->access = info_meta->access; + current_file->type = info_meta->filetype; + current_file->aux_type = info_meta->auxtype; + + return; +} + /** * Parse AppleSingle header and write attributes into prodos_file * struct - * @brief DecorateProdosFile + * @brief ASDecorateProdosFile * @param current_file * @param data */ -void DecorateProdosFile(struct prodos_file *current_file, unsigned char *data) +void ASDecorateProdosFile(struct prodos_file *current_file, unsigned char *data) { - struct as_file_entry *entries = GetEntries(data); - for (int i = 0; i < 2; ++i) { - printf(" Found entry with ID %04x\n", entries[i].entry_id); - } + struct as_file_header *header = ASParseHeader(data); + struct as_file_entry *entries = ASGetEntries(header, data); + for (int i = 0; i < header->num_entries; ++i) + switch(entries[i].entry_id) + { + case data_fork: + ASDecorateDataFork(current_file, data, &entries[i]); + break; + case prodos_file_info: + ASDecorateProdosFileInfo(current_file, data, &entries[i]); + break; + default: + printf(" Entry ID %d unsupported, ignoring!\n", entries[i].entry_id); + printf(" (See https://tools.ietf.org/html/rfc1740 for ID lookup)\n"); + break; + } return; } diff --git a/Src/File_AppleSingle.h b/Src/File_AppleSingle.h index 9703aac..e35d37a 100644 --- a/Src/File_AppleSingle.h +++ b/Src/File_AppleSingle.h @@ -19,39 +19,54 @@ typedef struct as_file_header { - DWORD magic; - DWORD version; - DWORD filler[4]; - WORD num_entries; + DWORD magic; + DWORD version; + DWORD filler[4]; + WORD num_entries; } as_file_header; typedef struct as_file_entry { - DWORD entry_id; - DWORD offset; - DWORD length; + DWORD entry_id; + DWORD offset; + DWORD length; } as_file_entry; typedef enum as_entry_types { - data_fork = 1, - resource_fork = 2, - real_name = 3, - comment = 4, - icon_bw = 5, - icon_color = 6, - file_dates_info = 8, - finder_info = 9, - mac_file_info = 10, - prodos_file_info = 11, - msdos_file_info = 12, - short_name = 13, - afp_file_info = 14, - directory_id = 15 + data_fork = 1, + resource_fork = 2, + real_name = 3, + comment = 4, + icon_bw = 5, + icon_color = 6, + file_dates_info = 8, + finder_info = 9, + mac_file_info = 10, + prodos_file_info = 11, + msdos_file_info = 12, + short_name = 13, + afp_file_info = 14, + directory_id = 15 } as_entry_types; +typedef struct as_prodos_info +{ + WORD access; + WORD filetype; + DWORD auxtype; +} as_prodos_info; + const unsigned char AS_MAGIC[4]; -struct as_file_entry *GetEntries(unsigned char *buf); -unsigned char *GetDataSegment(unsigned char *buf); -void DecorateProdosFile(struct prodos_file *current_file, unsigned char *data); +struct as_file_header *ASParseHeader(unsigned char *buf); +struct as_prodos_info *ASParseProdosEntry(unsigned char *entry_buf, DWORD length); + +void ASDecorateDataFork(struct prodos_file *current_file, unsigned char *data, as_file_entry *data_fork_entry); +void ASDeocrateProdosFileInfo(struct prodos_file *current_file, unsigned char *data, as_file_entry *prodos_entry); + +bool ASIsAppleSingle(unsigned char *buf); +struct as_file_entry *ASGetEntries(struct as_file_header *header, unsigned char *buf); +unsigned char *ASGetDataSegment(unsigned char *buf); + +void ASDecorateProdosFile(struct prodos_file *current_file, unsigned char *data); diff --git a/Src/Prodos_Add.c b/Src/Prodos_Add.c index 896d233..225b9bd 100644 --- a/Src/Prodos_Add.c +++ b/Src/Prodos_Add.c @@ -351,10 +351,10 @@ static struct prodos_file *LoadFile(char *file_path_data) // Load data. If an AppleSingle file, parse it. unsigned char *data = LoadBinaryFile(file_path_data, ¤t_file->data_length); - if (IsAppleSingle(data)) + if (ASIsAppleSingle(data)) { printf(" AppleSingle format detected!\n"); - DecorateProdosFile(current_file, data); + ASDecorateProdosFile(current_file, data); } else { From 0e2c79d0011473a3182deb438785b518b04137df Mon Sep 17 00:00:00 2001 From: David Stancu Date: Wed, 14 Mar 2018 21:58:13 -0400 Subject: [PATCH 06/18] fix bug / dont overwrite if applesingle header detected --- Src/Prodos_Add.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Src/Prodos_Add.c b/Src/Prodos_Add.c index 225b9bd..233f7af 100644 --- a/Src/Prodos_Add.c +++ b/Src/Prodos_Add.c @@ -351,7 +351,9 @@ static struct prodos_file *LoadFile(char *file_path_data) // Load data. If an AppleSingle file, parse it. unsigned char *data = LoadBinaryFile(file_path_data, ¤t_file->data_length); - if (ASIsAppleSingle(data)) + bool is_apple_single = ASIsAppleSingle(data); + + if (is_apple_single) { printf(" AppleSingle format detected!\n"); ASDecorateProdosFile(current_file, data); @@ -380,7 +382,7 @@ static struct prodos_file *LoadFile(char *file_path_data) /** Chargement des Informations du fichier contenue dans _FileInformation.txt **/ sprintf(file_path,"%s_FileInformation.txt",folder_path); found = GetFileInformation(file_path,file_name,current_file); - if(!found) + if(!found && !is_apple_single) { /* Valeurs par défaut */ current_file->type = 0x00; From a44b7dc52c8aaa0d8d777d40b734dbc78f310f9b Mon Sep 17 00:00:00 2001 From: David Stancu Date: Fri, 16 Mar 2018 23:51:01 -0400 Subject: [PATCH 07/18] fix path tokenization issue --- Src/Main.c | 12 ++++++++---- Src/Prodos_Add.c | 4 ++-- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/Src/Main.c b/Src/Main.c index c242360..000ede3 100644 --- a/Src/Main.c +++ b/Src/Main.c @@ -393,9 +393,9 @@ int main(int argc, char *argv[]) int fcharloc = 0; for (int i=strlen(param->file_path); i >= 0; --i) { - if (!strncmp(¶m->file_path[i], FOLDER_CHARACTER, sizeof(FOLDER_CHARACTER))) + if (!strncmp(¶m->file_path[i], &FOLDER_CHARACTER, 1)) { - fcharloc = i; + fcharloc = i + 1; break; } } @@ -403,10 +403,14 @@ int main(int argc, char *argv[]) // Prepare parameters for delete char *file_name = param->file_path + fcharloc; char *prodos_file_name = strdup(param->prodos_folder_path); - strcat(prodos_file_name, &FOLDER_CHARACTER); + + if (strncmp(&prodos_file_name[strlen(prodos_file_name) - 1], \ + &FOLDER_CHARACTER, strlen(FOLDER_CHARACTER))) + strcat(prodos_file_name, &FOLDER_CHARACTER); + strcat(prodos_file_name, file_name); - printf(" - Replacing file '%s' :\n",param->file_path); + printf(" - Replacing file '%s' :\n",prodos_file_name); DeleteProdosFile(current_image, prodos_file_name); AddFile(current_image, param->file_path, param->prodos_folder_path,1); diff --git a/Src/Prodos_Add.c b/Src/Prodos_Add.c index 233f7af..724b6b4 100644 --- a/Src/Prodos_Add.c +++ b/Src/Prodos_Add.c @@ -310,7 +310,7 @@ static struct prodos_file *LoadFile(char *file_path_data) // Start from end of string until we arrive to path delimiter strcpy(folder_path,file_path_data); for(i=strlen(folder_path); i>=0; i--) - if(!strncmp(&folder_path[i], FOLDER_CHARACTER, sizeof(FOLDER_CHARACTER))) + if(!strncmp(&folder_path[i], &FOLDER_CHARACTER, strlen(FOLDER_CHARACTER))) { folder_path[i+1] = '\0'; break; @@ -319,7 +319,7 @@ static struct prodos_file *LoadFile(char *file_path_data) // Similarly, also extract the filename strcpy(file_name,file_path_data); for(i=strlen(file_path_data); i>=0; i--) - if(!strncmp(&folder_path[i], FOLDER_CHARACTER, sizeof(FOLDER_CHARACTER))) + if(!strncmp(&folder_path[i], &FOLDER_CHARACTER, strlen(FOLDER_CHARACTER))) { strcpy(file_name,&file_path_data[i+1]); break; From 2187f8a9070faa8b949e3bd10aa0593036b1b22a Mon Sep 17 00:00:00 2001 From: David Stancu Date: Sat, 17 Mar 2018 11:36:15 -0400 Subject: [PATCH 08/18] portable endian test + os specific bswaps + fix replacefile bug on windows --- Src/File_AppleSingle.c | 24 ++++++++++++------------ Src/File_AppleSingle.h | 6 ++++-- Src/Main.c | 5 +++-- Src/Prodos_Add.c | 7 +++++++ Src/os/os.h | 3 +++ Src/os/posix.c | 14 ++++++++++++-- Src/os/win32.c | 10 ++++++++++ 7 files changed, 51 insertions(+), 18 deletions(-) diff --git a/Src/File_AppleSingle.c b/Src/File_AppleSingle.c index 8f2521a..54d6238 100644 --- a/Src/File_AppleSingle.c +++ b/Src/File_AppleSingle.c @@ -24,10 +24,10 @@ struct as_file_header *ASParseHeader(unsigned char *buf) struct as_file_header *header = malloc(sizeof(as_file_header)); memcpy(header, buf, sizeof(as_file_header)); - if (__ORDER_LITTLE_ENDIAN__) { - header->magic = __builtin_bswap32(header->magic); - header->version = __builtin_bswap32(header->version); - header->num_entries = __builtin_bswap16(header->num_entries); + if (IS_LITTLE_ENDIAN) { + header->magic = swap32(header->magic); + header->version = swap32(header->version); + header->num_entries = swap16(header->num_entries); } return header; @@ -43,11 +43,11 @@ struct as_prodos_info *ASParseProdosEntry(unsigned char *entry_buf, DWORD length struct as_prodos_info *prodos_entry = malloc(sizeof(as_prodos_info)); memcpy(prodos_entry, entry_buf, length); - if (__ORDER_LITTLE_ENDIAN__) + if (IS_LITTLE_ENDIAN) { - prodos_entry->access = __builtin_bswap16(prodos_entry->access); - prodos_entry->filetype = __builtin_bswap16(prodos_entry->filetype); - prodos_entry->auxtype = __builtin_bswap32(prodos_entry->auxtype); + prodos_entry->access = swap16(prodos_entry->access); + prodos_entry->filetype = swap16(prodos_entry->filetype); + prodos_entry->auxtype = swap32(prodos_entry->auxtype); } return prodos_entry; @@ -74,12 +74,12 @@ struct as_file_entry *ASGetEntries(struct as_file_header *header, unsigned char struct as_file_entry *buf_entries = buf + 26; memcpy(entries, buf_entries, header->num_entries * sizeof(as_file_entry)); - if (__ORDER_LITTLE_ENDIAN__) + if (IS_LITTLE_ENDIAN) for (int i = 0; i < header->num_entries; ++i) { - entries[i].entry_id = __builtin_bswap32(entries[i].entry_id); - entries[i].offset = __builtin_bswap32(entries[i].offset); - entries[i].length = __builtin_bswap32(entries[i].length); + entries[i].entry_id = swap32(entries[i].entry_id); + entries[i].offset = swap32(entries[i].offset); + entries[i].length = swap32(entries[i].length); } return entries; diff --git a/Src/File_AppleSingle.h b/Src/File_AppleSingle.h index e35d37a..38a51a0 100644 --- a/Src/File_AppleSingle.h +++ b/Src/File_AppleSingle.h @@ -17,6 +17,10 @@ #include "Dc_Shared.h" #include "Dc_Prodos.h" +const unsigned char AS_MAGIC[4]; + +#define IS_LITTLE_ENDIAN (uint32_t) AS_MAGIC != 0x00051600 + typedef struct as_file_header { DWORD magic; @@ -57,8 +61,6 @@ typedef struct as_prodos_info DWORD auxtype; } as_prodos_info; -const unsigned char AS_MAGIC[4]; - struct as_file_header *ASParseHeader(unsigned char *buf); struct as_prodos_info *ASParseProdosEntry(unsigned char *entry_buf, DWORD length); diff --git a/Src/Main.c b/Src/Main.c index 000ede3..b3c801e 100644 --- a/Src/Main.c +++ b/Src/Main.c @@ -404,9 +404,10 @@ int main(int argc, char *argv[]) char *file_name = param->file_path + fcharloc; char *prodos_file_name = strdup(param->prodos_folder_path); + // The tool does not use Windows path conventions if (strncmp(&prodos_file_name[strlen(prodos_file_name) - 1], \ - &FOLDER_CHARACTER, strlen(FOLDER_CHARACTER))) - strcat(prodos_file_name, &FOLDER_CHARACTER); + &FOLDER_CHARACTER, strlen(FOLDER_CHARACTER))) + strcat(prodos_file_name, "/"); strcat(prodos_file_name, file_name); diff --git a/Src/Prodos_Add.c b/Src/Prodos_Add.c index 724b6b4..e60b290 100644 --- a/Src/Prodos_Add.c +++ b/Src/Prodos_Add.c @@ -351,6 +351,13 @@ static struct prodos_file *LoadFile(char *file_path_data) // Load data. If an AppleSingle file, parse it. unsigned char *data = LoadBinaryFile(file_path_data, ¤t_file->data_length); + + if (data == NULL) + { + printf(" Error : Cannot load file %s\n", file_path_data); + return NULL; + } + bool is_apple_single = ASIsAppleSingle(data); if (is_apple_single) diff --git a/Src/os/os.h b/Src/os/os.h index 89a93bb..c151339 100644 --- a/Src/os/os.h +++ b/Src/os/os.h @@ -73,4 +73,7 @@ int my_mkdir(char *path); char *my_strcpy(char *s1, char *s2); char *my_strdup(const char *s); +uint32_t swap32(uint32_t num); +uint16_t swap16(uint16_t num); + /***********************************************************************/ diff --git a/Src/os/posix.c b/Src/os/posix.c index 7b0f33f..b2c43c2 100644 --- a/Src/os/posix.c +++ b/Src/os/posix.c @@ -172,11 +172,21 @@ void os_GetFileCreationModificationDate(char *path, struct prodos_file *file) { char *my_strcpy(char *s1, char *s2) { - return strcpy(s1, s2); + return strcpy(s1, s2); } char *my_strdup(const char *s) { - return strdup(s); + return strdup(s); +} + +uint32_t swap32(uint32_t num) +{ + return __builtin_bswap32(num); +} + +uint16_t swap16(uint16_t num) +{ + return __builtin_bswap16(num); } #endif diff --git a/Src/os/win32.c b/Src/os/win32.c index a96be49..7b3abdb 100644 --- a/Src/os/win32.c +++ b/Src/os/win32.c @@ -264,4 +264,14 @@ int my_mkdir(char *path) return mkdir(path); } +uint32_t swap32(uint32_t num) +{ + return _byteswap_ulong(num); +} + +uint16_t swap16(uint16_t num) +{ + return _byteswap_ushort(num); +} + #endif From fd687ce037f26ef313f041b711ad18fba91b4870 Mon Sep 17 00:00:00 2001 From: David Stancu Date: Sat, 17 Mar 2018 12:08:25 -0400 Subject: [PATCH 09/18] fix buffer overflow + clean up header --- Src/File_AppleSingle.c | 2 +- Src/File_AppleSingle.h | 13 ++++++++----- Src/Main.c | 7 +++++++ 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/Src/File_AppleSingle.c b/Src/File_AppleSingle.c index 54d6238..ca033b7 100644 --- a/Src/File_AppleSingle.c +++ b/Src/File_AppleSingle.c @@ -71,7 +71,7 @@ struct as_file_entry *ASGetEntries(struct as_file_header *header, unsigned char header->num_entries * sizeof(as_file_entry) ); - struct as_file_entry *buf_entries = buf + 26; + struct as_file_entry *buf_entries = buf + sizeof(as_file_header); memcpy(entries, buf_entries, header->num_entries * sizeof(as_file_entry)); if (IS_LITTLE_ENDIAN) diff --git a/Src/File_AppleSingle.h b/Src/File_AppleSingle.h index 38a51a0..687e7c4 100644 --- a/Src/File_AppleSingle.h +++ b/Src/File_AppleSingle.h @@ -21,6 +21,8 @@ const unsigned char AS_MAGIC[4]; #define IS_LITTLE_ENDIAN (uint32_t) AS_MAGIC != 0x00051600 +#pragma pack(1) + typedef struct as_file_header { DWORD magic; @@ -61,14 +63,15 @@ typedef struct as_prodos_info DWORD auxtype; } as_prodos_info; +#pragma pack(pop) + +bool ASIsAppleSingle(unsigned char *buf); + struct as_file_header *ASParseHeader(unsigned char *buf); struct as_prodos_info *ASParseProdosEntry(unsigned char *entry_buf, DWORD length); +struct as_file_entry *ASGetEntries(struct as_file_header *header, unsigned char *buf); void ASDecorateDataFork(struct prodos_file *current_file, unsigned char *data, as_file_entry *data_fork_entry); void ASDeocrateProdosFileInfo(struct prodos_file *current_file, unsigned char *data, as_file_entry *prodos_entry); - -bool ASIsAppleSingle(unsigned char *buf); -struct as_file_entry *ASGetEntries(struct as_file_header *header, unsigned char *buf); -unsigned char *ASGetDataSegment(unsigned char *buf); - void ASDecorateProdosFile(struct prodos_file *current_file, unsigned char *data); + diff --git a/Src/Main.c b/Src/Main.c index b3c801e..b5fc5de 100644 --- a/Src/Main.c +++ b/Src/Main.c @@ -542,6 +542,13 @@ struct parameter *GetParamLine(int argc, char *argv[]) struct parameter *param; char local_buffer[256]; + for (int i = 0; i < argc; ++i) + if (strlen(argv[i]) > 256) + { + printf(" Error: Argument too long!\n"); + return(NULL); + } + /* Vérifications */ if(argc < 3) { From 7a24451f8ef1d17fcfd7fd567fac6169366a6c8d Mon Sep 17 00:00:00 2001 From: David Stancu Date: Sat, 17 Mar 2018 21:15:58 -0400 Subject: [PATCH 10/18] first draft output / wip --- Src/File_AppleSingle.c | 76 ++++++++++++++++++++++++++++++++++-------- Src/File_AppleSingle.h | 2 ++ Src/Main.c | 32 ++++++++++++++---- Src/Prodos_Extract.c | 45 +++++++++++++++---------- Src/Prodos_Extract.h | 8 +++-- 5 files changed, 124 insertions(+), 39 deletions(-) diff --git a/Src/File_AppleSingle.c b/Src/File_AppleSingle.c index ca033b7..bd0a8d8 100644 --- a/Src/File_AppleSingle.c +++ b/Src/File_AppleSingle.c @@ -1,6 +1,17 @@ #include "File_AppleSingle.h" const unsigned char AS_MAGIC[] = {0x00, 0x05, 0x16, 0x00}; +const unsigned char AS_VERSION[] = {0x00, 0x02, 0x00, 0x00}; + +static uint32_t as_field32(uint32_t num) +{ + return IS_LITTLE_ENDIAN ? swap32(num) : num; +} + +static uint16_t as_field16(uint16_t num) +{ + return IS_LITTLE_ENDIAN ? swap16(num) : num; +} /** * Is this an AppleSingle file? @@ -22,13 +33,11 @@ bool ASIsAppleSingle(unsigned char *buf) struct as_file_header *ASParseHeader(unsigned char *buf) { struct as_file_header *header = malloc(sizeof(as_file_header)); - memcpy(header, buf, sizeof(as_file_header)); + struct as_file_header *buf_header = (as_file_header *) buf; - if (IS_LITTLE_ENDIAN) { - header->magic = swap32(header->magic); - header->version = swap32(header->version); - header->num_entries = swap16(header->num_entries); - } + header->magic = as_field32(buf_header->magic); + header->version = as_field32(buf_header->version); + header->num_entries = as_field16(buf_header->num_entries); return header; } @@ -41,14 +50,11 @@ struct as_file_header *ASParseHeader(unsigned char *buf) struct as_prodos_info *ASParseProdosEntry(unsigned char *entry_buf, DWORD length) { struct as_prodos_info *prodos_entry = malloc(sizeof(as_prodos_info)); - memcpy(prodos_entry, entry_buf, length); + struct as_prodos_info *buf_prodos_entry = (as_prodos_info *) entry_buf; - if (IS_LITTLE_ENDIAN) - { - prodos_entry->access = swap16(prodos_entry->access); - prodos_entry->filetype = swap16(prodos_entry->filetype); - prodos_entry->auxtype = swap32(prodos_entry->auxtype); - } + prodos_entry->access = as_field16(buf_prodos_entry->access); + prodos_entry->filetype = as_field16(buf_prodos_entry->filetype); + prodos_entry->auxtype = as_field32(buf_prodos_entry->auxtype); return prodos_entry; } @@ -156,3 +162,47 @@ void ASDecorateProdosFile(struct prodos_file *current_file, unsigned char *data) } return; } + +char *ASFromProdosFile(struct prodos_file *file) +{ + struct as_file_header *as_header = malloc(sizeof(as_file_header)); + as_header->magic = as_field32(AS_MAGIC); + as_header->version = as_field32(AS_VERSION); + as_header->num_entries = as_field16(2); + + int header_offset = sizeof(as_file_header) + 2 * sizeof(as_file_entry); + struct as_file_entry *data_entry = malloc(sizeof(as_file_entry)); + data_entry->entry_id = as_field_32(as_data_fork); + data_entry->length = as_field_32(sizeof(file->data)); + data_entry->offset = as_field_32(header_offset); + + int prodos_entry_offset = header_offset + sizeof(file->data); + struct as_file_entry *prodos_entry = malloc(sizeof(as_file_entry)); + prodos_entry->entry_id = as_field_32(prodos_file_info); + prodos_entry->length = as_field_32(sizeof(as_prodos_info)); + prodos_entry->offset = as_field_32(prodos_entry_offset); + + struct as_prodos_info *prodos_info = malloc(sizeof(as_prodos_info)); + prodos_info->access = file->access; + prodos_info->filetype = file->type; + prodos_info->auxtype = file->aux_type; + + char *payload = malloc(prodos_entry_offset + sizeof(as_prodos_info)); + char *seek = payload; + + memcpy(seek, as_header, sizeof(as_file_header)); + seek += sizeof(as_file_header); + + memcpy(seek, data_entry, sizeof(as_file_entry)); + seek += sizeof(as_file_entry); + + memcpy(seek, prodos_entry, sizeof(as_file_entry)); + seek += sizeof(as_file_entry); + + memcpy(seek, &file->data, sizeof(file->data)); + seek += sizeof(file->data); + + memcpy(seek, prodos_info, sizeof(as_prodos_info)); + + return payload; +} \ No newline at end of file diff --git a/Src/File_AppleSingle.h b/Src/File_AppleSingle.h index 687e7c4..f7b37b5 100644 --- a/Src/File_AppleSingle.h +++ b/Src/File_AppleSingle.h @@ -18,6 +18,7 @@ #include "Dc_Prodos.h" const unsigned char AS_MAGIC[4]; +const unsigned char AS_VERSION[4]; #define IS_LITTLE_ENDIAN (uint32_t) AS_MAGIC != 0x00051600 @@ -75,3 +76,4 @@ void ASDecorateDataFork(struct prodos_file *current_file, unsigned char *data, a void ASDeocrateProdosFileInfo(struct prodos_file *current_file, unsigned char *data, as_file_entry *prodos_entry); void ASDecorateProdosFile(struct prodos_file *current_file, unsigned char *data); +char *ASFromProdosFile(struct prodos_file *file); \ No newline at end of file diff --git a/Src/Main.c b/Src/Main.c index b5fc5de..6c615b1 100644 --- a/Src/Main.c +++ b/Src/Main.c @@ -9,6 +9,7 @@ #include #include #include +#include #if IS_WINDOWS #include @@ -78,7 +79,7 @@ int main(int argc, char *argv[]) verbose = 0; /* Message Information */ - printf("%s v 1.3.1, (c) Brutal Deluxe 2011-2013.\n",argv[0]); + printf("%s v 1.4.0 (c) Brutal Deluxe 2011-2013.\n",argv[0]); /* Vérification des paramètres */ if(argc < 3) @@ -94,6 +95,9 @@ int main(int argc, char *argv[]) if(!my_stricmp(argv[argc-1],"-V")) verbose = 1; + /* AppleSingle */ + bool output_apple_single = !my_stricmp(argv[argc - 1], "-A"); + /** Décode les paramètres **/ param = GetParamLine(argc-verbose,argv); if(param == NULL) @@ -137,6 +141,7 @@ int main(int argc, char *argv[]) { /* Information */ printf(" - Extract file '%s'\n",param->prodos_file_path); + if (output_apple_single) printf(" - Creating AppleSingle file!"); /** Charge l'image 2mg **/ current_image = LoadProdosImage(param->image_file_path); @@ -144,7 +149,12 @@ int main(int argc, char *argv[]) return(3); /** Extrait le fichier sur disque **/ - ExtractOneFile(current_image,param->prodos_file_path,param->output_directory_path); + ExtractOneFile( + current_image, + param->prodos_file_path, + param->output_directory_path, + output_apple_single + ); /* Libération mémoire */ mem_free_image(current_image); @@ -165,7 +175,12 @@ int main(int argc, char *argv[]) return(4); /** Extrait les fichiers du répertoire **/ - ExtractFolderFiles(current_image,folder_entry,param->output_directory_path); + ExtractFolderFiles( + current_image, + folder_entry, + param->output_directory_path, + output_apple_single + ); /* Stat */ printf(" => File(s) : %d, Folder(s) : %d, Error(s) : %d\n",current_image->nb_extract_file,current_image->nb_extract_folder,current_image->nb_extract_error); @@ -184,7 +199,11 @@ int main(int argc, char *argv[]) printf(" - Extract volume '%s' :\n",current_image->volume_header->volume_name_case); /** Extrait les fichiers du volume **/ - ExtractVolumeFiles(current_image,param->output_directory_path); + ExtractVolumeFiles( + current_image, + param->output_directory_path, + output_apple_single + ); /* Stat */ printf(" => File(s) : %d, Folder(s) : %d, Error(s) : %d\n",current_image->nb_extract_file,current_image->nb_extract_folder,current_image->nb_extract_error); @@ -500,7 +519,8 @@ void usage(char *program_path) printf(" ----\n"); printf(" %s EXTRACTFILE <[2mg|hdv|po]_image_path> \n",program_path); printf(" %s EXTRACTFOLDER <[2mg|hdv|po]_image_path> \n",program_path); - printf(" %s EXTRACTVOLUME <[2mg|hdv|po]_image_path> \n",program_path); + printf(" %s EXTRACTVOLUME <[2mg|hdv|po]_image_path> \n\n",program_path); + printf(" [-A] Extract as AppleSingle\n"); printf(" ----\n"); printf(" %s RENAMEFILE <[2mg|hdv|po]_image_path> \n",program_path); printf(" %s RENAMEFOLDER <[2mg|hdv|po]_image_path> \n",program_path); @@ -601,7 +621,7 @@ struct parameter *GetParamLine(int argc, char *argv[]) } /** EXTRACTFILE **/ - if(!my_stricmp(argv[1],"EXTRACTFILE") && argc == 5) + if(!my_stricmp(argv[1],"EXTRACTFILE") && argc >= 5) { param->action = ACTION_EXTRACT_FILE; diff --git a/Src/Prodos_Extract.c b/Src/Prodos_Extract.c index 74632c4..b7ad717 100644 --- a/Src/Prodos_Extract.c +++ b/Src/Prodos_Extract.c @@ -18,14 +18,22 @@ #include "Dc_Prodos.h" #include "os/os.h" #include "Prodos_Extract.h" +#include "File_AppleSingle.h" -static int CreateOutputFile(struct prodos_file *,char *); +static int CreateOutputFile(struct prodos_file *,char *, bool); static void SetFileInformation(char *,struct prodos_file *); -/**************************************************************/ -/* ExtractOneFile() : Extrait un fichier Prodos sur disque. */ -/**************************************************************/ -void ExtractOneFile(struct prodos_image *current_image, char *prodos_file_path, char *output_directory_path) +/** + * Extracts one file + * + * @brief ExtractOneFile + * + * @param current_image + * @param prodos_file_path + * @param output_directory_path + * @param output_apple_single + */ +void ExtractOneFile(struct prodos_image *current_image, char *prodos_file_path, char *output_directory_path, bool output_apple_single) { int error; struct file_descriptive_entry *current_entry; @@ -55,7 +63,7 @@ void ExtractOneFile(struct prodos_image *current_image, char *prodos_file_path, } /** Création du fichier sur disque **/ - error = CreateOutputFile(current_file,output_directory_path); + error = CreateOutputFile(current_file,output_directory_path,output_apple_single); /* Libération mémoire */ mem_free_file(current_file); @@ -65,7 +73,7 @@ void ExtractOneFile(struct prodos_image *current_image, char *prodos_file_path, /************************************************************************/ /* ExtractFolderFiles() : Fonction récursive d'extraction de fichier. */ /************************************************************************/ -void ExtractFolderFiles(struct prodos_image *current_image, struct file_descriptive_entry *folder_entry, char *output_directory_path) +void ExtractFolderFiles(struct prodos_image *current_image, struct file_descriptive_entry *folder_entry, char *output_directory_path, bool output_apple_single) { int i, error; char *windows_folder_path; @@ -130,7 +138,7 @@ void ExtractFolderFiles(struct prodos_image *current_image, struct file_descript } /** Création du fichier sur disque **/ - error = CreateOutputFile(current_file,windows_folder_path); + error = CreateOutputFile(current_file,windows_folder_path,output_apple_single); /* Libération mémoire */ mem_free_file(current_file); @@ -153,7 +161,7 @@ void ExtractFolderFiles(struct prodos_image *current_image, struct file_descript printf(" + Extract Folder : %s\n",current_entry->file_path); /** Récursivité **/ - ExtractFolderFiles(current_image,current_entry,windows_folder_path); + ExtractFolderFiles(current_image,current_entry,windows_folder_path,output_apple_single); } /** Libération mémoire **/ @@ -164,7 +172,7 @@ void ExtractFolderFiles(struct prodos_image *current_image, struct file_descript /****************************************************************************/ /* ExtractVolumeFiles() : Fonction d'extraction des fichiers d'un volume. */ /****************************************************************************/ -void ExtractVolumeFiles(struct prodos_image *current_image, char *output_directory_path) +void ExtractVolumeFiles(struct prodos_image *current_image, char *output_directory_path, bool output_apple_single) { int i, error; char *windows_folder_path; @@ -228,7 +236,7 @@ void ExtractVolumeFiles(struct prodos_image *current_image, char *output_directo } /** Création du fichier sur disque **/ - error = CreateOutputFile(current_file,windows_folder_path); + error = CreateOutputFile(current_file,windows_folder_path, output_apple_single); /* Libération mémoire */ mem_free_file(current_file); @@ -251,7 +259,7 @@ void ExtractVolumeFiles(struct prodos_image *current_image, char *output_directo printf(" + Extract Folder : %s\n",current_entry->file_path); /** Récursivité **/ - ExtractFolderFiles(current_image,current_entry,windows_folder_path); + ExtractFolderFiles(current_image,current_entry,windows_folder_path,output_apple_single); } /** Libération mémoire **/ @@ -266,7 +274,7 @@ void ExtractVolumeFiles(struct prodos_image *current_image, char *output_directo * @param output_directory_path * @return */ -static int CreateOutputFile(struct prodos_file *current_file, char *output_directory_path) +static int CreateOutputFile(struct prodos_file *current_file, char *output_directory_path, bool output_apple_single) { int error; char directory_path[1024]; @@ -291,10 +299,13 @@ static int CreateOutputFile(struct prodos_file *current_file, char *output_direc strcat(file_data_path,current_file->entry->file_name_case); // Append the file type and auxtype extension - char extension[7]; - strcat(file_data_path, "#"); - sprintf(extension, "%02hhX%04hX", current_file->entry->file_type, current_file->entry->file_aux_type); - strcat(file_data_path, extension); + if (!output_apple_single) + { + char extension[7]; + strcat(file_data_path, "#"); + sprintf(extension, "%02hhX%04hX", current_file->entry->file_type, current_file->entry->file_aux_type); + strcat(file_data_path, extension); + } // ResourceFork path strcpy(file_resource_path,file_data_path); diff --git a/Src/Prodos_Extract.h b/Src/Prodos_Extract.h index 5d1c133..883d9ba 100644 --- a/Src/Prodos_Extract.h +++ b/Src/Prodos_Extract.h @@ -6,8 +6,10 @@ /* Auteur : Olivier ZARDINI * Brutal Deluxe Software * Dec 2011 */ /***********************************************************************/ -void ExtractOneFile(struct prodos_image *,char *,char *); -void ExtractFolderFiles(struct prodos_image *,struct file_descriptive_entry *,char *); -void ExtractVolumeFiles(struct prodos_image *,char *); +#include + +void ExtractOneFile(struct prodos_image *, char *, char *, bool); +void ExtractFolderFiles(struct prodos_image *, struct file_descriptive_entry *, char *, bool); +void ExtractVolumeFiles(struct prodos_image *, char *, bool); /***********************************************************************/ From 633394a524cdc4eff769fd8cb6f8ad5df454c38e Mon Sep 17 00:00:00 2001 From: David Stancu Date: Sun, 18 Mar 2018 09:50:08 -0400 Subject: [PATCH 11/18] wip --- Src/Dc_Prodos.h | 1 - Src/File_AppleSingle.c | 39 +++++++++++++++++++++++---------------- Src/File_AppleSingle.h | 9 +++++++-- Src/Prodos_Extract.c | 10 +++++++++- 4 files changed, 39 insertions(+), 20 deletions(-) diff --git a/Src/Dc_Prodos.h b/Src/Dc_Prodos.h index afe0517..292a2d2 100644 --- a/Src/Dc_Prodos.h +++ b/Src/Dc_Prodos.h @@ -249,7 +249,6 @@ struct file_descriptive_entry struct file_descriptive_entry *next; }; - struct prodos_file { int entry_type; /* Seedling, Sapling, Tree, Extended */ diff --git a/Src/File_AppleSingle.c b/Src/File_AppleSingle.c index bd0a8d8..a1bf85b 100644 --- a/Src/File_AppleSingle.c +++ b/Src/File_AppleSingle.c @@ -1,7 +1,6 @@ #include "File_AppleSingle.h" const unsigned char AS_MAGIC[] = {0x00, 0x05, 0x16, 0x00}; -const unsigned char AS_VERSION[] = {0x00, 0x02, 0x00, 0x00}; static uint32_t as_field32(uint32_t num) { @@ -104,7 +103,7 @@ void ASDecorateDataFork(struct prodos_file *current_file, unsigned char *data, a unsigned char *data_entry = malloc(data_fork_entry->length); memcpy(data_entry, data + data_fork_entry->offset, data_fork_entry->length); - current_file->data = data; + current_file->data = data_entry; return; } @@ -163,31 +162,35 @@ void ASDecorateProdosFile(struct prodos_file *current_file, unsigned char *data) return; } -char *ASFromProdosFile(struct prodos_file *file) +struct as_from_prodos ASFromProdosFile(struct prodos_file *file) { struct as_file_header *as_header = malloc(sizeof(as_file_header)); - as_header->magic = as_field32(AS_MAGIC); - as_header->version = as_field32(AS_VERSION); + memcpy(&as_header->magic, AS_MAGIC, sizeof(AS_MAGIC)); + as_header->version = as_field32(2); as_header->num_entries = as_field16(2); int header_offset = sizeof(as_file_header) + 2 * sizeof(as_file_entry); struct as_file_entry *data_entry = malloc(sizeof(as_file_entry)); - data_entry->entry_id = as_field_32(as_data_fork); - data_entry->length = as_field_32(sizeof(file->data)); - data_entry->offset = as_field_32(header_offset); + data_entry->entry_id = as_field32(data_fork); + data_entry->length = as_field32(sizeof(file->data)); + data_entry->offset = as_field32(header_offset); - int prodos_entry_offset = header_offset + sizeof(file->data); + int prodos_entry_offset = header_offset + file->data_length; struct as_file_entry *prodos_entry = malloc(sizeof(as_file_entry)); - prodos_entry->entry_id = as_field_32(prodos_file_info); - prodos_entry->length = as_field_32(sizeof(as_prodos_info)); - prodos_entry->offset = as_field_32(prodos_entry_offset); + prodos_entry->entry_id = as_field32(prodos_file_info); + prodos_entry->length = as_field32(sizeof(as_prodos_info)); + prodos_entry->offset = as_field32(prodos_entry_offset); struct as_prodos_info *prodos_info = malloc(sizeof(as_prodos_info)); prodos_info->access = file->access; prodos_info->filetype = file->type; prodos_info->auxtype = file->aux_type; - char *payload = malloc(prodos_entry_offset + sizeof(as_prodos_info)); + char *payload = malloc( + prodos_entry_offset + \ + sizeof(as_prodos_info) + \ + file->data_length + ); char *seek = payload; memcpy(seek, as_header, sizeof(as_file_header)); @@ -199,10 +202,14 @@ char *ASFromProdosFile(struct prodos_file *file) memcpy(seek, prodos_entry, sizeof(as_file_entry)); seek += sizeof(as_file_entry); - memcpy(seek, &file->data, sizeof(file->data)); - seek += sizeof(file->data); + memcpy(seek, &file->data, file->data_length); + seek += file->data_length; memcpy(seek, prodos_info, sizeof(as_prodos_info)); - return payload; + struct as_from_prodos as_file; + as_file.length = (seek + sizeof(as_prodos_info)) - payload; + as_file.data = payload; + + return as_file; } \ No newline at end of file diff --git a/Src/File_AppleSingle.h b/Src/File_AppleSingle.h index f7b37b5..3d0e591 100644 --- a/Src/File_AppleSingle.h +++ b/Src/File_AppleSingle.h @@ -18,7 +18,6 @@ #include "Dc_Prodos.h" const unsigned char AS_MAGIC[4]; -const unsigned char AS_VERSION[4]; #define IS_LITTLE_ENDIAN (uint32_t) AS_MAGIC != 0x00051600 @@ -64,6 +63,12 @@ typedef struct as_prodos_info DWORD auxtype; } as_prodos_info; +typedef struct as_from_prodos +{ + uint16_t length; + char *data; +} as_from_prodos; + #pragma pack(pop) bool ASIsAppleSingle(unsigned char *buf); @@ -76,4 +81,4 @@ void ASDecorateDataFork(struct prodos_file *current_file, unsigned char *data, a void ASDeocrateProdosFileInfo(struct prodos_file *current_file, unsigned char *data, as_file_entry *prodos_entry); void ASDecorateProdosFile(struct prodos_file *current_file, unsigned char *data); -char *ASFromProdosFile(struct prodos_file *file); \ No newline at end of file +struct as_from_prodos ASFromProdosFile(struct prodos_file *file); \ No newline at end of file diff --git a/Src/Prodos_Extract.c b/Src/Prodos_Extract.c index b7ad717..5d00d5e 100644 --- a/Src/Prodos_Extract.c +++ b/Src/Prodos_Extract.c @@ -314,7 +314,15 @@ static int CreateOutputFile(struct prodos_file *current_file, char *output_direc /**********************************/ /** Création du Fichier : Data **/ /**********************************/ - error = CreateBinaryFile(file_data_path,current_file->data,current_file->data_length); + + if (output_apple_single) + { + struct as_from_prodos as_file = ASFromProdosFile(current_file); + error = CreateBinaryFile(file_data_path, as_file.data, as_file.length); + } + else + error = CreateBinaryFile(file_data_path,current_file->data,current_file->data_length); + if(error) { printf(" Error : Can't create file '%s' on disk at location '%s'.\n",current_file->entry->file_name_case,file_data_path); From 9321b77c825d870e3837f37748a0294cf441d720 Mon Sep 17 00:00:00 2001 From: David Stancu Date: Sun, 18 Mar 2018 11:41:18 -0400 Subject: [PATCH 12/18] wip / some bugfixes --- Src/File_AppleSingle.c | 10 +++++++--- Src/File_AppleSingle.h | 5 ++--- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/Src/File_AppleSingle.c b/Src/File_AppleSingle.c index a1bf85b..2790f1d 100644 --- a/Src/File_AppleSingle.c +++ b/Src/File_AppleSingle.c @@ -1,6 +1,6 @@ #include "File_AppleSingle.h" -const unsigned char AS_MAGIC[] = {0x00, 0x05, 0x16, 0x00}; +const unsigned int AS_MAGIC = (uint32_t) 0x00051600; static uint32_t as_field32(uint32_t num) { @@ -20,7 +20,11 @@ static uint16_t as_field16(uint16_t num) */ bool ASIsAppleSingle(unsigned char *buf) { - return memcmp(&buf, &AS_MAGIC, sizeof(AS_MAGIC)); + int buf_magic; + memcpy(&buf_magic, buf, sizeof(AS_MAGIC)); + buf_magic = as_field32(buf_magic); + + return buf_magic == AS_MAGIC; } /** @@ -165,7 +169,7 @@ void ASDecorateProdosFile(struct prodos_file *current_file, unsigned char *data) struct as_from_prodos ASFromProdosFile(struct prodos_file *file) { struct as_file_header *as_header = malloc(sizeof(as_file_header)); - memcpy(&as_header->magic, AS_MAGIC, sizeof(AS_MAGIC)); + as_header->magic = as_field32(AS_MAGIC); as_header->version = as_field32(2); as_header->num_entries = as_field16(2); diff --git a/Src/File_AppleSingle.h b/Src/File_AppleSingle.h index 3d0e591..8de772f 100644 --- a/Src/File_AppleSingle.h +++ b/Src/File_AppleSingle.h @@ -17,9 +17,8 @@ #include "Dc_Shared.h" #include "Dc_Prodos.h" -const unsigned char AS_MAGIC[4]; - -#define IS_LITTLE_ENDIAN (uint32_t) AS_MAGIC != 0x00051600 +const unsigned int AS_MAGIC; +#define IS_LITTLE_ENDIAN true #pragma pack(1) From d2e341cd4686ac16350da0ebd540b0385a5ce677 Mon Sep 17 00:00:00 2001 From: David Stancu Date: Sun, 18 Mar 2018 18:24:03 -0400 Subject: [PATCH 13/18] almost working output --- Src/File_AppleSingle.c | 28 ++++++++++++++-------------- Src/File_AppleSingle.h | 4 ++-- Src/Main.c | 2 +- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Src/File_AppleSingle.c b/Src/File_AppleSingle.c index 2790f1d..429868b 100644 --- a/Src/File_AppleSingle.c +++ b/Src/File_AppleSingle.c @@ -108,6 +108,7 @@ void ASDecorateDataFork(struct prodos_file *current_file, unsigned char *data, a unsigned char *data_entry = malloc(data_fork_entry->length); memcpy(data_entry, data + data_fork_entry->offset, data_fork_entry->length); current_file->data = data_entry; + current_file->data_length = data_fork_entry->length; return; } @@ -170,13 +171,14 @@ struct as_from_prodos ASFromProdosFile(struct prodos_file *file) { struct as_file_header *as_header = malloc(sizeof(as_file_header)); as_header->magic = as_field32(AS_MAGIC); - as_header->version = as_field32(2); + for (int i = 0; i < 4; ++i) as_header->filler[i] = 0; + as_header->version = as_field32(0x00020000); as_header->num_entries = as_field16(2); - int header_offset = sizeof(as_file_header) + 2 * sizeof(as_file_entry); + int header_offset = sizeof(as_file_header) + (2 * sizeof(as_file_entry)); struct as_file_entry *data_entry = malloc(sizeof(as_file_entry)); data_entry->entry_id = as_field32(data_fork); - data_entry->length = as_field32(sizeof(file->data)); + data_entry->length = as_field32(file->data_length); data_entry->offset = as_field32(header_offset); int prodos_entry_offset = header_offset + file->data_length; @@ -186,15 +188,13 @@ struct as_from_prodos ASFromProdosFile(struct prodos_file *file) prodos_entry->offset = as_field32(prodos_entry_offset); struct as_prodos_info *prodos_info = malloc(sizeof(as_prodos_info)); - prodos_info->access = file->access; - prodos_info->filetype = file->type; - prodos_info->auxtype = file->aux_type; - - char *payload = malloc( - prodos_entry_offset + \ - sizeof(as_prodos_info) + \ - file->data_length - ); + prodos_info->access = as_field32(file->access); + prodos_info->filetype = as_field32(file->type); + prodos_info->auxtype = as_field32(file->aux_type); + + int payload_size = prodos_entry_offset + sizeof(as_prodos_info); + + char *payload = malloc(payload_size); char *seek = payload; memcpy(seek, as_header, sizeof(as_file_header)); @@ -206,13 +206,13 @@ struct as_from_prodos ASFromProdosFile(struct prodos_file *file) memcpy(seek, prodos_entry, sizeof(as_file_entry)); seek += sizeof(as_file_entry); - memcpy(seek, &file->data, file->data_length); + memcpy(seek, file->data, file->data_length); seek += file->data_length; memcpy(seek, prodos_info, sizeof(as_prodos_info)); struct as_from_prodos as_file; - as_file.length = (seek + sizeof(as_prodos_info)) - payload; + as_file.length = payload_size; as_file.data = payload; return as_file; diff --git a/Src/File_AppleSingle.h b/Src/File_AppleSingle.h index 8de772f..41e796d 100644 --- a/Src/File_AppleSingle.h +++ b/Src/File_AppleSingle.h @@ -18,9 +18,9 @@ #include "Dc_Prodos.h" const unsigned int AS_MAGIC; -#define IS_LITTLE_ENDIAN true +#define IS_LITTLE_ENDIAN 'APPL' == (uint32_t) 0x4150504C -#pragma pack(1) +#pragma pack(push, 1) typedef struct as_file_header { diff --git a/Src/Main.c b/Src/Main.c index 6c615b1..9e8323a 100644 --- a/Src/Main.c +++ b/Src/Main.c @@ -141,7 +141,7 @@ int main(int argc, char *argv[]) { /* Information */ printf(" - Extract file '%s'\n",param->prodos_file_path); - if (output_apple_single) printf(" - Creating AppleSingle file!"); + if (output_apple_single) printf(" - Creating AppleSingle file!\n"); /** Charge l'image 2mg **/ current_image = LoadProdosImage(param->image_file_path); From 6b32fe58acc988b1bef2293f61d9b7bbc665272d Mon Sep 17 00:00:00 2001 From: David Stancu Date: Sun, 18 Mar 2018 22:51:15 -0400 Subject: [PATCH 14/18] needs more testing, but supposedly working!!!!! --- Src/File_AppleSingle.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/Src/File_AppleSingle.c b/Src/File_AppleSingle.c index 429868b..f815ed7 100644 --- a/Src/File_AppleSingle.c +++ b/Src/File_AppleSingle.c @@ -175,25 +175,24 @@ struct as_from_prodos ASFromProdosFile(struct prodos_file *file) as_header->version = as_field32(0x00020000); as_header->num_entries = as_field16(2); - int header_offset = sizeof(as_file_header) + (2 * sizeof(as_file_entry)); + uint32_t header_offset = sizeof(as_file_header) + (2 * sizeof(as_file_entry)); struct as_file_entry *data_entry = malloc(sizeof(as_file_entry)); data_entry->entry_id = as_field32(data_fork); data_entry->length = as_field32(file->data_length); data_entry->offset = as_field32(header_offset); - int prodos_entry_offset = header_offset + file->data_length; + uint32_t prodos_entry_offset = header_offset + file->data_length; struct as_file_entry *prodos_entry = malloc(sizeof(as_file_entry)); prodos_entry->entry_id = as_field32(prodos_file_info); prodos_entry->length = as_field32(sizeof(as_prodos_info)); prodos_entry->offset = as_field32(prodos_entry_offset); struct as_prodos_info *prodos_info = malloc(sizeof(as_prodos_info)); - prodos_info->access = as_field32(file->access); - prodos_info->filetype = as_field32(file->type); - prodos_info->auxtype = as_field32(file->aux_type); - - int payload_size = prodos_entry_offset + sizeof(as_prodos_info); + prodos_info->access = as_field16(file->entry->access); + prodos_info->filetype = as_field16(file->entry->file_type); + prodos_info->auxtype = as_field32(file->entry->file_aux_type); + uint32_t payload_size = prodos_entry_offset + sizeof(as_prodos_info); char *payload = malloc(payload_size); char *seek = payload; From 436bffe0e83478f841f45aa2e4269808b38dc09a Mon Sep 17 00:00:00 2001 From: David Stancu Date: Sun, 18 Mar 2018 22:57:44 -0400 Subject: [PATCH 15/18] update readme --- README.md | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index b474f94..f100d06 100644 --- a/README.md +++ b/README.md @@ -37,8 +37,13 @@ Any and all contributions are welcome. Included is also a `cadius.pro` file you ## Changelog +#### 1.4.0 +- Adds AppleSingle file format support, with initial support for data and ProDOS file info IDs 1 & 11 ([#7](https://github.com/mach-kernel/cadius/issues/7)). +- Fix path bugs on Windows ([#9](https://github.com/mach-kernel/cadius/issues/9)). +- Fix buffer overflow from [#12](https://github.com/mach-kernel/cadius/issues/12). + #### 1.3.2 -- Maintenance release / macro cleanup +- Maintenance release / macro cleanup. #### 1.3.1 - Resolves timestamp bugs in [#10](https://github.com/mach-kernel/cadius/issues/10). Thanks, @a2-4am! @@ -48,17 +53,17 @@ Any and all contributions are welcome. Included is also a `cadius.pro` file you - `REPLACEFILE` command, `DELETEFILE` support for type/auxtype suffix. #### 1.2-b3 -- Fix Windows build issues, make some shared OS methods static / remove from `os.c` ([@mach-kernel](https://github.com/mach-kernel)) +- Fix Windows build issues, make some shared OS methods static / remove from `os.c` ([@mach-kernel](https://github.com/mach-kernel)). #### 1.2-b2 -- Clean up OS macros, explicit `win32` and `posix` modules ([@mach-kernel](https://github.com/mach-kernel)) +- Clean up OS macros, explicit `win32` and `posix` modules ([@mach-kernel](https://github.com/mach-kernel)). #### 1.2-b1 -- UTF-8 encode all source files -- Initial POSIX support ([@mach-kernel](https://github.com/mach-kernel)) +- UTF-8 encode all source files. +- Initial POSIX support ([@mach-kernel](https://github.com/mach-kernel)). #### 1.1 -- Initial fork from BrutalDeluxe +- Initial fork from BrutalDeluxe. ## License From 5c04eeea15d271b811a55cb19ced52097a667aee Mon Sep 17 00:00:00 2001 From: David Stancu Date: Mon, 19 Mar 2018 18:43:19 -0400 Subject: [PATCH 16/18] allow EXTRACTFOLDER and EXTRACTVOLUME to work --- Src/Main.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Src/Main.c b/Src/Main.c index 9e8323a..4c8e07c 100644 --- a/Src/Main.c +++ b/Src/Main.c @@ -163,6 +163,7 @@ int main(int argc, char *argv[]) { /* Information */ printf(" - Extract folder '%s' :\n",param->prodos_folder_path); + if (output_apple_single) printf(" - Creating AppleSingle files!\n"); /** Charge l'image 2mg **/ current_image = LoadProdosImage(param->image_file_path); @@ -197,6 +198,7 @@ int main(int argc, char *argv[]) /* Information */ printf(" - Extract volume '%s' :\n",current_image->volume_header->volume_name_case); + if (output_apple_single) printf(" - Creating AppleSingle files!\n"); /** Extrait les fichiers du volume **/ ExtractVolumeFiles( @@ -647,7 +649,7 @@ struct parameter *GetParamLine(int argc, char *argv[]) } /** EXTRACTFOLDER **/ - if(!my_stricmp(argv[1],"EXTRACTFOLDER") && argc == 5) + if(!my_stricmp(argv[1],"EXTRACTFOLDER") && argc >= 5) { param->action = ACTION_EXTRACT_FOLDER; @@ -673,7 +675,7 @@ struct parameter *GetParamLine(int argc, char *argv[]) } /** EXTRACTVOLUME **/ - if(!my_stricmp(argv[1],"EXTRACTVOLUME") && argc == 4) + if(!my_stricmp(argv[1],"EXTRACTVOLUME") && argc >= 4) { param->action = ACTION_EXTRACT_VOLUME; From 094ce66b60431c6363fcda07c3a03f81481812a4 Mon Sep 17 00:00:00 2001 From: David Stancu Date: Mon, 19 Mar 2018 18:52:11 -0400 Subject: [PATCH 17/18] fix an extractvolume bug! --- README.md | 1 + Src/Prodos_Extract.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/README.md b/README.md index f100d06..b18e5aa 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,7 @@ Any and all contributions are welcome. Included is also a `cadius.pro` file you - Adds AppleSingle file format support, with initial support for data and ProDOS file info IDs 1 & 11 ([#7](https://github.com/mach-kernel/cadius/issues/7)). - Fix path bugs on Windows ([#9](https://github.com/mach-kernel/cadius/issues/9)). - Fix buffer overflow from [#12](https://github.com/mach-kernel/cadius/issues/12). +- Fix segfault when using `EXTRACTVOLUME`. #### 1.3.2 - Maintenance release / macro cleanup. diff --git a/Src/Prodos_Extract.c b/Src/Prodos_Extract.c index 5d00d5e..b23d750 100644 --- a/Src/Prodos_Extract.c +++ b/Src/Prodos_Extract.c @@ -429,6 +429,8 @@ static void SetFileInformation(char *file_information_path, struct prodos_file * /** Ajouts des lignes existantes **/ for(i=0; i Date: Thu, 22 Mar 2018 22:54:12 -0400 Subject: [PATCH 18/18] don't generate fileinformation.txt if exporting as applesingle --- README.md | 2 ++ Src/Prodos_Extract.c | 10 +++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b18e5aa..4f5446a 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,8 @@ Any and all contributions are welcome. Included is also a `cadius.pro` file you - Fix buffer overflow from [#12](https://github.com/mach-kernel/cadius/issues/12). - Fix segfault when using `EXTRACTVOLUME`. +A big thank you to [@oliverschmidt](https://github.com/oliverschmidt) for helping test this release! + #### 1.3.2 - Maintenance release / macro cleanup. diff --git a/Src/Prodos_Extract.c b/Src/Prodos_Extract.c index b23d750..cec6efa 100644 --- a/Src/Prodos_Extract.c +++ b/Src/Prodos_Extract.c @@ -340,9 +340,13 @@ static int CreateOutputFile(struct prodos_file *current_file, char *output_direc #endif /** Ajoute des informations du fichier dans le fichier FileInformation.txt **/ - strcpy(file_information_path,directory_path); - strcat(file_information_path,"_FileInformation.txt"); - SetFileInformation(file_information_path,current_file); + + if (!output_apple_single) + { + strcpy(file_information_path,directory_path); + strcat(file_information_path,"_FileInformation.txt"); + SetFileInformation(file_information_path,current_file); + } /**************************************/ /** Création du Fichier : Resource **/