API Change: DOS Packets for ACTION_EXAMINE_OBJECT/FH and fib_FileName/fib_Comment
[AROS.git] / workbench / fs / pipe / pipedir.c
blobab642e6467a01d0096c0210b8334f6b676d45445
1 /****************************************************************************
2 ** File: pipedir.c
3 ** Program: pipe-handler - an AmigaDOS handler for named pipes
4 ** Version: 1.2
5 ** Author: Ed Puckett qix@mit-oz
6 **
7 ** Copyright 1987 by EpAc Software. All Rights Reserved.
8 **
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"
29 #include "pipename.h"
30 #include "pipebuf.h"
31 #include "pipecreate.h"
32 #include "pipesched.h"
33 #include "pipe-handler.h"
34 #include "pipedir.h"
38 /*---------------------------------------------------------------------------
39 ** pipedir.c
40 ** ---------
41 ** This module handles the directory-related requests to the handler.
42 ** The functions contained here are not needed if the compile-time flag
43 ** PIPEDIR is false.
45 ** Visible Functions
46 ** -----------------
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 ** ---------------------
57 ** - none -
59 ** Local Functions
60 ** ---------------
61 ** void InitPipedirLock ()
62 ** void FillFIB (fib, DiskKey, FileName, Protection, Type, Size, NumBlocks, Datep)
65 static void InitPipedirLock (void);
66 static void FillFIB (
67 struct FileInfoBlock *fib,
68 SIPTR DiskKey,
69 char *FileName, /* null-terminated */
70 LONG Protection,
71 LONG Type,
72 LONG Size,
73 LONG NumBlocks,
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)
98 PIPEDATA *pipe;
100 { (void) DateStamp (&pipe->accessdate);
102 #if UPDATE_PIPEDATE
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.
118 void PipeLock (pkt)
120 struct DosPacket *pkt;
122 { char *name, *tapname;
123 ULONG size;
124 struct FileLock *lock;
125 PIPEDATA *pipe;
126 void InitPipedirLock();
129 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;
138 goto PLOCKEXIT;
141 if (! ParsePipeName (BPTRtoCptr (pkt->dp_Arg2), &name, &size, &tapname))
142 { pkt->dp_Res2= ERROR_INVALID_COMPONENT_NAME;
143 goto PLOCKEXIT;
146 if ( (lock == NULL) || ((pipe= (PIPEDATA *) lock->fl_Key) == NULL) )
147 { if (name[0] == '\0')
148 pkt->dp_Res1= (SIPTR)CptrtoBPTR (PipedirLock);
149 else
150 { if ((pipe= FindPipe (name)) == NULL)
151 { pkt->dp_Res2= ERROR_OBJECT_NOT_FOUND;
152 goto PLOCKEXIT;
155 pkt->dp_Res1= (SIPTR)CptrtoBPTR (pipe->lock);
156 ++pipe->lockct;
159 else /* lock sent in packet was on the pipe */
160 { if (name[0] != '\0')
161 { pkt->dp_Res2= ERROR_INVALID_COMPONENT_NAME;
162 goto PLOCKEXIT;
165 pkt->dp_Res1= (SIPTR)CptrtoBPTR (pipe->lock);
166 ++pipe->lockct;
169 PLOCKEXIT:
170 QuickReplyPkt (pkt);
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
181 ** returns an error.
184 void PipeDupLock (pkt)
186 struct DosPacket *pkt;
188 { struct FileLock *lock;
189 PIPEDATA *pipe;
192 pkt->dp_Res1= pkt->dp_Arg1; /* reuse same structure */
193 pkt->dp_Res2= 0;
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 */
200 QuickReplyPkt (pkt);
205 /*---------------------------------------------------------------------------
206 ** PipeUnLock() responds to UnLock requests.
209 void PipeUnLock (pkt)
211 struct DosPacket *pkt;
213 { struct FileLock *lock;
214 PIPEDATA *pipe;
217 if ((lock= (struct FileLock *) BPTRtoCptr (pkt->dp_Arg1)) == NULL)
218 { pkt->dp_Res1= 0;
219 pkt->dp_Res2= ERROR_INVALID_LOCK;
221 else
222 { if ((pipe= (PIPEDATA *) lock->fl_Key) != NULL)
223 { --pipe->lockct;
224 CheckWaiting (pipe); /* will discard if totally unused */
227 pkt->dp_Res1= 1; /* no error */
228 pkt->dp_Res2= 0;
231 QuickReplyPkt (pkt);
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;
248 PIPEDATA *pipe;
251 pkt->dp_Res1= 1; /* no error, for now */
252 pkt->dp_Res2= 0;
254 fib= (struct FileInfoBlock *) BPTRtoCptr (pkt->dp_Arg2);
256 if ((lock= (struct FileLock *) BPTRtoCptr (pkt->dp_Arg1)) == NULL)
257 { pkt->dp_Res1= 0;
258 pkt->dp_Res2= ERROR_OBJECT_NOT_FOUND;
260 else
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,
264 0, 0, &PipeDate );
266 else
267 { FillFIB ( fib, NULL, pipe->name,
268 (FIBF_EXECUTE | FIBF_DELETE), -1,
269 pipe->buf->len, 1, &pipe->accessdate );
273 QuickReplyPkt (pkt);
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;
306 goto EXNEXTREPLY;
309 if (lock->fl_Key != NULL) /* then an individual pipe */
310 { pkt->dp_Res2= ERROR_OBJECT_WRONG_TYPE;
311 goto EXNEXTREPLY;
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)
319 goto EXNEXTREPLY;
322 for (pipe= (PIPEDATA *) FirstItem (&pipelist); pipe != NULL; pipe= (PIPEDATA *) NextItem (pipe))
323 if (listitem == pipe)
324 break;
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 );
331 pkt->dp_Res1= 1;
332 pkt->dp_Res2= 0;
335 EXNEXTREPLY:
336 QuickReplyPkt (pkt);
341 /*---------------------------------------------------------------------------
342 ** PipeParentDir() responds to ParentDir requests.
345 void PipeParentDir (pkt)
347 struct DosPacket *pkt;
349 { struct FileLock *lock;
350 void InitPipedirLock();
353 InitPipedirLock ();
355 pkt->dp_Res2= 0;
357 if ((lock= (struct FileLock *) BPTRtoCptr (pkt->dp_Arg1)) == NULL)
358 { pkt->dp_Res1= 0;
359 pkt->dp_Res2= ERROR_INVALID_LOCK;
361 else
362 { if (lock->fl_Key == NULL) /* then lock is on handler */
363 pkt->dp_Res1= 0; /* root of current filing system */
364 else
365 pkt->dp_Res1= (SIPTR)CptrtoBPTR (PipedirLock);
368 QuickReplyPkt (pkt);
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;
395 LONG key;
397 { lock->fl_Link= 0;
398 lock->fl_Key= key;
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;
414 SIPTR DiskKey;
415 char *FileName; /* null-terminated */
416 LONG Protection;
417 LONG Type;
418 LONG Size;
419 LONG NumBlocks;
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; /* ??? */
429 fib->fib_Size= Size;
430 fib->fib_NumBlocks= NumBlocks;
432 CopyMem (Datep, &fib->fib_Date, sizeof (struct DateStamp));
434 fib->fib_Comment[0]= '\0'; /* empty BSTR */