2 Copyright © 1995-2006, The AROS Development Team. All rights reserved.
7 #include <aros/debug.h>
9 #include <exec/errors.h>
10 #include <exec/resident.h>
11 #include <exec/memory.h>
12 #include <exec/semaphores.h>
13 #include <exec/lists.h>
14 #include <exec/nodes.h>
15 #include <proto/exec.h>
16 #include <utility/tagitem.h>
17 #include <dos/dosextens.h>
18 #include <dos/filesystem.h>
19 #include <proto/dos.h>
20 #include <aros/symbolsets.h>
21 #include <aros/asmcall.h>
22 #if defined(__GNUC__) || defined(__INTEL_COMPILER)
23 #include "pipefs_handler_gcc.h"
26 #include LC_LIBDEFS_FILE
31 AROS_UFP3(LONG
, pipefsproc
,
32 AROS_UFPA(char *,argstr
,A0
),
33 AROS_UFPA(ULONG
,argsize
,D0
),
34 AROS_UFPA(struct ExecBase
*,SysBase
,A6
));
39 struct IOFileSys
*iofs
;
46 struct dirnode
*parent
; /* Parent directory */
49 struct DateStamp datestamp
;
57 struct dirnode
*parent
;
60 struct DateStamp datestamp
;
61 ULONG numusers
; /* Number of actual users of this pipe */
62 ULONG numwriters
; /* Num of actual writers */
63 ULONG numreaders
; /* Num of actual readers */
64 struct List waitinglist
; /* List of files waiting for a reader or a writer to become available */
65 struct List pendingwrites
; /* List of pending write requestes */
66 struct List pendingreads
; /* List of pending read requestes */
67 ULONG flags
; /* See below */
70 /* Flags for filenodes */
71 #define FNF_DELETEONCLOSE 1 /* Specify this flag when you want a pipe to be deleted
72 when it's closed. Useful for unnamed pipes */
79 static size_t LenFirstPart (STRPTR path
);
80 static struct filenode
*FindFile (struct pipefsbase
*pipefsbase
, struct dirnode
**dn_ptr
, STRPTR path
);
81 static struct filenode
*GetFile (struct pipefsbase
*pipefsbase
, STRPTR filename
, struct dirnode
*dn
, ULONG mode
, ULONG
*err
);
82 static ULONG
SendRequest (struct pipefsbase
*pipefsbase
, struct IOFileSys
*iofs
, BOOL abort
);
83 static STRPTR
StrDup (struct pipefsbase
*pipefsbase
, STRPTR str
);
86 static int GM_UNIQUENAME(Init
)(LIBBASETYPEPTR pipefsbase
)
88 DOSBase
= (struct DosLibrary
*)OpenLibrary("dos.library",39);
92 struct TagItem taglist
[]=
94 {NP_Entry
, (IPTR
)pipefsproc
},
95 {NP_Name
, (IPTR
)"pipefs.handler process"},
96 {NP_UserData
, (IPTR
)pipefsbase
},
100 pipefsbase
->proc
= CreateNewProc(taglist
);
102 if (pipefsbase
->proc
)
105 CloseLibrary((struct Library
*)DOSBase
);
111 static int GM_UNIQUENAME(Open
)
113 LIBBASETYPEPTR pipefsbase
,
114 struct IOFileSys
*iofs
,
122 /* Mark Message as recently used. */
123 iofs
->IOFS
.io_Message
.mn_Node
.ln_Type
=NT_REPLYMSG
;
125 /* Build a fake usernode */
126 un
= AllocVec(sizeof(*un
),MEMF_PUBLIC
|MEMF_CLEAR
);
129 dn
= AllocVec(sizeof(*dn
),MEMF_PUBLIC
|MEMF_CLEAR
);
133 dn
->name
= iofs
->io_Union
.io_OpenDevice
.io_DosName
;
137 DateStamp(&dn
->datestamp
);
139 un
->fn
= (struct filenode
*)dn
;
140 iofs
->IOFS
.io_Unit
=(struct Unit
*)un
;
141 iofs
->IOFS
.io_Device
=&pipefsbase
->device
;
143 iofs
->IOFS
.io_Error
=0;
151 iofs
->io_DosError
=ERROR_NO_FREE_STORE
;
153 iofs
->IOFS
.io_Error
=IOERR_OPENFAIL
;
158 static int GM_UNIQUENAME(Close
)
160 LIBBASETYPEPTR pipefsbase
,
161 struct IOFileSys
*iofs
167 un
= (struct usernode
*)iofs
->IOFS
.io_Unit
;
168 dn
= (struct dirnode
*)un
->fn
;
170 if(!IsListEmpty(&dn
->files
))
172 iofs
->io_DosError
=ERROR_OBJECT_IN_USE
;
184 static int GM_UNIQUENAME(Expunge
)(LIBBASETYPEPTR pipefsbase
)
187 This function is single-threaded by exec by calling Forbid.
188 Never break the Forbid() or strange things might happen.
191 SendRequest(pipefsbase
, NULL
, TRUE
);
193 /* Free all resources */
194 CloseLibrary((struct Library
*)pipefsbase
->dosbase
);
199 AROS_LH1(void, beginio
,
200 AROS_LHA(struct IOFileSys
*, iofs
, A1
),
201 struct pipefsbase
*, pipefsbase
, 5, Pipefs
)
205 BOOL enqueued
= FALSE
;
207 D(bug("COMMAND %d\n", iofs
->IOFS
.io_Command
));
208 switch(iofs
->IOFS
.io_Command
)
214 case FSA_EXAMINE_NEXT
:
219 case FSA_DELETE_OBJECT
:
221 error
= SendRequest(pipefsbase
, iofs
, FALSE
);
226 error
= ERROR_SEEK_ERROR
;
228 case FSA_IS_FILESYSTEM
:
229 iofs
->io_Union
.io_IS_FILESYSTEM
.io_IsFilesystem
= TRUE
;
231 case FSA_SET_FILE_SIZE
:
232 case FSA_EXAMINE_ALL
:
233 case FSA_CREATE_HARDLINK
:
234 case FSA_CREATE_SOFTLINK
:
236 error
= ERROR_NOT_IMPLEMENTED
;
240 error
= ERROR_ACTION_NOT_KNOWN
;
245 iofs
->io_DosError
=error
;
247 /* If the quick bit is not set and the request hasn't been redirected
248 send the message to the port
250 if(!(iofs
->IOFS
.io_Flags
&IOF_QUICK
) && !enqueued
)
251 ReplyMsg(&iofs
->IOFS
.io_Message
);
256 ADD2INITLIB(GM_UNIQUENAME(Init
), 0)
257 ADD2OPENDEV(GM_UNIQUENAME(Open
), 0)
258 ADD2CLOSEDEV(GM_UNIQUENAME(Close
), 0)
259 ADD2EXPUNGELIB(GM_UNIQUENAME(Expunge
), 0)
261 AROS_LH1(LONG
, abortio
,
262 AROS_LHA(struct IOFileSys
*, iofs
, A1
),
263 struct pipefsbase
*, pipefsbase
, 6, Pipefs
)
267 return SendRequest(pipefsbase
, iofs
, TRUE
);
272 static ULONG
SendRequest(struct pipefsbase
*pipefsbase
, struct IOFileSys
*iofs
, BOOL abort
)
274 struct pipefsmessage
*msg
= AllocVec(sizeof(*msg
), MEMF_PUBLIC
);
278 msg
->msg
.mn_Node
.ln_Type
= NT_MESSAGE
;
279 msg
->msg
.mn_Node
.ln_Name
= "PIPEFSMSG";
280 msg
->msg
.mn_Length
= sizeof(struct pipefsmessage
);
286 iofs
->IOFS
.io_Message
.mn_Node
.ln_Type
= NT_MESSAGE
;
287 iofs
->IOFS
.io_Flags
&= ~IOF_QUICK
;
290 PutMsg(&pipefsbase
->proc
->pr_MsgPort
, (struct Message
*)msg
);
295 return ERROR_NO_FREE_STORE
;
298 /* The helper process */
300 #define SendBack(msg, err) \
302 msg->iofs->io_DosError = err; \
303 ReplyMsg(&(msg)->iofs->IOFS.io_Message); \
307 static STRPTR
StrDup(struct pipefsbase
*pipefsbase
, STRPTR str
)
309 size_t len
= strlen(str
)+1;
310 STRPTR ret
= AllocVec(len
, MEMF_ANY
);
313 CopyMem(str
, ret
, len
);
319 Return the len of the first part in the path.
322 LenFirstPart("yyy/xxx") would return 3
323 LenFirstPart("xxxx") would return 4
326 static size_t LenFirstPart(STRPTR path
)
330 for (; path
[0] && path
[0] != '/'; path
++, len
++);
335 static struct filenode
*FindFile(struct pipefsbase
*pipefsbase
, struct dirnode
**dn_ptr
, STRPTR path
)
343 while (path
[0] == '/' && dn
)
349 if (!dn
) return NULL
;
351 if (!path
[0]) return (struct filenode
*)dn
;
355 D(bug("User wants %S to be a directory, but it's a file.\n", dn
->name
));
360 len
= LenFirstPart(path
);
361 nextpart
= &path
[len
];
362 fn
= (struct filenode
*)GetHead(&dn
->files
);
364 D(bug("Searching for %.*S.\n", len
, path
));
367 if (fn
->name
!= NULL
) {
368 D(bug("Comparing %S with %.*S.\n", fn
->name
, len
, path
));
369 if (strlen(fn
->name
) == len
&& strncasecmp(fn
->name
, path
, len
) == 0)
372 fn
= (struct filenode
*)GetSucc((struct Node
*)fn
);
377 if (nextpart
[0] == '/') nextpart
++;
379 dn
= (struct dirnode
*)fn
;
380 fn
= FindFile(pipefsbase
, &dn
, nextpart
);
388 static struct filenode
*NewFileNode(struct pipefsbase
*pipefsbase
, STRPTR filename
, ULONG flags
, struct dirnode
*dn
, ULONG
*err
)
392 fn
= AllocVec(sizeof(*fn
), MEMF_PUBLIC
|MEMF_CLEAR
);
395 if (filename
== NULL
|| (fn
->name
= StrDup(pipefsbase
, filename
)) != NULL
) {
396 fn
->type
= ST_PIPEFILE
;
398 DateStamp(&fn
->datestamp
);
399 NEWLIST(&fn
->waitinglist
);
400 NEWLIST(&fn
->pendingwrites
);
401 NEWLIST(&fn
->pendingreads
);
406 AddTail(&dn
->files
, (struct Node
*)fn
);
407 D(bug("New file created and added to the list\n"));
415 D(bug("AllocVec Failed. No more memory available\n"));
416 *err
= ERROR_NO_FREE_STORE
;
420 static struct filenode
*GetFile(struct pipefsbase
*pipefsbase
, STRPTR filename
, struct dirnode
*dn
, ULONG mode
, ULONG
*err
)
424 D(bug("User wants to open file %S.\n", filename
));
425 D(bug("Current directory is %S\n", dn
->name
));
427 if (dn
&& !dn
->parent
&& strcmp(filename
, "__UNNAMED__") == 0)
429 return NewFileNode(pipefsbase
, "__UNNAMED__", FNF_DELETEONCLOSE
, dn
, err
);
432 fn
= FindFile(pipefsbase
, &dn
, filename
);
435 D(bug("The file couldn't be found.\n"));
437 if (dn
&& mode
&FMF_CREATE
)
439 D(bug("But the user wants it to be created.\n"));
441 return NewFileNode(pipefsbase
, FilePart(filename
), 0, dn
, err
);
445 *err
= ERROR_OBJECT_NOT_FOUND
;
449 if (fn
&& fn
->type
> 0 && mode
&(FMF_WRITE
|FMF_READ
))
451 D(bug("The file is a directory, cannot be open for reading/writing\n"));
452 *err
= ERROR_OBJECT_WRONG_TYPE
;
461 struct ExecBase
*SysBase
;
463 # define SysBase _SysBase
467 AROS_UFH3(LONG
, pipefsproc
,
468 AROS_UFHA(char *,argstr
,A0
),
469 AROS_UFHA(ULONG
,argsize
,D0
),
470 AROS_UFHA(struct ExecBase
*,_SysBase
,A6
))
475 struct pipefsbase
*pipefsbase
;
476 struct pipefsmessage
*msg
;
483 me
= (struct Process
*)FindTask(0);
484 pipefsbase
= me
->pr_Task
.tc_UserData
;
489 WaitPort(&(me
->pr_MsgPort
));
493 (msg
=(struct pipefsmessage
*)GetMsg(&(me
->pr_MsgPort
))) &&
494 (cont
= (msg
->iofs
!= 0))
497 D(bug("Message received.\n"));
499 un
= (struct usernode
*)msg
->iofs
->IOFS
.io_Unit
;
502 if (msg
->curlen
) /* This field is abused too see whethet the user wants to abort the request */
504 struct pipefsmessage
*msg2
;
507 D(bug("The user wants to abort this request.\n"));
509 ForeachNode(&fn
->waitinglist
, msg2
)
511 if (msg2
->iofs
== msg
->iofs
)
516 if (un
->mode
& FMF_WRITE
)
518 if (un
->mode
& FMF_READ
)
526 if (!found
&& (un
->mode
& FMF_WRITE
))
528 ForeachNode(&fn
->pendingwrites
, msg2
)
530 if (msg2
->iofs
== msg
->iofs
)
537 if (!found
&& (un
->mode
& FMF_READ
))
539 ForeachNode(&fn
->pendingreads
, msg2
)
541 if (msg2
->iofs
== msg
->iofs
)
551 D(bug("Aborting the request.\n"));
552 Remove((struct Node
*)msg2
);
553 msg2
->iofs
->IOFS
.io_Error
= IOERR_ABORTED
;
554 SendBack(msg2
, ERROR_INTERRUPTED
);
558 D(bug("There was no I/O in process for this request.\n"));
565 switch (msg
->iofs
->IOFS
.io_Command
)
568 msg
->iofs
->io_Union
.io_OPEN
.io_FileMode
&= ~(FMF_WRITE
|FMF_READ
);
576 D(bug("Command is OPEN\n"));
579 I would have liked to put this AFTER GetFile(),
580 but then it would have been really difficult to
581 undo what's done in GetFile() if the following AllocVec()
584 un
= AllocVec(sizeof(*un
), MEMF_PUBLIC
);
587 SendBack(msg
, ERROR_NO_FREE_STORE
);
591 un
->mode
= msg
->iofs
->io_Union
.io_OPEN
.io_FileMode
;
593 fn
= GetFile(pipefsbase
, msg
->iofs
->io_Union
.io_OPEN
.io_Filename
, (struct dirnode
*)fn
, un
->mode
, &err
);
601 D(bug("File requested found.\n"));
602 D(bug("The requested file is %s.\n",
607 msg
->iofs
->IOFS
.io_Unit
= (struct Unit
*)un
;
617 stillwaiting
= !fn
->numwriters
|| !fn
->numreaders
;
619 if (un
->mode
== FMF_MODE_OLDFILE
) un
->mode
&= ~FMF_WRITE
;
620 if (un
->mode
== FMF_MODE_NEWFILE
) un
->mode
&= ~FMF_READ
;
622 if (un
->mode
& FMF_READ
)
624 D(bug("User wants to read. "));
627 if (un
->mode
& FMF_WRITE
)
629 D(bug("User wants to write. "));
633 D(bug("There are %d readers and %d writers at the moment\n", fn
->numreaders
, fn
->numwriters
));
635 if (!fn
->numwriters
|| !fn
->numreaders
)
637 if (un
->mode
&(FMF_WRITE
|FMF_READ
) && !(un
->mode
&FMF_NONBLOCK
))
640 If we're lacking of writers or readers
641 then add this message to a waiting list.
643 D(bug("There are no %s at the moment, so this %s must wait\n",
644 fn
->numwriters
?"readers":"writers",
645 fn
->numwriters
?"writer":"reader"));
647 AddTail(&fn
->waitinglist
, (struct Node
*)msg
);
657 Else wake up all the ones that were still waiting
659 struct pipefsmessage
*msg
;
661 D(bug("Finally there are enough readers and writers! "
662 "Wake up all of them\n"));
664 while ((msg
= (struct pipefsmessage
*)RemHead(&fn
->waitinglist
)))
674 struct usernode
*reader
, *writer
;
677 D(bug("Command is FSA_PIPE\n"));
679 if ((reader
= AllocVec(sizeof(struct usernode
), MEMF_PUBLIC
)) == NULL
) {
680 SendBack(msg
, ERROR_NO_FREE_STORE
);
683 if ((writer
= AllocVec(sizeof(struct usernode
), MEMF_PUBLIC
)) == NULL
) {
684 SendBack(msg
, ERROR_NO_FREE_STORE
);
688 fn
= NewFileNode(pipefsbase
, NULL
, FNF_DELETEONCLOSE
, (struct dirnode
*) fn
, &err
);
696 msg
->iofs
->IOFS
.io_Unit
= (struct Unit
*) reader
;
697 msg
->iofs
->io_Union
.io_PIPE
.io_Writer
= (struct Unit
*) writer
;
699 reader
->fn
= writer
->fn
= fn
;
702 reader
->mode
= FMF_READ
;
705 writer
->mode
= FMF_WRITE
;
714 D(bug("Command is FSA_CLOSE\n"));
716 if (un
->mode
& FMF_READ
)
718 D(bug("User was a reader. "));
720 D(bug("There are %d readers at the moment\n", fn
->numreaders
));
723 struct pipefsmessage
*msg
;
725 D(bug("There are no readers anymore. %s\n",
726 IsListEmpty(&fn
->pendingwrites
) ?
727 "There are no pending writes" :
728 "Reply to all the waiting writers"));
730 while ((msg
= (struct pipefsmessage
*)RemHead(&fn
->pendingwrites
)))
734 if (un
->mode
& FMF_WRITE
)
736 D(bug("User was a writer. "));
738 D(bug("There are %d writers at the moment\n", fn
->numwriters
));
742 struct pipefsmessage
*msg
;
744 D(bug("There are no writers anymore. %s\n",
745 IsListEmpty(&fn
->pendingreads
) ?
746 "There are no pending reads" :
747 "Reply to all the waiting readers"));
748 while ((msg
= (struct pipefsmessage
*)RemHead(&fn
->pendingreads
)))
750 msg
->iofs
->io_Union
.io_READ_WRITE
.io_Length
=
751 msg
->iofs
->io_Union
.io_READ_WRITE
.io_Length
- msg
->curlen
;
759 if (!un
->fn
->numusers
&& un
->fn
->type
<= 0 && (un
->fn
->flags
& FNF_DELETEONCLOSE
))
761 Remove((struct Node
*)fn
);
762 if (fn
->name
!= NULL
)
773 struct ExAllData
*ead
= msg
->iofs
->io_Union
.io_EXAMINE
.io_ead
;
774 const ULONG type
= msg
->iofs
->io_Union
.io_EXAMINE
.io_Mode
;
775 const ULONG size
= msg
->iofs
->io_Union
.io_EXAMINE
.io_Size
;
778 static const ULONG sizes
[]=
781 offsetof(struct ExAllData
,ed_Type
),
782 offsetof(struct ExAllData
,ed_Size
),
783 offsetof(struct ExAllData
,ed_Prot
),
784 offsetof(struct ExAllData
,ed_Days
),
785 offsetof(struct ExAllData
,ed_Comment
),
786 offsetof(struct ExAllData
,ed_OwnerUID
),
787 sizeof(struct ExAllData
)
790 D(bug("Command is EXAMINE\n"));
792 if (fn
->name
== NULL
) {
793 SendBack(msg
, ERROR_OBJECT_NOT_FOUND
);
797 D(bug("Examining file %S\n", fn
->name
));
801 D(bug("The user requested an invalid type\n"));
802 SendBack(msg
, ERROR_BAD_NUMBER
);
806 next
= (STRPTR
)ead
+ sizes
[type
];
807 end
= (STRPTR
)ead
+ size
;
809 if(next
>end
) /* > is correct. Not >= */
811 SendBack(msg
, ERROR_BUFFER_OVERFLOW
);
817 msg
->iofs
->io_DirPos
= (LONG
)GetHead(&((struct dirnode
*)fn
)->files
);
821 msg
->iofs
->io_DirPos
= (LONG
)fn
;
827 ead
->ed_OwnerUID
= 0;
828 ead
->ed_OwnerGID
= 0;
832 ead
->ed_Comment
= NULL
;
836 ead
->ed_Days
= fn
->datestamp
.ds_Days
;
837 ead
->ed_Mins
= fn
->datestamp
.ds_Minute
;
838 ead
->ed_Ticks
= fn
->datestamp
.ds_Tick
;
850 ead
->ed_Type
= fn
->type
;
855 STRPTR name
= fn
->name
;
862 SendBack(msg
, ERROR_BUFFER_OVERFLOW
);
866 if (!(*next
++ = *name
++))
874 ead
->ed_Next
= (struct ExAllData
*)(((IPTR
)next
+ AROS_PTRALIGN
- 1) & ~(AROS_PTRALIGN
- 1));
879 case FSA_EXAMINE_NEXT
:
881 struct FileInfoBlock
*fib
= msg
->iofs
->io_Union
.io_EXAMINE_NEXT
.io_fib
;
882 struct filenode
*fn
= (struct filenode
*)fib
->fib_DiskKey
;
884 D(bug("Command is EXAMINE_NEXT\n"));
888 D(bug("There are no more entries in this directory\n"));
889 SendBack(msg
, ERROR_NO_MORE_ENTRIES
);
893 if (fn
->name
== NULL
) {
894 SendBack(msg
, ERROR_OBJECT_NOT_FOUND
);
898 D(bug("Current directory is %S. Current file is %S\n", fn
->parent
->name
, fn
->name
));
900 fib
->fib_OwnerUID
= 0;
901 fib
->fib_OwnerGID
= 0;
902 fib
->fib_Date
.ds_Days
= fn
->datestamp
.ds_Days
;
903 fib
->fib_Date
.ds_Minute
= fn
->datestamp
.ds_Minute
;
904 fib
->fib_Date
.ds_Tick
= fn
->datestamp
.ds_Tick
;
905 fib
->fib_Protection
= 0;
907 fib
->fib_DirEntryType
= fn
->type
;
909 strncpy(fib
->fib_FileName
, fn
->name
, MAXFILENAMELENGTH
- 1);
910 fib
->fib_Comment
[0] = '\0';
912 fib
->fib_DiskKey
= (LONG
)GetSucc(fn
);
919 STRPTR filename
= msg
->iofs
->io_Union
.io_CREATE_DIR
.io_Filename
;
920 struct dirnode
*parent
= (struct dirnode
*)fn
;
923 D(bug("Command is FSA_CREATE_DIR\n"));
924 D(bug("Current directory is %S\n", parent
->name
));
925 D(bug("User wants to create directory %S\n", filename
));
927 dn
= (struct dirnode
*)FindFile(pipefsbase
, &parent
, filename
);
930 D(bug("The object %S already exists\n", filename
));
931 SendBack(msg
, ERROR_OBJECT_EXISTS
);
937 D(bug("The path is not valid.\n"));
938 SendBack(msg
, ERROR_OBJECT_NOT_FOUND
);
944 !(un
= AllocVec(sizeof(*un
), MEMF_PUBLIC
)) ||
945 !(dn
= AllocVec(sizeof(*dn
), MEMF_PUBLIC
)) ||
946 !(dn
->name
= StrDup(pipefsbase
, filename
))
949 SendBack(msg
, ERROR_NO_FREE_STORE
);
953 D(bug("Ok, there's room for this directory.\n"));
954 AddTail(&parent
->files
, (struct Node
*)dn
);
957 dn
->type
= ST_USERDIR
;
959 DateStamp(&dn
->datestamp
);
961 un
->fn
= (struct filenode
*)dn
;
963 msg
->iofs
->IOFS
.io_Unit
= (struct Unit
*)un
;
969 D(bug("Command is FSA_FILE_MODE\n"));
970 D(bug("Current mode is 0x%08x\n", un
->mode
));
972 un
->mode
&= ~msg
->iofs
->io_Union
.io_FILE_MODE
.io_Mask
;
973 un
->mode
|= msg
->iofs
->io_Union
.io_FILE_MODE
.io_FileMode
;
975 D(bug("New mode is 0x%08x\n", un
->mode
));
979 case FSA_DELETE_OBJECT
:
981 STRPTR filename
= msg
->iofs
->io_Union
.io_DELETE_OBJECT
.io_Filename
;
982 struct dirnode
*dn
= (struct dirnode
*)fn
;
984 if (fn
->name
== NULL
) {
985 SendBack(msg
, ERROR_OBJECT_NOT_FOUND
);
989 D(bug("Command is FSA_DELETE_OBJECT\n"));
990 D(bug("Current directory is %S\n", fn
->name
));
991 D(bug("User wants to delete the object %S\n", filename
));
993 fn
= FindFile(pipefsbase
, &dn
, filename
);
996 D(bug("The object doesn't exist\n"));
997 SendBack(msg
, ERROR_OBJECT_NOT_FOUND
);
1000 if (fn
->type
== ST_ROOT
)
1002 D(bug("The object is the root directory. Cannot be deleted\n"));
1003 SendBack(msg
, ERROR_OBJECT_WRONG_TYPE
);
1008 D(bug("The object is in use, cannot be deleted\n"));
1009 SendBack(msg
, ERROR_OBJECT_IN_USE
);
1012 if (fn
->type
> 0 && !IsListEmpty(&((struct dirnode
*)fn
)->files
))
1014 D(bug("The object is a directory, but is not empty, thus cannot be deleted\n"));
1015 SendBack(msg
, ERROR_DIRECTORY_NOT_EMPTY
);
1019 D(bug("Removing the object from it's parent directory\n"));
1021 Remove((struct Node
*)fn
);
1029 D(bug("Command is FSA_WRITE. "));
1030 if (!(un
->mode
& FMF_WRITE
))
1032 D(bug("User doesn't have permission to write.\n"));
1033 SendBack(msg
, ERROR_BAD_STREAM_NAME
);
1036 if (!fn
->numreaders
)
1038 D(bug("There are no more readers: PIPE BROKEN.\n"));
1039 SendBack(msg
, ERROR_BROKEN_PIPE
);
1042 if (un
->mode
& FMF_NONBLOCK
&& IsListEmpty(&fn
->pendingreads
))
1044 D(bug("There are no pending reads and the pipe is in nonblocking mode, so return EWOULDBLOCK\n"));
1045 SendBack(msg
, ERROR_WOULD_BLOCK
);
1049 D(bug("Enqueing the message\n"));
1050 msg
->curlen
= msg
->iofs
->io_Union
.io_READ_WRITE
.io_Length
;
1051 AddTail(&fn
->pendingwrites
, (struct Node
*)msg
);
1054 D(bug("Command is FSA_READ. "));
1055 if (!(un
->mode
& FMF_READ
))
1057 D(bug("User doesn't have permission to read.\n"));
1058 SendBack(msg
, ERROR_BAD_STREAM_NAME
);
1061 if (!fn
->numwriters
)
1063 D(bug("There's no data to read: send EOF\n"));
1064 msg
->iofs
->io_Union
.io_READ_WRITE
.io_Length
= 0;
1068 if (un
->mode
& FMF_NONBLOCK
&& IsListEmpty(&fn
->pendingwrites
))
1070 D(bug("There are no pending writes and the pipe is in nonblocking mode, so return EWOULDBLOCK\n"));
1071 SendBack(msg
, ERROR_WOULD_BLOCK
);
1075 D(bug("Enqueing the message\n"));
1076 msg
->curlen
= msg
->iofs
->io_Union
.io_READ_WRITE
.io_Length
;
1077 AddTail(&fn
->pendingreads
, (struct Node
*)msg
);
1081 while (!IsListEmpty(&fn
->pendingwrites
) && !IsListEmpty(&fn
->pendingreads
))
1083 struct pipefsmessage
*rmsg
= (struct pipefsmessage
*)RemHead(&fn
->pendingreads
);
1084 struct pipefsmessage
*wmsg
= (struct pipefsmessage
*)RemHead(&fn
->pendingwrites
);
1086 ULONG len
= (rmsg
->curlen
> wmsg
->curlen
) ?
1087 wmsg
->curlen
: rmsg
->curlen
;
1089 D(bug("Writer len = %d - Reader len = %d. Copying %d bytes\n",
1090 wmsg
->curlen
, rmsg
->curlen
, len
));
1094 wmsg
->iofs
->io_Union
.io_READ_WRITE
.io_Buffer
+
1095 wmsg
->iofs
->io_Union
.io_READ_WRITE
.io_Length
-
1098 rmsg
->iofs
->io_Union
.io_READ_WRITE
.io_Buffer
+
1099 rmsg
->iofs
->io_Union
.io_READ_WRITE
.io_Length
-
1105 wmsg
->curlen
-= len
;
1106 rmsg
->curlen
-= len
;
1108 D(bug("Writer curlen is now %d - Reader curlen is now %d\n",
1109 wmsg
->curlen
, rmsg
->curlen
));
1113 D(bug("Writer: finished its job.\n"));
1118 D(bug("Writer: not finished yet. Enqueueing the request again.\n"));
1119 AddTail(&fn
->pendingwrites
, (struct Node
*)wmsg
);
1124 D(bug("Reader: finished its job.\n"));
1130 ((struct usernode
*)rmsg
->iofs
->IOFS
.io_Unit
)->mode
& FMF_NONBLOCK
&&
1131 rmsg
->iofs
->io_Union
.io_READ_WRITE
.io_Length
> wmsg
->iofs
->io_Union
.io_READ_WRITE
.io_Length
1134 D(bug("Reader: wants to read more data than it's actually available, but since it's in nonblocking mode return anyway\n"));
1135 rmsg
->iofs
->io_Union
.io_READ_WRITE
.io_Length
= len
;
1140 D(bug("Reader: not finished yet. Enqueueing the request again.\n"));
1141 AddTail(&fn
->pendingreads
, (struct Node
*)rmsg
);
1145 D(bug("Coming back to wait for a new message\n"));