5 Copyright (C) 2001-2008 Neil Cafferkey
7 This file is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as
9 published by the Free Software Foundation; either version 2.1 of the
10 License, or (at your option) any later version.
12 This file is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public
18 License along with this file; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston,
24 #include <aros/config.h>
25 #include <aros/debug.h>
27 #include "handler_protos.h"
30 static const TEXT default_vol_name
[] = "RAM Disk";
33 static const UWORD examine_sizes
[] =
35 (UWORD
)OFFSET(ExAllData
, ed_Type
),
36 (UWORD
)OFFSET(ExAllData
, ed_Size
),
37 (UWORD
)OFFSET(ExAllData
, ed_Prot
),
38 (UWORD
)OFFSET(ExAllData
, ed_Days
),
39 (UWORD
)OFFSET(ExAllData
, ed_Comment
),
40 (UWORD
)OFFSET(ExAllData
, ed_OwnerUID
)
45 /****i* ram.handler/CmdStartup *********************************************
51 * handler = CmdStartup(name, dev_node,
54 * struct Handler *CmdStartup(STRPTR, struct DeviceNode *,
71 ****************************************************************************
75 BOOL
CmdStartup(struct Handler
*handler
, STRPTR name
, struct DeviceNode
*dev_node
,
76 struct MsgPort
*proc_port
)
78 struct DosList
*volume
;
79 struct Object
*root_dir
;
84 /* Open extra libraries */
87 base
= OpenLibrary(UTILITYNAME
, UTILITY_VERSION
);
93 #if !(AROS_FLAVOUR & AROS_FLAVOUR_BINCOMPAT)
94 base
= OpenLibrary("locale.library", LOCALE_VERSION
);
101 /* Initialise private handler structure */
105 handler
->proc_port
= proc_port
;
106 handler
->block_count
= MEMBLOCKS(StrSize(default_vol_name
)) +
107 MEMBLOCKS(sizeof(struct Handler
));
108 handler
->min_block_size
= MIN_BLOCK_SIZE
;
109 handler
->max_block_size
= MAX_BLOCK_SIZE
;
110 NewList((APTR
)&handler
->examinations
);
112 dev_node
->dn_Task
= proc_port
;
114 /* Create pools for zeroed, non-zeroed and public zeroed memory */
116 handler
->clear_pool
= CreatePool(MEMF_CLEAR
, CLEAR_PUDDLE_SIZE
,
117 CLEAR_PUDDLE_THRESH
);
118 if(handler
->clear_pool
== NULL
)
120 handler
->muddy_pool
= CreatePool(MEMF_ANY
, MUDDY_PUDDLE_SIZE
,
121 MUDDY_PUDDLE_THRESH
);
122 if(handler
->muddy_pool
== NULL
)
124 handler
->public_pool
= CreatePool(MEMF_PUBLIC
| MEMF_CLEAR
,
125 PUBLIC_PUDDLE_SIZE
, PUBLIC_PUDDLE_THRESH
);
126 if(handler
->public_pool
== NULL
)
129 /* Create a volume dos node */
131 volume
= MyMakeDosEntry(handler
, default_vol_name
, DLT_VOLUME
);
138 volume
->dol_Task
= proc_port
;
139 DateStamp(&volume
->dol_misc
.dol_volume
.dol_VolumeDate
);
140 volume
->dol_misc
.dol_volume
.dol_DiskType
= ID_DOS_DISK
;
142 /* Put volume node into dos list */
145 handler
->volume
= volume
;
147 /* Open default locale */
149 handler
->locale
= OpenLocale(NULL
);
151 /* Initialise notification handling */
153 NewList((APTR
)&handler
->notifications
);
154 port
= CreateMsgPort();
155 handler
->notify_port
= port
;
160 /* Create the root directory and get a shared lock on it */
164 root_dir
= CreateObject(handler
, default_vol_name
, ST_ROOT
, NULL
);
165 handler
->root_dir
= root_dir
;
168 if(LockObject(handler
, root_dir
, ACCESS_READ
) == NULL
)
183 /****i* ram.handler/CmdDie *************************************************
189 * success = CmdDie(handler)
191 * BOOL CmdDie(struct Handler *);
207 ****************************************************************************
211 BOOL
CmdDie(struct Handler
*handler
)
213 struct Object
*root_dir
;
216 root_dir
= handler
->root_dir
;
217 if(IsListEmpty(&root_dir
->elements
)
218 && IsListEmpty(&handler
->notifications
)
219 && IsListEmpty(&root_dir
->notifications
)
220 && root_dir
->lock
->lock_count
== 1)
221 DeleteHandler(handler
);
223 error
= ERROR_OBJECT_IN_USE
;
225 /* Return success indicator */
233 /****i* ram.handler/CmdIsFileSystem ****************************************
239 * result = CmdIsFileSystem()
241 * BOOL CmdIsFileSystem();
257 ****************************************************************************
261 BOOL
CmdIsFileSystem()
268 /****i* ram.handler/CmdFind ************************************************
274 * success = CmdFind(handler, handle, lock,
277 * BOOL CmdFind(struct Handler *, struct FileHandle *, struct Lock *,
294 ****************************************************************************
298 BOOL
CmdFind(struct Handler
*handler
, struct FileHandle
*handle
,
299 struct Lock
*lock
, const TEXT
*name
, ULONG type
)
303 struct Object
*file
, *parent
;
305 /* Set access mode */
307 if(type
== MODE_NEWFILE
)
314 if(type
== MODE_NEWFILE
&& handler
->locked
)
315 error
= ERROR_DISK_WRITE_PROTECTED
;
319 file
= GetHardObject(handler
, lock
, name
, &parent
);
324 /* Do any necessary file deletion or creation */
328 name
= FilePart(name
);
335 if((GetRealObject(file
)->protection
& FIBF_DELETE
) != 0)
336 error
= ERROR_DELETE_PROTECTED
;
338 if(((struct Node
*)file
)->ln_Pri
>= 0)
339 error
= ERROR_OBJECT_EXISTS
;
344 if(!AttemptDeleteObject(handler
, file
, FALSE
))
350 if(error
== 0 && file
== NULL
)
351 file
= CreateObject(handler
, name
, ST_FILE
, parent
);
359 /* Get a lock on the file */
363 lock
= LockObject(handler
, file
, mode
);
366 else if(type
== MODE_NEWFILE
)
367 lock
->changed
= TRUE
;
374 if(!CmdFHFromLock(handler
, handle
, lock
))
377 CmdFreeLock(handler
, lock
);
381 /* Set error and return success code */
389 /****i* ram.handler/CmdFHFromLock ******************************************
395 * success = CmdFHFromLock(handle, lock)
397 * BOOL CmdFHFromLock(struct FileHandle *, struct Lock *);
413 ****************************************************************************
417 BOOL
CmdFHFromLock(struct Handler
*handler
, struct FileHandle
*handle
,
421 struct Opening
*opening
= NULL
;
424 /* Check if access is allowed */
426 file
= (APTR
)((struct FileLock
*)lock
)->fl_Key
;
427 if(((struct Node
*)file
)->ln_Pri
!= ST_FILE
)
428 error
= ERROR_OBJECT_WRONG_TYPE
;
430 /* Create and initialise "opening" */
434 opening
= AllocPooled(handler
->clear_pool
, sizeof(struct Opening
));
437 opening
->file
= file
;
438 opening
->block
= (struct Block
*)file
->elements
.mlh_Head
;
439 AddTail((struct List
*)&lock
->openings
, (struct Node
*)opening
);
445 /* Put address of opening in file handle */
447 handle
->fh_Arg1
= (PINT
)opening
;
449 /* Set error and return success code */
457 /****i* ram.handler/CmdEnd *************************************************
463 * success = CmdEnd(handler, opening)
465 * BOOL CmdEnd(struct Handler *, struct Opening *);
481 ****************************************************************************
485 BOOL
CmdEnd(struct Handler
*handler
, struct Opening
*opening
)
487 struct Object
*file
, *parent
;
491 /* Close file and update its date and flags */
493 file
= opening
->file
;
499 file
->protection
&= ~FIBF_ARCHIVE
;
500 DateStamp(&file
->date
);
501 parent
= file
->parent
;
502 parent
->protection
&= ~FIBF_ARCHIVE
;
503 CopyMem(&file
->date
, &parent
->date
, sizeof(struct DateStamp
));
505 NotifyAll(handler
, file
, TRUE
);
508 error
= ERROR_DISK_WRITE_PROTECTED
;
513 Remove((APTR
)opening
);
514 CmdFreeLock(handler
, lock
);
515 FreePooled(handler
->clear_pool
, opening
, sizeof(struct Opening
));
518 /* Return success indicator */
526 /****i* ram.handler/CmdRead ************************************************
532 * actual_length = CmdRead(opening, buffer, length)
534 * UPINT CmdRead(struct Opening *, UBYTE *, UPINT);
550 ****************************************************************************
554 UPINT
CmdRead(struct Handler
*handler
, struct Opening
*opening
, UBYTE
*buffer
, UPINT length
)
559 /* Read file if it isn't read protected */
561 file
= opening
->file
;
563 if((file
->protection
& FIBF_READ
) != 0)
564 error
= ERROR_READ_PROTECTED
;
568 length
= ReadData(opening
, buffer
, length
);
576 /* Return number of bytes read */
584 /****i* ram.handler/CmdWrite ***********************************************
590 * actual_length = CmdWrite(handler, opening, buffer, length)
592 * UPINT CmdWrite(struct Handler *, struct Opening *, UBYTE *, UPINT);
608 ****************************************************************************
612 UPINT
CmdWrite(struct Handler
*handler
, struct Opening
*opening
,
613 UBYTE
*buffer
, UPINT length
)
619 /* Write to file if it isn't write protected */
621 file
= opening
->file
;
624 if((file
->protection
& FIBF_WRITE
) != 0)
625 error
= ERROR_WRITE_PROTECTED
;
628 error
= ERROR_DISK_WRITE_PROTECTED
;
632 length
= WriteData(handler
, opening
, buffer
, length
);
635 lock
->changed
= TRUE
;
642 /* Return number of bytes written */
650 /****i* ram.handler/CmdSeek ************************************************
656 * old_pos = CmdSeek(opening, offset, mode)
658 * PINT CmdSeek(struct Opening *, PINT, LONG);
674 ****************************************************************************
678 UPINT
CmdSeek(struct Handler
*handler
, struct Opening
*opening
, PINT offset
, LONG mode
)
682 UPINT block_pos
, block_length
, remainder
, old_pos
, new_pos
;
684 /* Get starting point */
686 file
= opening
->file
;
687 old_pos
= opening
->pos
;
689 if(mode
== OFFSET_BEGINNING
)
691 block
= (APTR
)file
->elements
.mlh_Head
;
692 new_pos
= block_pos
= 0;
694 else if(mode
== OFFSET_CURRENT
)
696 block
= opening
->block
;
697 block_pos
= opening
->block_pos
;
702 block
= (APTR
)file
->elements
.mlh_TailPred
;
703 block_pos
= file
->end_length
;
704 new_pos
= file
->length
;
707 /* Check new position is within file */
710 if(new_pos
> file
->length
)
712 SetIoErr(ERROR_SEEK_ERROR
);
720 block_length
= GetBlockLength(file
, block
);
721 remainder
= offset
+ block_pos
;
722 while(remainder
> block_length
)
724 remainder
-= block_length
;
725 block
= (APTR
)((struct MinNode
*)block
)->mln_Succ
;
726 block_length
= GetBlockLength(file
, block
);
729 block_pos
= remainder
;
735 block_length
= block_pos
;
737 while(remainder
>= block_length
&& remainder
> 0)
739 remainder
-= block_length
;
740 block
= (APTR
)((struct MinNode
*)block
)->mln_Pred
;
741 block_length
= GetBlockLength(file
, block
);
744 block_pos
= block_length
- remainder
;
747 /* Record new position for next access */
749 opening
->block
= block
;
750 opening
->block_pos
= block_pos
;
751 opening
->pos
= new_pos
;
753 /* Return old position */
760 /****i* ram.handler/CmdSetFileSize *****************************************
766 * new_length = CmdSetFileSize(handler, opening, offset, mode)
768 * PINT CmdSetFileSize(struct Handler *, struct Opening *, PINT, LONG);
784 ****************************************************************************
788 PINT
CmdSetFileSize(struct Handler
*handler
, struct Opening
*opening
,
789 PINT offset
, LONG mode
)
791 LONG error
= 0, new_size
;
795 /* Change file size if it's open for writing */
797 file
= opening
->file
;
800 if((file
->protection
& FIBF_WRITE
) != 0)
801 error
= ERROR_WRITE_PROTECTED
;
803 error
= ERROR_DISK_WRITE_PROTECTED
;
807 new_size
= ChangeFileSize(handler
, opening
, offset
, mode
);
811 lock
->changed
= TRUE
;
816 /* Return new file size */
824 /****i* ram.handler/CmdLocateObject ****************************************
830 * lock = CmdLocateObject(handler, lock,
833 * struct Lock *CmdLocateObject(struct Handler *, struct Lock *,
850 ****************************************************************************
854 struct Lock
*CmdLocateObject(struct Handler
*handler
, struct Lock
*lock
,
855 const TEXT
*name
, ULONG mode
)
857 struct Object
*object
;
859 /* Find the object and lock it */
861 object
= GetHardObject(handler
, lock
, name
, NULL
);
864 lock
= LockObject(handler
, object
, mode
);
875 /****i* ram.handler/CmdFreeLock ********************************************
881 * success = CmdFreeLock(handler, lock)
883 * BOOL CmdFreeLock(struct Handler *, struct Lock *);
888 * lock - May be NULL.
900 ****************************************************************************
904 BOOL
CmdFreeLock(struct Handler
*handler
, struct Lock
*lock
)
906 struct Object
*object
;
910 object
= (APTR
)((struct FileLock
*)lock
)->fl_Key
;
912 handler
->lock_count
--;
913 if((--lock
->lock_count
) == 0)
915 FreePooled(handler
->public_pool
, lock
, sizeof(struct Lock
));
925 /****i* ram.handler/CmdCopyDir *********************************************
931 * lock = CmdCopyDir(handler, lock)
933 * struct Lock *CmdCopyDir(struct Handler *, struct Lock *);
949 ****************************************************************************
953 struct Lock
*CmdCopyDir(struct Handler
*handler
, struct Lock
*lock
)
955 lock
= FIXLOCK(handler
, lock
);
956 lock
= LockObject(handler
, (APTR
)((struct FileLock
*)lock
)->fl_Key
,
964 /****i* ram.handler/CmdCopyDirFH *******************************************
970 * lock = CmdCopyDirFH(handler, opening)
972 * struct Lock *CmdCopyDirFH(struct Handler *, struct Opening *);
988 ****************************************************************************
992 struct Lock
*CmdCopyDirFH(struct Handler
*handler
,
993 struct Opening
*opening
)
995 return LockObject(handler
, opening
->file
, ACCESS_READ
);
1000 /****i* ram.handler/CmdParent **********************************************
1006 * lock = CmdParent(handler, lock)
1008 * struct Lock *CmdParent(struct Handler *, struct Lock *);
1024 ****************************************************************************
1028 struct Lock
*CmdParent(struct Handler
*handler
, struct Lock
*lock
)
1030 struct Object
*parent
;
1033 lock
= FIXLOCK(handler
, lock
);
1035 parent
= ((struct Object
*)((struct FileLock
*)lock
)->fl_Key
)->parent
;
1038 lock
= LockObject(handler
, parent
, ACCESS_READ
);
1051 /****i* ram.handler/CmdParentFH ********************************************
1057 * lock = CmdParentFH(handler, opening)
1059 * struct Lock *CmdParentFH(struct Handler *, struct Opening *);
1075 ****************************************************************************
1079 struct Lock
*CmdParentFH(struct Handler
*handler
,
1080 struct Opening
*opening
)
1082 struct Object
*parent
;
1085 parent
= opening
->file
->parent
;
1086 lock
= LockObject(handler
, parent
, ACCESS_READ
);
1093 /****i* ram.handler/CmdSameLock ********************************************
1099 * result = CmdSameLock(handler, lock1, lock2)
1101 * BOOL CmdSameLock(struct Handler *, struct Lock *, struct Lock *);
1117 ****************************************************************************
1121 BOOL
CmdSameLock(struct Handler
*handler
, struct Lock
*lock1
, struct Lock
*lock2
)
1124 return lock1
== lock2
;
1129 /****i* ram.handler/CmdCreateDir *******************************************
1135 * lock = CmdCreateDir(handler, lock, name)
1137 * struct Lock *CmdCreateDir(struct Handler *, struct Lock *, TEXT *);
1153 ****************************************************************************
1157 struct Lock
*CmdCreateDir(struct Handler
*handler
,
1158 struct Lock
*lock
, const TEXT
*name
)
1160 struct Object
*dir
, *parent
;
1163 /* Find parent directory and possible name clash */
1165 dir
= GetHardObject(handler
, lock
, name
, &parent
);
1168 /* Create a new directory */
1174 if(!handler
->locked
)
1176 dir
= CreateObject(handler
, FilePart(name
), ST_USERDIR
, parent
);
1179 lock
= LockObject(handler
, dir
, ACCESS_WRITE
);
1182 MatchNotifyRequests(handler
);
1183 NotifyAll(handler
, dir
, FALSE
);
1188 DeleteObject(handler
, dir
);
1195 error
= ERROR_DISK_WRITE_PROTECTED
;
1201 error
= ERROR_OBJECT_EXISTS
;
1203 /* Set error code and return lock on new directory */
1211 /****i* ram.handler/CmdExamineObject ***************************************
1214 * CmdExamineObject --
1217 * success = CmdExamineObject(handler, lock,
1220 * BOOL CmdExamineObject(struct Handler *, struct Lock *,
1221 * struct FileInfoBlock *);
1237 ****************************************************************************
1241 BOOL
CmdExamineObject(struct Handler
*handler
, struct Lock
*lock
,
1242 struct FileInfoBlock
*info
)
1244 lock
= FIXLOCK(handler
, lock
);
1245 return ExamineObject(handler
, (APTR
)((struct FileLock
*)lock
)->fl_Key
,
1251 /****i* ram.handler/CmdExamineFH *******************************************
1257 * success = CmdExamineFH(handler, opening,
1260 * BOOL CmdExamineFH(struct Handler *, struct Opening *,
1261 * struct FileInfoBlock *);
1277 ****************************************************************************
1281 BOOL
CmdExamineFH(struct Handler
*handler
, struct Opening
*opening
,
1282 struct FileInfoBlock
*info
)
1284 return ExamineObject(handler
, opening
->file
, info
);
1289 /****i* ram.handler/CmdExamineNext *****************************************
1295 * success = CmdExamineNext(handler, info)
1297 * BOOL CmdExamineNext(struct Handler *, struct FileInfoBlock *);
1313 ****************************************************************************
1317 BOOL
CmdExamineNext(struct Handler
*handler
, struct FileInfoBlock
*info
)
1319 return ExamineObject(handler
, NULL
, info
);
1324 /****i* ram.handler/CmdExamineAll ******************************************
1330 * success = CmdExamineAll(handler, opening, buffer, size,
1333 * BOOL CmdExamineAll(struct Handler *, struct Lock *, UBYTE *, ULONG,
1334 * ULONG, struct ExAllControl *);
1350 ****************************************************************************
1352 * Note: we work under the assumption that if an error occurs, the caller
1353 * will have to start from scratch if they want the rest of the entries.
1357 BOOL
CmdExamineAll(struct Handler
*handler
, struct Lock
*lock
,
1358 UBYTE
*buffer
, ULONG size
, ULONG type
, struct ExAllControl
*control
)
1361 ULONG entry_count
= 0;
1362 struct Object
*object
, *next_object
, *real_object
;
1363 TEXT
*name
, *comment
, *pattern
, *name_copy
, *comment_copy
;
1365 struct ExAllData
*entry
, *prev_entry
= NULL
;
1366 struct Hook
*match_hook
;
1367 UWORD struct_size
, name_size
, comment_size
, entry_size
;
1368 struct Examination
*examination
;
1370 /* Check we support the requested format */
1372 if(type
> ED_COMMENT
)
1373 error
= ERROR_BAD_NUMBER
;
1375 /* Get starting point */
1377 examination
= (APTR
)control
->eac_LastKey
;
1379 if(examination
!= NULL
)
1381 object
= examination
->next_object
;
1385 object
= (APTR
)((struct FileLock
*)lock
)->fl_Key
;
1386 object
= (APTR
)object
->elements
.mlh_Head
;
1391 next_object
= (struct Object
*)((struct Node
*)object
)->ln_Succ
;
1393 if(next_object
!= NULL
)
1395 struct_size
= examine_sizes
[type
- 1];
1396 name
= ((struct Node
*)object
)->ln_Name
;
1397 name_size
= StrSize(name
);
1398 if(((struct Node
*)object
)->ln_Pri
== ST_SOFTLINK
)
1399 comment
= &((struct Node
*)object
)->ln_Type
;
1401 comment
= object
->comment
;
1402 comment_size
= StrSize(comment
);
1403 entry_size
= struct_size
+ name_size
;
1404 if(type
>= ED_COMMENT
)
1405 entry_size
+= comment_size
;
1406 entry_size
= (entry_size
+ 1) & (~0x1);
1408 pattern
= control
->eac_MatchString
;
1410 match
= MatchPatternNoCase(pattern
, name
);
1414 if(match
&& entry_size
<= size
)
1418 entry
= (APTR
)buffer
;
1419 entry
->ed_Next
= NULL
;
1421 real_object
= GetRealObject(object
);
1422 name_copy
= buffer
+ struct_size
;
1423 CopyMem(name
, name_copy
, name_size
);
1424 entry
->ed_Name
= name_copy
;
1427 entry
->ed_Type
= ((struct Node
*)object
)->ln_Pri
;
1430 entry
->ed_Size
= real_object
->length
;
1432 if(type
>= ED_PROTECTION
)
1433 entry
->ed_Prot
= real_object
->protection
;
1437 entry
->ed_Days
= real_object
->date
.ds_Days
;
1438 entry
->ed_Mins
= real_object
->date
.ds_Minute
;
1439 entry
->ed_Ticks
= real_object
->date
.ds_Tick
;
1442 if(type
>= ED_COMMENT
)
1444 comment_copy
= buffer
+ struct_size
+ name_size
;
1445 CopyMem(comment
, comment_copy
, comment_size
);
1446 entry
->ed_Comment
= comment_copy
;
1449 /* Call the filter hook if present */
1451 match_hook
= control
->eac_MatchFunc
;
1452 if(match_hook
!= NULL
)
1453 match
= CallHookPkt(match_hook
, &type
, entry
);
1457 /* Prepare for next entry if current one accepted */
1461 buffer
+= entry_size
;
1464 if(prev_entry
!= NULL
)
1465 prev_entry
->ed_Next
= entry
;
1470 error
= ERROR_NO_FREE_STORE
;
1473 error
= ERROR_NO_MORE_ENTRIES
;
1475 object
= next_object
;
1478 /* Running out of space isn't an error unless no entries could fit */
1480 if(error
== ERROR_NO_FREE_STORE
&& entry_count
!= 0)
1483 /* Prepare for subsequent call */
1485 if(error
== 0 && examination
== NULL
)
1487 examination
= AllocPooled(handler
->clear_pool
,
1488 sizeof(struct Examination
));
1489 if(examination
!= NULL
)
1490 AddTail((APTR
)&handler
->examinations
, (APTR
)examination
);
1497 examination
->next_object
= object
;
1498 control
->eac_LastKey
= (UPINT
)examination
;
1502 CmdExamineAllEnd(handler
, lock
, buffer
, size
, type
, control
);
1505 control
->eac_Entries
= entry_count
;
1515 /****i* ram.handler/CmdExamineAllEnd ***************************************
1518 * CmdExamineAllEnd --
1521 * CmdExamineAllEnd(handler, opening, buffer,
1522 * size, type, control)
1524 * VOID CmdExamineAllEnd(struct Handler *, struct Lock *, UBYTE *,
1525 * ULONG, ULONG, struct ExAllControl *);
1541 ****************************************************************************
1545 VOID
CmdExamineAllEnd(struct Handler
*handler
, struct Lock
*lock
,
1546 UBYTE
*buffer
, ULONG size
, ULONG type
, struct ExAllControl
*control
)
1548 struct Examination
*examination
;
1550 examination
= (APTR
)control
->eac_LastKey
;
1551 if(examination
!= NULL
)
1553 Remove((APTR
)examination
);
1554 FreePooled(handler
->clear_pool
, examination
,
1555 sizeof(struct Examination
));
1563 /****i* ram.handler/CmdInfo ************************************************
1569 * success = CmdInfo(handler, info_data)
1571 * BOOL CmdExamineObject(struct Handler *, struct InfoData *);
1587 ****************************************************************************
1591 BOOL
CmdInfo(struct Handler
*handler
, struct InfoData
*info_data
)
1595 info_data
->id_NumSoftErrors
= 0;
1596 info_data
->id_UnitNumber
= 0;
1598 disk_state
= ID_WRITE_PROTECTED
;
1600 disk_state
= ID_VALIDATED
;
1601 info_data
->id_DiskState
= disk_state
;
1602 info_data
->id_NumBlocks
= handler
->block_count
1603 + MEMBLOCKS(AvailMem(MEMF_ANY
));
1604 info_data
->id_NumBlocksUsed
= handler
->block_count
;
1605 info_data
->id_BytesPerBlock
= MEM_BLOCKSIZE
;
1606 info_data
->id_DiskType
= ID_DOS_DISK
;
1607 info_data
->id_VolumeNode
= MKBADDR(handler
->volume
);
1608 info_data
->id_InUse
= DOSBOOL(handler
->lock_count
> 1);
1615 /****i* ram.handler/CmdSetProtect ******************************************
1621 * success = CmdSetProtect(handler, lock, name, flags)
1623 * BOOL CmdSetProtect(struct Handler *, struct Lock *, TEXT *, ULONG);
1639 ****************************************************************************
1643 BOOL
CmdSetProtect(struct Handler
*handler
, struct Lock
*lock
,
1644 const TEXT
*name
, ULONG flags
)
1647 struct Object
*object
;
1649 /* Set new protection flags if object isn't in use */
1651 object
= GetHardObject(handler
, lock
, name
, NULL
);
1655 error
= ERROR_DISK_WRITE_PROTECTED
;
1659 object
= GetRealObject(object
);
1660 object
->protection
= flags
;
1661 NotifyAll(handler
, object
, TRUE
);
1675 /****i* ram.handler/CmdSetComment ******************************************
1681 * success = CmdSetComment(handler, lock, name, comment)
1683 * BOOL CmdSetComment(struct Handler *, struct Lock *, TEXT *, TEXT *);
1699 ****************************************************************************
1703 BOOL
CmdSetComment(struct Handler
*handler
, struct Lock
*lock
,
1704 const TEXT
*name
, const TEXT
*comment
)
1707 struct Object
*object
;
1710 struct Locale
*locale
;
1715 object
= GetHardObject(handler
, lock
, name
, NULL
);
1719 /* Check comment isn't too long */
1722 > sizeof(((struct FileInfoBlock
*)NULL
)->fib_Comment
))
1723 error
= ERROR_COMMENT_TOO_BIG
;
1725 /* Check comment doesn't have any strange characters in it */
1726 if ((locale
= handler
->locale
)) {
1727 for(p
= comment
; (ch
= *p
) != '\0'; p
++)
1728 if((ch
& 0x80) == 0 && (!IsPrint(locale
, ch
) || IsCntrl(locale
, ch
)))
1729 error
= ERROR_INVALID_COMPONENT_NAME
;
1732 /* Check volume isn't write-protected */
1735 error
= ERROR_DISK_WRITE_PROTECTED
;
1737 /* Store new comment */
1741 block_diff
= SetString(handler
, &object
->comment
, comment
);
1742 if(block_diff
== -1)
1746 object
->block_count
+= block_diff
;
1747 handler
->block_count
+= block_diff
;
1751 /* Notify interested parties */
1755 NotifyAll(handler
, object
, FALSE
);
1766 /****i* ram.handler/CmdRenameObject ****************************************
1769 * CmdRenameObject --
1772 * success = CmdRenameObject(handler, old_lock, old_name,
1773 * new_lock, new_name)
1775 * BOOL CmdRenameObject(struct Handler *, struct Lock *, STRPTR,
1776 * struct Lock *, STRPTR);
1792 ****************************************************************************
1796 BOOL
CmdRenameObject(struct Handler
*handler
, struct Lock
*old_lock
,
1797 STRPTR old_name
, struct Lock
*new_lock
, STRPTR new_name
)
1799 struct Object
*parent
, *object
, *duplicate
, *p
;
1802 /* Get object to be moved */
1804 object
= GetHardObject(handler
, old_lock
, old_name
, NULL
);
1808 /* Get destination directory and check if a different object already has
1811 duplicate
= GetHardObject(handler
, new_lock
, new_name
, &parent
);
1812 if(duplicate
!= NULL
&& duplicate
!= object
)
1813 error
= ERROR_OBJECT_EXISTS
;
1817 /* Check for a circular rename */
1819 for(p
= parent
; p
!= NULL
; p
= p
->parent
)
1822 error
= ERROR_OBJECT_NOT_FOUND
;
1825 /* Check volume isn't write-protected */
1828 error
= ERROR_DISK_WRITE_PROTECTED
;
1830 /* Give the object its new name */
1834 if(!SetName(handler
, object
, FilePart(new_name
)))
1840 if(object
->parent
!= parent
)
1842 /* Remove object from old parent and place it in new parent */
1844 Remove((struct Node
*)object
);
1845 AddTail((struct List
*)&parent
->elements
, (struct Node
*)object
);
1846 object
->parent
= parent
;
1847 AdjustExaminations(handler
, object
);
1850 if(object
!= duplicate
)
1852 /* Update notifications */
1854 NotifyAll(handler
, object
, FALSE
);
1855 UnmatchNotifyRequests(handler
, object
);
1856 MatchNotifyRequests(handler
);
1859 NotifyAll(handler
, object
, FALSE
);
1862 /* Return success indicator */
1870 /****i* ram.handler/CmdRenameDisk ******************************************
1876 * success = CmdRenameDisk(handler, new_name)
1878 * BOOL CmdRenameDisk(struct Handler *, STRPTR);
1894 ****************************************************************************
1898 BOOL
CmdRenameDisk(struct Handler
*handler
, STRPTR new_name
)
1902 /* Check volume isn't write-protected */
1905 error
= ERROR_DISK_WRITE_PROTECTED
;
1907 /* Rename volume's DOS entry and root directory */
1910 if(!SetName(handler
, handler
->root_dir
, new_name
))
1914 if(!MyRenameDosEntry(handler
, handler
->volume
, new_name
))
1917 /* Return success indicator */
1925 /****i* ram.handler/CmdSetDate *********************************************
1931 * success = CmdSetDate(handler, lock, name,
1934 * BOOL CmdSetDate(struct Handler *, struct Lock *, STRPTR,
1935 * struct DateStamp *);
1951 ****************************************************************************
1955 BOOL
CmdSetDate(struct Handler
*handler
, struct Lock
*lock
, STRPTR name
,
1956 struct DateStamp
*date
)
1958 struct Object
*object
;
1961 /* Check volume isn't write-protected */
1964 error
= ERROR_DISK_WRITE_PROTECTED
;
1966 /* Get object and set its new date */
1970 object
= GetHardObject(handler
, lock
, name
, NULL
);
1973 object
= GetRealObject(object
);
1974 CopyMem(date
, &object
->date
, sizeof(struct DateStamp
));
1980 /* Notify interested parties */
1984 NotifyAll(handler
, object
, TRUE
);
1995 /****i* ram.handler/CmdDeleteObject ****************************************
1998 * CmdDeleteObject --
2001 * success = CmdDeleteObject(handler, lock, name)
2003 * BOOL CmdDeleteObject(struct Handler *, struct Lock *, STRPTR);
2019 ****************************************************************************
2023 BOOL
CmdDeleteObject(struct Handler
*handler
, struct Lock
*lock
,
2026 LONG error
= 0, pos
= -1;
2027 struct Object
*object
;
2029 /* Find object and check it can be deleted */
2031 object
= GetObject(handler
, lock
, name
, NULL
, &pos
);
2032 if(object
== NULL
|| pos
!= -1)
2036 error
= ERROR_DISK_WRITE_PROTECTED
;
2040 if((GetRealObject(object
)->protection
& FIBF_DELETE
) != 0)
2041 error
= ERROR_DELETE_PROTECTED
;
2044 /* Attempt to delete object */
2048 if(!AttemptDeleteObject(handler
, object
, TRUE
))
2060 /****i* ram.handler/CmdCurrentVolume ***************************************
2063 * CmdCurrentVolume --
2066 * volume = CmdCurrentVolume(handler)
2068 * struct DosList *CmdCurrentVolume(struct Handler *);
2084 ****************************************************************************
2088 struct DosList
*CmdCurrentVolume(struct Handler
*handler
)
2091 return handler
->volume
;
2096 /****i* ram.handler/CmdChangeMode ******************************************
2102 * success = CmdChangeMode(handler, type, thing, new_mode)
2104 * BOOL CmdChangeMode(struct Handler *, ULONG, APTR, ULONG);
2120 ****************************************************************************
2124 BOOL
CmdChangeMode(struct Handler
*handler
, ULONG type
, APTR thing
, ULONG new_mode
)
2127 struct Opening
*opening
;
2132 if(type
== CHANGE_FH
)
2134 opening
= (APTR
)((struct FileHandle
*)thing
)->fh_Arg1
;
2135 lock
= opening
->file
->lock
;
2140 /* Change mode if possible */
2142 if(new_mode
== ACCESS_WRITE
&& lock
->lock_count
> 1)
2144 error
= ERROR_OBJECT_IN_USE
;
2148 ((struct FileLock
*)lock
)->fl_Access
= new_mode
;
2151 /* Set error code and return result */
2159 /****i* ram.handler/CmdMakeLink ********************************************
2165 * success = CmdMakeLink(handler, lock, name, reference,
2168 * BOOL CmdMakeLink(struct Handler *, struct Lock *, STRPTR, APTR,
2185 ****************************************************************************
2189 BOOL
CmdMakeLink(struct Handler
*handler
, struct Lock
*lock
, STRPTR name
,
2190 APTR reference
, LONG link_type
)
2192 struct Object
*link
, *parent
, *target
= NULL
, *master_link
;
2193 LONG error
= 0, object_type
;
2195 struct MinNode
*node
;
2197 /* Find parent directory and possible name clash */
2199 link
= GetHardObject(handler
, lock
, name
, &parent
);
2201 error
= ERROR_OBJECT_EXISTS
;
2202 else if(parent
== NULL
)
2205 /* Determine link type */
2207 if(link_type
== LINK_HARD
)
2209 target
= (APTR
)((struct FileLock
*)reference
)->fl_Key
;
2210 if(((struct Node
*)target
)->ln_Pri
== ST_FILE
)
2211 object_type
= ST_LINKFILE
;
2213 object_type
= ST_LINKDIR
;
2216 object_type
= ST_SOFTLINK
;
2218 /* Check volume isn't write-protected */
2223 error
= ERROR_DISK_WRITE_PROTECTED
;
2226 /* Create a new link */
2230 link
= CreateObject(handler
, FilePart(name
), object_type
, parent
);
2235 /* Store link target */
2239 if(link_type
== LINK_HARD
)
2241 node
= target
->hard_link
.mln_Succ
;
2245 AddTail((APTR
)&master_link
->elements
, (APTR
)&target
->hard_link
);
2248 master_link
= HARDLINK(node
);
2249 AddTail((APTR
)&master_link
->elements
, (APTR
)&link
->hard_link
);
2254 SetString(handler
, (APTR
)&link
->soft_link_target
, reference
);
2255 if(block_diff
== -1)
2259 link
->block_count
+= block_diff
;
2260 handler
->block_count
+= block_diff
;
2268 NotifyAll(handler
, link
, FALSE
);
2270 /* Return success indicator */
2278 /****i* ram.handler/CmdReadLink ********************************************
2284 * success = CmdReadLink(handler, lock, name, buffer,
2287 * BOOL CmdReadLink(struct Handler *, struct Lock *, const TEXT *,
2304 ****************************************************************************
2308 LONG
CmdReadLink(struct Handler
*handler
, struct Lock
*lock
,
2309 const TEXT
*name
, TEXT
*buffer
, LONG buffer_size
)
2311 struct Object
*link
;
2312 LONG error
= 0, pos
, length
;
2315 /* Get link object */
2317 link
= GetObject(handler
, lock
, name
, NULL
, &pos
);
2320 else if(((struct Node
*)link
)->ln_Pri
!= ST_SOFTLINK
)
2321 error
= ERROR_OBJECT_WRONG_TYPE
;
2325 /* Copy part of path preceding link to buffer so that returned path
2326 will be relative to lock passed in */
2329 p
= name
+ StrLen(name
) - 1;
2333 while(p
!= name
&& *p
!= '/' && *p
!= ':')
2337 if(*p
== '/' || *p
== ':')
2339 if(buffer_size
>= length
+ 1)
2341 CopyMem(name
, buffer
, length
);
2342 buffer
[length
] = '\0';
2345 error
= ERROR_BUFFER_OVERFLOW
;
2350 /* Add link target to link's parent path */
2352 if(AddPart(buffer
, link
->soft_link_target
, buffer_size
))
2354 /* Add remainder of original path after link */
2358 if(!AddPart(buffer
, name
+ pos
, buffer_size
))
2359 error
= ERROR_LINE_TOO_LONG
;
2363 error
= ERROR_BUFFER_OVERFLOW
;
2366 /* Return path length or error indicator */
2368 if(error
== ERROR_BUFFER_OVERFLOW
)
2373 length
= StrLen(buffer
);
2381 /****i* ram.handler/CmdWriteProtect ****************************************
2384 * CmdWriteProtect --
2387 * success = CmdWriteProtect(handler, on, key)
2389 * BOOL CmdWriteProtect(struct Handler *, BOOL, ULONG);
2405 ****************************************************************************
2409 BOOL
CmdWriteProtect(struct Handler
*handler
, BOOL on
, ULONG key
)
2412 struct Object
*root_dir
;
2414 root_dir
= handler
->root_dir
;
2418 if(!handler
->locked
)
2419 root_dir
->length
= key
;
2421 error
= ERROR_DISK_WRITE_PROTECTED
;
2425 if(root_dir
->length
!= 0 && root_dir
->length
!= key
)
2426 error
= ERROR_INVALID_COMPONENT_NAME
;
2428 root_dir
->length
= 0;
2432 handler
->locked
= on
;
2434 /* Return success indicator */
2442 /****i* ram.handler/CmdFlush ***********************************************
2448 * success = CmdFlush()
2466 ****************************************************************************
2477 /****i* ram.handler/CmdAddNotify *******************************************
2483 * success = CmdAddNotify(handler, request)
2485 * BOOL CmdAddNotify(struct Handler *, struct NotifyRequest *);
2501 ****************************************************************************
2505 BOOL
CmdAddNotify(struct Handler
*handler
, struct NotifyRequest
*request
)
2508 struct Notification
*notification
;
2509 struct Object
*object
;
2511 notification
= AllocPooled(handler
->clear_pool
,
2512 sizeof(struct Notification
));
2513 if(notification
== NULL
)
2518 notification
->request
= request
;
2519 request
->nr_Flags
&= ~NRF_MAGIC
;
2521 object
= GetHardObject(handler
, NULL
, request
->nr_FullName
, NULL
);
2525 AddTail((APTR
)&object
->notifications
, (APTR
)notification
);
2526 if((request
->nr_Flags
& NRF_NOTIFY_INITIAL
) != 0)
2527 Notify(handler
, notification
);
2530 AddTail((APTR
)&handler
->notifications
, (APTR
)notification
);
2533 /* Return success indicator */
2541 /****i* ram.handler/CmdRemoveNotify ****************************************
2544 * CmdRemoveNotify --
2547 * success = CmdRemoveNotify(handler, request)
2549 * BOOL CmdRemoveNotify(struct Handler *, struct NotifyRequest *);
2565 ****************************************************************************
2569 BOOL
CmdRemoveNotify(struct Handler
*handler
, struct NotifyRequest
*request
)
2571 struct Notification
*notification
;
2573 notification
= FindNotification(handler
, request
);
2574 Remove((APTR
)notification
);
2575 FreePooled(handler
->clear_pool
, notification
,
2576 sizeof(struct Notification
));