/* * prop_string_append_cstring -- * Append a C string to a string. Returns true upon success. * The destination string must be mutable. */ bool prop_string_append_cstring(prop_string_t dst, const char *src) { char *ocp, *cp; size_t len; if (! prop_object_is_string(dst)) return (false); _PROP_ASSERT(src != NULL); if (dst->ps_flags & PS_F_NOCOPY) return (false); len = dst->ps_size + strlen(src); cp = _PROP_MALLOC(len + 1, M_PROP_STRING); if (cp == NULL) return (false); snprintf(cp, len + 1, "%s%s", prop_string_contents(dst), src); ocp = dst->ps_mutable; dst->ps_mutable = cp; dst->ps_size = len; if (ocp != NULL) _PROP_FREE(ocp, M_PROP_STRING); return (true); }
/* * prop_string_append -- * Append the contents of one string to another. Returns true * upon success. The destination string must be mutable. */ bool prop_string_append(prop_string_t dst, prop_string_t src) { char *ocp, *cp; size_t len; if (! (prop_object_is_string(dst) && prop_object_is_string(src))) return (false); if (dst->ps_flags & PS_F_NOCOPY) return (false); len = dst->ps_size + src->ps_size; cp = _PROP_MALLOC(len + 1, M_PROP_STRING); if (cp == NULL) return (false); snprintf(cp, len + 1, "%s%s", prop_string_contents(dst), prop_string_contents(src)); ocp = dst->ps_mutable; dst->ps_mutable = cp; dst->ps_size = len; if (ocp != NULL) _PROP_FREE(ocp, M_PROP_STRING); return (true); }
/* * prop_string_copy -- * Copy a string. If the original string is immutable, then the * copy is also immutable and references the same external data. */ prop_string_t prop_string_copy(prop_string_t ops) { prop_string_t ps; if (! prop_object_is_string(ops)) return (NULL); ps = _prop_string_alloc(); if (ps != NULL) { ps->ps_size = ops->ps_size; ps->ps_flags = ops->ps_flags; if (ops->ps_flags & PS_F_NOCOPY) ps->ps_immutable = ops->ps_immutable; else { char *cp = _PROP_MALLOC(ps->ps_size + 1, M_PROP_STRING); if (cp == NULL) { prop_object_release(ps); return (NULL); } strcpy(cp, prop_string_contents(ops)); ps->ps_mutable = cp; } } return (ps); }
/* * _prop_object_externalize_context_alloc -- * Allocate an externalize context. */ struct _prop_object_externalize_context * _prop_object_externalize_context_alloc(void) { struct _prop_object_externalize_context *ctx; ctx = _PROP_MALLOC(sizeof(*ctx), M_TEMP); if (ctx != NULL) { ctx->poec_buf = _PROP_MALLOC(BUF_EXPAND, M_TEMP); if (ctx->poec_buf == NULL) { _PROP_FREE(ctx, M_TEMP); return (NULL); } ctx->poec_len = 0; ctx->poec_capacity = BUF_EXPAND; ctx->poec_depth = 0; } return (ctx); }
/* ARGSUSED */ bool _prop_string_internalize(prop_stack_t stack, prop_object_t *obj, struct _prop_object_internalize_context *ctx) { prop_string_t string; char *str; size_t len, alen; if (ctx->poic_is_empty_element) { *obj = prop_string_create(); return (true); } /* No attributes recognized here. */ if (ctx->poic_tagattr != NULL) return (true); /* Compute the length of the result. */ if (_prop_object_internalize_decode_string(ctx, NULL, 0, &len, NULL) == false) return (true); str = _PROP_MALLOC(len + 1, M_PROP_STRING); if (str == NULL) return (true); if (_prop_object_internalize_decode_string(ctx, str, len, &alen, &ctx->poic_cp) == false || alen != len) { _PROP_FREE(str, M_PROP_STRING); return (true); } str[len] = '\0'; if (_prop_object_internalize_find_tag(ctx, "string", _PROP_TAG_TYPE_END) == false) { _PROP_FREE(str, M_PROP_STRING); return (true); } string = _prop_string_alloc(); if (string == NULL) { _PROP_FREE(str, M_PROP_STRING); return (true); } string->ps_mutable = str; string->ps_size = len; *obj = string; return (true); }
/* * prop_string_cstring -- * Return a copy of the contents of the string as a C string. * The string is allocated with the M_TEMP malloc type. */ char * prop_string_cstring(prop_string_t ps) { char *cp; if (! prop_object_is_string(ps)) return (NULL); cp = _PROP_MALLOC(ps->ps_size + 1, M_TEMP); if (cp != NULL) strcpy(cp, prop_string_contents(ps)); return (cp); }
/* * prop_string_create_cstring -- * Create a string that contains a copy of the provided C string. */ prop_string_t prop_string_create_cstring(const char *str) { prop_string_t ps; char *cp; size_t len; ps = _prop_string_alloc(); if (ps != NULL) { len = strlen(str); cp = _PROP_MALLOC(len + 1, M_PROP_STRING); if (cp == NULL) { prop_object_release(ps); return (NULL); } strcpy(cp, str); ps->ps_mutable = cp; ps->ps_size = len; } return (ps); }
/* * prop_string_copy_mutable -- * Copy a string, always returning a mutable copy. */ prop_string_t prop_string_copy_mutable(prop_string_t ops) { prop_string_t ps; char *cp; if (! prop_object_is_string(ops)) return (NULL); ps = _prop_string_alloc(); if (ps != NULL) { ps->ps_size = ops->ps_size; cp = _PROP_MALLOC(ps->ps_size + 1, M_PROP_STRING); if (cp == NULL) { prop_object_release(ps); return (NULL); } strcpy(cp, prop_string_contents(ops)); ps->ps_mutable = cp; } return (ps); }
/* * _prop_object_internalize_map_file -- * Map a file for the purpose of internalizing it. */ struct _prop_object_internalize_mapped_file * _prop_object_internalize_map_file(const char *fname) { struct stat sb; struct _prop_object_internalize_mapped_file *mf; size_t pgsize = (size_t)sysconf(_SC_PAGESIZE); size_t pgmask = pgsize - 1; bool need_guard = false; int fd; mf = _PROP_MALLOC(sizeof(*mf), M_TEMP); if (mf == NULL) return (NULL); fd = open(fname, O_RDONLY, 0400); if (fd == -1) { _PROP_FREE(mf, M_TEMP); return (NULL); } if (fstat(fd, &sb) == -1) { (void) close(fd); _PROP_FREE(mf, M_TEMP); return (NULL); } mf->poimf_mapsize = ((size_t)sb.st_size + pgmask) & ~pgmask; if (mf->poimf_mapsize < sb.st_size) { (void) close(fd); _PROP_FREE(mf, M_TEMP); return (NULL); } /* * If the file length is an integral number of pages, then we * need to map a guard page at the end in order to provide the * necessary NUL-termination of the buffer. */ if ((sb.st_size & pgmask) == 0) need_guard = true; mf->poimf_xml = mmap(NULL, need_guard ? mf->poimf_mapsize + pgsize : mf->poimf_mapsize, PROT_READ, MAP_FILE|MAP_SHARED, fd, (off_t)0); (void) close(fd); if (mf->poimf_xml == MAP_FAILED) { _PROP_FREE(mf, M_TEMP); return (NULL); } (void) madvise(mf->poimf_xml, mf->poimf_mapsize, MADV_SEQUENTIAL); if (need_guard) { if (mmap(mf->poimf_xml + mf->poimf_mapsize, pgsize, PROT_READ, MAP_ANON|MAP_PRIVATE|MAP_FIXED, -1, (off_t)0) == MAP_FAILED) { (void) munmap(mf->poimf_xml, mf->poimf_mapsize); _PROP_FREE(mf, M_TEMP); return (NULL); } mf->poimf_mapsize += pgsize; } return (mf); }
/* * _prop_object_internalize_context_alloc -- * Allocate an internalize context. */ struct _prop_object_internalize_context * _prop_object_internalize_context_alloc(const char *xml) { struct _prop_object_internalize_context *ctx; ctx = _PROP_MALLOC(sizeof(struct _prop_object_internalize_context), M_TEMP); if (ctx == NULL) return (NULL); ctx->poic_xml = ctx->poic_cp = xml; /* * Skip any whitespace and XML preamble stuff that we don't * know about / care about. */ for (;;) { while (_PROP_ISSPACE(*xml)) xml++; if (_PROP_EOF(*xml) || *xml != '<') goto bad; #define MATCH(str) (memcmp(&xml[1], str, sizeof(str) - 1) == 0) /* * Skip over the XML preamble that Apple XML property * lists usually include at the top of the file. */ if (MATCH("?xml ") || MATCH("!DOCTYPE plist")) { while (*xml != '>' && !_PROP_EOF(*xml)) xml++; if (_PROP_EOF(*xml)) goto bad; xml++; /* advance past the '>' */ continue; } if (MATCH("<!--")) { ctx->poic_cp = xml + 4; if (_prop_object_internalize_skip_comment(ctx) == false) goto bad; xml = ctx->poic_cp; continue; } #undef MATCH /* * We don't think we should skip it, so let's hope we can * parse it. */ break; } ctx->poic_cp = xml; return (ctx); bad: _PROP_FREE(ctx, M_TEMP); return (NULL); }