1 /* MiniDLNA media server
2 * Copyright (C) 2008-2010 Justin Maggard
4 * This file is part of MiniDLNA.
6 * MiniDLNA is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
10 * MiniDLNA is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with MiniDLNA. If not, see <http://www.gnu.org/licenses/>.
31 #include <sys/types.h>
35 #include <sys/resource.h>
37 #ifdef HAVE_SYS_INOTIFY_H
38 #include <sys/inotify.h>
40 #include "linux/inotify.h"
41 #include "linux/inotify-syscalls.h"
46 #include "upnpglobalvars.h"
56 extern time_t next_pl_fill
;
58 #define EVENT_SIZE ( sizeof (struct inotify_event) )
59 #define BUF_LEN ( 1024 * ( EVENT_SIZE + 16 ) )
60 #define DESIRED_WATCH_LIMIT 65536
62 #define PATH_BUF_SIZE PATH_MAX
66 int wd
; /* watch descriptor */
67 char *path
; /* watched path */
71 static struct watch
*watches
;
72 static struct watch
*lastwatch
= NULL
;
73 static pthread_t thread_id
;
76 get_path_from_wd(int wd
)
78 struct watch
*w
= watches
;
91 next_highest(unsigned int num
)
102 raise_watch_limit(unsigned int limit
)
104 FILE *max_watches
= fopen("/proc/sys/fs/inotify/max_user_watches", "r+");
109 if (fscanf(max_watches
, "%u", &limit
) < 1)
113 fprintf(max_watches
, "%u", next_highest(limit
));
118 monitor_add_watch(int fd
, const char * path
)
123 wd
= inotify_add_watch(fd
, path
, IN_CREATE
|IN_CLOSE_WRITE
|IN_DELETE
|IN_MOVE
);
124 if( wd
< 0 && errno
== ENOSPC
)
126 raise_watch_limit(0);
127 wd
= inotify_add_watch(fd
, path
, IN_CREATE
|IN_CLOSE_WRITE
|IN_DELETE
|IN_MOVE
);
131 DPRINTF(E_ERROR
, L_INOTIFY
, "inotify_add_watch(%s) [%s]\n", path
, strerror(errno
));
135 nw
= malloc(sizeof(struct watch
));
138 DPRINTF(E_ERROR
, L_INOTIFY
, "malloc() error\n");
143 nw
->path
= strdup(path
);
145 if( watches
== NULL
)
150 if( lastwatch
!= NULL
)
152 lastwatch
->next
= nw
;
156 DPRINTF(E_INFO
, L_INOTIFY
, "Added watch to %s [%d]\n", path
, wd
);
161 monitor_remove_watch(int fd
, const char * path
)
165 for( w
= watches
; w
; w
= w
->next
)
167 if( strcmp(path
, w
->path
) == 0 )
168 return(inotify_rm_watch(fd
, w
->wd
));
175 inotify_create_watches(int fd
)
178 unsigned int num_watches
= 0, watch_limit
;
181 struct media_dir_s
* media_path
;
183 for( media_path
= media_dirs
; media_path
!= NULL
; media_path
= media_path
->next
)
185 DPRINTF(E_DEBUG
, L_INOTIFY
, "Add watch to %s\n", media_path
->path
);
186 monitor_add_watch(fd
, media_path
->path
);
189 sql_get_table(db
, "SELECT PATH from DETAILS where MIME is NULL and PATH is not NULL", &result
, &rows
, NULL
);
190 for( i
=1; i
<= rows
; i
++ )
192 DPRINTF(E_DEBUG
, L_INOTIFY
, "Add watch to %s\n", result
[i
]);
193 monitor_add_watch(fd
, result
[i
]);
196 sqlite3_free_table(result
);
198 max_watches
= fopen("/proc/sys/fs/inotify/max_user_watches", "r");
201 if( fscanf(max_watches
, "%10u", &watch_limit
) < 1 )
204 if( (watch_limit
< DESIRED_WATCH_LIMIT
) || (watch_limit
< (num_watches
*4/3)) )
206 if (access("/proc/sys/fs/inotify/max_user_watches", W_OK
) == 0)
208 if( DESIRED_WATCH_LIMIT
>= (num_watches
*3/4) )
210 raise_watch_limit(8191U);
212 else if( next_highest(num_watches
) >= (num_watches
*3/4) )
214 raise_watch_limit(num_watches
);
218 raise_watch_limit(next_highest(num_watches
));
223 DPRINTF(E_WARN
, L_INOTIFY
, "WARNING: Inotify max_user_watches [%u] is low or close to the number of used watches [%u] "
224 "and I do not have permission to increase this limit. Please do so manually by "
225 "writing a higher value into /proc/sys/fs/inotify/max_user_watches.\n", watch_limit
, num_watches
);
231 DPRINTF(E_WARN
, L_INOTIFY
, "WARNING: Could not read inotify max_user_watches! "
232 "Hopefully it is enough to cover %u current directories plus any new ones added.\n", num_watches
);
239 inotify_remove_watches(int fd
)
241 struct watch
*w
= watches
;
242 struct watch
*last_w
;
248 inotify_rm_watch(fd
, w
->wd
);
259 inotify_thread(void *arg
)
261 struct pollfd pollfds
[1];
262 char buffer
[BUF_LEN
];
263 char path_buf
[PATH_MAX
];
265 char * esc_name
= NULL
;
270 sigdelset(&set
, SIGCHLD
);
271 pthread_sigmask(SIG_BLOCK
, &set
, NULL
);
273 pollfds
[0].fd
= inotify_init();
274 pollfds
[0].events
= POLLIN
;
276 if ( pollfds
[0].fd
< 0 )
277 DPRINTF(E_ERROR
, L_INOTIFY
, "inotify_init() failed!\n");
279 inotify_create_watches(pollfds
[0].fd
);
280 if (setpriority(PRIO_PROCESS
, 0, 19) == -1)
281 DPRINTF(E_WARN
, L_INOTIFY
, "Failed to reduce inotify thread priority\n");
282 sqlite3_release_memory(1<<31);
289 time_t diff
= next_pl_fill
- time(NULL
);
293 timeout
= diff
* 1000;
295 length
= poll(pollfds
, 1, timeout
);
298 if( next_pl_fill
&& (time(NULL
) >= next_pl_fill
) )
305 else if( length
< 0 )
307 if( (errno
== EINTR
) || (errno
== EAGAIN
) )
310 DPRINTF(E_ERROR
, L_INOTIFY
, "read failed!\n");
314 length
= read(pollfds
[0].fd
, buffer
, BUF_LEN
);
315 buffer
[BUF_LEN
-1] = '\0';
319 while( !quitting
&& i
< length
)
321 struct inotify_event
* event
= (struct inotify_event
*) &buffer
[i
];
324 if( *(event
->name
) == '.' )
326 i
+= EVENT_SIZE
+ event
->len
;
329 esc_name
= modifyString(strdup(event
->name
), "&", "&amp;", 0);
330 snprintf(path_buf
, sizeof(path_buf
), "%s/%s", get_path_from_wd(event
->wd
), event
->name
);
331 if ( event
->mask
& IN_ISDIR
&& (event
->mask
& (IN_CREATE
|IN_MOVED_TO
)) )
333 DPRINTF(E_DEBUG
, L_INOTIFY
, "The directory %s was %s.\n",
334 path_buf
, (event
->mask
& IN_MOVED_TO
? "moved here" : "created"));
335 monitor_insert_directory(pollfds
[0].fd
, esc_name
, path_buf
);
337 else if ( (event
->mask
& (IN_CLOSE_WRITE
|IN_MOVED_TO
|IN_CREATE
)) &&
338 (lstat(path_buf
, &st
) == 0) )
340 if( (event
->mask
& (IN_MOVED_TO
|IN_CREATE
)) && (S_ISLNK(st
.st_mode
) || st
.st_nlink
> 1) )
342 DPRINTF(E_DEBUG
, L_INOTIFY
, "The %s link %s was %s.\n",
343 (S_ISLNK(st
.st_mode
) ? "symbolic" : "hard"),
344 path_buf
, (event
->mask
& IN_MOVED_TO
? "moved here" : "created"));
345 if( stat(path_buf
, &st
) == 0 && S_ISDIR(st
.st_mode
) )
346 monitor_insert_directory(pollfds
[0].fd
, esc_name
, path_buf
);
348 monitor_insert_file(esc_name
, path_buf
);
350 else if( event
->mask
& (IN_CLOSE_WRITE
|IN_MOVED_TO
) && st
.st_size
> 0 )
352 if( (event
->mask
& IN_MOVED_TO
) ||
353 (sql_get_int_field(db
, "SELECT TIMESTAMP from DETAILS where PATH = '%q'", path_buf
) != st
.st_mtime
) )
355 DPRINTF(E_DEBUG
, L_INOTIFY
, "The file %s was %s.\n",
356 path_buf
, (event
->mask
& IN_MOVED_TO
? "moved here" : "changed"));
357 monitor_insert_file(esc_name
, path_buf
);
361 else if ( event
->mask
& (IN_DELETE
|IN_MOVED_FROM
) )
363 DPRINTF(E_DEBUG
, L_INOTIFY
, "The %s %s was %s.\n",
364 (event
->mask
& IN_ISDIR
? "directory" : "file"),
365 path_buf
, (event
->mask
& IN_MOVED_FROM
? "moved away" : "deleted"));
366 if ( event
->mask
& IN_ISDIR
)
367 monitor_remove_directory(pollfds
[0].fd
, path_buf
);
370 monitor_remove_file(path_buf
);
372 * When a symlink to a directory is deleted
373 * we cannot tell it from a regular file deletion
374 * to prevent its children from becoming orphans
375 * we delete the whole tree when it exists
377 monitor_remove_tree(path_buf
);
382 i
+= EVENT_SIZE
+ event
->len
;
385 inotify_remove_watches(pollfds
[0].fd
);
386 close(pollfds
[0].fd
);
395 if (!sqlite3_threadsafe() || sqlite3_libversion_number() < 3005001) {
396 DPRINTF(E_ERROR
, L_GENERAL
, "SQLite library is not threadsafe!"
397 "Inotify will be disabled.\n");
400 if (pthread_create(&thread_id
, NULL
, inotify_thread
, NULL
) != 0)
401 DPRINTF(E_FATAL
, L_GENERAL
, "pthread_create() failed [%s]\n",
409 if (thread_id
!= 0) {
410 pthread_kill(thread_id
, SIGCHLD
);
411 pthread_join(thread_id
, NULL
);