1 /****************************************************************************
3 ** Program: pipe-handler - an AmigaDOS handler for named pipes
5 ** Author: Ed Puckett qix@mit-oz
7 ** Copyright 1987 by EpAc Software. All Rights Reserved.
9 ** History: 05-Jan-87 Original Version (1.0)
10 ** 07-Feb-87 Added modifications for allowing shared locks
11 ** on individual pipes.
12 ** 12-Feb-87 Added PipeParentDir.
13 ** 12-Feb-87 Fixed bug in PipeLock(): previously ignored
14 ** lock passed in packet. Bug uncovered when
15 ** pipes became lockable, and thus assignable.
16 ** 27-Mar-87 Added PipeDupLock(). This was missing
17 ** in the original version!
20 #include <libraries/dos.h>
21 #include <libraries/dosextens.h>
22 #include <libraries/filehandler.h>
23 #include <exec/exec.h>
25 #include <proto/exec.h>
26 #include <proto/dos.h>
28 #include "pipelists.h"
31 #include "pipecreate.h"
32 #include "pipesched.h"
33 #include "pipe-handler.h"
38 /*---------------------------------------------------------------------------
41 ** This module handles the directory-related requests to the handler.
42 ** The functions contained here are not needed if the compile-time flag
47 ** void SetPipeDate (pipe)
48 ** void PipeLock (pkt)
49 ** void PipeDupLock (pkt)
50 ** void PipeUnLock (pkt)
51 ** void PipeExamine (pkt)
52 ** void PipeExNext (pkt)
53 ** void InitLock (lock, key)
55 ** Macros (in pipedir.h)
56 ** ---------------------
61 ** void InitPipedirLock ()
62 ** void FillFIB (fib, DiskKey, FileName, Protection, Type, Size, NumBlocks, Datep)
65 static void InitPipedirLock (void);
67 struct FileInfoBlock
*fib
,
69 char *FileName
, /* null-terminated */
74 struct DateStamp
*Datep
);
79 /*---------------------------------------------------------------------------
80 ** "PipedirLock" is the lock returned by PipeLock() to clients requesting a
81 ** shared lock on the handler. "LockBytes" is used for the storage of the
82 ** lock. InitLock() sets "PipedirLock" to point to the first longword within
83 ** "LockBytes" to ensure longword alignment for BCPL's sake.
86 static BYTE LockBytes
[sizeof (struct FileLock
) + 3];
87 static struct FileLock
*PipedirLock
= NULL
;
90 /*---------------------------------------------------------------------------
91 ** SetPipeDate() modifies the date field for the pipe sent. If the compile-
92 ** time flag UPDATE_PIPEDATE is true (see pipe-handler.h), the handler's date
93 ** is modified as well.
96 void SetPipeDate (pipe
)
100 { (void) DateStamp (&pipe
->accessdate
);
103 (void) DateStamp (&PipeDate
);
104 #endif /* UPDATE_PIPEDATE */
109 /*---------------------------------------------------------------------------
110 ** PipeLock() responds to Lock requests. Only multiple access locks are
111 ** granted. The same lock is returned to all clients for a given entity.
112 ** Note: the code which checks if the lock sent in the packet relies on
113 ** the fact that the pipe-handler does not allow subdirectories. If a lock
114 ** on a pipe is passed in, then that pipe is opened. Otherwise, the name is
115 ** parsed without reference to the lock.
120 struct DosPacket
*pkt
;
122 { char *name
, *tapname
;
124 struct FileLock
*lock
;
126 void InitPipedirLock();
131 pkt
->dp_Res1
= 0; /* error, for now */
132 pkt
->dp_Res2
= 0; /* clear for case of no error */
134 lock
= (struct FileLock
*) BPTRtoCptr (pkt
->dp_Arg1
);
136 if (pkt
->dp_Arg3
!= SHARED_LOCK
)
137 { pkt
->dp_Res2
= ERROR_OBJECT_WRONG_TYPE
;
141 if (! ParsePipeName (BPTRtoCptr (pkt
->dp_Arg2
), &name
, &size
, &tapname
))
142 { pkt
->dp_Res2
= ERROR_INVALID_COMPONENT_NAME
;
146 if ( (lock
== NULL
) || ((pipe
= (PIPEDATA
*) lock
->fl_Key
) == NULL
) )
147 { if (name
[0] == '\0')
148 pkt
->dp_Res1
= (SIPTR
)CptrtoBPTR (PipedirLock
);
150 { if ((pipe
= FindPipe (name
)) == NULL
)
151 { pkt
->dp_Res2
= ERROR_OBJECT_NOT_FOUND
;
155 pkt
->dp_Res1
= (SIPTR
)CptrtoBPTR (pipe
->lock
);
159 else /* lock sent in packet was on the pipe */
160 { if (name
[0] != '\0')
161 { pkt
->dp_Res2
= ERROR_INVALID_COMPONENT_NAME
;
165 pkt
->dp_Res1
= (SIPTR
)CptrtoBPTR (pipe
->lock
);
175 /*---------------------------------------------------------------------------
176 ** PipeDupLock() responds to DupLock requests. It is assumed that the lock
177 ** sent is valid. The same lock is returned; the only action taken is to
178 ** increment the lock count if the lock is on an individual pipe. If the
179 ** zero lock is sent, the zero lock is (properly) returned, even though this
180 ** handler should never receive that request. Notice that this routine never
184 void PipeDupLock (pkt
)
186 struct DosPacket
*pkt
;
188 { struct FileLock
*lock
;
192 pkt
->dp_Res1
= pkt
->dp_Arg1
; /* reuse same structure */
195 if ((lock
= (struct FileLock
*) BPTRtoCptr (pkt
->dp_Arg1
)) != NULL
)
196 { if ((pipe
= (PIPEDATA
*) lock
->fl_Key
) != NULL
)
197 ++pipe
->lockct
; /* lock is on an individual pipe */
205 /*---------------------------------------------------------------------------
206 ** PipeUnLock() responds to UnLock requests.
209 void PipeUnLock (pkt
)
211 struct DosPacket
*pkt
;
213 { struct FileLock
*lock
;
217 if ((lock
= (struct FileLock
*) BPTRtoCptr (pkt
->dp_Arg1
)) == NULL
)
219 pkt
->dp_Res2
= ERROR_INVALID_LOCK
;
222 { if ((pipe
= (PIPEDATA
*) lock
->fl_Key
) != NULL
)
224 CheckWaiting (pipe
); /* will discard if totally unused */
227 pkt
->dp_Res1
= 1; /* no error */
236 /*---------------------------------------------------------------------------
237 ** PipeExamine() responds to Examine requests. For locks on the handler, the
238 ** address first item of the pipelist is stored in the DiskKey field for
239 ** PipeExNext()'s reference.
242 void PipeExamine (pkt
)
244 struct DosPacket
*pkt
;
246 { struct FileInfoBlock
*fib
;
247 struct FileLock
*lock
;
251 pkt
->dp_Res1
= 1; /* no error, for now */
254 fib
= (struct FileInfoBlock
*) BPTRtoCptr (pkt
->dp_Arg2
);
256 if ((lock
= (struct FileLock
*) BPTRtoCptr (pkt
->dp_Arg1
)) == NULL
)
258 pkt
->dp_Res2
= ERROR_OBJECT_NOT_FOUND
;
261 { if ((pipe
= (PIPEDATA
*) lock
->fl_Key
) == NULL
) /* then this is a lock on the handler */
262 { FillFIB ( fib
, (SIPTR
)FirstItem (&pipelist
), HandlerName
,
263 (FIBF_EXECUTE
| FIBF_DELETE
), 1,
267 { FillFIB ( fib
, NULL
, pipe
->name
,
268 (FIBF_EXECUTE
| FIBF_DELETE
), -1,
269 pipe
->buf
->len
, 1, &pipe
->accessdate
);
278 /*---------------------------------------------------------------------------
279 ** PipeExNext() responds to ExNext requests. The DiskKey field of the
280 ** FileInfoBlock is assumed to be a pointer to the next pipe in the pipelist
281 ** which is to be listed in the directory. We then scan pipelist for this
282 ** pointer, and upon finding it, store its information in the FileInfoBlock
283 ** and store the address of the next pipe in pipelist in the DiskKey field.
284 ** If the pipe is not found in the list, or if DiskKey is NULL, then
285 ** ERROR_NO_MORE_ENTRIES is returned.
286 ** By rescanning the list each time, deletion of a pipe cannot hurt us
287 ** by causing a dangling pointer in DiskKey -- we just end the directory
288 ** listing there. This can cause incomplete directory information for the
289 ** cleint, however, if the last listed pipe is deleted before the client's
290 ** next ExNext() call.
293 void PipeExNext (pkt
)
295 struct DosPacket
*pkt
;
297 { struct FileLock
*lock
;
298 struct FileInfoBlock
*fib
;
299 PIPEDATA
*listitem
, *pipe
;
302 pkt
->dp_Res1
= 0; /* error, for now */
304 if ((lock
= (struct FileLock
*) BPTRtoCptr (pkt
->dp_Arg1
)) == NULL
)
305 { pkt
->dp_Res2
= ERROR_INVALID_LOCK
;
309 if (lock
->fl_Key
!= NULL
) /* then an individual pipe */
310 { pkt
->dp_Res2
= ERROR_OBJECT_WRONG_TYPE
;
314 pkt
->dp_Res2
= ERROR_NO_MORE_ENTRIES
; /* until found otherwise */
316 fib
= (struct FileInfoBlock
*) BPTRtoCptr (pkt
->dp_Arg2
);
318 if ((listitem
= (PIPEDATA
*) fib
->fib_DiskKey
) == NULL
)
322 for (pipe
= (PIPEDATA
*) FirstItem (&pipelist
); pipe
!= NULL
; pipe
= (PIPEDATA
*) NextItem (pipe
))
323 if (listitem
== pipe
)
326 if (listitem
== pipe
) /* then found next entry */
327 { FillFIB ( fib
, (SIPTR
)NextItem (listitem
), listitem
->name
,
328 (FIBF_EXECUTE
| FIBF_DELETE
), -1,
329 listitem
->buf
->len
, 1, &listitem
->accessdate
);
341 /*---------------------------------------------------------------------------
342 ** PipeParentDir() responds to ParentDir requests.
345 void PipeParentDir (pkt
)
347 struct DosPacket
*pkt
;
349 { struct FileLock
*lock
;
350 void InitPipedirLock();
357 if ((lock
= (struct FileLock
*) BPTRtoCptr (pkt
->dp_Arg1
)) == NULL
)
359 pkt
->dp_Res2
= ERROR_INVALID_LOCK
;
362 { if (lock
->fl_Key
== NULL
) /* then lock is on handler */
363 pkt
->dp_Res1
= 0; /* root of current filing system */
365 pkt
->dp_Res1
= (SIPTR
)CptrtoBPTR (PipedirLock
);
373 /*---------------------------------------------------------------------------
376 static void InitPipedirLock ()
378 { if (PipedirLock
== NULL
)
379 { PipedirLock
= (struct FileLock
*) (((SIPTR
) LockBytes
+ 3) & ((~0)<<2));
380 InitLock (PipedirLock
, NULL
);
386 /*---------------------------------------------------------------------------
387 ** InitLock() initializes locks returned to clients by PipeLock(). For locks
388 ** on individual pipes, the "fl_Key" field points to the associated pipe's
389 ** PIPEDATA structure. For the handler, the "fl_Key" field is NULL.
392 void InitLock (lock
, key
)
394 struct FileLock
*lock
;
399 lock
->fl_Access
= SHARED_LOCK
; /* only mode allowed */
400 lock
->fl_Task
= PipePort
; /* set during handler init */
401 lock
->fl_Volume
= CptrtoBPTR (DevNode
); /* also set during init */
406 /*---------------------------------------------------------------------------
407 ** FillFIB() fills a FileInfoBlock with the specified information. Note
408 ** that handlers must store BSTR's in the FileInfoBlock.
411 static void FillFIB (fib
, DiskKey
, FileName
, Protection
, Type
, Size
, NumBlocks
, Datep
)
413 struct FileInfoBlock
*fib
;
415 char *FileName
; /* null-terminated */
420 struct DateStamp
*Datep
;
422 { fib
->fib_DiskKey
= DiskKey
;
423 fib
->fib_DirEntryType
= Type
;
425 CstrtoFIB (FileName
, fib
->fib_FileName
, sizeof (fib
->fib_FileName
));
427 fib
->fib_Protection
= Protection
;
428 fib
->fib_EntryType
= Type
; /* ??? */
430 fib
->fib_NumBlocks
= NumBlocks
;
432 CopyMem (Datep
, &fib
->fib_Date
, sizeof (struct DateStamp
));
434 fib
->fib_Comment
[0]= '\0'; /* empty BSTR */