aboutsummaryrefslogtreecommitdiff
path: root/sys/fio/fwtacc.x
blob: bcedcae01931566478a491e25f61ee634fafa158 (plain) (blame)
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
# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.

include	<config.h>
include	<syserr.h>
include <finfo.h>
include	<fio.h>

define	MIN_DELAY	1
define	MAX_DELAY	60
define	INC_DELAY	1
define	SOMEFILE	"hlib$iraf.h"


# FWTACC -- Called if a file open fails.  Determine if failure to open file
# was due to the file already being open by another task.  If so, and file
# waiting is enabled in the environment, wait for file to become accessible,
# otherwise take error action.

procedure fwtacc (fd, fname)

int	fd				#I file we are trying to open
char	fname[ARB]			#I name of file

bool	locked
pointer	sp, osfn
int	perm, delay, chan, status, ofd
long	fi[LEN_FINFO]

int	access(), finfo()
bool	streq(), envgetb()
errchk	filerr, fmapfn
include	<fio.com>
define	noacc_ 91

begin
	call smark (sp)
	call salloc (osfn, SZ_PATHNAME, TY_CHAR)

	fp = fiodes[fd]
	if (FMODE(fp) == NEW_FILE)
	    call filerr (fname, SYS_FOPEN)

	# If file is blocked for some reason because it is already open
	# by this process, waiting would result in a deadlock.

	for (ofd=FIRST_FD;  ofd <= LAST_FD;  ofd=ofd+1)
	    if (ofd != fd && fiodes[ofd] != NULL)
		if (streq (fname, FNAME(fiodes[ofd])))
		    call filerr (fname, SYS_FWTOPNFIL)

	# If file waiting is enabled, the file exists and has write permission
	# for us but is not writable at the moment, wait for the file to
	# become available.  FINFO is used to determine the "permanent"
	# permissions for the file and the file owner.  ACCESS determines the
	# runtime accessibility of the file.  The permanent file protection may
	# permit writing but the file may not be accessible for writing at
	# runtime if opened for exclusive access by another process.

	if (finfo (fname, fi) == ERR)
	    call filerr (fname, SYS_FOPNNEXFIL)

	# Directory files are not accessible as files.
	if (FI_TYPE(fi) == FI_DIRECTORY)
	    goto noacc_

	# Test if we the open failed because we cannot physically open any
	# more files.

	call fmapfn (SOMEFILE, Memc[osfn], SZ_PATHNAME)
	call zopntx (Memc[osfn], READ_ONLY, chan)
	if (chan == ERR)
	    call filerr (fname, SYS_FTOOMANYFILES)
	else
	    call zclstx (chan, status)

	# If the file exists, we cannot access it, and there is no temporary
	# read or write lock in place on the file, then the file cannot be
	# accessed.

	perm = FI_PERM(fi)
	locked = false
	if (and (fflags[fd], FF_READ) != 0)
	    locked = locked || (and (perm, FF_RDLOCK) != 0)
	if (and (fflags[fd], FF_WRITE) != 0)
	    locked = locked || (and (perm, FF_WRLOCK) != 0)

	# If filewait is enabled, wait for the file to become accessible.
	if (envgetb ("filewait") && locked) {
	    call putline (STDERR, "Waiting for access to file '")
	    call putline (STDERR, fname)
	    call putline (STDERR, "'\n")

	    for (delay=MIN_DELAY;  delay > 0;  delay=delay+INC_DELAY) {
		call tsleep (min (delay, MAX_DELAY))

		if (access (fname,0,0) == NO)
		    call filerr (fname, SYS_FOPNNEXFIL)
		else if (access (fname,FMODE(fp),0) == YES) {
		    call sfree (sp)
		    return
		}
		
		# Verify that the file is still locked.
		if (finfo (fname, fi) == ERR)
		    call filerr (fname, SYS_FOPNNEXFIL)

		locked = false
		if (and (fflags[fd], FF_READ) != 0)
		    locked = locked || (and (perm, FF_RDLOCK) != 0)
		if (and (fflags[fd], FF_WRITE) != 0)
		    locked = locked || (and (perm, FF_WRLOCK) != 0)
		
		if (!locked)
		    break
	    }
	} 
noacc_
	call sfree (sp)
    	call filerr (fname, SYS_FWTNOACC)
end