char *find_prefix_line(struct buffer *buff, const char *prefix, int prefix_size) { int count; char *p = buff->space; char *end_p = p + buff->size; while (is_empty_character(*prefix) && prefix_size) { prefix++; prefix_size--; } if (prefix_size == 0) { return NULL; } end_p -= prefix_size; while (1) { for (count = 0; p < end_p && is_empty_character(*p); p++, count++); if (p >= end_p) { return NULL; } if (memcmp(p, prefix, prefix_size) == 0) { return p - count; } p = find_next_line(buff, p); if (p == NULL) { return NULL; } } return NULL; }
void grub_envblk_delete (grub_envblk_t envblk, const char *name) { char *p, *pend; int nl; nl = strlen (name); p = envblk->buf + sizeof (GRUB_ENVBLK_SIGNATURE) - 1; pend = envblk->buf + envblk->size; while (p + nl + 1 < pend) { if (strncmp (p, name, nl) == 0 && p[nl] == '=') { /* Found. */ int len = nl + 1; while (p + len < pend) { if (p[len] == '\n') break; else if (p[len] == '\\') len += 2; else len++; } if (p + len >= pend) /* Broken. */ return; len++; g_memmove (p, p + len, pend - (p + len)); grub_memset (pend - len, '#', len); break; } p = find_next_line (p, pend); } }
struct buffer *replace_prefix_line(struct buffer *buff, const char *prefix, int prefix_size, const char *new_line, int new_line_size) { char *p, *end_p, *q; struct buffer *new_buff; p = find_prefix_line(buff, prefix, prefix_size); if (p == NULL) { return NULL; } end_p = find_next_line(buff, p); if (end_p == NULL) { new_buff = malloc_buffer(buff->size + new_line_size + 1); } else { new_buff = malloc_buffer(buff->size - (end_p - p) + new_line_size + 1); } if (new_buff == NULL) { return NULL; } q = mem_area_copy(mem_area_copy(new_buff->space, buff->space, p - 1), new_line, new_line + new_line_size - 1); if (end_p == NULL) { return new_buff; } *q++ = '\n'; mem_area_copy(q, end_p, buff->space + buff->size - 1); return new_buff; }
/* Start from some arbitrary line on a polyline and walk back to find the first node (i.e. for which the number of connected lines <> 2) This line must not be a dead line (note that the arbitrary line cannot be a dead line because this has already been checked in main.c. */ int walk_back(struct Map_info *map, int start_line, int type) { int start_node, n1, n2; int line; int next_line; G_debug(2, "walk_back() start = %d", start_line); line = start_line; /* Otherwise find the start (i.e. travel in the negative direction) */ Vect_get_line_nodes(map, line, &start_node, NULL); while (1) { /* Find next line at start node */ next_line = find_next_line(map, line, start_node, type); G_debug(2, " next = %d", next_line); /* Keep going so long as not returned to start_line, i.e. if not a closed set of lines */ if (next_line == 0 || next_line == start_line) break; line = next_line; /* In a heavily edited binary vector map the relationship between the direction of a line (in terms of whether it is positive or negative in a node's line array) and the order of the line's nodes N1 and N2 is not constant. So here we flip the direction of travel if the initial direction of travel points back to the same line. */ Vect_get_line_nodes(map, next_line, &n1, &n2); if (n2 == start_node) start_node = n1; else start_node = n2; } return (line); }
/* Start from the first node on a polyline and walk to the other end, collecting the coordinates of each node en route. */ int walk_forward_and_pick_up_coords(struct Map_info *map, int start_line, int ltype, struct line_pnts *points, int *lines_visited, struct line_cats *Cats, int write_cats) { int cat_idx; int line, next_line, n1, n2; int type, node, next_node; struct line_pnts *pnts; struct line_cats *cats_tmp; G_debug(2, " walk_forward() start = %d", start_line); line = start_line; pnts = Vect_new_line_struct(); if (write_cats != NO_CATS) { cats_tmp = Vect_new_cats_struct(); } else { cats_tmp = NULL; } Vect_reset_line(points); /* Pick up first set of coordinates */ lines_visited[line] = 1; if (cats_tmp) type = Vect_read_line(map, pnts, Cats, line); else type = Vect_read_line(map, pnts, NULL, line); Vect_get_line_nodes(map, line, &n1, &n2); next_line = find_next_line(map, line, n1, ltype); if (next_line > 0) { /* continue at start node */ Vect_append_points(points, pnts, GV_BACKWARD); next_node = n1; } else { Vect_append_points(points, pnts, GV_FORWARD); next_line = find_next_line(map, line, n2, ltype); /* check end node */ if (next_line > 0) { next_node = n2; /* continue at end node */ } else { return 1; /* no other line */ } } /* While next line exist append coordinates */ line = next_line; node = next_node; while (line != 0 && line != start_line) { G_debug(2, " line = %d", line); type = Vect_read_line(map, pnts, cats_tmp, line); if (cats_tmp && write_cats == MULTI_CATS) { for (cat_idx = 0; cat_idx < cats_tmp->n_cats; cat_idx++) { Vect_cat_set(Cats, cats_tmp->field[cat_idx], cats_tmp->cat[cat_idx]); } } Vect_get_line_nodes(map, line, &n1, &n2); if (node == n1) { Vect_line_delete_point(pnts, 0); /* delete duplicate nodes */ Vect_append_points(points, pnts, GV_FORWARD); next_node = n2; } else { Vect_line_delete_point(pnts, pnts->n_points - 1); Vect_append_points(points, pnts, GV_BACKWARD); next_node = n1; } lines_visited[line] = 1; /* Find next one */ next_line = find_next_line(map, line, next_node, ltype); line = next_line; node = next_node; } if (cats_tmp) Vect_destroy_cats_struct(cats_tmp); return 1; }
int grub_envblk_set (grub_envblk_t envblk, const char *name, const char *value) { char *p, *pend; char *space; int found = 0; int nl; int vl; int i; nl = strlen (name); vl = escaped_value_len (value); p = envblk->buf + sizeof (GRUB_ENVBLK_SIGNATURE) - 1; pend = envblk->buf + envblk->size; /* First, look at free space. */ for (space = pend - 1; *space == '#'; space--) ; if (*space != '\n') /* Broken. */ return 0; space++; while (p + nl + 1 < space) { if (strncmp (p, name, nl) == 0 && p[nl] == '=') { int len; /* Found the same name. */ p += nl + 1; /* Check the length of the current value. */ len = 0; while (p + len < pend && p[len] != '\n') { if (p[len] == '\\') len += 2; else len++; } if (p + len >= pend) /* Broken. */ return 0; if (pend - space < vl - len) /* No space. */ return 0; if (vl < len) { /* Move the following characters backward, and fill the new space with harmless characters. */ g_memmove (p + vl, p + len, pend - (p + len)); grub_memset (space + len - vl, '#', len - vl); } else /* Move the following characters forward. */ g_memmove (p + vl, p + len, pend - (p + vl)); found = 1; break; } p = find_next_line (p, pend); } if (! found) { /* Append a new variable. */ if (pend - space < nl + 1 + vl + 1) /* No space. */ return 0; memcpy (space, name, nl); p = space + nl; *p++ = '='; } /* Write the value. */ for (i = 0; value[i]; i++) { if (value[i] == '\\' || value[i] == '\n') *p++ = '\\'; *p++ = value[i]; } *p = '\n'; return 1; }
void grub_envblk_iterate (grub_envblk_t envblk, int hook (const char *name, const char *value)) { char *p, *pend; p = envblk->buf + sizeof (GRUB_ENVBLK_SIGNATURE) - 1; pend = envblk->buf + envblk->size; while (p < pend) { if (*p != '#') { char *name; char *value; char *name_start, *name_end, *value_start; char *q; int ret; name_start = p; while (p < pend && *p != '=') p++; if (p == pend) /* Broken. */ return; name_end = p; p++; value_start = p; while (p < pend) { if (*p == '\n') break; else if (*p == '\\') p += 2; else p++; } if (p >= pend) /* Broken. */ return; name = g_malloc (p - name_start + 1); if (! name) /* out of memory. */ return; value = name + (value_start - name_start); memcpy (name, name_start, name_end - name_start); name[name_end - name_start] = '\0'; for (p = value_start, q = value; *p != '\n'; ++p) { if (*p == '\\') *q++ = *++p; else *q++ = *p; } *q = '\0'; ret = hook (name, value); g_free (name); if (ret) return; } p = find_next_line (p, pend); } }