159 lines
3.6 KiB
C
159 lines
3.6 KiB
C
/*
|
|
* nfs-server-generator:
|
|
* systemd generator to create ordering dependencies between
|
|
* nfs-server and various filesystem mounts
|
|
*
|
|
* 1/ nfs-server should start Before any 'nfs' mountpoints are
|
|
* mounted, in case they are loop-back mounts. This ordering is particularly
|
|
* important for the shutdown side, so the nfs-server is stopped
|
|
* after the filesystems are unmounted.
|
|
* 2/ nfs-server should start After all exported filesystems are mounted
|
|
* so there is no risk of exporting the underlying directory.
|
|
* This is particularly important for _net mounts which
|
|
* are not caught by "local-fs.target".
|
|
*/
|
|
|
|
#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 <alloca.h>
|
|
|
|
#include "misc.h"
|
|
#include "nfslib.h"
|
|
#include "exportfs.h"
|
|
#include "systemd.h"
|
|
|
|
/* A simple "set of strings" to remove duplicates
|
|
* found in /etc/exports
|
|
*/
|
|
struct list {
|
|
struct list *next;
|
|
char *name;
|
|
};
|
|
static int is_unique(struct list **lp, char *path)
|
|
{
|
|
struct list *l = *lp;
|
|
|
|
while (l) {
|
|
if (strcmp(l->name, path) == 0)
|
|
return 0;
|
|
l = l->next;
|
|
}
|
|
l = malloc(sizeof(*l));
|
|
if (l == NULL)
|
|
return 0;
|
|
l->name = path;
|
|
l->next = *lp;
|
|
*lp = l;
|
|
return 1;
|
|
}
|
|
|
|
static int has_noauto_flag(char *path)
|
|
{
|
|
FILE *fstab;
|
|
struct mntent *mnt;
|
|
|
|
fstab = setmntent("/etc/fstab", "r");
|
|
if (!fstab)
|
|
return 0;
|
|
|
|
while ((mnt = getmntent(fstab)) != NULL) {
|
|
int l = strlen(mnt->mnt_dir);
|
|
if (strncmp(mnt->mnt_dir, path, l) != 0)
|
|
continue;
|
|
if (path[l] && path[l] != '/')
|
|
continue;
|
|
if (hasmntopt(mnt, "noauto"))
|
|
break;
|
|
}
|
|
fclose(fstab);
|
|
return mnt != NULL;
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
char *path, *spath;
|
|
char dirbase[] = "/nfs-server.service.d";
|
|
char filebase[] = "/order-with-mounts.conf";
|
|
nfs_export *exp;
|
|
int i;
|
|
struct list *list = NULL;
|
|
FILE *f, *fstab;
|
|
struct mntent *mnt;
|
|
|
|
/* Avoid using any external services */
|
|
xlog_syslog(0);
|
|
|
|
if (argc != 4 || argv[1][0] != '/') {
|
|
fprintf(stderr, "nfs-server-generator: create systemd dependencies for nfs-server\n");
|
|
fprintf(stderr, "Usage: normal-dir early-dir late-dir\n");
|
|
exit(1);
|
|
}
|
|
|
|
path = alloca(strlen(argv[1]) + sizeof(dirbase) + sizeof(filebase));
|
|
if (!path)
|
|
exit(2);
|
|
if (export_read(_PATH_EXPORTS, 1) +
|
|
export_d_read(_PATH_EXPORTS_D, 1) == 0)
|
|
/* Nothing is exported, so nothing to do */
|
|
exit(0);
|
|
|
|
strcat(strcpy(path, argv[1]), dirbase);
|
|
mkdir(path, 0755);
|
|
strcat(path, filebase);
|
|
f = fopen(path, "w");
|
|
if (!f)
|
|
exit(1);
|
|
fprintf(f, "# Automatically generated by nfs-server-generator\n\n[Unit]\n");
|
|
|
|
for (i = 0; i < MCL_MAXTYPES; i++) {
|
|
for (exp = exportlist[i].p_head; exp; exp = exp->m_next) {
|
|
if (!is_unique(&list, exp->m_export.e_path))
|
|
continue;
|
|
if (exp->m_export.e_mountpoint)
|
|
continue;
|
|
if (has_noauto_flag(exp->m_export.e_path))
|
|
continue;
|
|
if (strchr(exp->m_export.e_path, ' '))
|
|
fprintf(f, "RequiresMountsFor=\"%s\"\n",
|
|
exp->m_export.e_path);
|
|
else
|
|
fprintf(f, "RequiresMountsFor=%s\n",
|
|
exp->m_export.e_path);
|
|
}
|
|
}
|
|
|
|
fstab = setmntent("/etc/fstab", "r");
|
|
if (!fstab)
|
|
exit(1);
|
|
|
|
while ((mnt = getmntent(fstab)) != NULL) {
|
|
if (strcmp(mnt->mnt_type, "nfs") != 0 &&
|
|
strcmp(mnt->mnt_type, "nfs4") != 0)
|
|
continue;
|
|
|
|
spath = systemd_escape(mnt->mnt_dir, ".mount");
|
|
if (!spath) {
|
|
fprintf(stderr,
|
|
"nfs-server-generator: convert path failed: %s\n",
|
|
mnt->mnt_dir);
|
|
continue;
|
|
}
|
|
fprintf(f, "Before=%s\n", spath);
|
|
}
|
|
|
|
fclose(fstab);
|
|
fclose(f);
|
|
|
|
exit(0);
|
|
}
|