1 (edited by Xalior 2018-05-29 11:25:11)

Topic: POSIX API Experimentation - ls.c

This may be a question for the z88dk forum, I'm not sure, but I thought I'd try here first - please excuse me if I am in the wrong place...

I wanted to experiment with the POSIX API, so have been trying to reduce each use case to as simple an example as I could, to make them easier to explain to others....

In that regard some of the GNU tools seemed obvious, and thought I would *TRY* and do some tutorials, simple goals with with excessive commenting, to help other users get started with the filesystem access from z88dk.

So, far from perfect here is my first very-most-simple port of ls.c, the objective is to purely get me a list of files in the current folder... https://gist.github.com/Xalior/11f4f129 … 027f850dfd

Enclosed inline for ease, but github has syntax highlights, etc.

#include <stdio.h>
#include <stdlib.h>
#include <input.h>
#include <arch/zx.h>
#include <arch/zx/esxdos.h>

void main() {
    unsigned char *cwd[128];
    char *curr_dir = NULL;
    unsigned char *dp = NULL;
    struct esxdos_dirent *dptr = NULL;
    unsigned int count = 0;

    // Get the value of environment variable PWD

    if(NULL == cwd)
        printf("\n ERROR : Could not get the working directory\n");
        return -1;
    } else {
        printf(" CWD   : %s\n", cwd);

    // Open the current directory
    dp = esxdos_f_opendir(cwd);
    if(NULL == dp)
        printf("\n ERROR : Could not open the working directory.\n");
        return -1;
    } else {
        printf(" DONE  : Opened the working directory. (%d)\n", dp);

    // Go through and display all the names (files or folders)
    // Contained in the directory.
    for(count = 0; NULL != (esxdos_f_readdir(dp, dptr)); count++)
        printf("Entry #%u: %u\n",count, *dptr->dir);
        printf("Str@1 #%u: %s\n",count, *dptr+sizeof(unsigned char));
    return 0;

Compiled with:

zcc +zx -vn -startup=30 -clib=new LS.c -o LS -subtype=dot -create-app

When I run the code I seem to end in an almost infinite loop with no filenames output.

The "logic" of '*dptr+sizeof(unsigned char)' is derived from reading the structure itself in the ESXDOS header code, to try and figure out the shape...

Can someone please give me a shove in the right direction? Hopefully that will be enough to unstick me...


Edited:  to fix a typo, and clarify source of sizeof logics.


Re: POSIX API Experimentation - ls.c

I think you've probably already solved this but just by coincidence I wrote a similar test program "dir.c" that is now in the zx next examples directory:

https://github.com/z88dk/z88dk/tree/mas … zxn/esxdos

It's not compiled as a dot command but as an sna snapshot that is a fast way to run stuff on the next.

// zcc +zxn -v -clib=sdcc_iy -SO3 --max-allocs-per-node200000 dir.c -o dir -subtype=sna -Cz"--clean" -create-app
// zcc +zxn -v -clib=new dir.c -o dir -subtype=sna -Cz"--clean" -create-app

#include <stdio.h>
#include <arch/zxn/esxdos.h>
#include <time.h>
#include <errno.h>

#pragma printf = "%B %s %lu %u"

struct esx_dirent_lfn file;
struct tm dt;

unsigned char cwd[ESX_PATHNAME_MAX+1];

void main(void)
   unsigned char dirh;
   printf("CWD: %s\n", cwd);
   dirh = esx_f_opendir_ex(cwd, ESX_DIR_USE_LFN);
   while (esx_f_readdir(dirh, &file) && (errno == 0))
      struct esx_dirent_slice *slice;

      slice = esx_slice_dirent(&file);
      tm_from_dostm(&dt, &slice->time);
      printf("attr: %08B\n", file.attr);
      printf("name: %s\n", file.name);
      printf("size: %lu\n", slice->size);
      printf("date: %02u/%02u/%u\n", dt.tm_mday, dt.tm_mon, dt.tm_year + 1900);
      printf("time: %02u:%02u:%02u\n", dt.tm_hour, dt.tm_min, dt.tm_sec);

This is using the nextos-esxdos api (everything is prefixed with "esx_*" instead of "esxdos_*") but the esxdos subset should work on esxdos too.  I will be bringing up the proper esxdos interface to the same level as soon as I can but in the meantime, as experiment, this nextos-esx interface is also available to the +zx target through arch/zx/esxdos.h.

The above is using lfn but this can be changed to 8.3 by using "esx_opendir()" instead of "esx_opendir_ex()".

The structure for directory entries varies a little depending on whether you ask for plus3 headers and/or lfn (nextos only) in the opendir call.  Normally you wouldn't want either option in esxdos so you would end up getting a "struct esx_dirent" that represents a directory entry and would be filled in by readdir().  All these directory entries have a variable-length zero terminated filename embedded in them so there is a function "esx_slice_dirent()" that will skip past the variable length part can give you access to the file size and datetime that follow.