summaryrefslogtreecommitdiffstats
path: root/systemd/rpc-pipefs-generator.c
diff options
context:
space:
mode:
Diffstat (limited to 'systemd/rpc-pipefs-generator.c')
-rw-r--r--systemd/rpc-pipefs-generator.c152
1 files changed, 152 insertions, 0 deletions
diff --git a/systemd/rpc-pipefs-generator.c b/systemd/rpc-pipefs-generator.c
new file mode 100644
index 0000000..3aaeaea
--- /dev/null
+++ b/systemd/rpc-pipefs-generator.c
@@ -0,0 +1,152 @@
+/*
+ * rpc-pipefs-generator:
+ * systemd generator to create ordering dependencies between
+ * nfs services and the rpc_pipefs mountpoint
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <mntent.h>
+
+#include "nfslib.h"
+#include "conffile.h"
+#include "systemd.h"
+
+#define RPC_PIPEFS_DEFAULT NFS_STATEDIR "/rpc_pipefs"
+
+static int generate_mount_unit(const char *pipefs_path, const char *pipefs_unit,
+ const char *dirname)
+{
+ char *path;
+ FILE *f;
+ size_t size = (strlen(dirname) + 1 + strlen(pipefs_unit) + 1);
+
+ path = malloc(size);
+ if (!path)
+ return 1;
+ snprintf(path, size, "%s/%s", dirname, pipefs_unit);
+ f = fopen(path, "w");
+ if (!f)
+ {
+ free(path);
+ return 1;
+ }
+
+ fprintf(f, "# Automatically generated by rpc-pipefs-generator\n\n[Unit]\n");
+ fprintf(f, "Description=RPC Pipe File System\n");
+ fprintf(f, "DefaultDependencies=no\n");
+ fprintf(f, "After=systemd-tmpfiles-setup.service\n");
+ fprintf(f, "Conflicts=umount.target\n");
+ fprintf(f, "\n[Mount]\n");
+ fprintf(f, "What=sunrpc\n");
+ fprintf(f, "Where=%s\n", pipefs_path);
+ fprintf(f, "Type=rpc_pipefs\n");
+
+ fclose(f);
+ free(path);
+ return 0;
+}
+
+static
+int generate_target(char *pipefs_path, const char *dirname)
+{
+ char *path;
+ char filebase[] = "/rpc_pipefs.target";
+ char *pipefs_unit;
+ FILE *f;
+ int ret = 0;
+
+ pipefs_unit = systemd_escape(pipefs_path, ".mount");
+ if (!pipefs_unit)
+ return 1;
+
+ ret = generate_mount_unit(pipefs_path, pipefs_unit, dirname);
+ if (ret) {
+ free(pipefs_unit);
+ return ret;
+ }
+
+ path = malloc(strlen(dirname) + 1 + sizeof(filebase));
+ if (!path) {
+ free(pipefs_unit);
+ return 2;
+ }
+ sprintf(path, "%s", dirname);
+ mkdir(path, 0755);
+ strcat(path, filebase);
+ f = fopen(path, "w");
+ if (!f)
+ {
+ free(path);
+ free(pipefs_unit);
+ return 1;
+ }
+
+ fprintf(f, "# Automatically generated by rpc-pipefs-generator\n\n[Unit]\n");
+ fprintf(f, "Requires=%s\n", pipefs_unit);
+ fprintf(f, "After=%s\n", pipefs_unit);
+ fclose(f);
+ free(path);
+ free(pipefs_unit);
+
+ return 0;
+}
+
+static int is_non_pipefs_mountpoint(char *path)
+{
+ FILE *mtab;
+ struct mntent *mnt;
+
+ mtab = setmntent("/etc/mtab", "r");
+ if (!mtab)
+ return 0;
+
+ while ((mnt = getmntent(mtab)) != NULL) {
+ if (strlen(mnt->mnt_dir) != strlen(path))
+ continue;
+ if (strncmp(mnt->mnt_dir, path, strlen(mnt->mnt_dir)))
+ continue;
+ if (strncmp(mnt->mnt_type, "rpc_pipefs", strlen(mnt->mnt_type)))
+ break;
+ }
+ fclose(mtab);
+ return mnt != NULL;
+}
+
+int main(int argc, char *argv[])
+{
+ int ret;
+ char *s;
+
+ /* Avoid using any external services */
+ xlog_syslog(0);
+
+ if (argc != 4 || argv[1][0] != '/') {
+ fprintf(stderr, "rpc-pipefs-generator: create systemd dependencies for nfs services\n");
+ fprintf(stderr, "Usage: normal-dir early-dir late-dir\n");
+ exit(1);
+ }
+
+ conf_init_file(NFS_CONFFILE);
+ s = conf_get_str("general", "pipefs-directory");
+ if (!s)
+ exit(0);
+ if (strlen(s) == strlen(RPC_PIPEFS_DEFAULT) &&
+ strcmp(s, RPC_PIPEFS_DEFAULT) == 0)
+ exit(0);
+
+ if (is_non_pipefs_mountpoint(s))
+ exit(1);
+
+ ret = generate_target(s, argv[1]);
+ exit(ret);
+}