2 * This file is part of DisOrder.
3 * Copyright (C) 2010, 2011 Richard Kettlewell
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.
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.
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/>.
18 /** @file server/mount.c
19 * @brief Periodically check for devices being mounted and unmounted
21 #include "disorder-server.h"
23 # include <sys/param.h>
24 # include <sys/ucred.h>
25 # include <sys/mount.h>
29 static int compare_fsstat(const void *av
, const void *bv
) {
30 const struct statfs
*a
= av
, *b
= bv
;
33 c
= memcmp(&a
->f_fsid
, &b
->f_fsid
, sizeof a
->f_fsid
);
36 c
= strcmp(a
->f_mntonname
, b
->f_mntonname
);
43 #if HAVE_GETFSSTAT || defined PATH_MTAB
44 void periodic_mount_check(ev_source
*ev_
) {
45 if(!config
->mount_rescan
)
48 /* On OS X, we keep track of the hash of the kernel's mounted
51 static unsigned char last
[20];
52 unsigned char *current
;
53 int nfilesystems
, space
;
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.
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
));
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
));
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
);
80 #elif defined PATH_PROC_MOUNTS
81 /* On Linux we hash /proc/mounts */
83 static unsigned char last
[20];
85 unsigned char *current
;
87 gcrypt_hash_handle h
= 0;
91 if((e
= gcry_md_open(&h
, GCRY_MD_SHA1
, 0))) {
92 disorder_error(0, "gcry_md_open: %s", gcry_strerror(e
));
95 if((fd
= open(PATH_PROC_MOUNTS
, O_RDONLY
)) < 0) {
96 disorder_error(errno
, "open %s", PATH_PROC_MOUNTS
);
100 n
= read(fd
, buffer
, sizeof buffer
);
102 gcry_md_write(h
, buffer
, n
);
105 else if(errno
!= EINTR
) {
106 disorder_error(errno
, "reading %s", PATH_PROC_MOUNTS
);
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
);
116 if(h
) gcry_md_close(h
);
117 if(fd
!= -1) close(fd
);
118 #elif defined PATH_MTAB
119 /* As a further alternative we track the modification time of /etc/mtab */
120 static time_t last_mount
;
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
;
131 void periodic_mount_check(ev_source
attribute((unused
)) *ev_
) {