File: readdir.c

package info (click to toggle)
cc65 2.19-2
  • links: PTS
  • area: main
  • in suites: forky, sid, trixie
  • size: 20,268 kB
  • sloc: ansic: 117,151; asm: 66,339; pascal: 4,248; makefile: 1,009; perl: 607
file content (132 lines) | stat: -rw-r--r-- 3,501 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/*
** Ullrich von Bassewitz, 2012-05-30. Based on code by Groepaz.
*/



#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <cbm.h>
#include "dir.h"

#include <stdio.h>


struct dirent* __fastcall__ readdir (register DIR* dir)
{
    register unsigned char* b;
    register unsigned char i;
    register unsigned char count;
    static unsigned char s;
    static unsigned char j;
    unsigned char buffer[0x40];
    static struct dirent entry;


    /* Remember the directory offset for this entry */
    entry.d_off = dir->off;

    /* Skip the basic line-link */
    if (!_dirread (dir, buffer, 2)) {
        /* errno already set */
        goto exitpoint;
    }

    /* Read the number of blocks */
    if (!_dirread (dir, &entry.d_blocks, sizeof (entry.d_blocks))) {
        goto exitpoint;
    }

    /* Read the next file entry into the buffer */
    for (count = 0, b = buffer; count < sizeof (buffer); ++b) {
        if (!_dirread1 (dir, b)) {
            goto exitpoint;
        }
        ++count;
        if (*b == '\0') {
            break;
        }
    }

    /* Bump the directory offset and include the bytes for line-link and size */
    dir->off += count + 4;

    /* End of directory is reached if the buffer contains "blocks free". It is
    ** sufficient here to check for the leading 'b'. buffer will contain at
    ** least one byte if we come here.
    */
    if (buffer[0] == 'b') {
        goto exitpoint;
    }

    /* Parse the buffer for the filename and file type */
    i = 0;
    j = 0;
    s = 0;
    b = buffer;
    while (i < count) {
        switch (s) {

            case 0:
                /* Searching for start of file name */
                if (*b == '"') {
                    s = 1;
                }
                break;

            case 1:
                /* Within file name */
                if (*b == '"') {
                    /* End of file name found. */
                    entry.d_name[j] = '\0';
                    entry.d_namlen = j;
                    if (entry.d_off > 2) {
                        /* Proceed with file type */
                        s = 2;
                    } else {
                        /* This is a disk header, so we're done */
                        entry.d_type = _CBM_T_HEADER;
                        return &entry;
                    }
                } else if (j < sizeof (entry.d_name) - 1) {
                    entry.d_name[j] = *b;
                    ++j;
                }
                break;

            case 2:
                /* Searching for file type */
                if (*b != ' ') {
                    entry.d_type = _cbm_filetype (*b);
                    if (*b == 'd') {
                        /* May be DEL or DIR, check next char */
                        s = 3;
                    } else {
                        /* Done */
                        return &entry;
                    }
                }
                break;

            case 3:
                /* Distinguish DEL or DIR file type entries */
                switch (*b) {
                    case 'e':                                   break;
                    case 'i': entry.d_type = _CBM_T_DIR;        break;
                    default:  entry.d_type = _CBM_T_OTHER;      break;
                }
                return &entry;
        }
        ++i;
        ++b;
    }

    /* Something went wrong when parsing the directory entry */
    _errno = EIO;
exitpoint:
    return 0;
}