示例#1
0
/**
 * nsm_retire_monitored_hosts - back up all hosts from "sm/" to "sm.bak/"
 *
 * Returns the count of host records that were moved.
 *
 * Note that if any error occurs during this process, some monitor
 * records may be left in the "sm" directory.
 */
unsigned int
nsm_retire_monitored_hosts(void)
{
	unsigned int count = 0;
	struct dirent *de;
	char *path;
	DIR *dir;

	path = nsm_make_pathname(NSM_MONITOR_DIR);
	if (path == NULL) {
		xlog(L_ERROR, "Failed to allocate path for " NSM_MONITOR_DIR);
		return count;
	}

	dir = opendir(path);
	free(path);
	if (dir == NULL) {
		xlog_warn("Failed to open " NSM_MONITOR_DIR ": %m");
		return count;
	}

	while ((de = readdir(dir)) != NULL) {
		char *src, *dst;

		if (de->d_type != (unsigned char)DT_REG)
			continue;
		if (de->d_name[0] == '.')
			continue;

		src = nsm_make_record_pathname(NSM_MONITOR_DIR, de->d_name);
		if (src == NULL) {
			xlog_warn("Bad monitor file name, skipping");
			continue;
		}

		dst = nsm_make_record_pathname(NSM_NOTIFY_DIR, de->d_name);
		if (dst == NULL) {
			free(src);
			xlog_warn("Bad notify file name, skipping");
			continue;
		}

		if (rename(src, dst) == -1)
			xlog_warn("Failed to rename %s -> %s: %m",
				src, dst);
		else {
			xlog(D_GENERAL, "Retired record for mon_name %s",
					de->d_name);
			count++;
		}

		free(dst);
		free(src);
	}

	(void)closedir(dir);
	return count;
}
示例#2
0
/**
 * nsm_insert_monitored_host - write callback data for one host to disk
 * @hostname: C string containing a hostname
 * @sap: sockaddr containing NLM callback address
 * @mon: SM_MON arguments to save
 *
 * Returns true if successful, otherwise false if some error occurs.
 */
_Bool
nsm_insert_monitored_host(const char *hostname, const struct sockaddr *sap,
		const struct mon *m)
{
	static char buf[LINELEN + 1 + SM_MAXSTRLEN + 2];
	char *path;
	_Bool result = false;
	ssize_t len;
	size_t size;
	int fd;

	path = nsm_make_record_pathname(NSM_MONITOR_DIR, hostname);
	if (path == NULL) {
		xlog(L_ERROR, "Failed to insert: bad monitor hostname '%s'",
				hostname);
		return false;
	}

	size = nsm_create_monitor_record(buf, sizeof(buf), sap, m);
	if (size == 0) {
		xlog(L_ERROR, "Failed to insert: record too long");
		goto out;
	}

	/*
	 * If exclusive create fails, we're adding a new line to an
	 * existing file.
	 */
	fd = open(path, O_WRONLY | O_CREAT | O_EXCL | O_SYNC, S_IRUSR | S_IWUSR);
	if (fd == -1) {
		if (errno != EEXIST) {
			xlog(L_ERROR, "Failed to insert: creating %s: %m", path);
			goto out;
		}

		result = nsm_append_monitored_host(path, buf);
		goto out;
	}
	result = true;

	len = write(fd, buf, size);
	if (exact_error_check(len, size)) {
		xlog_warn("Failed to insert: writing %s: %m", path);
		(void)unlink(path);
		result = false;
	}

	if (close(fd) == -1) {
		xlog(L_ERROR, "Failed to insert: closing %s: %m", path);
		(void)unlink(path);
		result = false;
	}

out:
	free(path);
	return result;
}
示例#3
0
/*
 * Given a filename, reads data from a file under "directory"
 * and invokes @func so caller can populate their in-core
 * database with this data.
 */
static unsigned int
nsm_load_host(const char *directory, const char *filename, nsm_populate_t func)
{
	char buf[LINELEN + 1 + SM_MAXSTRLEN + 2];
	unsigned int result = 0;
	struct stat stb;
	char *path;
	FILE *f;

	path = nsm_make_record_pathname(directory, filename);
	if (path == NULL)
		goto out_err;

	if (lstat(path, &stb) == -1) {
		xlog(L_ERROR, "Failed to stat %s: %m", path);
		goto out_freepath;
	}
	if (!S_ISREG(stb.st_mode)) {
		xlog(D_GENERAL, "Skipping non-regular file %s",
				path);
		goto out_freepath;
	}

	f = fopen(path, "r");
	if (f == NULL) {
		xlog(L_ERROR, "Failed to open %s: %m", path);
		goto out_freepath;
	}

	while (fgets(buf, (int)sizeof(buf), f) != NULL) {
		buf[sizeof(buf) - 1] = '\0';
		result += nsm_read_line(filename, stb.st_mtime, buf, func);
	}
	if (result == 0)
		xlog(L_ERROR, "Failed to read monitor data from %s", path);

	(void)fclose(f);

out_freepath:
	free(path);
out_err:
	return result;
}
示例#4
0
/**
 * nsm_retire_monitored_hosts - back up all hosts from "sm/" to "sm.bak/"
 *
 * Returns the count of host records that were moved.
 *
 * Note that if any error occurs during this process, some monitor
 * records may be left in the "sm" directory.
 */
unsigned int
nsm_retire_monitored_hosts(void)
{
	unsigned int count = 0;
	struct dirent *de;
	char *path;
	DIR *dir;

	path = nsm_make_pathname(NSM_MONITOR_DIR);
	if (path == NULL) {
		xlog(L_ERROR, "Failed to allocate path for " NSM_MONITOR_DIR);
		return count;
	}

	dir = opendir(path);
	free(path);
	if (dir == NULL) {
		xlog_warn("Failed to open " NSM_MONITOR_DIR ": %m");
		return count;
	}

	while ((de = readdir(dir)) != NULL) {
		char *src, *dst;
		struct stat stb;

		if (de->d_name[0] == '.')
			continue;

		src = nsm_make_record_pathname(NSM_MONITOR_DIR, de->d_name);
		if (src == NULL) {
			xlog_warn("Bad monitor file name, skipping");
			continue;
		}

		/* NB: not all file systems fill in d_type correctly */
		if (lstat(src, &stb) == -1) {
			xlog_warn("Bad monitor file %s, skipping: %m",
					de->d_name);
			free(src);
			continue;
		}
		if (!S_ISREG(stb.st_mode)) {
			xlog(D_GENERAL, "Skipping non-regular file %s",
					de->d_name);
			free(src);
			continue;
		}

		dst = nsm_make_record_pathname(NSM_NOTIFY_DIR, de->d_name);
		if (dst == NULL) {
			free(src);
			xlog_warn("Bad notify file name, skipping");
			continue;
		}

		if (rename(src, dst) == -1)
			xlog_warn("Failed to rename %s -> %s: %m",
				src, dst);
		else {
			xlog(D_GENERAL, "Retired record for mon_name %s",
					de->d_name);
			count++;
		}

		free(dst);
		free(src);
	}

	(void)closedir(dir);
	return count;
}
示例#5
0
static void
nsm_delete_host(const char *directory, const char *hostname,
		const char *mon_name, const char *my_name)
{
	char line[LINELEN + 1 + SM_MAXSTRLEN + 2];
	char *outbuf = NULL;
	struct stat stb;
	char *path, *next;
	size_t remaining;
	FILE *f;

	path = nsm_make_record_pathname(directory, hostname);
	if (path == NULL) {
		xlog(L_ERROR, "Bad filename, not deleting");
		return;
	}

	if (stat(path, &stb) == -1) {
		xlog(L_ERROR, "Failed to delete: "
			"could not stat original file %s: %m", path);
		goto out;
	}
	remaining = (size_t)stb.st_size + 1;

	outbuf = malloc(remaining);
	if (outbuf == NULL) {
		xlog(L_ERROR, "Failed to delete: no memory");
		goto out;
	}

	f = fopen(path, "r");
	if (f == NULL) {
		xlog(L_ERROR, "Failed to delete: "
			"could not open original file %s: %m", path);
		goto out;
	}

	/*
	 * Walk the records in the file, and copy the non-matching
	 * ones to our output buffer.
	 */
	next = outbuf;
	while (fgets(line, (int)sizeof(line), f) != NULL) {
		struct sockaddr_in sin;
		struct mon m;
		size_t len;

		if (!nsm_parse_line(line, &sin, &m)) {
			xlog(L_ERROR, "Failed to delete: "
				"could not parse original file %s", path);
			(void)fclose(f);
			goto out;
		}

		if (strcmp(mon_name, m.mon_id.mon_name) == 0 &&
			 strcmp(my_name, m.mon_id.my_id.my_name) == 0)
			continue;

		/* nsm_parse_line destroys the contents of line[], so
		 * reconstruct the copy in our output buffer. */
		len = nsm_create_monitor_record(next, remaining,
					(struct sockaddr *)(char *)&sin, &m);
		if (len == 0) {
			xlog(L_ERROR, "Failed to delete: "
				"could not construct output record");
			(void)fclose(f);
			goto out;
		}
		next += len;
		remaining -= len;
	}

	(void)fclose(f);

	/*
	 * If nothing was copied when we're done, then unlink the file.
	 * Otherwise, atomically update the contents of the file.
	 */
	if (next != outbuf) {
		if (!nsm_atomic_write(path, outbuf, strlen(outbuf)))
			xlog(L_ERROR, "Failed to delete: "
				"could not write new file %s: %m", path);
	} else {
		if (unlink(path) == -1)
			xlog(L_ERROR, "Failed to delete: "
				"could not unlink file %s: %m", path);
	}

out:
	free(outbuf);
	free(path);
}