15 * 'struct dirent' is funny, because POSIX doesn't require
16 * the definition to be more than a header for a variable
17 * buffer. Thus, allocate a 'big chunk' of memory, and use
18 * it as a buffer.
19 */
20 entry = (struct dirent*)malloc (
21 sizeof (struct dirent) + name_max);
22 if (entry == NULL)
23 errno_abort ('Allocating dirent');
24
25 status = pthread_mutex_lock (&crew->mutex);
26 if (status != 0)
27 err_abort (status, 'Lock crew mutex');
28
29 /*
30 * There won't be any work when the crew is created, so wait
31 * until something's put on the queue.
32 */
33 while (crew->work_count == 0) {
34 status = pthread_cond_wait (&crew->go, &crew->mutex);
35 if (status != 0)
36 err_abort (status, 'Wait for go');
37 }
38
39 status = pthread_mutex_unlock (&crew->mutex);
40 if (status != 0)
41 err_abort (status, 'Unlock mutex');
42
43 DPRINTF (('Crew %d starting
', mine->index));
44
45 /*
46 * Now, as long as there's work, keep doing it.
47 */
48 while (1) {
49 /*
50 * Wait while there is nothing to do, and
51 * the hope of something coming along later. If
52 * crew->first is NULL, there's no work. But if
53 * crew->work_count goes to zero, we're done.
54 */
55 status = pthread_mutex_lock (&crew->mutex);
56 if (status != 0)
57 err_abort (status, 'Lock crew mutex');
58
59 DPRINTF (('Crew %d top: first is %#lx, count is %d
',
60 mine->index, crew->first, crew->work_count));
61 while (crew->first == NULL) {
62 status = pthread_cond_wait (&crew->go, &crew- >mutex);
63 if (status != 0)
64 err_abort (status, 'Wait for work');
65 }
66
67 DPRINTF (('Crew %d woke: %#lx, %d
',
68 mine->index, crew->first, crew->work_count));
69
70 /*
71 * Remove and process a work item.
72 */
73 work = crew->first;
74 crew->first = work->next;
75 if (crew->first == NULL)
76 crew->last = NULL;
77
78 DPRINTF (('Crew %d took %#lx, leaves first %#lx, last %#lx
',
79 mine->index, work, crew->first, crew->last));
80
81 status = pthread_mutex_unlock (&crew->mutex);
82 if (status != 0)
83 err_abort (status, 'Unlock mutex');
84
85 /*
86 * We have a work item. Process it, which may involve
87 * queuing new work items.
88 */
89 status = lstat (work->path, &filestat);
90
91 if (S_ISLNK (filestat.st_mode))
92 printf (
93 'Thread %d: %s is a link, skipping.
',
94 mine->index,
95 work->path);
96 else if (S_ISDIR (filestat.st_mode)) {
97 DIR *directory;
98 struct dirent *result;
99
100 /*
101 * If the file is a directory, search it and place
102 * all files onto the queue as new work items.
103 */
104 directory = opendir (work->path);
105 if (directory == NULL) {
106 fprintf (
107 stderr, 'Unable to open directory %s: %d (%s)
',
108 work->path,
109 errno, strerror (errno));
110 continue;
111 }
112