use old style synchronization barrier. It might be that we will need a separate file...
[AROS.git] / rom / dos / startnotify.c
blob6e391ae4f44c2b23bcf2a6dbccbae699082214d4
1 /*
2 Copyright © 1995-2013, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc:
6 Lang: English
7 */
9 #include <dos/notify.h>
10 #include <dos/exall.h>
11 #include <proto/dos.h>
12 #include <aros/debug.h>
13 #include <string.h>
15 #include "dos_intern.h"
17 /*****************************************************************************
19 NAME */
21 AROS_LH1(BOOL, StartNotify,
23 /* SYNOPSIS */
24 AROS_LHA(struct NotifyRequest *, notify, D1),
26 /* LOCATION */
27 struct DosLibrary *, DOSBase, 148, Dos)
29 /* FUNCTION
30 Send a notification request to a filesystem. You will then be notified
31 whenever the file (or directory) changes.
33 INPUTS
34 notify - a notification request for the file or directory to monitor
36 RESULT
37 Success/failure indicator.
39 NOTES
40 The file or directory connected to a notification request does not
41 have to exist at the time of calling StartNotify(). The NotifyRequest
42 used with this function should not be altered while active.
44 EXAMPLE
46 BUGS
48 SEE ALSO
49 EndNotify(), <dos/notify.h>
51 INTERNALS
53 *****************************************************************************/
55 AROS_LIBFUNC_INIT
57 LONG err;
58 struct DevProc *dvp;
59 UBYTE buf[MAXFILENAMELENGTH+1], *buf2, *p;
60 ULONG len, len2;
61 BPTR lock = BNULL;
63 /* set up some defaults */
64 notify->nr_MsgCount = 0;
65 notify->nr_FullName = NULL;
67 D(bug("[StartNotify] Request 0x%p, Name %s\n", notify, notify->nr_Name));
69 /* turn the filename into a device and dir lock */
70 if ((dvp = GetDeviceProc(notify->nr_Name, NULL)) == NULL)
71 return DOSFALSE;
73 /* remember the handler for EndNotify() */
74 notify->nr_Handler = dvp->dvp_Port;
76 /* if no lock is returned by GetDeviceProc() (eg if the path is for a
77 * device or volume root), then get the handler to resolve the name of the
78 * device root lock */
79 if (dvp->dvp_Lock == BNULL)
81 UBYTE name[MAXFILENAMELENGTH+1], *src, *dst;
82 struct FileInfoBlock *fib;
84 src = notify->nr_Name;
85 dst = name;
87 while (*src != ':')
88 *dst++ = *src++;
90 *dst++ = ':';
91 *dst++ = '\0';
93 if ((fib = AllocDosObject(DOS_FIB, NULL)) == NULL) {
94 FreeDeviceProc(dvp);
95 return DOSFALSE;
98 if((lock = Lock(name, SHARED_LOCK)) == BNULL) {
99 FreeDosObject(DOS_FIB, fib);
100 FreeDeviceProc(dvp);
101 return DOSFALSE;
104 if (!Examine(lock, fib)) {
105 FreeDosObject(DOS_FIB, fib);
106 FreeDeviceProc(dvp);
107 return DOSFALSE;
110 /* copy it to our processing buffer */
111 src = fib->fib_FileName;
112 dst = buf;
114 while (*src != '\0')
115 *dst++ = *src++;
117 *dst++ = ':';
118 *dst++ = '\0';
120 FreeDosObject(DOS_FIB, fib);
123 /* otherwise we need to expand the name using the lock */
124 else
126 /* get the name */
127 if (NameFromLock(dvp->dvp_Lock, buf, sizeof(buf)) == DOSFALSE)
129 FreeDeviceProc(dvp);
130 return DOSFALSE;
134 len = strlen(buf);
136 /* if it's not some absolute base thing, then add a dir seperator for
137 * the concat operation below */
138 if (buf[len-1] != ':') {
139 buf[len] = '/';
140 len++;
143 /* look for the ':' following the assign name in the path provided by
144 * the caller */
145 p = notify->nr_Name;
146 while (*p && *p != ':')
147 p++;
149 /* if we found it, move past it */
150 if (*p)
151 p++;
153 /* hit the end, so the name is a relative path, and we take all of it */
154 else
155 p = notify->nr_Name;
157 len2 = strlen(p);
159 if ((buf2 = AllocVec(len + len2 + 1, MEMF_PUBLIC)) == NULL)
161 SetIoErr(ERROR_NO_FREE_STORE);
163 /* cleanup */
164 if (lock != BNULL)
165 UnLock(lock);
166 FreeDeviceProc(dvp);
168 return DOSFALSE;
171 /* concatenate the two bits */
172 CopyMem(buf, buf2, len);
173 CopyMem(p, buf2 + len, len2 + 1);
175 /* that's our expanded name */
176 notify->nr_FullName = buf2;
178 /* send the request, with error reporting */
181 err = fs_AddNotify(notify, dvp, lock, DOSBase);
182 } while (err != 0 && ErrorReport(err, REPORT_LOCK, 0, notify->nr_Handler) == DOSFALSE);
184 /* cleanup */
185 if (lock != BNULL)
186 UnLock(lock);
187 FreeDeviceProc(dvp);
189 /* something broke, clean up */
190 if (err != 0)
192 if (notify->nr_FullName != notify->nr_Name)
194 FreeVec(notify->nr_FullName);
195 notify->nr_FullName = NULL;
198 SetIoErr(err);
199 return DOSFALSE;
202 D(bug("[StartNotify] nr_Handler 0x%p\n", notify->nr_Handler));
204 return DOSTRUE;
206 AROS_LIBFUNC_EXIT
207 } /* StartNotify */