/* * _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); }
/* * _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 < (size_t)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); } #ifndef __minix (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; } #endif return (mf); }