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 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
|
;
; Ullrich von Bassewitz, 16.11.2002
;
; int open (const char* name, int flags, ...); /* May take a mode argument */
.export _open
.destructor closeallfiles, 5
.import addysp, popax
.import scratch, fnparse, fnaddmode, fncomplete, fnset
.import opencmdchannel, closecmdchannel, readdiskerror
.import fnunit, fnisfile
.import _close
.importzp sp, tmp2, tmp3
.include "errno.inc"
.include "fcntl.inc"
.include "filedes.inc"
.include "cbm.inc"
;--------------------------------------------------------------------------
; closeallfiles: Close all open files.
.proc closeallfiles
ldx #MAX_FDS-1
loop: lda fdtab,x
beq next ; Skip unused entries
; Close this file
txa
pha ; Save current value of X
ldx #0
jsr _close
pla
tax
; Next file
next: dex
bpl loop
rts
.endproc
;--------------------------------------------------------------------------
; _open
.proc _open
; Throw away any additional parameters passed through the ellipsis
dey ; Parm count < 4 shouldn't be needed to be...
dey ; ...checked (it generates a c compiler warning)
dey
dey
beq parmok ; Branch if parameter count ok
jsr addysp ; Fix stack, throw away unused parameters
; Parameters ok. Pop the flags and save them into tmp3
parmok: jsr popax ; Get flags
sta tmp3
; Get the filename from stack and parse it. Bail out if is not ok
jsr popax ; Get name
jsr fnparse ; Parse it
tax
bne oserror ; Bail out if problem with name
; Get a free file handle and remember it in tmp2
jsr freefd
lda #EMFILE ; Load error code
bcs seterrno ; Jump in case of errors
stx tmp2
; Check the flags. We cannot have both, read and write flags set, and we cannot
; open a file for writing without creating it.
lda tmp3
and #(O_RDWR | O_CREAT)
cmp #O_RDONLY ; Open for reading?
beq doread ; Yes: Branch
cmp #(O_WRONLY | O_CREAT) ; Open for writing?
beq dowrite
; Invalid open mode
lda #EINVAL
; Error entry. Sets _errno, clears _oserror, returns -1
seterrno:
jmp __directerrno
; Error entry: Close the file and exit. OS error code is in A on entry
closeandexit:
pha
lda tmp2
clc
adc #LFN_OFFS
jsr CLOSE
ldx fnunit
jsr closecmdchannel
pla
; Error entry: Set oserror and errno using error code in A and return -1
oserror:jmp __mappederrno
; Read bit is set. Add an 'r' to the name
doread: lda #'r'
jsr fnaddmode ; Add the mode to the name
lda #LFN_READ
bne common ; Branch always
; If O_TRUNC is set, scratch the file, but ignore any errors
dowrite:
lda tmp3
and #O_TRUNC
beq notrunc
jsr scratch
; Complete the the file name. Check for append mode here.
notrunc:
lda tmp3 ; Get the mode again
and #O_APPEND ; Append mode?
bne append ; Branch if yes
; Setup the name for create mode
lda #'w'
jsr fncomplete ; Add type and mode to the name
jmp appendcreate
; Append bit is set. Add an 'a' to the name
append: lda #'a'
jsr fnaddmode ; Add open mode to file name
appendcreate:
lda #LFN_WRITE
; Common read/write code. Flags in A, handle in tmp2
common: sta tmp3
jsr fnset ; Set the file name
lda tmp2
clc
adc #LFN_OFFS
ldx fnunit
ldy fnisfile ; Is this a standard file on disk?
beq nofile ; Branch if not
tay ; Use the LFN also as SA for files
nofile: ; ... else use SA=0 (read)
jsr SETLFS ; Set the file params
jsr OPEN
bcs oserror
; Open the the drive command channel and read it
ldx fnunit
jsr opencmdchannel
bne closeandexit
ldx fnunit
jsr readdiskerror
bne closeandexit ; Branch on error
; File is open. Mark it as open in the table
ldx tmp2
lda tmp3
sta fdtab,x
lda fnunit
sta unittab,x ; Remember
; Done. Return the handle in a/x
txa ; Handle
ldx #0
stx __oserror ; Clear _oserror
rts
.endproc
|