bug: uses wrong list counter, which incurs an array overflow/undefined behaviour...
[AROS-Contrib.git] / libs / desktop / worker.c
blob29fee4b44c98b56c1aa1b32da829969a86f99de9
1 /*
2 Copyright © 1995-2003, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #define MUIMASTER_YES_INLINE_STDARG
8 #define DEBUG 1
9 #include <aros/debug.h>
11 #include <exec/types.h>
12 #include <exec/memory.h>
14 #include <proto/exec.h>
15 #include <proto/dos.h>
16 #include <proto/icon.h>
17 #include <proto/intuition.h>
19 #include "worker.h"
21 #include "desktop_intern.h"
23 #include "desktop_intern_protos.h"
25 #include <stdarg.h>
26 #include <string.h>
29 FUTURE WORK: 1. The worker should work inbetween messages from a
30 requester. This will give faster results. 2. The WorkerMessage structure
31 is a bit bloated, perhaps have a seperate message for starts?
34 void scan(struct ScannerWorkerContext *swc)
36 struct ExAllData *ead;
37 struct SingleResult *sr = NULL;
38 int i = 0;
39 UBYTE *fullPath;
40 BPTR fileLock;
41 struct FileInfoBlock *fib;
42 ULONG commentSize;
44 swc->swc_More = ExAll
46 swc->swc_DirLock, (struct ExAllData *) swc->swc_Buffer,
47 SCAN_BUFFER, ED_OWNER, swc->swc_EAC
50 if (swc->swc_EAC->eac_Entries)
52 ead = swc->swc_Buffer;
53 sr = (struct SingleResult *) AllocVec
55 swc->swc_EAC->eac_Entries * sizeof(struct SingleResult), MEMF_ANY
57 for (i = 0; i < swc->swc_EAC->eac_Entries; i++)
59 ULONG length = strlen(swc->swc_DirName) + 1 /* strlen("/") */
60 + strlen(ead->ed_Name) + 1 /* '\0' */;
62 sr[i].sr_Name = ead->ed_Name;
64 fullPath = AllocVec(length, MEMF_ANY);
66 strlcpy(fullPath, swc->swc_DirName, length);
67 if (swc->swc_DirName[strlen(swc->swc_DirName) - 1] != ':')
69 strlcat(fullPath, "/", length);
71 strlcat(fullPath, ead->ed_Name, length);
73 sr[i].sr_DiskObject = GetDiskObjectNew(fullPath);
75 fileLock = Lock(fullPath, ACCESS_READ);
76 if (fileLock)
78 fib = AllocDosObject(DOS_FIB, NULL);
79 if (fib)
81 if (Examine(fileLock, fib))
83 commentSize = strlen(fib->fib_Comment) + 1;
84 sr[i].sr_Comment = AllocVec(commentSize, MEMF_ANY);
85 CopyMem(fib->fib_Comment, sr[i].sr_Comment,
86 commentSize);
87 sr[i].sr_Script = fib->fib_Protection & FIBF_SCRIPT;
88 sr[i].sr_Pure = fib->fib_Protection & FIBF_PURE;
89 sr[i].sr_Archive = fib->fib_Protection & FIBF_ARCHIVE;
90 sr[i].sr_Read = fib->fib_Protection & FIBF_READ;
91 sr[i].sr_Write = fib->fib_Protection & FIBF_WRITE;
92 sr[i].sr_Execute = fib->fib_Protection & FIBF_EXECUTE;
93 sr[i].sr_Delete = fib->fib_Protection & FIBF_DELETE;
94 sr[i].sr_Type = fib->fib_DirEntryType;
95 sr[i].sr_Size = fib->fib_Size;
96 sr[i].sr_LastModified = fib->fib_Date;
98 FreeDosObject(DOS_FIB, fib);
100 UnLock(fileLock);
103 ead = ead->ed_Next;
105 FreeVec(fullPath);
109 ((struct WorkerScanRequest *) swc->swc_CurrentRequest)->wsr_Results =
110 swc->swc_EAC->eac_Entries;
111 ((struct WorkerScanRequest *) swc->swc_CurrentRequest)->wsr_ResultsArray =
113 ((struct WorkerScanRequest *) swc->swc_CurrentRequest)->wsr_More =
114 swc->swc_More;
117 void startScan(struct ScannerWorkerContext *swc)
119 UBYTE *dirName;
120 UWORD bufferSize = 100;
121 BOOL success;
123 // a pointer to this buffer is given to the iconobserver class and
124 // will be freed when the class is destroyed
125 swc->swc_Buffer = (STRPTR) AllocVec(SCAN_BUFFER, MEMF_ANY);
126 swc->swc_DirLock =
127 ((struct WorkerScanRequest *) swc->swc_CurrentRequest)->wsr_DirLock;
128 swc->swc_EAC =
129 (struct ExAllControl *) AllocDosObject(DOS_EXALLCONTROL, NULL);
130 swc->swc_EAC->eac_LastKey = 0;
132 dirName = (UBYTE *) AllocVec(bufferSize, MEMF_ANY);
133 success = NameFromLock(swc->swc_DirLock, dirName, bufferSize);
134 if (!success)
136 while (IoErr() == ERROR_LINE_TOO_LONG)
138 FreeVec(bufferSize);
139 bufferSize += 50;
140 dirName = (UBYTE *) AllocVec(bufferSize, MEMF_ANY);
141 success = NameFromLock(swc->swc_DirLock, dirName, bufferSize);
142 if (success)
143 break;
147 swc->swc_DirName = dirName;
149 scan(swc);
152 void resumeScan(struct ScannerWorkerContext *swc)
154 swc->swc_Buffer = (STRPTR) AllocVec(SCAN_BUFFER, MEMF_ANY);
155 scan(swc);
158 void stopScan(struct ScannerWorkerContext *swc)
160 ExAllEnd(swc->swc_DirLock, (struct ExAllData *) swc->swc_Buffer,
161 SCAN_BUFFER, ED_OWNER, swc->swc_EAC);
164 void destroyScanWorker(struct ScannerWorkerContext *swc)
166 UnLock(swc->swc_DirLock);
167 FreeDosObject(DOS_EXALLCONTROL, swc->swc_EAC);
168 FreeVec(swc->swc_DirName);
169 FreeVec(swc);
172 ULONG workerEntry(void)
174 BOOL running = TRUE;
175 struct MsgPort *port;
176 struct WorkerMessage *msg;
177 struct ScannerWorkerContext *swc = NULL;
179 port = &((struct Process *) FindTask(NULL))->pr_MsgPort;
181 while (running)
183 WaitPort(port);
185 while ((msg = (struct WorkerMessage *) (GetMsg(port))))
187 switch (msg->w_Command)
189 case WM_START:
191 swc =
192 (struct ScannerWorkerContext *)
193 AllocVec(sizeof(struct ScannerWorkerContext),
194 MEMF_ANY);
195 swc->swc_Context.workerAction = msg->w_Command;
196 swc->swc_Context.start = (APTR) startScan;
197 swc->swc_Context.resume = (APTR) resumeScan;
198 swc->swc_Context.stop = (APTR) stopScan;
199 swc->swc_EAC = NULL;
200 swc->swc_DirLock = NULL;
201 swc->swc_More = FALSE;
202 swc->swc_Buffer = NULL;
203 swc->swc_CurrentRequest =
204 (struct WorkerMessage *) msg;
205 swc->swc_Context.start(swc);
206 if (!swc->swc_More)
208 ((struct WorkerScanRequest *) swc->
209 swc_CurrentRequest)->wsr_More = FALSE;
210 running = FALSE;
211 destroyScanWorker(swc);
213 break;
215 case WM_RESUME:
216 swc->swc_CurrentRequest = msg;
217 swc->swc_Context.resume(swc);
218 if (!swc->swc_More)
220 ((struct WorkerScanRequest *) swc->
221 swc_CurrentRequest)->wsr_More = FALSE;
222 running = FALSE;
223 destroyScanWorker(swc);
225 break;
227 case WM_STOP:
228 if (msg)
229 swc->swc_Context.stop(swc);
230 destroyScanWorker(swc);
231 running = FALSE;
232 break;
234 default:
235 break;
238 ReplyMsg((struct Message *) msg);
242 return 0;
245 struct WorkerMessage *createWorkerScanMessage(ULONG workerCommand,
246 ULONG workerAction,
247 ULONG messageID,
248 struct MsgPort *replyPort,
249 BPTR dirLock)
251 struct WorkerMessage *wm = NULL;
252 struct WorkerScanRequest *sr;
254 sr = AllocVec(sizeof(struct WorkerScanRequest), MEMF_ANY);
255 sr->wsr_WMessage.w_Message.mn_Node.ln_Type = NT_MESSAGE;
256 sr->wsr_WMessage.w_Message.mn_ReplyPort = replyPort;
257 sr->wsr_WMessage.w_Message.mn_Length = sizeof(struct WorkerScanRequest);
258 sr->wsr_WMessage.w_Command = workerCommand;
260 sr->wsr_WMessage.w_Action = workerAction;
261 sr->wsr_WMessage.w_ID = messageID;
262 sr->wsr_DirLock = dirLock;
263 wm = (struct WorkerMessage *) sr;
265 return wm;
268 struct MsgPort *startScannerWorker(ULONG id, BPTR dirLock,
269 struct MsgPort *replyPort)
271 struct Process *process;
272 struct ScannerWorkerMessage *msg;
274 process = CreateNewProcTags
276 NP_Entry, (IPTR) workerEntry,
277 NP_Name, (IPTR) "Worker_Scanner",
278 NP_StackSize, 8192,
279 TAG_DONE
282 if (process == NULL) return NULL;
284 msg = createWorkerScanMessage
286 WM_START, WA_SCANNER, id, replyPort, dirLock
289 PutMsg(&process->pr_MsgPort, (struct Message *) msg);
292 return &process->pr_MsgPort;