/* * Note: if text was provided, this just returns that text. If you * really need the text to be rebuilt in a canonical form, set the * text, ask for the bitmaps, then set the bitmaps. (Setting the * bitmaps clears any stored text.) This design is deliberate: if * we're editing archives, we don't want to discard flags just because * they aren't supported on the current system. The bitmap<->text * conversions are platform-specific (see below). */ const char * archive_entry_fflags_text(struct archive_entry *entry) { const char *f; char *p; if (archive_mstring_get_mbs(entry->archive, &entry->ae_fflags_text, &f) == 0) { if (f != NULL) return (f); } else if (errno == ENOMEM) __archive_errx(1, "No memory"); if (entry->ae_fflags_set == 0 && entry->ae_fflags_clear == 0) return (NULL); p = ae_fflagstostr(entry->ae_fflags_set, entry->ae_fflags_clear); if (p == NULL) return (NULL); archive_mstring_copy_mbs(&entry->ae_fflags_text, p); free(p); if (archive_mstring_get_mbs(entry->archive, &entry->ae_fflags_text, &f) == 0) return (f); if (errno == ENOMEM) __archive_errx(1, "No memory"); return (NULL); }
/* * Again, mimic gtar: inclusions are always anchored (have to match * the beginning of the path) even though exclusions are not anchored. */ static int match_path_inclusion(struct archive_match *a, struct match *m, int mbs, const void *pn) { /* Recursive operation requires only a prefix match. */ int flag = a->recursive_include ? PATHMATCH_NO_ANCHOR_END : 0; int r; if (mbs) { const char *p; r = archive_mstring_get_mbs(&(a->archive), &(m->pattern), &p); if (r == 0) return (archive_pathmatch(p, (const char *)pn, flag)); } else { const wchar_t *p; r = archive_mstring_get_wcs(&(a->archive), &(m->pattern), &p); if (r == 0) return (archive_pathmatch_w(p, (const wchar_t *)pn, flag)); } if (errno == ENOMEM) return (error_nomem(a)); return (0); }
/* * Call back functions for archive_rb. */ static int cmp_node_mbs(const struct archive_rb_node *n1, const struct archive_rb_node *n2) { struct match_file *f1 = (struct match_file *)(uintptr_t)n1; struct match_file *f2 = (struct match_file *)(uintptr_t)n2; const char *p1, *p2; archive_mstring_get_mbs(NULL, &(f1->pathname), &p1); archive_mstring_get_mbs(NULL, &(f2->pathname), &p2); if (p1 == NULL) return (1); if (p2 == NULL) return (-1); return (strcmp(p1, p2)); }
const char * archive_entry_uname(struct archive_entry *entry) { const char *p; if (archive_mstring_get_mbs(entry->archive, &entry->ae_uname, &p) == 0) return (p); return (NULL); }
const char * archive_entry_symlink(struct archive_entry *entry) { const char *p; if ((entry->ae_set & AE_SET_SYMLINK) && archive_mstring_get_mbs( entry->archive, &entry->ae_symlink, &p) == 0) return (p); return (NULL); }
const char * archive_entry_sourcepath(struct archive_entry *entry) { const char *p; if (archive_mstring_get_mbs( entry->archive, &entry->ae_sourcepath, &p) == 0) return (p); return (NULL); }
const char * archive_entry_uname(struct archive_entry *entry) { const char *p; if (archive_mstring_get_mbs(entry->archive, &entry->ae_uname, &p) == 0) return (p); if (errno == ENOMEM) __archive_errx(1, "No memory"); return (NULL); }
static int cmp_key_mbs(const struct archive_rb_node *n, const void *key) { struct match_file *f = (struct match_file *)(uintptr_t)n; const char *p; archive_mstring_get_mbs(NULL, &(f->pathname), &p); if (p == NULL) return (-1); return (strcmp(p, (const char *)key)); }
const char * archive_entry_symlink(struct archive_entry *entry) { const char *p; if ((entry->ae_set & AE_SET_SYMLINK) == 0) return (NULL); if (archive_mstring_get_mbs( entry->archive, &entry->ae_symlink, &p) == 0) return (p); if (errno == ENOMEM) __archive_errx(1, "No memory"); return (NULL); }
static int match_list_unmatched_inclusions_next(struct archive_match *a, struct match_list *list, int mbs, const void **vp) { struct match *m; *vp = NULL; if (list->unmatched_eof) { list->unmatched_eof = 0; return (ARCHIVE_EOF); } if (list->unmatched_next == NULL) { if (list->unmatched_count == 0) return (ARCHIVE_EOF); list->unmatched_next = list->first; } for (m = list->unmatched_next; m != NULL; m = m->next) { int r; if (m->matches) continue; if (mbs) { const char *p; r = archive_mstring_get_mbs(&(a->archive), &(m->pattern), &p); if (r < 0 && errno == ENOMEM) return (error_nomem(a)); if (p == NULL) p = ""; *vp = p; } else { const wchar_t *p; r = archive_mstring_get_wcs(&(a->archive), &(m->pattern), &p); if (r < 0 && errno == ENOMEM) return (error_nomem(a)); if (p == NULL) p = L""; *vp = p; } list->unmatched_next = m->next; if (list->unmatched_next == NULL) /* To return EOF next time. */ list->unmatched_eof = 1; return (ARCHIVE_OK); } list->unmatched_next = NULL; return (ARCHIVE_EOF); }
/* * Note: if text was provided, this just returns that text. If you * really need the text to be rebuilt in a canonical form, set the * text, ask for the bitmaps, then set the bitmaps. (Setting the * bitmaps clears any stored text.) This design is deliberate: if * we're editing archives, we don't want to discard flags just because * they aren't supported on the current system. The bitmap<->text * conversions are platform-specific (see below). */ const char * archive_entry_fflags_text(struct archive_entry *entry) { const char *f; char *p; if (archive_mstring_get_mbs(entry->archive, &entry->ae_fflags_text, &f) == 0 && f != NULL) return (f); if (entry->ae_fflags_set == 0 && entry->ae_fflags_clear == 0) return (NULL); p = ae_fflagstostr(entry->ae_fflags_set, entry->ae_fflags_clear); if (p == NULL) return (NULL); archive_mstring_copy_mbs(&entry->ae_fflags_text, p); free(p); if (archive_mstring_get_mbs(entry->archive, &entry->ae_fflags_text, &f) == 0) return (f); return (NULL); }
static int match_owner_name_mbs(struct archive_match *a, struct match_list *list, const char *name) { struct match *m; const char *p; if (name == NULL || *name == '\0') return (0); for (m = list->first; m; m = m->next) { if (archive_mstring_get_mbs(&(a->archive), &(m->pattern), &p) < 0 && errno == ENOMEM) return (error_nomem(a)); if (p != NULL && strcmp(p, name) == 0) { m->matches++; return (1); } } return (0); }
/* * This is a little odd, but it matches the default behavior of * gtar. In particular, 'a*b' will match 'foo/a1111/222b/bar' * */ static int match_path_exclusion(struct archive_match *a, struct match *m, int mbs, const void *pn) { int flag = PATHMATCH_NO_ANCHOR_START | PATHMATCH_NO_ANCHOR_END; int r; if (mbs) { const char *p; r = archive_mstring_get_mbs(&(a->archive), &(m->pattern), &p); if (r == 0) return (archive_pathmatch(p, (const char *)pn, flag)); } else { const wchar_t *p; r = archive_mstring_get_wcs(&(a->archive), &(m->pattern), &p); if (r == 0) return (archive_pathmatch_w(p, (const wchar_t *)pn, flag)); } if (errno == ENOMEM) return (error_nomem(a)); return (0); }
static int file_open(struct archive *a, void *client_data) { int flags; struct write_file_data *mine; struct stat st; #if defined(_WIN32) && !defined(__CYGWIN__) wchar_t *fullpath; #endif const wchar_t *wcs; const char *mbs; mine = (struct write_file_data *)client_data; flags = O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_CLOEXEC; /* * Open the file. */ mbs = NULL; wcs = NULL; #if defined(_WIN32) && !defined(__CYGWIN__) if (archive_mstring_get_wcs(a, &mine->filename, &wcs) != 0) { if (errno == ENOMEM) archive_set_error(a, errno, "No memory"); else { archive_mstring_get_mbs(a, &mine->filename, &mbs); archive_set_error(a, errno, "Can't convert '%s' to WCS", mbs); } return (ARCHIVE_FATAL); } fullpath = __la_win_permissive_name_w(wcs); if (fullpath != NULL) { mine->fd = _wopen(fullpath, flags, 0666); free(fullpath); } else mine->fd = _wopen(wcs, flags, 0666); #else if (archive_mstring_get_mbs(a, &mine->filename, &mbs) != 0) { if (errno == ENOMEM) archive_set_error(a, errno, "No memory"); else { archive_mstring_get_wcs(a, &mine->filename, &wcs); archive_set_error(a, errno, "Can't convert '%S' to MBS", wcs); } return (ARCHIVE_FATAL); } mine->fd = open(mbs, flags, 0666); __archive_ensure_cloexec_flag(mine->fd); #endif if (mine->fd < 0) { if (mbs != NULL) archive_set_error(a, errno, "Failed to open '%s'", mbs); else archive_set_error(a, errno, "Failed to open '%S'", wcs); return (ARCHIVE_FATAL); } if (fstat(mine->fd, &st) != 0) { if (mbs != NULL) archive_set_error(a, errno, "Couldn't stat '%s'", mbs); else archive_set_error(a, errno, "Couldn't stat '%S'", wcs); return (ARCHIVE_FATAL); } /* * Set up default last block handling. */ if (archive_write_get_bytes_in_last_block(a) < 0) { if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode) || S_ISFIFO(st.st_mode)) /* Pad last block when writing to device or FIFO. */ archive_write_set_bytes_in_last_block(a, 0); else /* Don't pad last block otherwise. */ archive_write_set_bytes_in_last_block(a, 1); } /* * If the output file is a regular file, don't add it to * itself. If it's a device file, it's okay to add the device * entry to the output archive. */ if (S_ISREG(st.st_mode)) archive_write_set_skip_file(a, st.st_dev, st.st_ino); return (ARCHIVE_OK); }