lclevy / ADFlib

A free, portable and open implementation of the Amiga filesystem
GNU General Public License v2.0
84 stars 29 forks source link

adfEndOfFile() never triggers and adfFileRead only gives "blank" data #71

Closed flpDiskJ closed 7 months ago

flpDiskJ commented 7 months ago

Trying to write my own command line tool using this library and I'm having some weird issues. Firstly adfEndOfFile() never triggers so the program gets stuck in the while loop and continues to make the output file larger. Note: push() should add a file to the currently opened adf and pull() should extract a file from the adf. Second issue is when trying to extract a file from the adf (manually setting the byte limit to get around the first issue) adfFileRead() seems to only output zeroed bytes. There's a good chance I'm just doing something wrong but I can't figure out anything more from the seemingly outdated API.

void push()
{
    if (!adf_open)
    {
        printf("        No ADF open!\n");
        return;
    }
    char filename[INPUT_MAX];
    printf("Filename: ");
    scanf("%s", &filename);
    FILE *fp = fopen(&filename[0], "rb");
    if (!fp)
    {
        printf("        Failed to read file!\n");
        return;
    }
    struct AdfFile *afp = adfFileOpen(vol, &filename[0], 'w');
    if (!afp)
    {
        printf("        Failed to create file!\n");
        fclose(fp);
        return;
    }
    uint8_t byte;
    int byte_return = 0;
    while (1)
    {
        fread(&byte, 1, 1, fp);
        byte_return = adfFileWrite(afp, 1, &byte);
        if (byte_return != 1)
        {
            printf("        Disk Write Error.\n");
            break;
        }
        if (feof(fp))
        {
            break;
        }
    }
    adfFileClose(afp);
    fclose(fp);
}

void pull()
{
    if (!adf_open)
    {
        printf("        No ADF open!\n");
        return;
    }
    char filename[INPUT_MAX];
    printf("Filename: ");
    scanf("%s", &filename);
    FILE *fp = fopen(&filename[0], "wb");
    if (!fp)
    {
        printf("        Failed to open output file!\n");
        return;
    }
    struct AdfFile *afp = adfFileOpen(vol, &filename[0], 'r');
    if (!afp)
    {
        printf("        Failed to open file!\n");
        fclose(fp);
        return;
    }
    uint8_t byte;
    while (!adfEndOfFile(afp))
    {
        adfFileRead(afp, 1, &byte);
        fwrite(&byte, 1, 1, fp);
    }
    adfFileClose(afp);
    fclose(fp);
}
t-w commented 7 months ago

Hi,

For sure, there is one thing incorrect: the use of "r" and "w" with adfFileOpen. Have a look at the file adf_file.h, there is a list of modes for opening the file.

This is kind of our (my) fault, as the documentation is still not updated after many changes done... Not enough time for that, yet. Sorry about that. Please have a look at examples and .h files to be sure about the current API.

Second thing: when doing I/O operations, like opening/reading/writing files, always check the status of the operation. Checking them will help you to catch and to debug where the problem is. In your code, you do not check the result of adfFileRead() (not sure, but you might have had the file opened for writing only, due to the problem above...).

A tip: enable and read carefully all warnings that are shown, for instance with GCC:

$ cc -c -Wall -Wextra -pedantic push.c -o push.o
push.c: In function ‘push’:
push.c:66:13: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘char (*)[256]’ [-Wformat=]
   66 |     scanf("%s", &filename);
      |            ~^   ~~~~~~~~~
      |             |   |
      |             |   char (*)[256]
      |             char *

and make them disappear (fix reported problems) - unless you are 100% sure what you are doing...

Let know if this helped.

flpDiskJ commented 7 months ago

Thanks for the info. I'll give it a go and report back.

flpDiskJ commented 7 months ago

Yep you were right! Instead of 'w' and 'r' it is 1 for read and 2 for write.

typedef enum {
    ADF_FILE_MODE_READ      = 0x01,   /* 01 */
    ADF_FILE_MODE_WRITE     = 0x02,   /* 10 */
    //ADF_FILE_MODE_READWRITE = 0x03    /* 11 */
} AdfFileMode;