/* This opens the rulesfile, but first checks for the lock, and if the file is opened sets the lock. Returns the pointer to the file, or NULL if failed. */ FILE * rules_file_open(const int debuglvl, const struct vuurmuur_config *cnf, const char *path, const char *mode, int caller) { FILE *lock_fp = NULL, *fp = NULL; char *lock_path = NULL; size_t i = 0, lockpath_len = 0; /* safety */ if(!path || !mode) { (void)vrprint.error(-1, "Internal Error", "parameter problem " "(in: %s:%d).", __FUNC__, __LINE__); return(NULL); } lockpath_len = strlen(path) + 6; if(lockpath_len == 0) return(NULL); if(!(lock_path = malloc(lockpath_len))) { (void)vrprint.error(-1, "Error", "malloc failed: %s " "(in: %s:%d).", strerror(errno), __FUNC__, __LINE__); return(NULL); } if(strlcpy(lock_path, path, lockpath_len) >= lockpath_len) { (void)vrprint.error(-1, "Error", "string overflow " "(in: %s:%d).", __FUNC__, __LINE__); free(lock_path); return(NULL); } if(strlcat(lock_path, ".LOCK", lockpath_len) >= lockpath_len) { (void)vrprint.error(-1, "Error", "string overflow " "(in: %s:%d).", __FUNC__, __LINE__); free(lock_path); return(NULL); } /* try to open the lockfile */ lock_fp = fopen(lock_path, "r"); if(lock_fp != NULL) { /* we are locked! enter wait loop */ (void)vrprint.warning("Warning", "rulesfile is locked, will try for 60 seconds."); for(i = 0; i < 60; i++) { /* close the lockfile */ if(fclose(lock_fp) < 0) return(NULL); lock_fp = fopen(lock_path, "r"); if(lock_fp != NULL) { /* we are still locked! */ sleep(1); } else break; } /* one last try */ lock_fp = fopen(lock_path, "r"); if(lock_fp != NULL) { (void)vrprint.error(-1, "Error", "opening rulesfile timed out, check if there was a crash."); fclose(lock_fp); free(lock_path); return(NULL); } } lock_fp = fopen(lock_path, "w"); if(!lock_fp) { (void)vrprint.error(-1, "Error", "creating lockfile failed: %s.", strerror(errno)); return(NULL); } else { fprintf(lock_fp, "%d\n", caller); fclose(lock_fp); free(lock_path); } fp = vuurmuur_fopen(debuglvl, cnf, path, mode); return(fp); }
int tell_textdir(void *backend, const char *name, const char *question, const char *answer, int overwrite, enum vrmr_objecttypes type) { int retval = 0; char *file_location = NULL; char line[512] = "", *line_ptr = NULL, *tmp_line_ptr = NULL; int i = 0, found = 0, skip = 0; FILE *fp = NULL; struct vrmr_list storelist; struct vrmr_list_node *d_node = NULL; assert(backend && name && question && answer); vrmr_debug(HIGH, "question: %s, answer: %s, name: %s, overwrite: %d, type: %d", question, answer, name, overwrite, type); struct textdir_backend *tb = (struct textdir_backend *)backend; if (!tb->backend_open) { vrmr_error(-1, "Error", "backend not opened yet"); return (-1); } /* only uppercase allowed */ while (question[i]) { if ((question[i] >= 'a') && (question[i] <= 'z')) return (-1); ++i; } if (!(file_location = get_filelocation(backend, name, type))) return (-1); /* first open the file for reading */ if (!(fp = vuurmuur_fopen(tb->cfg, file_location, "r"))) { vrmr_error(-1, "Error", "unable to open file '%s' for reading: %s.", file_location, strerror(errno)); free(file_location); return (-1); } /* initialize the store list */ vrmr_list_setup(&storelist, free); /* loop trough the current file */ while (fgets(line, MAX_LINE_LENGTH, fp) != NULL) { skip = 0; size_t line_size = sizeof(line); if (!(line_ptr = malloc(line_size))) { vrmr_error(-1, "Error", "malloc failed: %s", strerror(errno)); /* cleanup */ vrmr_list_cleanup(&storelist); free(file_location); fclose(fp); return (-1); } if (strncmp(question, line, strlen(question)) == 0 && line[strlen(question)] == '=') { if (overwrite && !found) { snprintf(line_ptr, line_size, "%s=\"%s\"\n", question, answer); found = 1; } else if (overwrite && found) { skip = 1; } else { (void)strlcpy(line_ptr, line, line_size); found = 1; } } else { (void)strlcpy(line_ptr, line, line_size); } /* now append the line to the storelist, except if we were told to skip this one. Then just free the data. */ if (!skip) { if (vrmr_list_append(&storelist, line_ptr) == NULL) { vrmr_error(-1, "Internal Error", "inserting line into temporary storage list failed"); /* cleanup */ vrmr_list_cleanup(&storelist); free(line_ptr); free(file_location); fclose(fp); return (-1); } } else { /* free and null */ free(line_ptr); line_ptr = NULL; } } /* if we are not overwriting and the type of data is already found somewhere, we try to insert is just below the last one. */ if (!overwrite && found) { if (!(line_ptr = malloc(sizeof(line)))) { vrmr_error(-1, "Error", "malloc failed: %s", strerror(errno)); /* cleanup */ vrmr_list_cleanup(&storelist); free(file_location); fclose(fp); return (-1); } /* assemble the line */ snprintf(line_ptr, sizeof(line), "%s=\"%s\"\n", question, answer); /* loop the list bottom up so we match the last one first */ for (d_node = storelist.bot; d_node; d_node = d_node->prev) { if (!(tmp_line_ptr = d_node->data)) { vrmr_error(-1, "Internal Error", "NULL pointer"); /* cleanup */ vrmr_list_cleanup(&storelist); free(file_location); free(line_ptr); fclose(fp); return (-1); } /* check if the line is the same. If so insert after it. */ if (strncmp(question, tmp_line_ptr, strlen(question)) == 0) { if (vrmr_list_insert_after(&storelist, d_node, line_ptr) == NULL) { vrmr_error(-1, "Internal Error", "inserting line into temporary storage list " "failed"); /* cleanup */ vrmr_list_cleanup(&storelist); free(file_location); free(line_ptr); fclose(fp); return (-1); } /* after inserting we're done */ line_ptr = NULL; break; } /* Don't free line_ptr yet, because it might be used again in the * next iteration */ } /* we no longer need these */ tmp_line_ptr = NULL; free(line_ptr); line_ptr = NULL; } /* if its not found, we insert it at the end of the list */ if (found == 0) { /* first alloc */ if (!(line_ptr = malloc(sizeof(line)))) { vrmr_error(-1, "Error", "malloc failed: %s.", strerror(errno)); /* cleanup */ vrmr_list_cleanup(&storelist); free(file_location); fclose(fp); return (-1); } snprintf(line_ptr, sizeof(line), "%s=\"%s\"\n", question, answer); /* append into the list */ if (vrmr_list_append(&storelist, line_ptr) == NULL) { vrmr_error(-1, "Internal Error", "inserting line into temporary storage list failed"); /* cleanup */ vrmr_list_cleanup(&storelist); free(file_location); free(line_ptr); fclose(fp); return (-1); } /* we no longer need this */ line_ptr = NULL; } /* close the file */ (void)fclose(fp); /* now open the file for writing */ if (!(fp = vuurmuur_fopen(tb->cfg, file_location, "w+"))) { vrmr_error(-1, "Error", "unable to open file '%s' for writing: %s", file_location, strerror(errno)); /* cleanup */ vrmr_list_cleanup(&storelist); free(file_location); return (-1); } /* print the list into the file */ for (d_node = storelist.top; d_node; d_node = d_node->next) { if (d_node->data == NULL) continue; fprintf(fp, "%s", (char *)d_node->data); } (void)fclose(fp); /* destroy the temp storage */ vrmr_list_cleanup(&storelist); free(file_location); return (retval); }