📄 dpkg.c
字号:
return;}void free_package(common_node_t *node){ int i; if (node != NULL) { for (i = 0; i < node->num_of_edges; i++) { if (node->edge[i] != NULL) { free(node->edge[i]); } } if (node->edge != NULL) { free(node->edge); } if (node != NULL) { free(node); } }}unsigned int fill_package_struct(char *control_buffer){ common_node_t *new_node = (common_node_t *) xcalloc(1, sizeof(common_node_t)); char **field_name = xmalloc(sizeof(char *)); char **field_value = xmalloc(sizeof(char *)); int field_start = 0; int num = -1; int buffer_length = strlen(control_buffer); new_node->version = search_name_hashtable("unknown"); while (field_start < buffer_length) { field_start += read_package_field(&control_buffer[field_start], field_name, field_value); if (*field_name == NULL) { goto fill_package_struct_cleanup; // Oh no, the dreaded goto statement !! } if (strcmp(*field_name, "Package") == 0) { new_node->name = search_name_hashtable(*field_value); } else if (strcmp(*field_name, "Version") == 0) { new_node->version = search_name_hashtable(*field_value); } else if (strcmp(*field_name, "Pre-Depends") == 0) { add_split_dependencies(new_node, *field_value, EDGE_PRE_DEPENDS); } else if (strcmp(*field_name, "Depends") == 0) { add_split_dependencies(new_node, *field_value, EDGE_DEPENDS); } else if (strcmp(*field_name, "Replaces") == 0) { add_split_dependencies(new_node, *field_value, EDGE_REPLACES); } else if (strcmp(*field_name, "Provides") == 0) { add_split_dependencies(new_node, *field_value, EDGE_PROVIDES); } else if (strcmp(*field_name, "Conflicts") == 0) { add_split_dependencies(new_node, *field_value, EDGE_CONFLICTS); } else if (strcmp(*field_name, "Suggests") == 0) { add_split_dependencies(new_node, *field_value, EDGE_SUGGESTS); } else if (strcmp(*field_name, "Recommends") == 0) { add_split_dependencies(new_node, *field_value, EDGE_RECOMMENDS); } else if (strcmp(*field_name, "Enhances") == 0) { add_split_dependencies(new_node, *field_value, EDGE_ENHANCES); }fill_package_struct_cleanup: if (*field_name) { free(*field_name); } if (*field_value) { free(*field_value); } } free(field_name); free(field_value); if (new_node->version == search_name_hashtable("unknown")) { free_package(new_node); return(-1); } num = search_package_hashtable(new_node->name, new_node->version, VER_EQUAL); if (package_hashtable[num] == NULL) { package_hashtable[num] = new_node; } else { free_package(new_node); } return(num);}/* if num = 1, it returns the want status, 2 returns flag, 3 returns status */unsigned int get_status(const unsigned int status_node, const int num){ char *status_string = name_hashtable[status_hashtable[status_node]->status]; char *state_sub_string; unsigned int state_sub_num; int len; int i; /* set tmp_string to point to the start of the word number */ for (i = 1; i < num; i++) { /* skip past a word */ status_string += strcspn(status_string, " "); /* skip past the seperating spaces */ status_string += strspn(status_string, " "); } len = strcspn(status_string, " \n\0"); state_sub_string = xstrndup(status_string, len); state_sub_num = search_name_hashtable(state_sub_string); free(state_sub_string); return(state_sub_num);}void set_status(const unsigned int status_node_num, const char *new_value, const int position){ const unsigned int new_value_len = strlen(new_value); const unsigned int new_value_num = search_name_hashtable(new_value); unsigned int want = get_status(status_node_num, 1); unsigned int flag = get_status(status_node_num, 2); unsigned int status = get_status(status_node_num, 3); int want_len = strlen(name_hashtable[want]); int flag_len = strlen(name_hashtable[flag]); int status_len = strlen(name_hashtable[status]); char *new_status; switch (position) { case (1): want = new_value_num; want_len = new_value_len; break; case (2): flag = new_value_num; flag_len = new_value_len; break; case (3): status = new_value_num; status_len = new_value_len; break; default: error_msg_and_die("DEBUG ONLY: this shouldnt happen"); } new_status = (char *) xmalloc(want_len + flag_len + status_len + 3); sprintf(new_status, "%s %s %s", name_hashtable[want], name_hashtable[flag], name_hashtable[status]); status_hashtable[status_node_num]->status = search_name_hashtable(new_status); free(new_status); return;}void index_status_file(const char *filename){ FILE *status_file; char *control_buffer; char *status_line; status_node_t *status_node = NULL; unsigned int status_num; status_file = xfopen(filename, "r"); while ((control_buffer = fgets_str(status_file, "\n\n")) != NULL) { const unsigned int package_num = fill_package_struct(control_buffer); if (package_num != -1) { status_node = xmalloc(sizeof(status_node_t)); /* fill_package_struct doesnt handle the status field */ status_line = strstr(control_buffer, "Status:"); if (status_line != NULL) { status_line += 7; status_line += strspn(status_line, " \n\t"); status_line = xstrndup(status_line, strcspn(status_line, "\n\0")); status_node->status = search_name_hashtable(status_line); free(status_line); } status_node->package = package_num; status_num = search_status_hashtable(name_hashtable[package_hashtable[status_node->package]->name]); status_hashtable[status_num] = status_node; } free(control_buffer); } fclose(status_file); return;}char *get_depends_field(common_node_t *package, const int depends_type){ char *depends = NULL; char *old_sep = (char *)xcalloc(1, 3); char *new_sep = (char *)xcalloc(1, 3); int line_size = 0; int depends_size; int i; for (i = 0; i < package->num_of_edges; i++) { if ((package->edge[i]->type == EDGE_OR_PRE_DEPENDS) || (package->edge[i]->type == EDGE_OR_DEPENDS)) { } if ((package->edge[i]->type == depends_type) || (package->edge[i]->type == depends_type + 1)) { /* Check if its the first time through */ depends_size = 8 + strlen(name_hashtable[package->edge[i]->name]) + strlen(name_hashtable[package->edge[i]->version]); line_size += depends_size; depends = (char *) xrealloc(depends, line_size + 1); /* Check to see if this dependency is the type we are looking for * +1 to check for 'extra' types, e.g. ored dependecies */ strcpy(old_sep, new_sep); if (package->edge[i]->type == depends_type) { strcpy(new_sep, ", "); } else if (package->edge[i]->type == depends_type + 1) { strcpy(new_sep, "| "); } if (depends_size == line_size) { strcpy(depends, ""); } else { if ((strcmp(old_sep, "| ") == 0) && (strcmp(new_sep, "| ") == 0)) { strcat(depends, " | "); } else { strcat(depends, ", "); } } strcat(depends, name_hashtable[package->edge[i]->name]); if (strcmp(name_hashtable[package->edge[i]->version], "NULL") != 0) { if (package->edge[i]->operator == VER_EQUAL) { strcat(depends, " (= "); } else if (package->edge[i]->operator == VER_LESS) { strcat(depends, " (<< "); } else if (package->edge[i]->operator == VER_LESS_EQUAL) { strcat(depends, " (<= "); } else if (package->edge[i]->operator == VER_MORE) { strcat(depends, " (>> "); } else if (package->edge[i]->operator == VER_MORE_EQUAL) { strcat(depends, " (>= "); } else { strcat(depends, " ("); } strcat(depends, name_hashtable[package->edge[i]->version]); strcat(depends, ")"); } } } return(depends);}void write_buffer_no_status(FILE *new_status_file, const char *control_buffer){ char *name; char *value; int start = 0; while (1) { start += read_package_field(&control_buffer[start], &name, &value); if (name == NULL) { break; } if (strcmp(name, "Status") != 0) { fprintf(new_status_file, "%s: %s\n", name, value); } } return;}/* This could do with a cleanup */void write_status_file(deb_file_t **deb_file){ FILE *old_status_file = xfopen("/var/lib/dpkg/status", "r"); FILE *new_status_file = xfopen("/var/lib/dpkg/status.udeb", "w"); char *package_name; char *status_from_file; char *control_buffer = NULL; char *tmp_string; int status_num; int field_start = 0; int write_flag; int i = 0; /* Update previously known packages */ while ((control_buffer = fgets_str(old_status_file, "\n\n")) != NULL) { tmp_string = strstr(control_buffer, "Package:") + 8; tmp_string += strspn(tmp_string, " \n\t"); package_name = xstrndup(tmp_string, strcspn(tmp_string, "\n\0")); write_flag = FALSE; tmp_string = strstr(control_buffer, "Status:"); if (tmp_string != NULL) { /* Seperate the status value from the control buffer */ tmp_string += 7; tmp_string += strspn(tmp_string, " \n\t"); status_from_file = xstrndup(tmp_string, strcspn(tmp_string, "\n")); } else { status_from_file = NULL; } /* Find this package in the status hashtable */ status_num = search_status_hashtable(package_name); if (status_hashtable[status_num] != NULL) { const char *status_from_hashtable = name_hashtable[status_hashtable[status_num]->status]; if (strcmp(status_from_file, status_from_hashtable) != 0) { /* New status isnt exactly the same as old status */ const int state_status = get_status(status_num, 3); if ((strcmp("installed", name_hashtable[state_status]) == 0) || (strcmp("unpacked", name_hashtable[state_status]) == 0)) { /* We need to add the control file from the package */ i = 0; while(deb_file[i] != NULL) { if (strcmp(package_name, name_hashtable[package_hashtable[deb_file[i]->package]->name]) == 0) { /* Write a status file entry with a modified status */ /* remove trailing \n's */ write_buffer_no_status(new_status_file, deb_file[i]->control_file); set_status(status_num, "ok", 2); fprintf(new_status_file, "Status: %s\n\n", name_hashtable[status_hashtable[status_num]->status]); write_flag = TRUE; break; } i++; } /* This is temperary, debugging only */ if (deb_file[i] == NULL) { error_msg_and_die("ALERT: Couldnt find a control file, your status file may be broken, status may be incorrect for %s", package_name); } } else if (strcmp("not-installed", name_hashtable[state_status]) == 0) { /* Only write the Package, Status, Priority and Section lines */ fprintf(new_status_file, "Package: %s\n", package_name); fprintf(new_status_file, "Status: %s\n", status_from_hashtable); while (1) { char *field_name; char *field_value; field_start += read_package_field(&control_buffer[field_start], &field_name, &field_value); if (field_name == NULL) { break; } if ((strcmp(field_name, "Priority") == 0) || (strcmp(field_name, "Section") == 0)) { fprintf(new_status_file, "%s: %s\n", field_name, field_value); } } write_flag = TRUE; fputs("\n", new_status_file); } else if (strcmp("config-files", name_hashtable[state_status]) == 0) { /* only change the status line */ while (1) { char *field_name; char *field_value; field_start += read_package_field(&control_buffer[field_start], &field_name, &field_value); if (field_name == NULL) { break; } /* Setup start point for next field */ if (strcmp(field_name, "Status") == 0) { fprintf(new_status_file, "Status: %s\n", status_from_hashtable); } else { fprintf(new_status_file, "%s: %s\n", field_name, field_value); } } write_flag = TRUE; fputs("\n", new_status_file); } } } /* If the package from the status file wasnt handle above, do it now*/ if (write_flag == FALSE) { fprintf(new_status_file, "%s\n\n", control_buffer); } if (status_from_file != NULL) { free(status_from_file); } free(package_name); free(control_buffer); } /* Write any new packages */ for(i = 0; deb_file[i] != NULL; i++) { status_num = search_status_hashtable(name_hashtable[package_hashtable[deb_file[i]->package]->name]); if (strcmp("reinstreq", name_hashtable[get_status(status_num, 2)]) == 0) { write_buffer_no_status(new_status_file, deb_file[i]->control_file); set_status(status_num, "ok", 2); fprintf(new_status_file, "Status: %s\n\n", name_hashtable[status_hashtable[status_num]->status]); } } fclose(old_status_file); fclose(new_status_file); /* Create a seperate backfile to dpkg */ if (rename("/var/lib/dpkg/status", "/var/lib/dpkg/status.udeb.bak") == -1) { struct stat stat_buf; if (stat("/var/lib/dpkg/status", &stat_buf) == 0) { error_msg_and_die("Couldnt create backup status file"); } /* Its ok if renaming the status file fails becasue status * file doesnt exist, maybe we are starting from scratch */ error_msg("No status file found, creating new one"); } if (rename("/var/lib/dpkg/status.udeb", "/var/lib/dpkg/status") == -1) { error_msg_and_die("DANGER: Couldnt create status file, you need to manually repair your status file"); }}int check_deps(deb_file_t **deb_file, int deb_start, int dep_max_count){ int *conflicts = NULL; int conflicts_num = 0; int state_status; int state_flag; int state_want; unsigned int status_package_num; int i = deb_start; int j, k; /* Check for conflicts * TODO: TEST if conflicts with other packages to be installed * * Add install packages and the packages they provide * to the list of files to check conflicts for */ /* Create array of package numbers to check against * installed package for conflicts*/ while (deb_file[i] != NULL) { const unsigned int package_num = deb_file[i]->package; conflicts = xrealloc(conflicts, sizeof(int) * (conflicts_num + 1)); conflicts[conflicts_num] = package_num; conflicts_num++; /* add provides to conflicts list */ for (j = 0; j < package_hashtable[package_num]->num_of_edges; j++) { if (package_hashtable[package_num]->edge[j]->type == EDGE_PROVIDES) { const int conflicts_package_num = search_package_hashtable( package_hashtable[package_num]->edge[j]->name, package_hashtable[package_num]->edge[j]->version, package_hashtable[package_num]->edge[j]->operator); if (package_hashtable[conflicts_package_num] == NULL) { /* create a new package */ common_node_t *new_node = (common_node_t *) xmalloc(sizeof(common_node_t)); new_node->name = package_hashtable[package_num]->edge[j]->name; new_node->version = package_hashtable[package_num]->edge[j]->version; new_node->num_of_edges = 0; new_node->edge = NULL; package_hashtable[conflicts_package_num] = new_node; } conflicts = xrealloc(conflicts, sizeof(int) * (conflicts_num + 1)); conflicts[conflicts_num] = conflicts_package_num; conflicts_num++; } } i++; } /* Check conflicts */ for (i = 0; i < conflicts_num; i++) { /* Check for conflicts */ for (j = 0; j < STATUS_HASH_PRIME; j++) { if (status_hashtable[j] == NULL) { continue; } state_flag = get_status(j, 2); state_status = get_status(j, 3); if ((state_status != search_name_hashtable("installed")) && (state_flag != search_name_hashtable("want-install"))) { continue; } status_package_num = status_hashtable[j]->package; for (k = 0; k < package_hashtable[status_package_num]->num_of_edges; k++) { const edge_t *package_edge = package_hashtable[status_package_num]->edge[k]; if (package_edge->type != EDGE_CONFLICTS) { continue; } if (package_edge->name != package_hashtable[conflicts[i]]->name) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -