3 * Revision 1.20 1999/09/11 17:05:14 Michiel
6 * Revision 1.19 1999/05/14 11:31:34 Michiel
7 * Long filename support implemented; bugfixes
9 * Revision 1.18 1999/03/25 22:03:12 Michiel
10 * Allow setdeldir for muROOT_UID only
11 * Check volume for setdeldir
12 * Added deldir inquiry option
14 * Revision 1.17 1999/02/22 16:27:21 Michiel
17 * Revision 1.16 1998/09/27 11:26:37 Michiel
18 * Error incurred softlock can now be disabled in dd_WriteProtect
20 * Revision 1.15 1998/05/31 16:27:42 Michiel
21 * added ACTION_IS_PFS2
23 * Revision 1.14 1998/05/29 19:31:18 Michiel
26 * Revision 1.13 1998/05/27 20:16:13 Michiel
28 * Allow ID_PFS2_DISK in custom packets
30 * Revision 1.12 1997/03/03 22:04:04 Michiel
33 * Revision 1.11 1996/03/14 19:29:43 Michiel
34 * using new NewFile specification
36 * Revision 1.10 1996/03/07 10:06:34 Michiel
37 * DICE MakeIndex fix (wt)
38 * Rename MuAF access (wt)
40 * Revision 1.9 1996/01/30 12:48:52 Michiel
41 * --- working tree overlap ---
44 * Revision 1.8 1995/12/29 11:03:17 Michiel
45 * dd_SetRollover added
47 * Revision 1.7 1995/12/20 11:28:10 Michiel
50 * Revision 1.6 1995/12/07 15:25:38 Michiel
51 * rollover support and bugfixes
53 * Revision 1.5 1995/11/07 14:52:34 Michiel
54 * FreeUnusedResources after flush
56 * Revision 1.4 1995/09/01 11:14:40 Michiel
57 * fixed enforcer hit in dd_Open
61 /**********************
65 static SIPTR
NotKnown(struct DosPacket
*pkt
, globaldata
* g
);
66 static SIPTR
NotYetImplemented(struct DosPacket
*pkt
, globaldata
* g
);
67 static SIPTR
dd_IsFileSystem(struct DosPacket
*pkt
, globaldata
* g
);
68 static SIPTR
dd_Quit(struct DosPacket
*pkt
, globaldata
* g
);
69 static SIPTR
dd_CurrentVolume(struct DosPacket
*pkt
, globaldata
* g
);
70 static SIPTR
dd_Lock(struct DosPacket
*pkt
, globaldata
* g
);
71 static SIPTR
dd_Unlock(struct DosPacket
*pkt
, globaldata
* g
);
72 static SIPTR
dd_DupLock(struct DosPacket
*pkt
, globaldata
* g
);
73 static SIPTR
dd_CreateDir(struct DosPacket
*pkt
, globaldata
* g
);
74 static SIPTR
dd_Parent(struct DosPacket
*pkt
, globaldata
* g
);
75 static SIPTR
dd_SameLock(struct DosPacket
*pkt
, globaldata
* g
);
76 static SIPTR
dd_Open(struct DosPacket
*pkt
, globaldata
* g
);
77 static SIPTR
dd_OpenFromLock(struct DosPacket
*pkt
, globaldata
* g
);
78 static SIPTR
dd_Close(struct DosPacket
*pkt
, globaldata
* g
);
79 static SIPTR
dd_ChangeMode(struct DosPacket
*pkt
, globaldata
* g
);
80 static SIPTR
dd_SeekRead(struct DosPacket
*pkt
, globaldata
* g
);
81 static SIPTR
dd_WriteSFS(struct DosPacket
*pkt
, globaldata
* g
);
82 static SIPTR
dd_Relabel(struct DosPacket
*pkt
, globaldata
* g
);
83 static SIPTR
dd_AddBuffers(struct DosPacket
*pkt
, globaldata
* g
);
84 static SIPTR
dd_Info(struct DosPacket
*pkt
, globaldata
* g
);
85 static SIPTR
dd_Flush(struct DosPacket
*pkt
, globaldata
* g
);
86 static SIPTR
dd_WriteProtect(struct DosPacket
*pkt
, globaldata
* g
);
87 static SIPTR
dd_SerializeDisk(struct DosPacket
*pkt
, globaldata
* g
);
88 static SIPTR
dd_DeleteObject(struct DosPacket
*pkt
, globaldata
* g
);
89 static SIPTR
dd_Rename(struct DosPacket
*pkt
, globaldata
* g
);
90 static SIPTR
dd_SetProperty(struct DosPacket
*pkt
, globaldata
* g
);
91 static SIPTR
dd_Examine(struct DosPacket
*pkt
, globaldata
* g
);
92 static SIPTR
dd_ExamineAll(struct DosPacket
*pkt
, globaldata
* g
);
93 static SIPTR
dd_MakeLink(struct DosPacket
*pkt
, globaldata
* g
);
94 static SIPTR
dd_ReadLink(struct DosPacket
*pkt
, globaldata
* g
);
95 static SIPTR
dd_InhibitOn(struct DosPacket
*pkt
, globaldata
* g
);
96 static SIPTR
dd_InhibitOff(struct DosPacket
*pkt
, globaldata
* g
);
97 static SIPTR
dd_Format(struct DosPacket
*pkt
, globaldata
* g
);
98 static SIPTR
dd_AddNotify(struct DosPacket
*pkt
, globaldata
* g
);
99 static SIPTR
dd_RemoveNotify(struct DosPacket
*pkt
, globaldata
* g
);
100 static SIPTR
dd_SignalIdle(struct DosPacket
*pkt
, globaldata
* g
);
102 /* internal packets; PFS2 extensions */
103 static int dd_CheckCustomPacket(LONG id
);
104 static SIPTR
dd_IsPFS2 (struct DosPacket
*pkt
, globaldata
*g
);
105 static SIPTR
dd_KillEmpty(struct DosPacket
*pkt
, globaldata
* g
);
106 static SIPTR
dd_RemoveDirEntry(struct DosPacket
*pkt
, globaldata
* g
);
109 static SIPTR
dd_Sleep(struct DosPacket
*pkt
, globaldata
* g
);
110 static SIPTR
dd_UpdateAnode(struct DosPacket
*pkt
, globaldata
* g
);
111 static SIPTR
dd_SetFileSize(struct DosPacket
*pkt
, globaldata
*g
);
113 static SIPTR
dd_MakeRollover(struct DosPacket
*pkt
, globaldata
* g
);
114 static SIPTR
dd_SetRollover(struct DosPacket
*pkt
, globaldata
*g
);
115 #endif /* ROLLOVER */
117 static SIPTR
dd_SetDeldir(struct DosPacket
*pkt
, globaldata
*g
);
119 #endif /* ExtraPackets */
120 #if defined(__MORPHOS__)
121 static LONG
dd_MorphOSQueryAttr(struct DosPacket
*pkt
, globaldata
*g
);
125 /**********************
129 static SIPTR
NotKnown(struct DosPacket
*pkt
, globaldata
* g
)
131 pkt
->dp_Res2
= ERROR_ACTION_NOT_KNOWN
;
135 static SIPTR
NotYetImplemented(struct DosPacket
*pkt
, globaldata
* g
)
137 pkt
->dp_Res2
= ERROR_NOT_IMPLEMENTED
;
141 static SIPTR
dd_IsFileSystem(struct DosPacket
*pkt
, globaldata
* g
)
146 /* causes PFS2 to quit. The dieing-flag will cause main to call
147 * Quit() after returning the packet
149 static SIPTR
dd_Quit(struct DosPacket
*pkt
, globaldata
* g
)
155 struct volumedata
*volume
= g
->currentvolume
;
157 if (!volume
|| (IsMinListEmpty(&volume
->fileentries
) && IsMinListEmpty(&volume
->notifylist
)))
164 pkt
->dp_Res2
= ERROR_OBJECT_IN_USE
;
170 static SIPTR
dd_CurrentVolume(struct DosPacket
*pkt
, globaldata
* g
)
172 /* arguments fixed 18-04-94 */
173 // ARG1 = APTR fileentry. (filled in by Open()) of NULL
174 // RES1 = BPTR to volume node structure
175 // RES2 = Unit number
177 pkt
->dp_Res2
= g
->startup
->fssm_Unit
;
181 if (g
->currentvolume
)
182 return (SIPTR
)MKBADDR(g
->currentvolume
->devlist
);
187 return (SIPTR
)MKBADDR(((fileentry_t
*) pkt
->dp_Arg1
)->le
.volume
->devlist
);
191 /**********************
195 static SIPTR
dd_Lock(struct DosPacket
*pkt
, globaldata
* g
)
197 // ARG1 = Lock on directory ARG2 is relative to (BPTR)
198 // ARG2 = BSTR Name of object
199 // ARG3 = LONG mode: SHARED_LOCK, EXCLUSIVE_LOCK
200 // RES1 = Lock on requested object (0=failure)
201 // RES2 = failurecode
203 lockentry_t
*parentfe
;
205 union objectinfo filefi
, *parentfi
;
206 UBYTE pathname
[PATHSIZE
], *fullname
;
208 SIPTR
*error
= &pkt
->dp_Res2
;
210 struct extrafields extrafields
;
216 GetFileInfoFromLock(pkt
->dp_Arg1
, 0, parentfe
, parentfi
);
217 BCPLtoCString(pathname
, (DSTR
)BARG2(pkt
));
218 DB(Trace(1, "Lock", "locking : %s parent: %lx \n", pathname
, pkt
->dp_Arg1
));
219 DB(if (parentfi
) Trace(1, "Lock", "anodenr = %lx and %lx \n", parentfe
->nextanode
,
220 (parentfi
->file
.direntry
? parentfi
->file
.direntry
->anode
: ANODE_ROOTDIR
)));
221 SkipColon(fullname
, pathname
);
224 * .. if no filename then lock parent
226 if (parentfi
&& !*fullname
)
228 else if (!FindObject(parentfi
, fullname
, &filefi
, error
, g
))
230 DB(Trace(1, "Lock", "failed at locktime : %s\n", fullname
));
234 // Add object to list
235 if (IsVolume(filefi
))
237 type
.value
= ET_VOLUME
+ ET_SHAREDREAD
;
241 type
.value
= ET_LOCK
;
242 type
.flags
.access
= (pkt
->dp_Arg3
== EXCLUSIVE_LOCK
? ET_EXCLREAD
: ET_SHAREDREAD
);
246 GetExtraFieldsOI(&filefi
, &extrafields
, g
);
248 GetExtraFields(filefi
.file
.direntry
, &extrafields
);
251 flags
= muGetRelationship(extrafields
);
253 if (!(flags
& muRel_PROPERTY_ACCESS
) &&
254 (*error
= muFS_CheckReadAccess(extrafields
.prot
, flags
, g
)))
256 #endif /* MULTIUSER */
259 if (!(filefe
= MakeListEntry(&filefi
, type
, error
, g
)))
262 if (!AddListEntry(filefe
))
264 DB(Trace(1, "dd_Lock", "object in use"));
266 FreeListEntry(filefe
, g
);
267 *error
= ERROR_OBJECT_IN_USE
;
271 DB(Trace(1, "Lock", "adres: %lx\n", filefe
));
273 return (SIPTR
)MKBADDR(&filefe
->lock
);
276 static SIPTR
dd_Unlock(struct DosPacket
*pkt
, globaldata
* g
)
278 // ARG1 = LOCK to free
281 listentry_t
*listentry
;
283 listentry
= ListEntryFromLock(pkt
->dp_Arg1
);
286 // not needed: UpdateLE(listentry, g);
287 RemoveListEntry(listentry
, g
);
293 static SIPTR
dd_DupLock(struct DosPacket
*pkt
, globaldata
* g
)
295 // ARG1 = BPTR lock to duplicate / filehandle->fh_Arg1 to dup
296 // RES1 = Duplicated lock
297 // RES2 = failure code if RES1=0
299 // scrfe: oorspronkelijke fileentry
300 // dstfe: copy van scrfe
302 lockentry_t
*srcfe
, *dstfe
;
303 union objectinfo filefi
;
308 if (!g
->currentvolume
)
310 pkt
->dp_Res2
= ERROR_NO_DISK
;
314 /* return lock to root (GURU 605) */
315 filefi
.volume
.root
= 0;
316 filefi
.volume
.volume
= g
->currentvolume
;
317 type
.value
= ET_VOLUME
+ ET_SHAREDREAD
;
318 if (!(dstfe
= (lockentry_t
*)MakeListEntry(&filefi
, type
, &pkt
->dp_Res2
, g
)))
324 /* get entry struct */
325 if (pkt
->dp_Type
== ACTION_COPY_DIR
)
326 srcfe
= LockEntryFromLock(pkt
->dp_Arg1
);
328 srcfe
= (lockentry_t
*)pkt
->dp_Arg1
;
330 if (!CheckVolume(srcfe
->le
.volume
, 0, &pkt
->dp_Res2
, g
))
332 UpdateLE((listentry_t
*)srcfe
, g
);
334 /* only allow SHAREDREAD locks & fe's */
335 if (srcfe
->le
.type
.flags
.access
!= ET_SHAREDREAD
)
337 pkt
->dp_Res2
= ERROR_OBJECT_IN_USE
;
341 if (!(dstfe
= (lockentry_t
*) AllocMemP(sizeof(lockentry_t
), g
)))
343 pkt
->dp_Res2
= ERROR_NO_FREE_STORE
;
347 /* only copy the listentry_t part. The extension fields (nextanode,
348 * nextentry and nextdirblock are all zero
350 CopyMem(srcfe
, dstfe
, sizeof(listentry_t
));
352 /* if COPY_DIR_FH then update type to LOCK */
353 if (pkt
->dp_Type
== ACTION_COPY_DIR_FH
)
354 dstfe
->le
.type
.flags
.type
= ETF_LOCK
;
357 if (!AddListEntry((listentry_t
*)dstfe
))
359 FreeListEntry((listentry_t
*)dstfe
, g
); // Niet mogelijk SHAREDREAD always copyable
361 pkt
->dp_Res2
= ERROR_OBJECT_IN_USE
;
365 DB(Trace(1, "DupLock", "of %lx adres: %lx\n", srcfe
, dstfe
));
366 return (SIPTR
)MKBADDR(&dstfe
->le
.lock
);
369 static SIPTR
dd_CreateDir(struct DosPacket
*pkt
, globaldata
* g
)
371 // ARG1 = Lock on directory ARG2 is relative to (BPTR)
372 // ARG2 = BSTR Name of new directory
373 // RES1 = Lock on new directory
374 // RES2 = failurecode (if res1 = DOSFALSE)
376 lockentry_t
*parentle
, *newdirle
;
377 union objectinfo path
, *parentfi
;
378 UBYTE
*dirname
, pathname
[PATHSIZE
];
380 SIPTR
*error
= &pkt
->dp_Res2
;
383 struct extrafields extrafields
;
388 GetFileInfoFromLock(pkt
->dp_Arg1
, 1, parentle
, parentfi
);
389 BCPLtoCString(pathname
, (DSTR
)BARG2(pkt
));
390 SkipColon(dirname
, pathname
);
391 zonderpad
= GetFullPath(parentfi
, dirname
, &path
, error
, g
);
400 GetExtraFieldsOI(&path
, &extrafields
);
402 GetExtraFields(path
.file
.direntry
, &extrafields
);
404 flags
= muGetRelationship(extrafields
);
405 if (*error
= muFS_CheckWriteAccess(extrafields
.prot
, flags
, g
))
408 #endif /* MU_CHECKDIR */
409 #endif /* MULTIUSER */
411 newdirle
= NewDir(&path
, zonderpad
, error
, g
);
415 PFSDoNotify(&newdirle
->le
.info
.file
, TRUE
, g
);
416 return (SIPTR
)MKBADDR(&newdirle
->le
.lock
);
422 static SIPTR
dd_Parent(struct DosPacket
*pkt
, globaldata
* g
)
424 // ACTION_PARENT en ACTION_PARENT_FH
425 // ARG1 = BPTR Lock on object to get the parent of
426 // ARG1.FH = filehandle->dp_Arg1 == &listentry
427 // RES1 = BPTR Parent lock
428 // RES2 = failure code (if res1 = 0)
430 lockentry_t
*childfe
;
431 listentry_t
*parentfe
;
433 union objectinfo
*childfi
, parentfi
;
434 SIPTR
*error
= &pkt
->dp_Res2
;
436 // get fe & fi of child
437 if (pkt
->dp_Type
== ACTION_PARENT
)
438 childfe
= LockEntryFromLock(pkt
->dp_Arg1
);
440 childfe
= (lockentry_t
*) (pkt
->dp_Arg1
);
442 /* check if volume present and update lock */
445 if (!CheckVolume(childfe
->le
.volume
, 0, error
, g
))
447 UpdateLE((listentry_t
*)childfe
, g
);
448 childfi
= &childfe
->le
.info
;
452 if (!g
->currentvolume
)
454 *error
= ERROR_NO_DISK
;
461 if (!GetParent(childfi
, &parentfi
, &pkt
->dp_Res2
, g
))
464 // make and enter a fileentry
466 type
.flags
.type
= IsVolume(parentfi
) ? (ETF_VOLUME
) : (ETF_LOCK
);
467 type
.flags
.access
= ET_SHAREDREAD
;
469 if (!(parentfe
= MakeListEntry(&parentfi
, type
, &pkt
->dp_Res2
, g
)))
472 if (!AddListEntry(parentfe
))
474 FreeListEntry(parentfe
, g
);
475 pkt
->dp_Res2
= ERROR_OBJECT_IN_USE
;
476 //NormalErrorMsg("ßE Parent failed", NULL);
480 return (SIPTR
)MKBADDR(&parentfe
->lock
);
484 /* Somehow a filehandler should send opposite values: */
485 #define H_LOCK_SAME 1
486 #define H_LOCK_SAME_VOLUME 0
488 static SIPTR
dd_SameLock(struct DosPacket
*pkt
, globaldata
* g
)
490 // ARG1 = BPTR Lock 1 to compare
491 // ARG2 = BPTR Lock 2 to compare
492 // RES1 = LONG result of compare
493 // RES2 = CODE failurecode (if res1 = LOCK_DIFFERENT)
495 lockentry_t
*lock1
, *lock2
;
497 lock1
= LockEntryFromLock(pkt
->dp_Arg1
);
498 UpdateLE((listentry_t
*)lock1
, g
);
499 lock2
= LockEntryFromLock(pkt
->dp_Arg2
);
500 UpdateLE((listentry_t
*)lock2
, g
);
503 if (!lock1
|| !lock2
)
505 pkt
->dp_Res2
= ERROR_INVALID_LOCK
;
506 return LOCK_DIFFERENT
;
509 if (lock1
->le
.volume
!= lock2
->le
.volume
)
510 return LOCK_DIFFERENT
;
512 if (lock1
->le
.anodenr
== lock2
->le
.anodenr
)
515 return H_LOCK_SAME_VOLUME
;
519 /**********************
520 * Filehandle functions
523 static SIPTR
dd_Open(struct DosPacket
*pkt
, globaldata
* g
)
525 // ARG1 = BPTR Filehandle to fill in
526 // ARG2 = BPTR LOCK on directory ARG3 is relative to
527 // ARG3 = BSTR Name of file to be opened
528 // RES1 = Success/Failure (DOSTRUE/DOSFALSE)
529 // RES2 = failure code
531 // fullname: name inclusief pat
532 // filename: filename zonder pat
533 // pathfi: fileinfo van path van te openen file
534 // filefi: fileinfo van te openen file
535 // mode: nodetype van fileentry van file
537 // GURUbook: ACTION_FINDINPUT premits write access (598)
539 struct FileHandle
*filehandle
;
541 lockentry_t
*parentfe
;
542 union objectinfo pathfi
, filefi
, *parentfi
;
544 SIPTR
*error
= &pkt
->dp_Res2
;
545 UBYTE pathname
[PATHSIZE
], *fullname
, *filename
= NULL
;
548 struct extrafields extrafields
;
551 struct extrafields path_extrafields
;
553 #endif /* MU_CHECKDIR */
554 #endif /* MULTIUSER */
556 // -I- benodigde waarden afleiden van pakket
557 filehandle
= (struct FileHandle
*)BADDR(pkt
->dp_Arg1
);
558 GetFileInfoFromLock(pkt
->dp_Arg2
, 0, parentfe
, parentfi
);
559 BCPLtoCString(pathname
, (DSTR
)BARG3(pkt
));
560 DB(Trace(1, "Open", "%s\n", pathname
));
561 SkipColon(fullname
, pathname
);
563 /* 15.9: check if path is file. If so it has to be opened
564 * if an empty string was specified as filename
567 if (parentfi
&& IsFile(*parentfi
) && *fullname
== 0)
574 /* Get path to file */
575 if (!(filename
= GetFullPath(parentfi
, fullname
, &pathfi
, error
, g
)))
578 /* try to locate file */
579 found
= FindObject(&pathfi
, filename
, &filefi
, error
, g
);
584 /* softlinks cannot directly be opened */
585 if (IsSoftLink(filefi
))
587 *error
= ERROR_IS_SOFT_LINK
;
591 /* check if file (only files can be opened) */
593 if ((IsVolume(filefi
) || IsDelDir(filefi
) || IsDir(filefi
)))
595 if ((IsVolume(filefi
) || IsDir(filefi
)))
598 *error
= ERROR_OBJECT_WRONG_TYPE
;
603 type
.value
= ET_FILEENTRY
;
607 if (IsVolume(pathfi
))
608 memset(&path_extrafields
, 0, sizeof(struct extrafields
));
611 GetExtraFieldsOI(&pathfi
, &path_extrafields
);
613 GetExtraFields(pathfi
.file
.direntry
, &path_extrafields
);
615 #endif /* MU_CHECKDIR */
619 GetExtraFieldsOI(&filefi
, &extrafields
, g
);
621 GetExtraFields(filefi
.file
.direntry
, &extrafields
);
627 path_flags
= muGetRelationshipA(g
->user
, (path_extrafields
.uid
<< 16) + path_extrafields
.gid
, NULL
);
630 flags
= muGetRelationshipA(g
->user
, (extrafields
.uid
<< 16) + extrafields
.gid
, NULL
);
635 path_flags
= ((path_extrafields
.uid
== muNOBODY_UID
) << muRelB_NO_OWNER
) | muRelF_NOBODY
;
638 flags
= ((extrafields
.uid
== muNOBODY_UID
) << muRelB_NO_OWNER
) | muRelF_NOBODY
;
640 #endif /* MULTIUSER */
642 switch (pkt
->dp_Type
)
644 case ACTION_FINDINPUT
:
649 if ((*error
= muFS_CheckReadAccess(extrafields
.prot
, flags
, g
)))
652 type
.flags
.access
= ET_SHAREDREAD
;
655 case ACTION_FINDUPDATE
:
660 if ((*error
= muFS_CheckWriteAccess(extrafields
.prot
, flags
, g
)))
666 if ((*error
= muFS_CheckWriteAccess(path_extrafields
.prot
, path_flags
, g
)))
669 #endif /* MU_CHECKDIR */
670 #endif /* MULTIUSER */
674 if ((*error
= NewFile (found
, &pathfi
, filename
, &filefi
, g
)))
676 DB(Trace(1, "NewFile", "update failed"));
681 type
.flags
.access
= ET_SHAREDWRITE
;
684 case ACTION_FINDOUTPUT
:
688 if ((*error
= muFS_CheckDeleteAccess(extrafields
.prot
, flags
, g
)))
691 if ((*error
= muFS_CheckWriteAccess(extrafields
.prot
, flags
, g
)))
696 if ((*error
= muFS_CheckWriteAccess(path_extrafields
.prot
, path_flags
, g
)))
698 #endif /* MU_CHECKDIR */
699 #else /* MULTIUSER */
701 #endif /* MULTIUSER */
703 if ((*error
= NewFile (found
, &pathfi
, filename
, &filefi
, g
)))
705 DB(Trace(1, "Newfile", "output failed"));
709 type
.flags
.access
= ET_EXCLWRITE
;
713 *error
= ERROR_ACTION_NOT_KNOWN
;
717 /* Add file to list */
718 if (!(filefe
= MakeListEntry(&filefi
, type
, error
, g
)))
721 if (!AddListEntry(filefe
))
723 DB(Trace(1, "dd_Open", "AddListEntry failed"));
724 FreeListEntry(filefe
, g
);
725 *error
= ERROR_OBJECT_IN_USE
;
729 /* if the file was created, the user has to be notified */
730 ((fileentry_t
*) filefe
)->checknotify
= !found
;
731 filehandle
->fh_Arg1
= (SIPTR
)filefe
; // We get this with Read(), Write() etc
736 static SIPTR
dd_OpenFromLock(struct DosPacket
*pkt
, globaldata
* g
)
738 // ARG1 = BPTR to filehandle
739 // ARG2 = BPTR lock on file to open
740 // RES1 = BOOL Success/failure (DOSTRUE/DOSFALSE)
741 // RES2 = failurecode (if res1 = DOSFALSE)
743 struct FileHandle
*filehandle
;
744 listentry_t
*lockentry
, *fileentry
;
747 filehandle
= (struct FileHandle
*)BADDR(pkt
->dp_Arg1
);
748 if (!(lockentry
= ListEntryFromLock(pkt
->dp_Arg2
)) ||
749 !CheckVolume(lockentry
->volume
, 0, &pkt
->dp_Res2
, g
))
752 UpdateLE(lockentry
, g
);
753 if (!IsFile(lockentry
->info
))
755 pkt
->dp_Res2
= ERROR_OBJECT_WRONG_TYPE
;
759 type
.value
= (lockentry
->lock
.fl_Access
== EXCLUSIVE_LOCK
) ? \
760 (ET_FILEENTRY
| ET_EXCLWRITE
) : (ET_FILEENTRY
| ET_SHAREDREAD
);
761 if (!(fileentry
= MakeListEntry(&lockentry
->info
, type
, &pkt
->dp_Res2
, g
)))
764 /* oude lock verwijderen; nieuwe fileentry toevoegen
765 * addlistentry zou eigenlijk niet fout moeten kunnen gaan
767 RemoveListEntry(lockentry
, g
);
768 if (!AddListEntry(fileentry
)) /* should not go wrong */
770 FreeListEntry(fileentry
, g
);
771 pkt
->dp_Res2
= ERROR_OBJECT_IN_USE
;
775 filehandle
->fh_Arg1
= (SIPTR
)fileentry
;
779 static SIPTR
dd_Close(struct DosPacket
*pkt
, globaldata
* g
)
782 fileentry_t
*fe
= (fileentry_t
*)pkt
->dp_Arg1
;
790 if (!CheckVolume(fe
->le
.volume
, 1, &error
, g
))
792 UpdateLE((listentry_t
*) fe
, g
);
793 Touch(&fe
->le
.info
.file
, g
);
794 size
= GetDEFileSize(fe
->le
.info
.file
.direntry
, g
);
795 if (fe
->originalsize
!= size
)
796 UpdateLinks(fe
->le
.info
.file
.direntry
, g
);
798 PFSDoNotify(&fe
->le
.info
.file
, TRUE
, g
);
802 RemoveListEntry((listentry_t
*) fe
, g
);
806 static SIPTR
dd_ChangeMode(struct DosPacket
*pkt
, globaldata
* g
)
808 // ARG1 = LONG type of object to change - either CHANGE_FH or CHANGE_LOCK
809 // ARG2 = BPTR object to be changed
810 // ARG3 = LONG new mode for object
811 // RES1 = Success/failure (DOSTRUE/DOSFALSE)
814 listentry_t
*listentry
;
816 if (pkt
->dp_Arg1
== CHANGE_FH
)
817 listentry
= (listentry_t
*)
818 (((struct FileHandle
*)BADDR(pkt
->dp_Arg2
))->fh_Arg1
);
820 listentry
= ListEntryFromLock(pkt
->dp_Arg2
);
824 if (!CheckVolume(listentry
->volume
, 0, &pkt
->dp_Res2
, g
))
827 UpdateLE(listentry
, g
);
832 return ChangeAccessMode(listentry
, pkt
->dp_Arg3
, &pkt
->dp_Res2
);
835 /* reading and seeking in an open file */
836 static SIPTR
dd_SeekRead(struct DosPacket
*pkt
, globaldata
* g
)
839 // ARG1 = APTR fileentry. (filled in by Open())
840 // ARG2 = APTR buffer to put data into
841 // ARG3 = LONG #bytes to read
842 // RES1 = LONG #bytes read, 0=eof, -1=error
843 // RES2 = CODE failurecode if RES1=-1
846 // ARG1 = APTR fileentry. (filled in by Open())
847 // ARG2 = LONG offset
848 // ARG3 = LONG seek mode
849 // RES1 = LONG absolute offset before seek
850 // RES2 = CODE failurecode if RES1=-1
852 listentry_t
*listentry
;
854 listentry
= (listentry_t
*) pkt
->dp_Arg1
;
855 if (!CheckVolume(listentry
->volume
, 0, &pkt
->dp_Res2
, g
))
858 UpdateLE(listentry
, g
);
860 if (pkt
->dp_Type
== ACTION_READ
)
862 return (LONG
)ReadFromObject((fileentry_t
*) listentry
,
863 (UBYTE
*)pkt
->dp_Arg2
, (ULONG
)pkt
->dp_Arg3
,
868 return SeekInObject((fileentry_t
*) listentry
,
869 (LONG
)pkt
->dp_Arg2
, (LONG
)pkt
->dp_Arg3
,
874 /* Write to an open file, or change its size (SFS = SetFileSize) */
875 static SIPTR
dd_WriteSFS(struct DosPacket
*pkt
, globaldata
* g
)
878 // ARG1 = APTR fileentry. (filled in by Open())
879 // ARG2 = APTR buffer to put data into
880 // ARG3 = LONG #bytes to read
881 // RES1 = LONG #bytes read, 0=eof, -1=error
882 // RES2 = CODE failurecode if RES1=-1
884 // ACTION_SET_FILE_SIZE
885 // ARG1 = APTR fileentry. (filled in by Open())
886 // ARG2 = LONG offset
888 // RES1 = LONG new file size
889 // RES2 = CODE failurecode if RES1=-1
891 listentry_t
*listentry
;
893 listentry
= (listentry_t
*)pkt
->dp_Arg1
;
894 if (!CheckVolume(listentry
->volume
, 1, &pkt
->dp_Res2
, g
))
896 UpdateLE(listentry
, g
);
898 if (pkt
->dp_Type
== ACTION_WRITE
)
900 return (LONG
)WriteToObject((fileentry_t
*)listentry
,
901 (UBYTE
*)pkt
->dp_Arg2
, (ULONG
)pkt
->dp_Arg3
,
904 else /* SetFileSize */
906 return ChangeObjectSize((fileentry_t
*)listentry
,
907 pkt
->dp_Arg2
, pkt
->dp_Arg3
, &pkt
->dp_Res2
, g
);
912 /**********************
916 /* change the name of a volume */
917 static SIPTR
dd_Relabel(struct DosPacket
*pkt
, globaldata
* g
)
919 // ARG1 = BSTR new disk name
920 // RES1 = BOOL Success/failure (DOSTRUE/DOSFALSE)
922 UBYTE newlabel
[FNSIZE
];
923 struct volumedata
*volume
;
924 struct DeviceList
*devlist
;
928 if (g
->user
->uid
!= muROOT_UID
)
930 pkt
->dp_Res2
= ERROR_DISK_WRITE_PROTECTED
;
935 BCPLtoCString(newlabel
, (DSTR
)BARG1(pkt
));
936 volume
= g
->currentvolume
;
938 if (!CheckVolume(volume
, 1, &pkt
->dp_Res2
, g
))
941 /* make new doslist entry COPY VAN DISKINSERTSEQUENCE */
942 devlist
= (struct DeviceList
*)MakeDosEntry(newlabel
, DLT_VOLUME
);
945 /* change rootblock */
946 if (RenameDisk(newlabel
, g
))
948 /* free old devlist */
949 // LockDosList (LDF_VOLUMES|LDF_READ);
951 RemDosEntry((struct DosList
*)volume
->devlist
);
952 FreeDosEntry((struct DosList
*)volume
->devlist
);
953 // UnLockDosList (LDF_VOLUMES|LDF_READ);
956 /* fill in new. Diskname NIET */
957 g
->currentvolume
->devlist
= devlist
;
958 devlist
->dl_Task
= g
->msgport
;
959 devlist
->dl_VolumeDate
.ds_Days
= volume
->rootblk
->creationday
;
960 devlist
->dl_VolumeDate
.ds_Minute
= volume
->rootblk
->creationminute
;
961 devlist
->dl_VolumeDate
.ds_Tick
= volume
->rootblk
->creationtick
;
962 devlist
->dl_LockList
= BNULL
; // disk still inserted
963 devlist
->dl_DiskType
= volume
->rootblk
->disktype
;
966 AddDosEntry((struct DosList
*)devlist
);
967 volume
->devlist
= (struct DeviceList
*)devlist
;
969 /* alle locks veranderen */
970 for (fe
= HeadOf(&volume
->fileentries
); fe
->next
; fe
= fe
->next
)
971 fe
->lock
.fl_Volume
= MKBADDR(devlist
);
975 pkt
->dp_Res2
= ERROR_INVALID_COMPONENT_NAME
;
981 pkt
->dp_Res2
= ERROR_NO_FREE_STORE
; // ??
988 /* change the size of the cache */
989 static SIPTR
dd_AddBuffers(struct DosPacket
*pkt
, globaldata
* g
)
991 // ARG1 = LONG (number of buffers)
992 // RES1 = BOOL Success/failure (DOSTRUE/DOSFALSE)
993 // RES2 = new total number of cache buffers or failurecode (if res1 = DOSFALSE)
995 struct lru_cachedblock
*lrunode
, *nextnode
;
1001 for (lrunode
= (struct lru_cachedblock
*)g
->glob_lrudata
.LRUqueue
.mlh_Head
; lrunode
->next
;
1004 FlushBlock(&lrunode
->cblk
, g
);
1005 nextnode
= lrunode
->next
;
1010 numbuffers
= g
->dosenvec
->de_NumBuffers
;
1011 numbuffers
= max(0, numbuffers
+ (LONG
)pkt
->dp_Arg1
);
1012 g
->dosenvec
->de_NumBuffers
= numbuffers
;
1014 while (!InitLRU(g
, SIZEOF_RESBLOCK
))
1015 g
->dosenvec
->de_NumBuffers
--;
1017 pkt
->dp_Res2
= g
->dosenvec
->de_NumBuffers
;
1018 return (LONG
)g
->dosenvec
->de_NumBuffers
;
1022 static SIPTR
dd_Info(struct DosPacket
*pkt
, globaldata
* g
)
1024 // ARG1 = diskinfo: BPTR to InfoData to fill in
1025 // info: BPTR lock on volume
1026 // ARG2 = info: BPTR to InfoData to fill in
1027 // RES1 = BOOL Success/failure (DOSTRUE/DOSFALSE)
1029 struct InfoData
*info
;
1031 struct volumedata
*volume
;
1034 if (pkt
->dp_Type
== ACTION_DISK_INFO
)
1036 info
= (struct InfoData
*)BARG1(pkt
);
1037 volume
= g
->currentvolume
;
1041 le
= LockEntryFromLock(pkt
->dp_Arg1
);
1042 volume
= le
? (le
->le
.volume
) : (g
->currentvolume
);
1043 if (volume
!= g
->currentvolume
)
1045 pkt
->dp_Res2
= ERROR_DEVICE_NOT_MOUNTED
;
1048 info
= (struct InfoData
*)BARG2(pkt
);
1053 info
->id_NumSoftErrors
= volume
->numsofterrors
;
1054 info
->id_UnitNumber
= g
->startup
->fssm_Unit
;
1055 info
->id_DiskState
= g
->softprotect
? ID_WRITE_PROTECTED
: g
->diskstate
;
1056 info
->id_NumBlocks
= volume
->numblocks
- g
->rootblock
->lastreserved
1057 - g
->rootblock
->alwaysfree
- 1;
1058 info
->id_NumBlocksUsed
= info
->id_NumBlocks
- alloc_data
.alloc_available
;
1059 info
->id_BytesPerBlock
= volume
->bytesperblock
;
1061 // 1.x C:Info only understands DOS\0
1062 info
->id_DiskType
= DOSBase
->dl_lib
.lib_Version
>= 37 ? ID_INTER_FFS_DISK
: ID_DOS_DISK
;
1064 info
->id_DiskType
= ID_INTER_FFS_DISK
; // c:Info does not like this
1066 info
->id_VolumeNode
= MKBADDR(volume
->devlist
);
1067 info
->id_InUse
= !IsMinListEmpty(&volume
->fileentries
);
1073 info
->id_NumSoftErrors
= 0;
1074 info
->id_UnitNumber
= g
->startup
->fssm_Unit
;
1075 info
->id_DiskState
= g
->diskstate
;
1076 info
->id_NumBlocks
= g
->geom
->dg_TotalSectors
- 2;
1077 info
->id_NumBlocksUsed
= 0;
1078 info
->id_BytesPerBlock
= g
->geom
->dg_SectorSize
;
1079 info
->id_DiskType
= g
->disktype
;
1080 info
->id_VolumeNode
= 0;
1087 /* flush cache (BTW: doesn't actually flush the cache right now) */
1088 static SIPTR
dd_Flush(struct DosPacket
*pkt
, globaldata
* g
)
1091 FreeUnusedResources(g
->currentvolume
, g
);
1096 /* soft-writeprotect disk */
1097 static SIPTR
dd_WriteProtect(struct DosPacket
*pkt
, globaldata
* g
)
1099 // ARG1 = BOOL DOSTRUE = write protect; DOSFALSE = un-writeprotect
1100 // ARG2 = LONG 32 bit pass key
1101 // RES1 = Success/failure (DOSTRUE/DOSFALSE)
1103 if (pkt
->dp_Arg1
) /* protecting */
1105 if (g
->softprotect
) /* already protected */
1108 /* updatedisk can cause a softprotect, so check again */
1109 if (!g
->softprotect
)
1112 g
->protectkey
= pkt
->dp_Arg2
;
1116 else /* un protecting */
1118 if (!g
->softprotect
)
1120 if (g
->softprotect
< 0)
1123 if (!g
->protectkey
|| g
->protectkey
== pkt
->dp_Arg2
||
1124 g
->protectkey
== ~0)
1134 /* make disk unique by timestamping it */
1135 static SIPTR
dd_SerializeDisk(struct DosPacket
*pkt
, globaldata
* g
)
1137 // RES1 = BOOL Success/failure (DOSTRUE/DOSFALSE)
1138 // RES2 = failurecode (if res1 = DOSFALSE)
1139 struct DateStamp time
;
1140 struct rootblock
*rbl
;
1144 /* bitmap is not needed, so read just bear rootblock */
1145 if (!(rbl
= AllocBufmem(BLOCKSIZE
, g
)))
1147 pkt
->dp_Res2
= ERROR_NO_FREE_STORE
;
1151 pkt
->dp_Res2
= RawRead((UBYTE
*)rbl
, 1, ROOTBLOCK
, g
);
1155 /* Adding 3 to the tick prevents problems after format */
1156 rbl
->creationday
= (UWORD
)time
.ds_Days
;
1157 rbl
->creationminute
= (UWORD
)time
.ds_Minute
;
1158 rbl
->creationtick
= (UWORD
)time
.ds_Tick
+ 3;
1159 pkt
->dp_Res2
= RawWrite((UBYTE
*)rbl
, 1, ROOTBLOCK
, g
);
1163 g
->request
->iotd_Req
.io_Command
= CMD_UPDATE
;
1164 DoIO((struct IORequest
*)g
->request
);
1174 /**********************
1177 static SIPTR
dd_DeleteObject(struct DosPacket
*pkt
, globaldata
* g
)
1179 // ARG1 = Lock to which ARG2 is relative (BPTR)
1180 // ARG2 = BSTR Name of object to be deleted
1181 // RES1 = BOOL Success/failure (DOSTRUE/DOSFALSE)
1182 // RES2 = failurecode (if res1 = DOSFALSE)
1184 lockentry_t
*parentfe
;
1185 union objectinfo
*parentfi
, filefi
;
1186 UBYTE
*filename
, pathname
[PATHSIZE
];
1187 SIPTR
*error
= &pkt
->dp_Res2
;
1189 struct extrafields extrafields
;
1193 GetFileInfoFromLock(pkt
->dp_Arg1
, 1, parentfe
, parentfi
);
1194 BCPLtoCString(pathname
, (DSTR
)BARG2(pkt
));
1195 SkipColon(filename
, pathname
);
1196 LocateFile(parentfi
, filename
, filefi
, error
);
1200 GetExtraFieldsOI(&filefi
, &extrafields
, g
);
1202 GetExtraFields(filefi
.file
.direntry
, &extrafields
);
1204 flags
= muGetRelationship(extrafields
);
1205 if (*error
= muFS_CheckDeleteAccess(extrafields
.prot
, flags
, g
))
1207 #endif /* MULTIUSER */
1209 PFSDoNotify(&filefi
.file
, TRUE
, g
);
1210 return DeleteObject(&filefi
, &pkt
->dp_Res2
, g
);
1213 static SIPTR
dd_Rename(struct DosPacket
*pkt
, globaldata
* g
)
1215 // ARG1 = BPTR Lock to which ARG2 is relative
1216 // ARG2 = BSTR Name of object to rename
1217 // ARG3 = BPTR Lock to target directory
1218 // ARG4 = BSTR New name of object
1219 // RES1 = BOOL Success/failure (DOSTRUE/DOSFALSE)
1220 // RES2 = failurecode (if res1 = DOSFALSE)
1222 lockentry_t
*srcdirfe
, *dstdirfe
;
1223 union objectinfo
*srcdirfi
, *dstdirfi
;
1224 UBYTE
*srcname
, srcpathname
[PATHSIZE
], *dstname
, dstpathname
[PATHSIZE
];
1225 struct volumedata
*srcvol
, *dstvol
;
1226 SIPTR
*error
= &pkt
->dp_Res2
;
1227 union objectinfo pathoi
, sourceoi
;
1231 struct extrafields extrafields
;
1235 GetFileInfoFromLock(pkt
->dp_Arg1
, 1, srcdirfe
, srcdirfi
);
1236 GetFileInfoFromLock(pkt
->dp_Arg3
, 1, dstdirfe
, dstdirfi
);
1237 BCPLtoCString(srcpathname
, (DSTR
)BARG2(pkt
));
1238 BCPLtoCString(dstpathname
, (DSTR
)BARG4(pkt
));
1239 DB(Trace(1, "Rename", "renaming %s to %s\n", srcpathname
, dstpathname
));
1241 SkipColon(srcname
, srcpathname
);
1242 SkipColon(dstname
, dstpathname
);
1244 /* check rename across devices (NOT needed; done by DOS */
1245 srcvol
= srcdirfe
? srcdirfe
->le
.volume
: g
->currentvolume
;
1246 dstvol
= dstdirfe
? dstdirfe
->le
.volume
: g
->currentvolume
;
1247 if (srcvol
!= dstvol
)
1249 *error
= ERROR_RENAME_ACROSS_DEVICES
;
1255 --> check source AND destination directories against write access
1256 #endif /* MU_CHECKDIR */
1258 if (!(objectname
= GetFullPath (srcdirfi
, srcname
, &pathoi
, error
, g
)) ||
1259 !FindObject (&pathoi
, objectname
, &sourceoi
, error
, g
))
1262 CheckPropertyAccess (sourceoi
, extrafields
, flags
, error
);
1263 if (!CheckVolume(srcvol
, 1, error
, g
))
1267 result
= RenameAndMove (&pathoi
, &sourceoi
, dstdirfi
, dstname
,
1274 /* change a object property: filenote, protection, owner, date */
1275 static SIPTR
dd_SetProperty(struct DosPacket
*pkt
, globaldata
* g
)
1278 // ARG2 = BPTR Lock to which arg3 is relative
1279 // ARG3 = BSTR Name of object
1280 // ARG4 = LONG new property
1281 // RES1 = BOOL Success/failure (DOSTRUE/DOSFALSE)
1282 // RES2 = failurecode (if res1 = DOSFALSE)
1284 lockentry_t
*parentfe
;
1285 union objectinfo
*parentfi
, objectfi
;
1286 SIPTR
*error
= &pkt
->dp_Res2
;
1287 UBYTE
*filename
, pathname
[PATHSIZE
], comment
[PATHSIZE
];
1289 struct extrafields extrafields
;
1293 GetFileInfoFromLock(pkt
->dp_Arg2
, 1, parentfe
, parentfi
);
1294 BCPLtoCString(pathname
, (DSTR
)BARG3(pkt
));
1295 SkipColon(filename
, pathname
);
1296 LocateFile(parentfi
, filename
, objectfi
, error
);
1297 CheckPropertyAccess(objectfi
, extrafields
, flags
, error
);
1298 PFSDoNotify(&objectfi
.file
, TRUE
, g
);
1300 switch (pkt
->dp_Type
)
1302 case ACTION_SET_PROTECT
:
1303 return ProtectFile(&objectfi
.file
, (ULONG
)pkt
->dp_Arg4
, error
, g
);
1305 case ACTION_SET_COMMENT
:
1306 BCPLtoCString(comment
, (DSTR
)BARG4(pkt
));
1307 return AddComment(&objectfi
, comment
, error
, g
);
1309 case ACTION_SET_DATE
:
1310 return SetDate(&objectfi
, (struct DateStamp
*)pkt
->dp_Arg4
, error
, g
);
1312 case ACTION_SET_OWNER
:
1313 return SetOwnerID(&objectfi
.file
, pkt
->dp_Arg4
, error
, g
);
1320 * Examine directory contents
1322 static SIPTR
dd_Examine(struct DosPacket
*pkt
, globaldata
* g
)
1324 // ARG1 = LOCK or filehandle of object to examine
1325 // ARG2 = BPTR FileInfoBlock to fill in
1326 // RES1 = Success/failure (DOSTRUE/DOSFALSE)
1329 listentry_t
*listentry
;
1331 if (pkt
->dp_Type
== ACTION_EXAMINE_FH
)
1332 listentry
= (listentry_t
*) pkt
->dp_Arg1
;
1334 listentry
= ListEntryFromLock(pkt
->dp_Arg1
);
1338 if (!CheckVolume(listentry
->volume
, 0, &pkt
->dp_Res2
, g
))
1341 UpdateLE(listentry
, g
);
1342 UpdateLE_exa((lockentry_t
*) listentry
, g
);
1344 else if (!g
->currentvolume
)
1346 pkt
->dp_Res2
= ERROR_NO_DISK
;
1350 if (pkt
->dp_Type
== ACTION_EXAMINE_NEXT
)
1351 return ExamineNextFile((lockentry_t
*) listentry
,
1352 (struct FileInfoBlock
*)BARG2(pkt
),
1355 return ExamineFile(listentry
,
1356 (struct FileInfoBlock
*)BARG2(pkt
),
1360 static SIPTR
dd_ExamineAll(struct DosPacket
*pkt
, globaldata
* g
)
1362 // ARG1 = BPTR Lock on directory to examine
1363 // ARG2 = APTR Buffer to store resultsobject to be changed
1364 // ARG3 = LONG Length (in bytes) of buffer (arg2)
1365 // ARG4 = LONG Type of request
1366 // ARG5 = APTR (!!) Control structure to store information
1367 // RES1 = Continuation-flag - DOSFALSE indicates termination
1368 // RES2 = Failure code if RES1 is DOSFALSE
1370 listentry_t
*listentry
;
1371 DB(Trace(1, "ExamineAll", "1: %lx 2: %lx 3: %ld 4: %ld 5: %lx\n", pkt
->dp_Arg1
, pkt
->dp_Arg2
,
1372 pkt
->dp_Arg3
, pkt
->dp_Arg4
, pkt
->dp_Arg5
));
1374 listentry
= ListEntryFromLock(pkt
->dp_Arg1
);
1377 if (!CheckVolume(listentry
->volume
, 0, &pkt
->dp_Res2
, g
))
1380 UpdateLE(listentry
, g
);
1381 UpdateLE_exa((lockentry_t
*) listentry
, g
);
1383 else if (!g
->currentvolume
)
1385 pkt
->dp_Res2
= ERROR_NO_DISK
;
1389 return ExamineAll((lockentry_t
*)listentry
,
1390 (UBYTE
*)pkt
->dp_Arg2
, (ULONG
)pkt
->dp_Arg3
, pkt
->dp_Arg4
,
1391 (struct ExAllControl
*)(pkt
->dp_Arg5
),
1395 /* make a hard or softlink */
1396 static SIPTR
dd_MakeLink(struct DosPacket
*pkt
, globaldata
* g
)
1398 // ARG1 = BPTR LOCK on directory ARG2 is relative to
1399 // ARG2 = BSTR Name of link
1400 // ARG3 = BPTR FileLock (LINK_HARD)
1401 // const char * (LINK_SOFT)
1402 // ARG4 = LONG type of link
1404 // RES2 = failure code
1406 lockentry_t
*parentle
, *targetle
;
1407 union objectinfo path
, linkinfo
, *parentfi
;
1408 UBYTE linkname
[PATHSIZE
];
1409 UBYTE
*zonderpad
, *fullname
;
1413 struct extrafields extrafields
;
1417 SIPTR
*error
= &pkt
->dp_Res2
;
1419 GetFileInfoFromLock(pkt
->dp_Arg1
, 1, parentle
, parentfi
);
1420 BCPLtoCString(linkname
, (DSTR
)BARG2(pkt
));
1421 SkipColon(fullname
, linkname
);
1423 if (!(zonderpad
= GetFullPath(parentfi
, fullname
, &path
, &pkt
->dp_Res2
, g
)))
1428 if (!IsVolume(path
))
1431 GetExtraFieldsOI(&path
, &extrafields
);
1433 GetExtraFields(path
.file
.direntry
, &extrafields
);
1435 flags
= muGetRelationship(extrafields
);
1436 if (pkt
->dp_Res2
= muFS_CheckWriteAccess(extrafields
.prot
, flags
, g
))
1439 #endif /* MU_CHECKDIR */
1440 #endif /* MULTIUSER */
1444 * Arg4 sometimes seems to be -1 instead of 1 when softlinks are meant,
1445 * so I will treat everything not LINK_HARD as LINK_SOFT
1447 if (pkt
->dp_Arg4
!= LINK_HARD
)
1449 result
= CreateSoftLink(&path
, zonderpad
, (STRPTR
) pkt
->dp_Arg3
, &linkinfo
,
1452 PFSDoNotify(&linkinfo
.file
, TRUE
, g
);
1457 /* check if lock is ours (it could be alien) */
1458 targetle
= LockEntryFromLock(pkt
->dp_Arg3
);
1459 if (!targetle
|| (BADDR(targetle
->le
.lock
.fl_Volume
) != g
->currentvolume
->devlist
))
1461 pkt
->dp_Res2
= ERROR_OBJECT_WRONG_TYPE
;
1465 /* don't do this until you know the lock is ours */
1466 UpdateLE((listentry_t
*)targetle
, g
);
1468 result
= CreateLink(&path
, zonderpad
, &targetle
->le
.info
, &linkinfo
, &pkt
->dp_Res2
, g
);
1471 PFSUpdateNotify(linkinfo
.file
.dirblock
->blk
.anodenr
, zonderpad
,
1472 targetle
->le
.info
.file
.direntry
->anode
, g
);
1473 PFSDoNotify(&linkinfo
.file
, TRUE
, g
);
1479 /* read a softlink: finding out which file (ascii) it is referring to */
1480 static SIPTR
dd_ReadLink(struct DosPacket
*pkt
, globaldata
* g
)
1482 // ARG1 = BPTR LOCK on directory ARG2 is relative to
1483 // ARG2 = BSTR Name of link
1484 // ARG3 = STRPTR buffer to store result
1485 // ARG4 = ULONG size of buffer
1487 // RES2 = failure code
1489 lockentry_t
*parentle
;
1490 union objectinfo linkfi
, *parentfi
;
1492 SIPTR
*error
= &pkt
->dp_Res2
;
1494 GetFileInfoFromLock(pkt
->dp_Arg1
, 0, parentle
, parentfi
);
1496 /* strip upto first : */
1497 SkipColon(fullname
, (char *)pkt
->dp_Arg2
);
1499 if (!(FindObject(parentfi
, fullname
, &linkfi
,
1502 if (pkt
->dp_Res2
!= ERROR_IS_SOFT_LINK
)
1506 return ReadSoftLink(&linkfi
, (char *)pkt
->dp_Arg3
, pkt
->dp_Arg4
, &pkt
->dp_Res2
, g
);
1510 /**********************
1511 * goto inhibited state
1514 /* inhibit called from uninhibited state */
1515 static SIPTR
dd_InhibitOn(struct DosPacket
*pkt
, globaldata
* g
)
1517 // ARG1 = BOOL DOSTRUE = inhibit; DOSFALSE = uninhibit
1518 // RES1 = Success/failure (DOSTRUE/DOSFALSE)
1520 if (pkt
->dp_Arg1
!= DOSFALSE
) /* don't check for DOSTRUE (Holger Kruse!) */
1522 while (g
->currentvolume
) /* inefficiënt.. */
1523 DiskRemoveSequence(g
);
1527 g
->DoCommand
= InhibitedCommands
;
1528 g
->disktype
= ID_BUSY
;
1531 /* else ->already uninhibited */
1535 /* Inhibit called from inhibited state */
1536 static SIPTR
dd_InhibitOff(struct DosPacket
*pkt
, globaldata
* g
)
1538 // ARG1 = BOOL DOSTRUE = inhibit; DOSFALSE = uninhibit
1539 // RES1 = Success/failure (DOSTRUE/DOSFALSE)
1541 if (pkt
->dp_Arg1
!= DOSFALSE
) /* don't check for DOSTRUE (Holger Kruse) */
1548 if (g
->inhibitcount
<= 0)
1552 g
->request
->iotd_Req
.io_Command
= CMD_CLEAR
;
1553 DoIO((struct IORequest
*)g
->request
);
1556 g
->DoCommand
= NormalCommands
;
1566 static SIPTR
dd_Format(struct DosPacket
*pkt
, globaldata
* g
)
1568 /* argumenten stemmen NIET met de dosmanual overeen */
1569 // ARG1 = BSTR Name of device (with trailing ':')
1570 // ARG2 = LONG Type of format (file system specific ==> ID_FDOS_DISK of 0)
1571 // RES1 = BOOL Success/failure (DOSTRUE/DOSFALSE)
1572 // RES2 = failurecode (if res1 = DOSFALSE)
1575 if (g
->user
->uid
!= muROOT_UID
)
1577 pkt
->dp_Res2
= ERROR_DISK_WRITE_PROTECTED
;
1582 /* Ik neem aan dat er geen Lock check nodig is ... */
1583 /* if not inhibited then 'remove disk' */
1584 if (g
->inhibitcount
== 0)
1587 while (g
->currentvolume
)
1588 DiskRemoveSequence(g
); // should always succeed now
1593 return FDSFormat((DSTR
)BADDR(pkt
->dp_Arg1
), pkt
->dp_Arg2
, &pkt
->dp_Res2
, g
);
1597 /**********************
1600 static SIPTR
dd_AddNotify (struct DosPacket
*pkt
, globaldata
*g
)
1602 // ARG1 = APTR struct NotifyRequest *
1603 // RES1 = BOOL Success/failure (DOSTRUE/DOSFALSE)
1604 // RES2 = failurecode (if res1 = DOSFALSE)
1606 struct NotifyRequest
*nr
= (struct NotifyRequest
*)pkt
->dp_Arg1
;
1607 struct notifyobject
*no
;
1608 union objectinfo oi
, filefi
;
1613 if (!(no
= AllocMemP (sizeof(struct notifyobject
), g
)))
1616 /* strip upto first : */
1617 name
= strchr (nr
->nr_FullName
, ':');
1621 name
= nr
->nr_FullName
;
1623 /* search for notification object */
1625 no
->unparsed
= NULL
;
1626 temp
= FilePart (name
);
1628 if (!(no
->objectname
= AllocMemP (t
+2, g
)))
1630 ctodstr (temp
, no
->objectname
);
1631 intltoupper (no
->objectname
);
1633 if (!(GetFullPath(NULL
, name
, &oi
, &pkt
->dp_Res2
, g
)))
1637 temp
= PathPart (g
->unparsed
);
1638 *temp
= 0; /* cut of filepart */
1639 t
= strlen (g
->unparsed
);
1640 if (!(no
->unparsed
= no
->namemem
= AllocMemP(t
+2, g
)))
1642 ctodstr (g
->unparsed
, no
->unparsed
);
1643 intltoupper (no
->unparsed
);
1644 no
->unparsed
++; /* make it a cstring!! */
1651 /* try to locate object */
1652 found
= FindObject (&oi
, no
->objectname
+1, &filefi
, &pkt
->dp_Res2
, g
);
1655 no
->anodenr
= IsVolume(filefi
) ? ANODE_ROOTDIR
: filefi
.file
.direntry
->anode
;
1662 pkt
->dp_Res2
= ERROR_OBJECT_WRONG_TYPE
;
1667 /* set object id (anodenr) */
1669 no
->parentanodenr
= ANODE_ROOTDIR
;
1671 no
->parentanodenr
= oi
.file
.direntry
->anode
;
1673 /* add notification to list */
1674 MinAddHead (&g
->currentvolume
->notifylist
, no
);
1676 /* do initial message, if necessary */
1677 if (found
&& (nr
->nr_Flags
& NRF_NOTIFY_INITIAL
))
1683 FreeMemP (no
->objectname
, g
);
1687 pkt
->dp_Res2
= ERROR_NO_FREE_STORE
;
1691 static SIPTR
dd_RemoveNotify (struct DosPacket
*pkt
, globaldata
* g
)
1693 // ARG1 = APTR struct NotifyRequest *
1694 // RES1 = BOOL Success/failure (DOSTRUE/DOSFALSE)
1695 // RES2 = failurecode (if res1 = DOSFALSE)
1697 struct NotifyRequest
*nr
= (struct NotifyRequest
*)pkt
->dp_Arg1
;
1698 struct notifyobject
*no
;
1701 * BTW: pending messages that return after RemoveNotify
1705 /* remove from queue */
1706 for (no
= HeadOf(&g
->currentvolume
->notifylist
); no
->next
; no
= no
->next
)
1711 FreeMemP (no
->namemem
, g
);
1712 FreeMemP (no
->objectname
, g
);
1722 /**********************
1723 * internal and PFS2 extended packets
1727 * Check if packet really is a PFS2 custom packet
1729 static int dd_CheckCustomPacket(LONG id
)
1731 if (id
== ID_PFS2_DISK
|| id
== ID_AFS_DISK
)
1738 * Check if filesystem is PFS2
1740 static SIPTR
dd_IsPFS2 (struct DosPacket
*pkt
, globaldata
*g
)
1742 // ARG1 = ID_PFS2_DISK
1743 // RES1 = DOSTRUE (is PFS2), otherwise it isn't
1744 // RES2 = Upper: version, Lower: revision
1746 if (!dd_CheckCustomPacket(pkt
->dp_Arg1
))
1748 return NotKnown (pkt
, g
);
1752 pkt
->dp_Res2
= (VERNUM
<<16) + REVNUM
;
1760 static SIPTR
dd_KillEmpty(struct DosPacket
*pkt
, globaldata
* g
)
1762 // ARG1 = lock to parent directory
1763 // ARG2 = ID_PFS2_DISK or ID
1765 lockentry_t
*parentfe
;
1766 union objectinfo
*parentfi
;
1767 SIPTR
*error
= &pkt
->dp_Res2
;
1769 if (!dd_CheckCustomPacket(pkt
->dp_Arg2
))
1772 GetFileInfoFromLock(pkt
->dp_Arg1
, 1, parentfe
, parentfi
);
1773 return KillEmpty(parentfi
, g
);
1778 * remove direntry, without freeing diskspace or checking
1779 * validity. Useful for corrupt files & entries.
1781 static SIPTR
dd_RemoveDirEntry(struct DosPacket
*pkt
, globaldata
* g
)
1783 // ARG1 = ID_PFS2_DISK
1784 // ARG2 = Lock to which ARG2 is relative (BPTR)
1785 // ARG3 = STRPTR Name of object to be deleted
1786 // RES1 = BOOL Success/failure (DOSTRUE/DOSFALSE)
1787 // RES2 = failurecode (if res1 = DOSFALSE)
1789 lockentry_t
*parentfe
;
1790 union objectinfo
*parentfi
, filefi
;
1791 UBYTE
*filename
, *pathname
;
1792 SIPTR
*error
= &pkt
->dp_Res2
;
1794 if (!dd_CheckCustomPacket(pkt
->dp_Arg1
))
1797 GetFileInfoFromLock(pkt
->dp_Arg2
, 1, parentfe
, parentfi
);
1798 pathname
= (UBYTE
*)pkt
->dp_Arg3
;
1799 SkipColon(filename
, pathname
);
1800 LocateFile(parentfi
, filename
, filefi
, error
);
1802 return forced_RemoveDirEntry(&filefi
, &pkt
->dp_Res2
, g
);
1808 * exit or leave SLEEP_MODE
1810 static SIPTR
dd_Sleep(struct DosPacket
*pkt
, globaldata
* g
)
1812 // ARG1 = MODE_PFS2_DISK
1813 // ARG2 = on/off (DOSTRUE = on; DOSFALSE = off)
1814 // ARG3 = ULONG signalnr
1815 // ARG4 = struct Task *task
1816 // RES1 = struct MsgPort *sleepport or NULL for failure;
1819 if (!dd_CheckCustomPacket(pkt
->dp_Arg1
))
1824 if (pkt
->dp_Arg2
== DOSFALSE
)
1827 g
->sleeptask
= NULL
;
1833 pkt
->dp_Res2
= ERROR_OBJECT_IN_USE
; /* already locked */
1839 if (pkt
->dp_Arg2
== DOSFALSE
)
1843 g
->sleeptask
= (struct Task
*)pkt
->dp_Arg4
;
1844 g
->alarmsignal
= (ULONG
)pkt
->dp_Arg3
;
1846 return (SIPTR
)g
->sleepport
;
1852 * add or remove Idle message
1854 * ARG1 = MODE_PFS2_DISK
1855 * ARG2 = add/remove (DOSTRUE = add; DOSFALSE = remove)
1856 * ARG3 = ULONG signalnr (UPPER = read, LOWER = write)
1857 * remove: handle to remove
1858 * ARG4 = struct Task *task
1859 * RES1 = Idlehandle or DOSFALSE for failure
1862 static SIPTR
dd_SignalIdle(struct DosPacket
*pkt
, globaldata
* g
)
1864 struct idlehandle
*handle
;
1866 if (!dd_CheckCustomPacket(pkt
->dp_Arg1
))
1869 if (pkt
->dp_Arg2
== DOSTRUE
)
1871 handle
= (struct idlehandle
*)AllocMemP (sizeof(struct idlehandle
), g
);
1875 handle
->task
= (struct Task
*)pkt
->dp_Arg4
;
1876 handle
->cleansignal
= pkt
->dp_Arg3
>> 16;
1877 handle
->dirtysignal
= pkt
->dp_Arg3
& 0xffff;
1878 MinAddHead (&g
->idlelist
, handle
);
1879 return (SIPTR
)handle
;
1883 MinRemove (pkt
->dp_Arg3
);
1884 FreeMemP ((void *)pkt
->dp_Arg3
, g
);
1890 static SIPTR
dd_UpdateAnode(struct DosPacket
*pkt
, globaldata
* g
)
1892 // ARG1 = MODE_PFS2_DISK
1893 // ARG2 = old anodenr
1894 // ARG3 = new anodenr (0 = invalidate references)
1895 // RES1 = updatecount or -1 for failure
1896 // RES2 = failurecode if Res1 = -1
1898 if (!dd_CheckCustomPacket(pkt
->dp_Arg1
))
1901 return UpdateAnode(pkt
->dp_Arg2
, pkt
->dp_Arg3
, g
);
1906 static SIPTR
dd_MakeRollover(struct DosPacket
*pkt
, globaldata
* g
)
1908 // ARG1 = MODE_PFS2_DISK
1909 // ARG2 = BPTR LOCK on directory ARG3 is relative to
1910 // ARG3 = APTR name of rollover file
1911 // ARG4 = WORD desired rollover size in blocks
1913 // RES2 = failure code
1915 lockentry_t
*parentle
;
1916 union objectinfo path
, rolloverinfo
, *parentfi
;
1917 UBYTE
*rollovername
;
1918 UBYTE
*zonderpad
, *fullname
;
1919 SIPTR
*error
= &pkt
->dp_Res2
;
1922 if (!dd_CheckCustomPacket(pkt
->dp_Arg1
))
1925 GetFileInfoFromLock(pkt
->dp_Arg2
, 1, parentle
, parentfi
);
1926 rollovername
= (UBYTE
*)pkt
->dp_Arg3
;
1927 SkipColon(fullname
, rollovername
);
1929 if (!(zonderpad
= GetFullPath(parentfi
, fullname
, &path
, error
, g
)))
1932 result
= CreateRollover(&path
, zonderpad
, (ULONG
)pkt
->dp_Arg4
,
1933 &rolloverinfo
, error
, g
);
1936 PFSDoNotify (&rolloverinfo
.file
, TRUE
, g
);
1942 /* Read and set rollover info
1944 static SIPTR
dd_SetRollover(struct DosPacket
*pkt
, globaldata
*g
)
1946 // ARG1 = MODE_PFS2_DISK
1947 // ARG2 = APTR fileentry (filled in by Open())
1948 // ARG3 = APTR struct rolloverinfo
1950 // RES2 = failure code
1952 listentry_t
*rlfile
;
1953 SIPTR
*error
= &pkt
->dp_Res2
;
1955 if (!dd_CheckCustomPacket(pkt
->dp_Arg1
))
1957 rlfile
= (listentry_t
*)pkt
->dp_Arg2
;
1958 if (!CheckVolume(rlfile
->volume
, 1, error
, g
))
1960 if ((*error
= SetRollover((fileentry_t
*)rlfile
, (struct rolloverinfo
*)pkt
->dp_Arg3
, g
)))
1967 static SIPTR
dd_SetDeldir(struct DosPacket
*pkt
, globaldata
*g
)
1969 // ARG1 = MODE_PFS2_DISK
1970 // ARG2 = number of deldirblocks wanted (0 = disable, -1 = check)
1972 // RES2 = failure code
1974 SIPTR
*error
= &pkt
->dp_Res2
;
1976 if (!dd_CheckCustomPacket(pkt
->dp_Arg1
))
1980 if (g
->user
->uid
!= muROOT_UID
)
1982 *error
= ERROR_DISK_WRITE_PROTECTED
;
1987 /* check if a volume is inserted */
1988 if (!CheckVolume(g
->currentvolume
, 1, error
, g
))
1991 /* just an inquiry */
1992 if (pkt
->dp_Arg2
== -1)
1994 *error
= g
->currentvolume
->rblkextension
->blk
.deldirsize
;
1998 if ((*error
= SetDeldir(pkt
->dp_Arg2
, g
)))
2006 /* set filename size. failure codes:
2007 * ACTION_BAD_NUMBER = grootte illegaal of kleiner dan huidig
2009 static SIPTR
dd_SetFileSize(struct DosPacket
*pkt
, globaldata
*g
)
2011 // ACTION_SET_FNSIZE 2222
2012 // ARG1 = MODE_PFS2_DISK
2013 // ARG2 = New maximum filename size (0 = huidige waarde opvragen)
2015 // RES2 = failure code / current or new fnsize
2017 if (!dd_CheckCustomPacket(pkt
->dp_Arg1
))
2022 if (pkt
->dp_Arg2
< 30 || pkt
->dp_Arg2
< FILENAMESIZE
)
2024 pkt
->dp_Res2
= ERROR_BAD_NUMBER
;
2028 if (pkt
->dp_Arg2
>= FNSIZE
)
2030 pkt
->dp_Res2
= ERROR_OBJECT_TOO_LARGE
;
2035 if (g
->currentvolume
&& g
->currentvolume
->rblkextension
)
2039 g
->rootblock
->options
|= MODE_LONGFN
;
2040 g
->fnsize
= g
->currentvolume
->rblkextension
->blk
.fnsize
= pkt
->dp_Arg2
;
2043 pkt
->dp_Res2
= g
->fnsize
;
2047 pkt
->dp_Res2
= ERROR_NO_DISK
;
2051 #if defined(__MORPHOS__)
2052 static LONG
dd_MorphOSQueryAttr(struct DosPacket
*pkt
, globaldata
*g
)
2054 // ACTION_QUERY_ATTR 26407
2055 // ARG1 = LONG attr, which attribute you want to know about
2056 // ARG2 = void *storage, memory to hold the return value
2057 // ARG3 = LONG storagesize, size of storage reserved for
2059 // RES2 = failure code
2060 // ERROR_BAD_NUMBER for unimplemented/unknown attributes
2061 // ERROR_LINE_TOO_LONG for buffer too small to hold the result
2063 APTR storage
= (APTR
) pkt
->dp_Arg2
;
2064 LONG storage_size
= pkt
->dp_Arg3
;
2066 switch (pkt
->dp_Arg1
)
2068 case FQA_MaxFileNameLength
:
2069 if (storage_size
>= sizeof(LONG
))
2071 *(LONG
*)storage
= FILENAMESIZE
- 1;
2076 case FQA_MaxVolumeNameLength
:
2077 if (storage_size
>= sizeof(LONG
))
2079 *(LONG
*)storage
= DNSIZE
- 1;
2084 case FQA_IsCaseSensitive
:
2085 if (storage_size
>= sizeof(LONG
))
2087 *(LONG
*)storage
= FALSE
;
2092 case FQA_MaxFileSize
:
2093 if (storage_size
>= sizeof(QUAD
))
2095 *(QUAD
*)storage
= 0x7fffffffLL
;
2100 /* let dos.library handle these - fall thru */
2101 case FQA_DeviceType
:
2103 case FQA_NumBlocksUsed
:
2105 /* unknown/unhandled attribute */
2107 pkt
->dp_Res2
= ERROR_BAD_NUMBER
;
2111 /* Not enough buffer storage */
2112 pkt
->dp_Res2
= ERROR_LINE_TOO_LONG
;
2117 #if EXTENDED_PACKETS_OS4
2119 #define DP64_INIT -3
2120 /* Not real one but close enough */
2121 struct DosPacket64OS4
2136 static listentry_t
*InitOS464(struct DosPacket
*pkt
, globaldata
*g
, BOOL errortype
)
2138 struct DosPacket64OS4
*dp
= (struct DosPacket64OS4
*)pkt
;
2139 listentry_t
*listentry
;
2141 dp
->dp_Res0
= DP64_INIT
;
2143 listentry
= (listentry_t
*) pkt
->dp_Arg1
;
2144 if (!CheckVolume(listentry
->volume
, 0, &pkt
->dp_Res2
, g
)) {
2145 dp
->dp_Res1
= errortype
? -1 : 0;
2146 dp
->dp_Res2
= ERROR_INVALID_LOCK
;
2149 UpdateLE(listentry
, g
);
2150 if (!IsFile(listentry
->info
)) {
2151 dp
->dp_Res1
= errortype
? -1 : 0;
2152 dp
->dp_Res2
= ERROR_OBJECT_WRONG_TYPE
;
2158 static void dd_GetFileSize64(struct DosPacket
*pkt
, globaldata
*g
)
2160 struct DosPacket64OS4
*dp
= (struct DosPacket64OS4
*)pkt
;
2161 listentry_t
*listentry
;
2163 listentry
= InitOS464(pkt
, g
, TRUE
);
2166 dp
->dp_Res1
= GetDEFileSize(listentry
->info
.file
.direntry
, g
);
2169 static void dd_ChangeFileSize64(struct DosPacket
*pkt
, globaldata
*g
)
2171 struct DosPacket64OS4
*dp
= (struct DosPacket64OS4
*)pkt
;
2172 listentry_t
*listentry
;
2176 listentry
= InitOS464(pkt
, g
, FALSE
);
2179 pos
= ChangeFileSize((fileentry_t
*)listentry
, dp
->dp_Arg2
, dp
->dp_Arg3
, &error
, g
);
2181 dp
->dp_Res1
= DOSFALSE
;
2182 dp
->dp_Res2
= error
;
2184 dp
->dp_Res1
= DOSTRUE
;
2188 static void dd_GetFilePosition64(struct DosPacket
*pkt
, globaldata
*g
)
2190 struct DosPacket64OS4
*dp
= (struct DosPacket64OS4
*)pkt
;
2191 listentry_t
*listentry
;
2195 listentry
= InitOS464(pkt
, g
, TRUE
);
2198 pos
= SeekInObject((fileentry_t
*)listentry
, OFFSET_CURRENT
, 0, &error
, g
);
2201 dp
->dp_Res2
= error
;
2207 static void dd_ChangeFilePosition64(struct DosPacket
*pkt
, globaldata
*g
)
2209 struct DosPacket64OS4
*dp
= (struct DosPacket64OS4
*)pkt
;
2210 listentry_t
*listentry
;
2214 listentry
= InitOS464(pkt
, g
, FALSE
);
2217 pos
= SeekInObject((fileentry_t
*)listentry
, dp
->dp_Arg3
, dp
->dp_Arg2
, &error
, g
);
2219 dp
->dp_Res1
= DOSFALSE
;
2220 dp
->dp_Res2
= error
;
2222 dp
->dp_Res1
= DOSTRUE
;