Ejemplo n.º 1
0
/**
 * nsm_update_kernel_state - attempt to post new NSM state to kernel
 * @state: NSM state number
 *
 */
void
nsm_update_kernel_state(const int state)
{
	ssize_t result;
	char buf[20];
	int fd, len;

	fd = open(NSM_KERNEL_STATE_FILE, O_WRONLY);
	if (fd == -1) {
		xlog(D_GENERAL, "Failed to open " NSM_KERNEL_STATE_FILE ": %m");
		return;
	}

	len = snprintf(buf, sizeof(buf), "%d", state);
	if (error_check(len, sizeof(buf))) {
		xlog_warn("Failed to form NSM state number string");
		return;
	}

	result = write(fd, buf, strlen(buf));
	if (exact_error_check(result, strlen(buf)))
		xlog_warn("Failed to write NSM state number: %m");

	if (close(fd) == -1)
		xlog(L_ERROR, "Failed to close NSM state file "
				NSM_KERNEL_STATE_FILE ": %m");
}
Ejemplo n.º 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;
}
Ejemplo n.º 3
0
/**
 * nsm_get_state - retrieve on-disk NSM state number
 *
 * Returns an odd NSM state number read from disk, or an initial
 * state number.  Zero is returned if some error occurs.
 */
int
nsm_get_state(_Bool update)
{
	int fd, state = 0;
	ssize_t result;
	char *path = NULL;

	path = nsm_make_pathname(NSM_STATE_FILE);
	if (path == NULL) {
		xlog(L_ERROR, "Failed to allocate path for " NSM_STATE_FILE);
		goto out;
	}

	fd = open(path, O_RDONLY);
	if (fd == -1) {
		if (errno != ENOENT) {
			xlog(L_ERROR, "Failed to open %s: %m", path);
			goto out;
		}

		xlog(L_NOTICE, "Initializing NSM state");
		state = 1;
		update = true;
		goto update;
	}

	result = read(fd, &state, sizeof(state));
	if (exact_error_check(result, sizeof(state))) {
		xlog_warn("Failed to read %s: %m", path);

		xlog(L_NOTICE, "Initializing NSM state");
		state = 1;
		update = true;
		goto update;
	}

	if ((state & 1) == 0)
		state++;

update:
	if(fd >= 0)
		(void)close(fd);

	if (update) {
		state += 2;
		if (!nsm_atomic_write(path, &state, sizeof(state)))
			state = 0;
	}

out:
	free(path);
	return state;
}
Ejemplo n.º 4
0
/*
 * Use "mktemp, write, rename" to update the contents of a file atomically.
 *
 * Returns true if completely successful, or false if some error occurred.
 */
static _Bool
nsm_atomic_write(const char *path, const void *buf, const size_t buflen)
{
	_Bool result = false;
	ssize_t len;
	char *temp;
	int fd;

	temp = nsm_make_temp_pathname(path);
	if (temp == NULL) {
		xlog(L_ERROR, "Failed to create new path for %s", path);
		goto out;
	}

	fd = open(temp, O_CREAT | O_TRUNC | O_SYNC | O_WRONLY, 0644);
	if (fd == -1) {
		xlog(L_ERROR, "Failed to create %s: %m", temp);
		goto out;
	}

	len = write(fd, buf, buflen);
	if (exact_error_check(len, buflen)) {
		xlog(L_ERROR, "Failed to write %s: %m", temp);
		(void)close(fd);
		(void)unlink(temp);
		goto out;
	}

	if (close(fd) == -1) {
		xlog(L_ERROR, "Failed to close %s: %m", temp);
		(void)unlink(temp);
		goto out;
	}

	if (rename(temp, path) == -1) {
		xlog(L_ERROR, "Failed to rename %s -> %s: %m",
				temp, path);
		(void)unlink(temp);
		goto out;
	}

	/* Ostensibly, a sync(2) is not needed here because
	 * open(O_CREAT), write(O_SYNC), and rename(2) are
	 * already synchronous with persistent storage, for
	 * any file system we care about. */

	result = true;

out:
	free(temp);
	return result;
}
Ejemplo n.º 5
0
static _Bool
nsm_append_monitored_host(const char *path, const char *line)
{
	_Bool result = false;
	char *buf = NULL;
	struct stat stb;
	size_t buflen;
	ssize_t len;
	int fd;

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

	buf = malloc(buflen + 1);
	if (buf == NULL) {
		xlog(L_ERROR, "Failed to insert: no memory");
		goto out;
	}
	memset(buf, 0, buflen + 1);

	fd = open(path, O_RDONLY);
	if (fd == -1) {
		xlog(L_ERROR, "Failed to insert: "
			"could not open original file %s: %m", path);
		goto out;
	}

	len = read(fd, buf, (size_t)stb.st_size);
	if (exact_error_check(len, (size_t)stb.st_size)) {
		xlog(L_ERROR, "Failed to insert: "
			"could not read original file %s: %m", path);
		(void)close(fd);
		goto out;
	}
	(void)close(fd);

	strcat(buf, line);

	if (nsm_atomic_write(path, buf, buflen))
		result = true;

out:
	free(buf);
	return result;
}