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
|
;
; Christian Groessler, Jan-2003
;
; int open(const char *name,int flags,...);
;
.include "atari.inc"
.include "fcntl.inc"
.include "errno.inc"
.include "fd.inc"
.include "zeropage.inc"
.export _open
.destructor closeallfiles, 5
.import _close
.import clriocb
.import fddecusage,newfd
.import findfreeiocb
.import incsp4
.import ldaxysp,addysp
.import __oserror
.ifdef UCASE_FILENAME
.import ucase_fn
.endif
.proc _open
dey ; parm count < 4 shouldn't be needed to be checked
dey ; (it generates a c compiler warning)
dey
dey
beq parmok ; parameter count ok
jsr addysp ; fix stack, throw away unused parameters
parmok: jsr findfreeiocb
beq iocbok ; we found one
lda #<EMFILE ; "too many open files"
seterr: jsr __directerrno
jsr incsp4 ; clean up stack
lda #$FF
tax
rts ; return -1
; process the mode argument
iocbok: stx tmp4
jsr clriocb ; init with zero
ldy #1
jsr ldaxysp ; get mode
ldx tmp4
pha
and #O_APPEND
beq no_app
pla
and #15
cmp #O_RDONLY ; DOS supports append with write-only only
beq invret
cmp #O_RDWR
beq invret
lda #OPNOT|APPEND
bne set
.ifndef UCASE_FILENAME
invret: lda #<EINVAL ; file name is too long
jmp seterr
.endif
no_app: pla
and #15
cmp #O_RDONLY
bne l1
lda #OPNIN
set: sta ICAX1,x
bne cont
l1: cmp #O_WRONLY
bne l2
lda #OPNOT
bne set
l2: ; O_RDWR
lda #OPNOT|OPNIN
bne set
; process the filename argument
cont: ldy #3
jsr ldaxysp
.ifdef UCASE_FILENAME
.ifdef DEFAULT_DEVICE
ldy #$80
.else
ldy #$00
.endif
sty tmp2 ; set flag for ucase_fn
jsr ucase_fn
bcc ucok1
invret: lda #<EINVAL ; file name is too long
jmp seterr
ucok1:
.endif ; defined UCASE_FILENAME
ldy tmp4
;AX - points to filename
;Y - iocb to use, if open needed
jsr newfd ; maybe we don't need to open and can reuse an iocb
; returns fd num to use in tmp2, all regs unchanged
bcs doopen ; C set: open needed
lda #0 ; clears N flag
beq finish
doopen: sta ICBAL,y
txa
sta ICBAH,y
ldx tmp4
lda #OPEN
sta ICCOM,x
jsr CIOV
; clean up the stack
finish: php
txa
pha
tya
pha
.ifdef UCASE_FILENAME
ldy tmp3 ; get size
jsr addysp ; free used space on the stack
.endif ; defined UCASE_FILENAME
jsr incsp4 ; clean up stack
pla
tay
pla
tax
plp
bpl ok
sty tmp3 ; remember error code
lda #CLOSE
sta ICCOM,x
jsr CIOV ; close IOCB again since open failed
jsr fddecusage ; and decrement usage counter of fd
lda tmp3 ; put error code into A
jmp __mappederrno
ok: lda tmp2 ; get fd
ldx #0
stx __oserror
rts
.endproc
; closeallfiles: Close all files opened by the program.
.proc closeallfiles
lda #MAX_FD_INDEX-1
loop: ldx #0
pha
jsr _close
pla
clc
sbc #0
bpl loop
rts
.endproc
|