1;
2; Ullrich von Bassewitz, 16.11.2002
3;
4; int open (const char* name, int flags, ...);  /* May take a mode argument */
5
6
7        .export         _open
8        .destructor     closeallfiles, 5
9
10        .import         addysp, popax
11        .import         scratch, fnparse, fnaddmode, fncomplete, fnset
12        .import         opencmdchannel, closecmdchannel, readdiskerror
13        .import         fnunit, fnisfile
14        .import         _close
15        .importzp       sp, tmp2, tmp3
16
17        .include        "errno.inc"
18        .include        "fcntl.inc"
19        .include        "filedes.inc"
20        .include        "cbm.inc"
21
22
23;--------------------------------------------------------------------------
24; closeallfiles: Close all open files.
25
26.proc   closeallfiles
27
28        ldx     #MAX_FDS-1
29loop:   lda     fdtab,x
30        beq     next            ; Skip unused entries
31
32; Close this file
33
34        txa
35        pha                     ; Save current value of X
36        ldx     #0
37        jsr     _close
38        pla
39        tax
40
41; Next file
42
43next:   dex
44        bpl     loop
45
46        rts
47
48.endproc
49
50;--------------------------------------------------------------------------
51; _open
52
53.proc   _open
54
55; Throw away any additional parameters passed through the ellipsis
56
57        dey                     ; Parm count < 4 shouldn't be needed to be...
58        dey                     ; ...checked (it generates a c compiler warning)
59        dey
60        dey
61        beq     parmok          ; Branch if parameter count ok
62        jsr     addysp          ; Fix stack, throw away unused parameters
63
64; Parameters ok. Pop the flags and save them into tmp3
65
66parmok: jsr     popax           ; Get flags
67        sta     tmp3
68
69; Get the filename from stack and parse it. Bail out if is not ok
70
71        jsr     popax           ; Get name
72        jsr     fnparse         ; Parse it
73        tax
74        bne     oserror         ; Bail out if problem with name
75
76; Get a free file handle and remember it in tmp2
77
78        jsr     freefd
79        lda     #EMFILE         ; Load error code
80        bcs     seterrno        ; Jump in case of errors
81        stx     tmp2
82
83; Check the flags. We cannot have both, read and write flags set, and we cannot
84; open a file for writing without creating it.
85
86        lda     tmp3
87        and     #(O_RDWR | O_CREAT)
88        cmp     #O_RDONLY       ; Open for reading?
89        beq     doread          ; Yes: Branch
90        cmp     #(O_WRONLY | O_CREAT)   ; Open for writing?
91        beq     dowrite
92
93; Invalid open mode
94
95        lda     #EINVAL
96
97; Error entry. Sets _errno, clears _oserror, returns -1
98
99seterrno:
100        jmp     __directerrno
101
102; Error entry: Close the file and exit. OS error code is in A on entry
103
104closeandexit:
105        pha
106        lda     tmp2
107        clc
108        adc     #LFN_OFFS
109        jsr     CLOSE
110        ldx     fnunit
111        jsr     closecmdchannel
112        pla
113
114; Error entry: Set oserror and errno using error code in A and return -1
115
116oserror:jmp     __mappederrno
117
118; Read bit is set. Add an 'r' to the name
119
120doread: lda     #'r'
121        jsr     fnaddmode       ; Add the mode to the name
122        lda     #LFN_READ
123        bne     common          ; Branch always
124
125; If O_TRUNC is set, scratch the file, but ignore any errors
126
127dowrite:
128        lda     tmp3
129        and     #O_TRUNC
130        beq     notrunc
131        jsr     scratch
132
133; Complete the the file name. Check for append mode here.
134
135notrunc:
136        lda     tmp3            ; Get the mode again
137        and     #O_APPEND       ; Append mode?
138        bne     append          ; Branch if yes
139
140; Setup the name for create mode
141
142        lda     #'w'
143        jsr     fncomplete      ; Add type and mode to the name
144        jmp     appendcreate
145
146; Append bit is set. Add an 'a' to the name
147
148append: lda     #'a'
149        jsr     fnaddmode       ; Add open mode to file name
150appendcreate:
151        lda     #LFN_WRITE
152
153; Common read/write code. Flags in A, handle in tmp2
154
155common: sta     tmp3
156        jsr     fnset           ; Set the file name
157
158        lda     tmp2
159        clc
160        adc     #LFN_OFFS
161        ldx     fnunit
162        ldy     fnisfile        ; Is this a standard file on disk?
163        beq     nofile          ; Branch if not
164        tay                     ; Use the LFN also as SA for files
165nofile:                         ; ... else use SA=0 (read)
166        jsr     SETLFS          ; Set the file params
167
168        jsr     OPEN
169        bcs     oserror
170
171; Open the the drive command channel and read it
172
173        ldx     fnunit
174        jsr     opencmdchannel
175        bne     closeandexit
176        ldx     fnunit
177        jsr     readdiskerror
178        bne     closeandexit    ; Branch on error
179
180; File is open. Mark it as open in the table
181
182        ldx     tmp2
183        lda     tmp3
184        sta     fdtab,x
185        lda     fnunit
186        sta     unittab,x       ; Remember
187
188; Done. Return the handle in a/x
189
190        txa                     ; Handle
191        ldx     #0
192        stx     __oserror       ; Clear _oserror
193        rts
194
195.endproc
196
197