add placeholder for classic magicmenu pull-down-on-titlebar behaviour when using...
[AROS.git] / workbench / fs / pipe / pipedir.c
bloba2d25878a97148bb8951edc472764a6c68577a09
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);
174 /*---------------------------------------------------------------------------
175 ** PipeFHFromLock() responds to FHFromLock requests. It is assumed that the
176 ** lock sent is valid.
179 void PipeFHFromLock (pkt)
181 struct DosPacket *pkt;
183 { struct FileLock *lock;
184 PIPEDATA *pipe;
185 PIPEKEY *pipekey;
186 struct FileHandle *fh;
189 pkt->dp_Res1= DOSFALSE;
190 pkt->dp_Res2= ERROR_OBJECT_NOT_FOUND;
192 if ((fh= (struct FileHandle *) BPTRtoCptr (pkt->dp_Arg1)) != NULL) {
193 if ((lock= (struct FileLock *) BPTRtoCptr (pkt->dp_Arg2)) != NULL) {
194 if ((pipe= (PIPEDATA *) lock->fl_Key) != NULL) {
195 if ((pipekey= (PIPEKEY *) AllocMem (sizeof (PIPEKEY), ALLOCMEM_FLAGS)) != NULL) {
196 pipekey->pipe = pipe;
197 pipekey->openmode = (lock->fl_Access == ACCESS_READ) ? OPEN_FOR_READ : OPEN_FOR_WRITE;
198 pipekey->iotype = (lock->fl_Access == ACCESS_READ) ? PIPEREAD : PIPEWRITE;
199 fh->fh_Arg1 = (SIPTR)pipekey;
200 pkt->dp_Res1= DOSTRUE;
201 pkt->dp_Res2= 0;
207 QuickReplyPkt (pkt);
212 /*---------------------------------------------------------------------------
213 ** PipeDupLock() responds to DupLock requests. It is assumed that the lock
214 ** sent is valid. The same lock is returned; the only action taken is to
215 ** increment the lock count if the lock is on an individual pipe. If the
216 ** zero lock is sent, the zero lock is (properly) returned, even though this
217 ** handler should never receive that request. Notice that this routine never
218 ** returns an error.
221 void PipeDupLock (pkt)
223 struct DosPacket *pkt;
225 { struct FileLock *lock;
226 PIPEDATA *pipe;
229 pkt->dp_Res1= pkt->dp_Arg1; /* reuse same structure */
230 pkt->dp_Res2= 0;
232 if ((lock= (struct FileLock *) BPTRtoCptr (pkt->dp_Arg1)) != NULL)
233 { if ((pipe= (PIPEDATA *) lock->fl_Key) != NULL)
234 ++pipe->lockct; /* lock is on an individual pipe */
237 QuickReplyPkt (pkt);
241 /*---------------------------------------------------------------------------
242 ** PipeDupLockFH() responds to DupLockFH requests. It is assumed that the fh
243 ** sent is valid. The lock for the fh is returned; the only action taken is to
244 ** increment the lock count if the lock is on an individual pipe.
247 void PipeDupLockFH (pkt)
249 struct DosPacket *pkt;
251 { PIPEKEY *pipekey;
252 PIPEDATA *pipe;
254 pkt->dp_Res1= 0;
255 pkt->dp_Res2= ERROR_OBJECT_NOT_FOUND;
258 if ((pipekey= (PIPEKEY *) (pkt->dp_Arg1)) != NULL)
259 { if ((pipe= pipekey->pipe) != NULL) {
260 ++pipe->lockct; /* lock is on an individual pipe */
261 pkt->dp_Res1= (SIPTR)MKBADDR(pipe->lock);
262 pkt->dp_Res2= 0;
266 QuickReplyPkt (pkt);
271 /*---------------------------------------------------------------------------
272 ** PipeUnLock() responds to UnLock requests.
275 void PipeUnLock (pkt)
277 struct DosPacket *pkt;
279 { struct FileLock *lock;
280 PIPEDATA *pipe;
283 if ((lock= (struct FileLock *) BPTRtoCptr (pkt->dp_Arg1)) == NULL)
284 { pkt->dp_Res1= 0;
285 pkt->dp_Res2= ERROR_INVALID_LOCK;
287 else
288 { if ((pipe= (PIPEDATA *) lock->fl_Key) != NULL)
289 { --pipe->lockct;
290 CheckWaiting (pipe); /* will discard if totally unused */
293 pkt->dp_Res1= 1; /* no error */
294 pkt->dp_Res2= 0;
297 QuickReplyPkt (pkt);
302 /*---------------------------------------------------------------------------
303 ** PipeExamine() responds to Examine requests. For locks on the handler, the
304 ** address first item of the pipelist is stored in the DiskKey field for
305 ** PipeExNext()'s reference.
308 void PipeExamine (pkt)
310 struct DosPacket *pkt;
312 { struct FileInfoBlock *fib;
313 struct FileLock *lock;
314 PIPEDATA *pipe;
317 pkt->dp_Res1= 1; /* no error, for now */
318 pkt->dp_Res2= 0;
320 fib= (struct FileInfoBlock *) BPTRtoCptr (pkt->dp_Arg2);
322 if ((lock= (struct FileLock *) BPTRtoCptr (pkt->dp_Arg1)) == NULL)
323 { pkt->dp_Res1= 0;
324 pkt->dp_Res2= ERROR_OBJECT_NOT_FOUND;
326 else
327 { if ((pipe= (PIPEDATA *) lock->fl_Key) == NULL) /* then this is a lock on the handler */
328 { FillFIB ( fib, (SIPTR)FirstItem (&pipelist), HandlerName,
329 (FIBF_EXECUTE | FIBF_DELETE), ST_ROOT,
330 0, 0, &PipeDate );
332 else
333 { FillFIB ( fib, (SIPTR)NULL, pipe->name,
334 (FIBF_EXECUTE | FIBF_DELETE), ST_PIPEFILE,
335 pipe->buf->len, 1, &pipe->accessdate );
339 QuickReplyPkt (pkt);
344 /*---------------------------------------------------------------------------
345 ** PipeExNext() responds to ExNext requests. The DiskKey field of the
346 ** FileInfoBlock is assumed to be a pointer to the next pipe in the pipelist
347 ** which is to be listed in the directory. We then scan pipelist for this
348 ** pointer, and upon finding it, store its information in the FileInfoBlock
349 ** and store the address of the next pipe in pipelist in the DiskKey field.
350 ** If the pipe is not found in the list, or if DiskKey is NULL, then
351 ** ERROR_NO_MORE_ENTRIES is returned.
352 ** By rescanning the list each time, deletion of a pipe cannot hurt us
353 ** by causing a dangling pointer in DiskKey -- we just end the directory
354 ** listing there. This can cause incomplete directory information for the
355 ** cleint, however, if the last listed pipe is deleted before the client's
356 ** next ExNext() call.
359 void PipeExNext (pkt)
361 struct DosPacket *pkt;
363 { struct FileLock *lock;
364 struct FileInfoBlock *fib;
365 PIPEDATA *listitem, *pipe;
368 pkt->dp_Res1= 0; /* error, for now */
370 if ((lock= (struct FileLock *) BPTRtoCptr (pkt->dp_Arg1)) == NULL)
371 { pkt->dp_Res2= ERROR_INVALID_LOCK;
372 goto EXNEXTREPLY;
375 if (lock->fl_Key != (IPTR)NULL) /* then an individual pipe */
376 { pkt->dp_Res2= ERROR_OBJECT_WRONG_TYPE;
377 goto EXNEXTREPLY;
380 pkt->dp_Res2= ERROR_NO_MORE_ENTRIES; /* until found otherwise */
382 fib= (struct FileInfoBlock *) BPTRtoCptr (pkt->dp_Arg2);
384 if ((listitem= (PIPEDATA *) fib->fib_DiskKey) == NULL)
385 goto EXNEXTREPLY;
388 for (pipe= (PIPEDATA *) FirstItem (&pipelist); pipe != NULL; pipe= (PIPEDATA *) NextItem (pipe))
389 if (listitem == pipe)
390 break;
392 if (listitem == pipe) /* then found next entry */
393 { FillFIB ( fib, (SIPTR)NextItem (listitem), listitem->name,
394 (FIBF_EXECUTE | FIBF_DELETE), ST_PIPEFILE,
395 listitem->buf->len, 1, &listitem->accessdate );
397 pkt->dp_Res1= 1;
398 pkt->dp_Res2= 0;
401 EXNEXTREPLY:
402 QuickReplyPkt (pkt);
407 /*---------------------------------------------------------------------------
408 ** PipeExFH() responds to ExFH requests.
411 void PipeExFH (pkt)
413 struct DosPacket *pkt;
415 { struct FileInfoBlock *fib;
416 PIPEKEY *pipekey;
417 PIPEDATA *pipe;
419 pkt->dp_Res1= 0; /* error, for now */
421 if ((pipekey= (PIPEKEY *) pkt->dp_Arg1) == NULL)
422 { pkt->dp_Res2= ERROR_OBJECT_WRONG_TYPE;
423 goto EXFHREPLY;
426 fib= (struct FileInfoBlock *) BPTRtoCptr (pkt->dp_Arg2);
428 pipe=pipekey->pipe;
429 FillFIB ( fib, (SIPTR)NextItem (pipe), pipe->name,
430 (FIBF_EXECUTE | FIBF_DELETE), ST_PIPEFILE,
431 pipe->buf->len, 1, &pipe->accessdate );
433 pkt->dp_Res1= DOSTRUE;
434 pkt->dp_Res2= 0;
436 EXFHREPLY:
437 QuickReplyPkt (pkt);
442 /*---------------------------------------------------------------------------
443 ** PipeParentDir() responds to ParentDir requests.
446 void PipeParentDir (pkt)
448 struct DosPacket *pkt;
450 { struct FileLock *lock;
451 void InitPipedirLock();
454 InitPipedirLock ();
456 pkt->dp_Res2= 0;
458 if ((lock= (struct FileLock *) BPTRtoCptr (pkt->dp_Arg1)) == NULL)
459 { pkt->dp_Res1= 0;
460 pkt->dp_Res2= ERROR_INVALID_LOCK;
462 else
463 { if (lock->fl_Key == (IPTR)NULL) /* then lock is on handler */
464 pkt->dp_Res1= 0; /* root of current filing system */
465 else
466 pkt->dp_Res1= (SIPTR)CptrtoBPTR (PipedirLock);
469 QuickReplyPkt (pkt);
474 /*---------------------------------------------------------------------------
475 ** PipeParentFH() responds to ParentFH requests.
478 void PipeParentFH (pkt)
480 struct DosPacket *pkt;
482 { PIPEKEY *pipekey;
483 void InitPipedirLock();
486 InitPipedirLock ();
488 pkt->dp_Res2= 0;
490 if ((pipekey= (PIPEKEY *) (pkt->dp_Arg1)) == NULL)
491 { pkt->dp_Res1= 0;
492 pkt->dp_Res2= ERROR_INVALID_LOCK;
494 else
496 pkt->dp_Res1= (SIPTR)CptrtoBPTR (PipedirLock);
499 QuickReplyPkt (pkt);
504 /*---------------------------------------------------------------------------
507 static void InitPipedirLock ()
509 { if (PipedirLock == NULL)
510 { PipedirLock= (struct FileLock *) (((SIPTR) LockBytes + 3) & ((~0)<<2));
511 InitLock (PipedirLock, NULL);
517 /*---------------------------------------------------------------------------
518 ** InitLock() initializes locks returned to clients by PipeLock(). For locks
519 ** on individual pipes, the "fl_Key" field points to the associated pipe's
520 ** PIPEDATA structure. For the handler, the "fl_Key" field is NULL.
523 void InitLock (lock, key)
525 struct FileLock *lock;
526 LONG key;
528 { lock->fl_Link= 0;
529 lock->fl_Key= key;
530 lock->fl_Access= SHARED_LOCK; /* only mode allowed */
531 lock->fl_Task= PipePort; /* set during handler init */
532 lock->fl_Volume= CptrtoBPTR (DevNode); /* also set during init */
537 /*---------------------------------------------------------------------------
538 ** FillFIB() fills a FileInfoBlock with the specified information. Note
539 ** that handlers must store BSTR's in the FileInfoBlock.
542 static void FillFIB (fib, DiskKey, FileName, Protection, Type, Size, NumBlocks, Datep)
544 struct FileInfoBlock *fib;
545 SIPTR DiskKey;
546 char *FileName; /* null-terminated */
547 LONG Protection;
548 LONG Type;
549 LONG Size;
550 LONG NumBlocks;
551 struct DateStamp *Datep;
553 { fib->fib_DiskKey= DiskKey;
554 fib->fib_DirEntryType= Type;
556 CstrtoFIB (FileName, fib->fib_FileName, sizeof (fib->fib_FileName));
558 fib->fib_Protection= Protection;
559 fib->fib_EntryType= Type; /* ??? */
560 fib->fib_Size= Size;
561 fib->fib_NumBlocks= NumBlocks;
563 CopyMem (Datep, &fib->fib_Date, sizeof (struct DateStamp));
565 fib->fib_Comment[0]= '\0'; /* empty BSTR */