chiark / gitweb /
plugins/tracklength-gstreamer.c: Rewrite to use `GstDiscoverer'.
[disorder] / server / mount.c
CommitLineData
18f94073
RK
1/*
2 * This file is part of DisOrder.
8a886602 3 * Copyright (C) 2010, 2011 Richard Kettlewell
18f94073
RK
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program 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.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18/** @file server/mount.c
19 * @brief Periodically check for devices being mounted and unmounted
20 */
21#include "disorder-server.h"
22#if HAVE_GETFSSTAT
23# include <sys/param.h>
24# include <sys/ucred.h>
25# include <sys/mount.h>
26#endif
27
28#if HAVE_GETFSSTAT
29static int compare_fsstat(const void *av, const void *bv) {
30 const struct statfs *a = av, *b = bv;
31 int c;
32
33 c = memcmp(&a->f_fsid, &b->f_fsid, sizeof a->f_fsid);
34 if(c)
35 return c;
36 c = strcmp(a->f_mntonname, b->f_mntonname);
37 if(c)
38 return c;
39 return 0;
40}
41#endif
42
439409a3 43#if HAVE_GETFSSTAT || defined PATH_MTAB
18f94073 44void periodic_mount_check(ev_source *ev_) {
8488cf7d
RK
45 if(!config->mount_rescan)
46 return;
18f94073
RK
47#if HAVE_GETFSSTAT
48 /* On OS X, we keep track of the hash of the kernel's mounted
49 * filesystem list */
50 static int first = 1;
51 static unsigned char last[20];
52 unsigned char *current;
53 int nfilesystems, space;
54 struct statfs *buf;
55 gcrypt_hash_handle h;
56 gcry_error_t e;
57
58 space = getfsstat(NULL, 0, MNT_NOWAIT);
59 buf = xcalloc(space, sizeof *buf);
60 nfilesystems = getfsstat(buf, space * sizeof *buf, MNT_NOWAIT);
61 if(nfilesystems > space)
62 // The array grew between check and use! We just give up and try later.
63 return;
64 // Put into order so we get a bit of consistency
65 qsort(buf, nfilesystems, sizeof *buf, compare_fsstat);
66 if((e = gcry_md_open(&h, GCRY_MD_SHA1, 0))) {
67 disorder_error(0, "gcry_md_open: %s", gcry_strerror(e));
68 return;
69 }
70 for(int n = 0; n < nfilesystems; ++n) {
71 gcry_md_write(h, &buf[n].f_fsid, sizeof buf[n].f_fsid);
72 gcry_md_write(h, buf[n].f_mntonname, 1 + strlen(buf[n].f_mntonname));
73 }
74 current = gcry_md_read(h, GCRY_MD_SHA1);
75 if(!first && memcmp(current, last, sizeof last))
76 trackdb_rescan(ev_, 1/*check*/, 0, 0);
77 memcpy(last, current, sizeof last);
78 first = 0;
498b46a2 79 gcry_md_close(h);
8138da17
RK
80#elif defined PATH_PROC_MOUNTS
81 /* On Linux we hash /proc/mounts */
82 static int first = 1;
83 static unsigned char last[20];
84
85 unsigned char *current;
86 int fd = -1, n;
87 gcrypt_hash_handle h = 0;
88 gcry_error_t e;
89 char buffer[1024];
90
91 if((e = gcry_md_open(&h, GCRY_MD_SHA1, 0))) {
92 disorder_error(0, "gcry_md_open: %s", gcry_strerror(e));
93 goto done;
94 }
95 if((fd = open(PATH_PROC_MOUNTS, O_RDONLY)) < 0) {
96 disorder_error(errno, "open %s", PATH_PROC_MOUNTS);
97 goto done;
98 }
99 for(;;) {
100 n = read(fd, buffer, sizeof buffer);
101 if(n > 0)
102 gcry_md_write(h, buffer, n);
103 else if(n == 0)
104 break;
105 else if(errno != EINTR) {
106 disorder_error(errno, "reading %s", PATH_PROC_MOUNTS);
107 goto done;
108 }
109 }
110 current = gcry_md_read(h, GCRY_MD_SHA1);
111 if(!first && memcmp(current, last, sizeof last))
112 trackdb_rescan(ev_, 1/*check*/, 0, 0);
113 memcpy(last, current, sizeof last);
114 first = 0;
115 done:
116 if(h) gcry_md_close(h);
117 if(fd != -1) close(fd);
18f94073 118#elif defined PATH_MTAB
8138da17 119 /* As a further alternative we track the modification time of /etc/mtab */
18f94073
RK
120 static time_t last_mount;
121 struct stat sb;
122
123 if(stat(PATH_MTAB, &sb) >= 0) {
124 if(last_mount != 0 && last_mount != sb.st_mtime)
125 trackdb_rescan(ev_, 1/*check*/, 0, 0);
126 last_mount = sb.st_mtime;
127 }
128#endif
129}
439409a3
RK
130#else
131void periodic_mount_check(ev_source attribute((unused)) *ev_ ) {
132}
133#endif
18f94073
RK
134
135/*
136Local Variables:
137c-basic-offset:2
138comment-column:40
139fill-column:79
140indent-tabs-mode:nil
141End:
142*/