/** * 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; }
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; }
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); }