tools/adflib: build only host variant which is used by Sam440 target
[AROS.git] / rom / filesys / pfs3 / fs / dd_support.c
blob5aa55776e0c15904cd3d1795100177c10a35f850
1 /* $Id$ */
2 /* $Log: dd_support.c $
3 * Revision 1.9 1999/02/22 16:33:43 Michiel
4 * Changes for increasing deldir capacity
6 * Revision 1.8 1998/09/27 11:26:37 Michiel
7 * ErrorMsg param
9 * Revision 1.7 1997/03/03 22:04:04 Michiel
10 * Release 16.21
12 * Revision 1.6 1996/03/29 17:02:54 Michiel
13 * update sleeproutines
15 * Revision 1.5 1996/01/30 12:49:23 Michiel
16 * --- working tree overlap ---
17 * new notify routines
18 * */
20 /**********************
21 * function prototypes
24 static BOOL RenameDisk(UBYTE *, globaldata *);
26 static void NotifyUser(struct NotifyRequest *nr, globaldata *g);
27 static struct notifyobject *CheckNotify(ULONG parentanodenr, DSTR objectname,
28 struct notifyobject *no, BOOL checkparent, globaldata *);
29 void PFSDoNotify(struct fileinfo *object, BOOL checkparent, globaldata *g);
30 void PFSUpdateNotify(ULONG dirnode, DSTR filename, ULONG anodenr, globaldata *g);
32 /* AFS extensions */
33 #if EXTRAPACKETS
34 static void Sleep (globaldata *g);
35 static void Awake (globaldata *g);
36 static void Alarm (globaldata *g);
37 static LONG UpdateAnode (ULONG old, ULONG new, globaldata *g);
38 void HandleSleepMsg (globaldata *g);
39 #endif
41 /**********************
42 * macros
45 #define SkipColon(filename,pathname) \
46 do { \
47 if ((filename = strchr ((pathname), ':'))) \
48 filename++; \
49 else \
50 filename=(pathname); \
51 } while (0)
53 #define LocateFile(parentfi,filename,objectfi,error) \
54 do { \
55 if (!FindObject (parentfi, filename, &(objectfi), error, g)) \
56 return DOSFALSE; \
58 if (IsVolume(objectfi)) \
59 { \
60 *error = ERROR_OBJECT_WRONG_TYPE; \
61 return DOSFALSE; \
62 } \
63 } while (0)
65 #if MULTIUSER
66 #define muGetRelationship(extrafields) \
67 ((g->muFS_ready) ? \
68 (muGetRelationshipA (g->user, ((extrafields).uid << 16) + (extrafields).gid, NULL)) : \
69 ((((extrafields).uid == muNOBODY_UID) << muRelB_NO_OWNER) | muRelF_NOBODY))
71 #if DELDIR
72 #define CheckPropertyAccess(objectfi,extrafields,flags, error) \
73 do { \
74 GetExtraFieldsOI (&(objectfi), &(extrafields), g); \
75 if (g->muFS_ready) \
76 flags = muGetRelationshipA (g->user, ((extrafields).uid << 16) + (extrafields).gid, NULL); \
77 else \
78 flags = (((extrafields).uid == muNOBODY_UID) << muRelB_NO_OWNER) | muRelF_NOBODY; \
80 if (!(flags & muRel_PROPERTY_ACCESS)) \
81 { \
82 *error = ERROR_WRITE_PROTECTED; \
83 return DOSFALSE; \
84 } \
85 } while (0)
86 #else /* DELDIR */
87 #define CheckPropertyAccess(objectfi,extrafields,flags, error) \
88 do { \
89 GetExtraFields ((objectfi).file.direntry, &(extrafields)); \
90 if (g->muFS_ready) \
91 flags = muGetRelationshipA (g->user, ((extrafields).uid << 16) + (extrafields).gid, NULL); \
92 else \
93 flags = (((extrafields).uid == muNOBODY_UID) << muRelB_NO_OWNER) | muRelF_NOBODY; \
95 if (!(flags & muRel_PROPERTY_ACCESS)) \
96 { \
97 *error = ERROR_WRITE_PROTECTED; \
98 return DOSFALSE; \
99 } \
100 } while (0)
101 #endif /* DELDIR */
103 #else /* MULTIUSER */
104 #define muGetRelationship(extrafields)
105 #define CheckPropertyAccess(objectfi,extrafields,flags,error)
106 #endif /* MULTIUSER */
109 * BPTR, BOOL, listentry_t *, union objectinfo *
111 #define GetFileInfoFromLock(argument, access, fe, fi) \
112 do { \
113 if ((fe = LockEntryFromLock (argument))) \
115 if (!CheckVolume ((fe)->le.volume, access, error, g)) \
116 return DOSFALSE; \
117 UpdateLE ((listentry_t *)(fe), g); \
118 fi = &(fe)->le.info; \
120 else \
122 if (!g->currentvolume) \
124 *error = ERROR_NO_DISK; \
125 return DOSFALSE; \
127 fi = NULL; \
129 } while (0)
133 /**********************
134 * rename disk
137 static BOOL RenameDisk (UBYTE *newname, globaldata *g) //%4.5
139 UBYTE *diskname;
140 struct volumedata *volume = g->currentvolume;
142 ENTER("RenameDisk");
144 if (g->currentvolume && (strlen(newname) < DNSIZE))
146 /* Write changes directly to disk to prevent disk recognition problems.
147 * (So DON'T use updatedisk)
149 diskname = volume->rootblk->diskname;
150 *diskname = strlen(newname);
151 CopyMem (newname, diskname+1, strlen(newname));
152 RawWrite ((UBYTE *)volume->rootblk, 1, ROOTBLOCK, g); /* %7.2 */
153 g->request->iotd_Req.io_Command = CMD_UPDATE;
154 DoIO ((struct IORequest *)g->request);
155 volume->rootblockchangeflag = FALSE;
156 return DOSTRUE;
158 else
160 return DOSFALSE;
165 /**********************
166 * notify stuff
169 static void NotifyUser (struct NotifyRequest *nr, globaldata *g)
171 struct NotifyMessage *msg;
173 if (nr->nr_MsgCount && (nr->nr_Flags & NRF_WAIT_REPLY))
175 nr->nr_Flags |= NRF_MAGIC;
176 return;
179 if (nr->nr_Flags & NRF_SEND_MESSAGE)
181 if (!(msg = AllocMemP (sizeof(struct NotifyMessage), g)))
182 return;
184 msg->nm_ExecMessage.mn_ReplyPort = g->notifyport;
185 msg->nm_ExecMessage.mn_Length = sizeof(struct NotifyMessage);
186 msg->nm_Class = NOTIFY_CLASS;
187 msg->nm_Code = NOTIFY_CODE;
188 msg->nm_NReq = nr;
189 PutMsg (nr->nr_stuff.nr_Msg.nr_Port, &msg->nm_ExecMessage);
190 nr->nr_MsgCount++;
192 else if (nr->nr_Flags & NRF_SEND_SIGNAL)
194 Signal (nr->nr_stuff.nr_Signal.nr_Task, 1<<nr->nr_stuff.nr_Signal.nr_SignalNum);
199 * Checks if there is a notify for the object identified by anodenr
201 static struct notifyobject *
202 CheckNotify (ULONG parentanodenr, DSTR objectname, struct notifyobject *no,
203 BOOL checkparent, globaldata *g)
205 if (!no)
206 no = HeadOf(&g->currentvolume->notifylist);
207 else
208 no = no->next;
210 for ( ; no->next; no=no->next)
212 /* file match */
213 if (no->parentanodenr == parentanodenr)
215 if (intlcmp(no->objectname, objectname))
216 return no;
219 /* parent match */
220 if (checkparent && no->anodenr == parentanodenr)
221 return no;
224 return NULL;
228 * Notifies change of object & dir object is in
230 void PFSDoNotify (struct fileinfo *object, BOOL checkparent, globaldata *g)
232 struct notifyobject *no = NULL;
234 #if DELDIR
235 if ((IPTR)object->direntry <= SPECIAL_DELFILE)
236 return;
237 #endif
239 while ((no = CheckNotify (object->dirblock->blk.anodenr,
240 (DSTR)&object->direntry->nlength, no, checkparent, g)))
241 NotifyUser(no->req, g);
246 * To be called when a object named filename is created in dir
247 * dirnode. This routine checks if there is a partially parsed
248 * notify request in that directory that matches the newly
249 * created object. If so, the parsing of the notify request
250 * can continue.
252 void PFSUpdateNotify (ULONG dirnode, DSTR filename, ULONG anodenr, globaldata *g)
254 struct notifyobject *no = NULL;
255 UBYTE *temp;
257 for (no = HeadOf(&g->currentvolume->notifylist); no->next; no=no->next)
259 /* check for parsed path match */
260 if (no->parentanodenr == dirnode)
262 if (no->unparsed)
264 /* check if we can continue parsing */
265 temp = strchr(no->unparsed, '/');
266 if (temp)
267 *temp = 0;
269 if (intlcdcmp(no->unparsed, filename))
271 if (temp)
272 no->unparsed = *(temp+1) ? (temp+1) : NULL;
273 else
274 no->unparsed = NULL;
276 no->parentanodenr = anodenr;
279 if (temp)
280 *temp = '/';
282 else
284 /* check if new object is a notify object */
285 if (intlcmp(no->objectname, filename))
287 no->anodenr = anodenr;
295 /**********************
296 * AFS extension
299 #if EXTRAPACKETS
301 * Enter MODE_SLEEP
303 * All direct directory block references are replaced by an
304 * anode reference. The reference can later be restored by
305 * searching the object in the directory identified by the
306 * diranodenr.
308 * Examine chains have to be broken since sleepwalkers are
309 * allowed to change directory order
311 static void Sleep (globaldata *g)
313 listentry_t *le;
314 struct volumedata *volume = g->currentvolume;
316 if (volume)
318 /* first update disk */
319 UpdateDisk (g);
321 /* flush references */
322 for (le=HeadOf (&volume->fileentries); le->next; le=le->next)
324 if (!IsVolumeEntry(le))
326 /* load flushed references */
327 if (le->dirblocknr)
328 LoadDirBlock (le->dirblocknr, g);
330 le->diranodenr = le->info.file.dirblock->blk.anodenr;
333 if (IsFileEntry(le))
335 fileentry_t *fe = (fileentry_t *)le;
337 if (fe->anodechain)
338 DetachAnodeChain (fe->anodechain, g);
340 fe->currnode = NULL;
344 /* now kill all flushed references (they are now replaced
345 * by anode references in le->diranodenr)
347 for (le=HeadOf (&volume->fileentries); le->next; le=le->next)
349 le->dirblocknr = 0;
351 /* terminate examine chains */
352 if (le->type.flags.dir && !IsDelDir(le->info))
354 ((lockentry_t *)le)->nextentry.direntry = NULL;
355 ((lockentry_t *)le)->nextentry.dirblock = NULL;
356 ((lockentry_t *)le)->nextdirblocknr = 0;
357 ((lockentry_t *)le)->nextdirblockoffset = 0;
362 /* flush cache. Watch it: FreeUnusedResources also calls
363 * the conventional FlushBlock!
365 FreeUnusedResources (volume, g);
368 /* set sleepmode */
369 g->sleepmode = TRUE;
371 /* enter sleepmode */
372 g->DoCommand = SleepCommands;
376 * Leave MODE_SLEEP
378 * Reload all essential blocks. References are restored by searching
379 * by anodenr in the directory identified by diranodenr (using FetchObject)
381 static void Awake (globaldata *g)
383 listentry_t *le;
384 struct volumedata *volume = g->currentvolume;
385 struct rootblock *rootblock;
386 SIPTR error;
388 if (volume)
390 /* reload current rootblock */
391 rootblock = volume->rootblk;
392 RawRead((UBYTE *)rootblock, rootblock->rblkcluster, ROOTBLOCK, g);
394 /* reload rootblock extension */
395 if (rootblock->extension && (rootblock->options & MODE_EXTENSION))
396 RawRead((UBYTE *)&volume->rblkextension->blk, volume->rescluster,
397 rootblock->extension, g);
399 /* reload deldir */
400 // if (rootblock->deldir && (rootblock->options & MODE_DELDIR))
401 // RawRead((UBYTE *)&volume->deldir->blk, volume->rescluster,
402 // rootblock->deldir, g);
404 /* reconfigure modules */
405 InitModules (volume, FALSE, g);
407 /* restore references */
408 for (le=HeadOf (&volume->fileentries); le->next; le=le->next)
410 if (!IsVolumeEntry(le))
412 if (!FetchObject(le->diranodenr, le->anodenr, &le->info, g))
413 ErrorMsg(AFS_ERROR_UNSLEEP, NULL, g); /* -> kill, invalidate lock <- */
415 if (IsFileEntry(le))
417 ULONG offset;
418 fileentry_t *fe = (fileentry_t *)le;
420 /* restore anodechain and fe->currnode */
421 if (!(fe->anodechain = GetAnodeChain(fe->le.anodenr, g)))
422 ; /* kill, invalidate */
424 offset = fe->offset;
425 fe->currnode = &fe->anodechain->head;
426 fe->offset = fe->blockoffset = fe->anodeoffset = 0;
427 if (SeekInObject(fe, offset, OFFSET_BEGINNING, &error, g) == -1)
428 ErrorMsg(AFS_ERROR_UNSLEEP, NULL, g); /* -> kill, invalidate */
434 // --> prevent 'normal' reference-restore on loading
435 // directory blocks
437 /* unset sleepmode */
438 g->sleepmode = FALSE;
440 /* awake */
441 g->DoCommand = NormalCommands;
445 * Disk accessing packets are pending --> wake up!
446 * Handshaking sleeptask <-> AFS
448 static void Alarm (globaldata *g)
450 ULONG sleepmask = 1<<g->alarmsignal;
452 /* signal task that we want to wake up */
453 Signal (g->sleeptask, sleepmask);
455 while (g->sleepmode)
457 WaitPort (g->sleepport);
458 HandleSleepMsg (g);
465 * Reflect changed anode in locklist references
466 * returns number of references updated
467 * (MODE_SLEEP only)
469 static LONG UpdateAnode (ULONG old, ULONG new, globaldata *g)
471 listentry_t *le;
472 struct notifyobject *no;
473 LONG i=0;
474 struct volumedata *volume = g->currentvolume;
477 * Update fileentry list
480 for (le=(listentry_t *)HeadOf(&volume->fileentries); le->next; le=le->next)
482 if (!IsVolumeEntry(le))
484 if (le->anodenr == old)
486 i++;
487 if (!new)
488 ; /* invalidate le */
489 le->anodenr = new;
492 if (le->diranodenr == old)
494 i++;
495 le->diranodenr = new;
501 * Update notify list
504 for (no=HeadOf(&g->currentvolume->notifylist); no->next; no=no->next)
506 if (no->anodenr == old)
508 i++;
509 no->anodenr = new;
513 return i;
517 * Message handler for messages on the sleepport
519 void HandleSleepMsg (globaldata *g)
521 struct Message *msg;
523 while ((msg = GetMsg (g->sleepport)))
525 if (g->sleepmode)
527 g->action = (struct DosPacket *)msg->mn_Node.ln_Name;
528 (g->DoCommand)(g->action, g);
530 else
532 g->action->dp_Res1 = DOSFALSE;
533 g->action->dp_Res2 = ERROR_ACTION_NOT_KNOWN;
536 ReturnPacket (g->action, g->sleepport, g);
540 #endif