summaryrefslogtreecommitdiffstats
path: root/utils/nfsdcld/legacy.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 06:03:02 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 06:03:02 +0000
commit4897093455a2bf08f3db3a1132cc2f6f5484d77c (patch)
tree9e6373544263f003139431fb4b08f9766e1ed530 /utils/nfsdcld/legacy.c
parentInitial commit. (diff)
downloadnfs-utils-4897093455a2bf08f3db3a1132cc2f6f5484d77c.tar.xz
nfs-utils-4897093455a2bf08f3db3a1132cc2f6f5484d77c.zip
Adding upstream version 1:2.6.4.upstream/1%2.6.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'utils/nfsdcld/legacy.c')
-rw-r--r--utils/nfsdcld/legacy.c171
1 files changed, 171 insertions, 0 deletions
diff --git a/utils/nfsdcld/legacy.c b/utils/nfsdcld/legacy.c
new file mode 100644
index 0000000..b89374c
--- /dev/null
+++ b/utils/nfsdcld/legacy.c
@@ -0,0 +1,171 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <dirent.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <limits.h>
+#include "cld.h"
+#include "sqlite.h"
+#include "xlog.h"
+#include "legacy.h"
+
+#define NFSD_RECDIR_FILE "/proc/fs/nfsd/nfsv4recoverydir"
+
+/*
+ * Loads client records from the v4recovery directory into the database.
+ * Records are prefixed with the string "hash:" and include the '\0' byte.
+ *
+ * Called during database initialization as part of a one-time "upgrade".
+ */
+void
+legacy_load_clients_from_recdir(int *num_records)
+{
+ int fd;
+ DIR *v4recovery;
+ struct dirent *entry;
+ char recdirname[PATH_MAX+1];
+ char buf[NFS4_OPAQUE_LIMIT];
+ char *nl;
+ ssize_t n;
+
+ fd = open(NFSD_RECDIR_FILE, O_RDONLY);
+ if (fd < 0) {
+ xlog(D_GENERAL, "Unable to open %s: %m", NFSD_RECDIR_FILE);
+ return;
+ }
+ n = read(fd, recdirname, PATH_MAX);
+ close(fd);
+ if (n < 0) {
+ xlog(D_GENERAL, "Unable to read from %s: %m", NFSD_RECDIR_FILE);
+ return;
+ }
+ /* the output from the proc file isn't null-terminated */
+ recdirname[PATH_MAX] = '\0';
+ nl = strchr(recdirname, '\n');
+ if (!nl)
+ return;
+ *nl = '\0';
+ v4recovery = opendir(recdirname);
+ if (!v4recovery)
+ return;
+ while ((entry = readdir(v4recovery))) {
+ int ret;
+
+ /* skip "." and ".." */
+ if (entry->d_name[0] == '.') {
+ switch (entry->d_name[1]) {
+ case '\0':
+ continue;
+ case '.':
+ if (entry->d_name[2] == '\0')
+ continue;
+ }
+ }
+ /* prefix legacy records with the string "hash:" */
+ ret = snprintf(buf, sizeof(buf), "hash:%s", entry->d_name);
+ /* if there's a problem, then skip this entry */
+ if (ret < 0 || (size_t)ret >= sizeof(buf)) {
+ xlog(L_WARNING, "%s: unable to build client string for %s!",
+ __func__, entry->d_name);
+ continue;
+ }
+ /* legacy client records need to include the null terminator */
+ ret = sqlite_insert_client((unsigned char *)buf, strlen(buf) + 1);
+ if (ret)
+ xlog(L_WARNING, "%s: unable to insert %s: %d", __func__,
+ entry->d_name, ret);
+ else
+ (*num_records)++;
+ }
+ closedir(v4recovery);
+}
+
+/*
+ * Cleans out the v4recovery directory.
+ *
+ * Called upon receipt of the first "GraceDone" upcall only.
+ */
+void
+legacy_clear_recdir(void)
+{
+ int fd;
+ DIR *v4recovery;
+ struct dirent *entry;
+ char recdirname[PATH_MAX+1];
+ char dirname[PATH_MAX];
+ char *nl;
+ ssize_t n;
+
+ fd = open(NFSD_RECDIR_FILE, O_RDONLY);
+ if (fd < 0) {
+ xlog(D_GENERAL, "Unable to open %s: %m", NFSD_RECDIR_FILE);
+ return;
+ }
+ n = read(fd, recdirname, PATH_MAX);
+ close(fd);
+ if (n < 0) {
+ xlog(D_GENERAL, "Unable to read from %s: %m", NFSD_RECDIR_FILE);
+ return;
+ }
+ /* the output from the proc file isn't null-terminated */
+ recdirname[PATH_MAX] = '\0';
+ nl = strchr(recdirname, '\n');
+ if (!nl)
+ return;
+ *nl = '\0';
+ v4recovery = opendir(recdirname);
+ if (!v4recovery)
+ return;
+ while ((entry = readdir(v4recovery))) {
+ int len;
+
+ /* skip "." and ".." */
+ if (entry->d_name[0] == '.') {
+ switch (entry->d_name[1]) {
+ case '\0':
+ continue;
+ case '.':
+ if (entry->d_name[2] == '\0')
+ continue;
+ }
+ }
+ len = snprintf(dirname, sizeof(dirname), "%s/%s", recdirname,
+ entry->d_name);
+ /* if there's a problem, then skip this entry */
+ if (len < 0 || (size_t)len >= sizeof(dirname)) {
+ xlog(L_WARNING, "%s: unable to build filename for %s!",
+ __func__, entry->d_name);
+ continue;
+ }
+ len = rmdir(dirname);
+ if (len)
+ xlog(L_WARNING, "%s: unable to rmdir %s: %d", __func__,
+ dirname, len);
+ }
+ closedir(v4recovery);
+}