int file_size_action(const char *filename, struct stat *statbuf, void *userdata, int depth) { struct action_data *data = userdata; data->writep += sizeof(struct envfs_inode); data->writep += PAD4(strlen(filename) + 1 - strlen(data->base)); data->writep += sizeof(struct envfs_inode_end); if (S_ISLNK(statbuf->st_mode)) { char path[PATH_MAX]; memset(path, 0, PATH_MAX); if (readlink(filename, path, PATH_MAX - 1) < 0) { perror("read"); return 0; } data->writep += PAD4(strlen(path) + 1); } else { data->writep += PAD4(statbuf->st_size); } return 1; }
static void envfs_save_inode(struct action_data *data, struct envfs_entry *env) { struct envfs_inode *inode; struct envfs_inode_end *inode_end; int namelen = strlen(env->name) + 1; inode = data->writep; inode->magic = ENVFS_32(ENVFS_INODE_MAGIC); inode->headerlen = ENVFS_32(PAD4(namelen) + sizeof(struct envfs_inode_end)); inode->size = ENVFS_32(env->size); data->writep += sizeof(struct envfs_inode); strcpy(data->writep, env->name); data->writep += PAD4(namelen); inode_end = data->writep; inode_end->magic = ENVFS_32(ENVFS_INODE_END_MAGIC); inode_end->mode = ENVFS_32(env->mode); data->writep += sizeof(struct envfs_inode_end); memcpy(data->writep, env->buf, env->size); data->writep += PAD4(env->size); }
PsdStatus PsdFile::readAdditionalInfo() { assert(mAdditionalInfoBlock.mAddress != NULL); if (mAdditionalInfoBlock.mLength == 0) return PsdStatusOK; const uint8_t *ptr = mAdditionalInfoBlock.mAddress, *end = mAdditionalInfoBlock.getEndAddress() - 4; const uint8_t *key; uint32_t length; PsdStatus status; while (ptr < end) { if (!CHECK_FOUR_CHAR(ptr, '8', 'B', 'I', 'M') && !CHECK_FOUR_CHAR(ptr, '8', 'B', '6', '4')) { LOG_ALWAYS("Global addtional info signature is not found. (%u)", uint32_t(ptr - mMapped.get().mAddress)); return PsdStatusOK; } key = ptr + 4; length = PsdUtils::fetch32(ptr + 8); ptr += 12; if (CHECK_FOUR_CHAR(key, 'L', 'r', '1', '6')) { LOG_DEBUG("Layers are stored in global additional info."); readLayerCount(ptr); if (mLayersCount > 0) { const uint8_t *data = ptr + 2; status = readLayers(data, ptr + length); if (status != PsdStatusOK) return status; } } // XXX test shows it should be pad by 4, psdparse is not able to parse this though ptr += PAD4(length); } return PsdStatusOK; }
static int write_header(struct archive_write *a, struct archive_entry *entry) { int64_t ino; struct cpio *cpio; const char *p, *path; int pathlength, ret, ret_final; char h[c_header_size]; struct archive_string_conv *sconv; struct archive_entry *entry_main; size_t len; int pad; cpio = (struct cpio *)a->format_data; ret_final = ARCHIVE_OK; sconv = get_sconv(a); #if defined(_WIN32) && !defined(__CYGWIN__) /* Make sure the path separators in pahtname, hardlink and symlink * are all slash '/', not the Windows path separator '\'. */ entry_main = __la_win_entry_in_posix_pathseparator(entry); if (entry_main == NULL) { archive_set_error(&a->archive, ENOMEM, "Can't allocate ustar data"); return(ARCHIVE_FATAL); } if (entry != entry_main) entry = entry_main; else entry_main = NULL; #else entry_main = NULL; #endif ret = archive_entry_pathname_l(entry, &path, &len, sconv); if (ret != 0) { if (errno == ENOMEM) { archive_set_error(&a->archive, ENOMEM, "Can't allocate memory for Pathname"); ret_final = ARCHIVE_FATAL; goto exit_write_header; } archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Can't translate pathname '%s' to %s", archive_entry_pathname(entry), archive_string_conversion_charset_name(sconv)); ret_final = ARCHIVE_WARN; } pathlength = (int)len + 1; /* Include trailing null. */ memset(h, 0, c_header_size); format_hex(0x070701, h + c_magic_offset, c_magic_size); format_hex(archive_entry_devmajor(entry), h + c_devmajor_offset, c_devmajor_size); format_hex(archive_entry_devminor(entry), h + c_devminor_offset, c_devminor_size); ino = archive_entry_ino64(entry); if (ino > 0xffffffff) { archive_set_error(&a->archive, ERANGE, "large inode number truncated"); ret_final = ARCHIVE_WARN; } /* TODO: Set ret_final to ARCHIVE_WARN if any of these overflow. */ format_hex(ino & 0xffffffff, h + c_ino_offset, c_ino_size); format_hex(archive_entry_mode(entry), h + c_mode_offset, c_mode_size); format_hex(archive_entry_uid(entry), h + c_uid_offset, c_uid_size); format_hex(archive_entry_gid(entry), h + c_gid_offset, c_gid_size); format_hex(archive_entry_nlink(entry), h + c_nlink_offset, c_nlink_size); if (archive_entry_filetype(entry) == AE_IFBLK || archive_entry_filetype(entry) == AE_IFCHR) { format_hex(archive_entry_rdevmajor(entry), h + c_rdevmajor_offset, c_rdevmajor_size); format_hex(archive_entry_rdevminor(entry), h + c_rdevminor_offset, c_rdevminor_size); } else { format_hex(0, h + c_rdevmajor_offset, c_rdevmajor_size); format_hex(0, h + c_rdevminor_offset, c_rdevminor_size); } format_hex(archive_entry_mtime(entry), h + c_mtime_offset, c_mtime_size); format_hex(pathlength, h + c_namesize_offset, c_namesize_size); format_hex(0, h + c_checksum_offset, c_checksum_size); /* Non-regular files don't store bodies. */ if (archive_entry_filetype(entry) != AE_IFREG) archive_entry_set_size(entry, 0); /* Symlinks get the link written as the body of the entry. */ ret = archive_entry_symlink_l(entry, &p, &len, sconv); if (ret != 0) { if (errno == ENOMEM) { archive_set_error(&a->archive, ENOMEM, "Can't allocate memory for Likname"); ret_final = ARCHIVE_FATAL; goto exit_write_header; } archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT, "Can't translate linkname '%s' to %s", archive_entry_symlink(entry), archive_string_conversion_charset_name(sconv)); ret_final = ARCHIVE_WARN; } if (len > 0 && p != NULL && *p != '\0') ret = format_hex(strlen(p), h + c_filesize_offset, c_filesize_size); else ret = format_hex(archive_entry_size(entry), h + c_filesize_offset, c_filesize_size); if (ret) { archive_set_error(&a->archive, ERANGE, "File is too large for this format."); ret_final = ARCHIVE_FAILED; goto exit_write_header; } ret = __archive_write_output(a, h, c_header_size); if (ret != ARCHIVE_OK) { ret_final = ARCHIVE_FATAL; goto exit_write_header; } /* Pad pathname to even length. */ ret = __archive_write_output(a, path, pathlength); if (ret != ARCHIVE_OK) { ret_final = ARCHIVE_FATAL; goto exit_write_header; } pad = PAD4(pathlength + c_header_size); if (pad) { ret = __archive_write_output(a, "\0\0\0", pad); if (ret != ARCHIVE_OK) { ret_final = ARCHIVE_FATAL; goto exit_write_header; } } cpio->entry_bytes_remaining = archive_entry_size(entry); cpio->padding = (int)PAD4(cpio->entry_bytes_remaining); /* Write the symlink now. */ if (p != NULL && *p != '\0') { ret = __archive_write_output(a, p, strlen(p)); if (ret != ARCHIVE_OK) { ret_final = ARCHIVE_FATAL; goto exit_write_header; } pad = PAD4(strlen(p)); ret = __archive_write_output(a, "\0\0\0", pad); if (ret != ARCHIVE_OK) { ret_final = ARCHIVE_FATAL; goto exit_write_header; } } exit_write_header: if (entry_main) archive_entry_free(entry_main); return (ret_final); }
static int archive_write_newc_header(struct archive_write *a, struct archive_entry *entry) { struct cpio *cpio; const char *p, *path; int pathlength, ret; struct cpio_header_newc h; int pad; cpio = (struct cpio *)a->format_data; ret = 0; path = archive_entry_pathname(entry); pathlength = strlen(path) + 1; /* Include trailing null. */ memset(&h, 0, sizeof(h)); format_hex(0x070701, &h.c_magic, sizeof(h.c_magic)); format_hex(archive_entry_devmajor(entry), &h.c_devmajor, sizeof(h.c_devmajor)); format_hex(archive_entry_devminor(entry), &h.c_devminor, sizeof(h.c_devminor)); if (archive_entry_ino64(entry) > 0xffffffff) { archive_set_error(&a->archive, ERANGE, "large inode number truncated"); ret = ARCHIVE_WARN; } format_hex(archive_entry_ino64(entry) & 0xffffffff, &h.c_ino, sizeof(h.c_ino)); format_hex(archive_entry_mode(entry), &h.c_mode, sizeof(h.c_mode)); format_hex(archive_entry_uid(entry), &h.c_uid, sizeof(h.c_uid)); format_hex(archive_entry_gid(entry), &h.c_gid, sizeof(h.c_gid)); format_hex(archive_entry_nlink(entry), &h.c_nlink, sizeof(h.c_nlink)); if (archive_entry_filetype(entry) == AE_IFBLK || archive_entry_filetype(entry) == AE_IFCHR) { format_hex(archive_entry_rdevmajor(entry), &h.c_rdevmajor, sizeof(h.c_rdevmajor)); format_hex(archive_entry_rdevminor(entry), &h.c_rdevminor, sizeof(h.c_rdevminor)); } else { format_hex(0, &h.c_rdevmajor, sizeof(h.c_rdevmajor)); format_hex(0, &h.c_rdevminor, sizeof(h.c_rdevminor)); } format_hex(archive_entry_mtime(entry), &h.c_mtime, sizeof(h.c_mtime)); format_hex(pathlength, &h.c_namesize, sizeof(h.c_namesize)); format_hex(0, &h.c_checksum, sizeof(h.c_checksum)); /* Non-regular files don't store bodies. */ if (archive_entry_filetype(entry) != AE_IFREG) archive_entry_set_size(entry, 0); /* Symlinks get the link written as the body of the entry. */ p = archive_entry_symlink(entry); if (p != NULL && *p != '\0') format_hex(strlen(p), &h.c_filesize, sizeof(h.c_filesize)); else format_hex(archive_entry_size(entry), &h.c_filesize, sizeof(h.c_filesize)); ret = (a->compressor.write)(a, &h, sizeof(h)); if (ret != ARCHIVE_OK) return (ARCHIVE_FATAL); /* Pad pathname to even length. */ ret = (a->compressor.write)(a, path, pathlength); if (ret != ARCHIVE_OK) return (ARCHIVE_FATAL); pad = PAD4(pathlength + sizeof(struct cpio_header_newc)); if (pad) ret = (a->compressor.write)(a, "\0\0\0", pad); if (ret != ARCHIVE_OK) return (ARCHIVE_FATAL); cpio->entry_bytes_remaining = archive_entry_size(entry); cpio->padding = PAD4(cpio->entry_bytes_remaining); /* Write the symlink now. */ if (p != NULL && *p != '\0') { ret = (a->compressor.write)(a, p, strlen(p)); if (ret != ARCHIVE_OK) return (ARCHIVE_FATAL); pad = PAD4(strlen(p)); ret = (a->compressor.write)(a, "\0\0\0", pad); } return (ret); }
PsdStatus PsdLayer::readMeta(const uint8_t *data, const uint8_t *end) { assert(data != NULL); LOG_DEBUG("[Layer] %08X\n", uint32_t(data - mFile->mMapped.get().mAddress)); const uint8_t *dataSanity = data + sizeof(PsdLayerRecordMeta1) + sizeof(PsdLayerRecordMeta2) + 8; if (dataSanity > end) return PsdStatusFileOutOfRange; PsdStatus status; const PsdLayerRecordMeta1 *meta1 = (const PsdLayerRecordMeta1 *) data; PsdUtils::fetchRect(&mRect, &meta1->mRect); // The layer region may exceed the image size mAdjustedRect.mRight = mRect.mRight <= mFile->getWidth() ? mRect.mRight : mFile->getWidth(); mAdjustedRect.mBottom = mRect.mBottom <= mFile->getHeight() ? mRect.mBottom : mFile->getHeight(); mAdjustedRect.mLeft = mRect.mLeft >= 0 ? (mRect.mLeft <= mAdjustedRect.mRight ? mRect.mLeft : mAdjustedRect.mRight) : 0; mAdjustedRect.mTop = mRect.mTop >= 0 ? (mRect.mTop <= mAdjustedRect.mBottom ? mRect.mTop : mAdjustedRect.mBottom) : 0; mChannels = ntohs(meta1->mChannels); LOG_DEBUG("(%d, %d, %d, %d) (%d, %d, %d, %d) channels: %u\n", mRect.mLeft, mRect.mTop, mRect.mRight, mRect.mBottom, mAdjustedRect.mLeft, mAdjustedRect.mTop, mAdjustedRect.mRight, mAdjustedRect.mBottom, mChannels); data += sizeof(PsdLayerRecordMeta1); dataSanity += mChannels * sizeof(PsdChannelInfo); if (dataSanity > end) return PsdStatusFileOutOfRange; const PsdChannelInfo *channelsInfo = (const PsdChannelInfo *) data; mChannelsInfo.resize(mChannels); for (uint16_t i = 0; i < mChannels; i++) { mChannelsInfo[i].mId = ntohs(channelsInfo[i].mId); mChannelsInfo[i].mLength = ntohl(channelsInfo[i].mLength); mImageDataBlock.mLength += mChannelsInfo[i].mLength; LOG_DEBUG("channel %u: id: %d len: %u\n", i, mChannelsInfo[i].mId, mChannelsInfo[i].mLength); } LOG_DEBUG("image data length: %u\n", mImageDataBlock.mLength); data += sizeof(PsdChannelInfo) * mChannels; if (!CHECK_FOUR_CHAR(data, '8', 'B', 'I', 'M')) { LOG_ALWAYS("Blend mode signature not found"); return PsdStatusFileMalformed; } data += 4; const PsdLayerRecordMeta2 *meta2 = (const PsdLayerRecordMeta2 *) data; memcpy(mBlendMode, meta2->mBlendMode, sizeof(mBlendMode)); mOpacity = meta2->mOpacity; mClipping = meta2->mClipping; mFlags = meta2->mFlags; mFiller = meta2->mFiller; if (mFiller != 0) { LOG_DEBUG("Filler is not zero\n"); return PsdStatusFileMalformed; } mExtraDataBlock.assign((const uint8_t *)(meta2 + 1)); if (mExtraDataBlock.getEndAddress() > end || mExtraDataBlock.mLength < 4) return PsdStatusFileOutOfRange; mMaskInfoBlock.assign(mExtraDataBlock.mAddress); status = readMaskData(); if (status != PsdStatusOK) return status; if (mMaskInfoBlock.getEndAddress() + 4 > end) return PsdStatusFileOutOfRange; mBlendingRangesBlock.assign(mMaskInfoBlock.getEndAddress()); mName = PsdUtils::fetchPascalString(mBlendingRangesBlock.getEndAddress()); mAdditionalInfoBlock.mAddress = mBlendingRangesBlock.getEndAddress() + PAD4(mName.size() + 1); if (mExtraDataBlock.getEndAddress() < mAdditionalInfoBlock.mAddress) return PsdStatusFileOutOfRange; mAdditionalInfoBlock.mLength = (ptrdiff_t) mExtraDataBlock.getEndAddress() - (ptrdiff_t) mAdditionalInfoBlock.mAddress; LOG_DEBUG("layer addtional info: %u + %u\n", uint32_t(mAdditionalInfoBlock.mAddress - mFile->mMapped.get().mAddress), mAdditionalInfoBlock.mLength); if (mAdditionalInfoBlock.mLength > 0) { status = readAdditionalInfo(); if (status != PsdStatusOK) return status; } return PsdStatusOK; }
int file_save_action(const char *filename, struct stat *statbuf, void *userdata, int depth) { struct action_data *data = userdata; struct envfs_inode *inode; struct envfs_inode_end *inode_end; int fd; int namelen = strlen(filename) + 1 - strlen(data->base); inode = (struct envfs_inode*)data->writep; inode->magic = ENVFS_32(ENVFS_INODE_MAGIC); inode->headerlen = ENVFS_32(PAD4(namelen + sizeof(struct envfs_inode_end))); data->writep += sizeof(struct envfs_inode); strcpy(data->writep, filename + strlen(data->base)); data->writep += PAD4(namelen); inode_end = (struct envfs_inode_end*)data->writep; data->writep += sizeof(struct envfs_inode_end); inode_end->magic = ENVFS_32(ENVFS_INODE_END_MAGIC); inode_end->mode = ENVFS_32(S_IRWXU | S_IRWXG | S_IRWXO); if (S_ISLNK(statbuf->st_mode)) { char path[PATH_MAX]; int len; memset(path, 0, PATH_MAX); if (readlink(filename, path, PATH_MAX - 1) < 0) { perror("read"); goto out; } len = strlen(path) + 1; inode_end->mode |= ENVFS_32(S_IFLNK); memcpy(data->writep, path, len); inode->size = ENVFS_32(len); data->writep += PAD4(len); debug("handling symlink %s size %ld namelen %d headerlen %d\n", filename + strlen(data->base), len, namelen, ENVFS_32(inode->headerlen)); } else { debug("handling file %s size %ld namelen %d headerlen %d\n", filename + strlen(data->base), statbuf->st_size, namelen, ENVFS_32(inode->headerlen)); inode->size = ENVFS_32(statbuf->st_size); fd = open(filename, O_RDONLY); if (fd < 0) { printf("Open %s %s\n", filename, errno_str()); goto out; } if (read(fd, data->writep, statbuf->st_size) < statbuf->st_size) { perror("read"); goto out; } close(fd); data->writep += PAD4(statbuf->st_size); } out: return 1; }
/** * Restore the last environment into the current one * @param[in] filename from where to restore * @param[in] dir where to store the last content * @return 0 on success, anything else in case of failure * * Note: This function will also be used on the host! See note in the header * of this file. */ int envfs_load(char *filename, char *dir) { struct envfs_super super; void *buf = NULL, *buf_free = NULL; int envfd; int fd, ret = 0; char *str, *tmp; int headerlen_full; unsigned long size; /* for envfs < 1.0 */ struct envfs_inode_end inode_end_dummy; inode_end_dummy.mode = ENVFS_32(S_IRWXU | S_IRWXG | S_IRWXO); inode_end_dummy.magic = ENVFS_32(ENVFS_INODE_END_MAGIC); envfd = open(filename, O_RDONLY); if (envfd < 0) { printf("Open %s %s\n", filename, errno_str()); return -1; } /* read superblock */ ret = read(envfd, &super, sizeof(struct envfs_super)); if ( ret < sizeof(struct envfs_super)) { perror("read"); ret = -errno; goto out; } if ( ENVFS_32(super.magic) != ENVFS_MAGIC) { printf("envfs: wrong magic on %s\n", filename); ret = -EIO; goto out; } if (crc32(0, (unsigned char *)&super, sizeof(struct envfs_super) - 4) != ENVFS_32(super.sb_crc)) { printf("wrong crc on env superblock\n"); ret = -EIO; goto out; } size = ENVFS_32(super.size); buf = xmalloc(size); buf_free = buf; ret = read(envfd, buf, size); if (ret < size) { perror("read"); ret = -errno; goto out; } if (crc32(0, (unsigned char *)buf, size) != ENVFS_32(super.crc)) { printf("wrong crc on env\n"); ret = -EIO; goto out; } if (super.major < ENVFS_MAJOR) printf("envfs version %d.%d loaded into %d.%d\n", super.major, super.minor, ENVFS_MAJOR, ENVFS_MINOR); while (size) { struct envfs_inode *inode; struct envfs_inode_end *inode_end; uint32_t inode_size, inode_headerlen, namelen; inode = (struct envfs_inode *)buf; buf += sizeof(struct envfs_inode); if (ENVFS_32(inode->magic) != ENVFS_INODE_MAGIC) { printf("envfs: wrong magic on %s\n", filename); ret = -EIO; goto out; } inode_size = ENVFS_32(inode->size); inode_headerlen = ENVFS_32(inode->headerlen); namelen = strlen(inode->data) + 1; if (super.major < 1) inode_end = &inode_end_dummy; else inode_end = (struct envfs_inode_end *)(buf + PAD4(namelen)); debug("loading %s size %d namelen %d headerlen %d\n", inode->data, inode_size, namelen, inode_headerlen); str = concat_path_file(dir, inode->data); tmp = strdup(str); make_directory(dirname(tmp)); free(tmp); headerlen_full = PAD4(inode_headerlen); buf += headerlen_full; if (ENVFS_32(inode_end->magic) != ENVFS_INODE_END_MAGIC) { printf("envfs: wrong inode_end_magic on %s\n", filename); ret = -EIO; goto out; } if (S_ISLNK(ENVFS_32(inode_end->mode))) { debug("symlink: %s -> %s\n", str, (char*)buf); if (symlink((char*)buf, str) < 0) { printf("symlink: %s -> %s :", str, (char*)buf); perror(""); } free(str); } else { fd = open(str, O_WRONLY | O_CREAT | O_TRUNC, 0644); free(str); if (fd < 0) { printf("Open %s\n", errno_str()); ret = fd; goto out; } ret = write(fd, buf, inode_size); if (ret < inode_size) { perror("write"); ret = -errno; close(fd); goto out; } close(fd); } buf += PAD4(inode_size); size -= headerlen_full + PAD4(inode_size) + sizeof(struct envfs_inode); } ret = 0; out: close(envfd); if (buf_free) free(buf_free); return ret; }
void readlayerinfo(psd_file_t f, struct psd_header *h, int i) { psd_bytes_t extralen, extrastart; int j, chid, namelen; char *chidstr, tmp[10]; struct layer_info *li = h->linfo + i; // process layer record li->top = get4B(f); li->left = get4B(f); li->bottom = get4B(f); li->right = get4B(f); li->channels = get2Bu(f); VERBOSE("\n"); UNQUIET(" layer %d: (%4d,%4d,%4d,%4d), %d channels (%4d rows x %4d cols)\n", i, li->top, li->left, li->bottom, li->right, li->channels, li->bottom-li->top, li->right-li->left); if( li->bottom < li->top || li->right < li->left || li->channels > 64 ) // sanity check { alwayswarn("### something's not right about that, trying to skip layer.\n"); fseeko(f, 6*li->channels+12, SEEK_CUR); skipblock(f, "layer info: extra data"); li->chan = NULL; li->chindex = NULL; li->nameno = li->name = li->unicode_name = NULL; } else { li->chan = checkmalloc(li->channels*sizeof(struct channel_info)); li->chindex = checkmalloc((li->channels+3)*sizeof(int)); li->chindex += 3; // so we can index array from [-3] (hackish) for(j = -3; j < li->channels; ++j) li->chindex[j] = -1; // fetch info on each of the layer's channels for(j = 0; j < li->channels; ++j){ li->chan[j].id = chid = get2B(f); li->chan[j].length = GETPSDBYTES(f); li->chan[j].rawpos = 0; li->chan[j].rowpos = NULL; li->chan[j].unzipdata = NULL; if(chid >= -3 && chid < li->channels) li->chindex[chid] = j; else warn_msg("unexpected channel id %d", chid); switch(chid){ case UMASK_CHAN_ID: chidstr = " (user layer mask)"; break; case LMASK_CHAN_ID: chidstr = " (layer mask)"; break; case TRANS_CHAN_ID: chidstr = " (transparency mask)"; break; default: if(h->mode != SCAVENGE_MODE && chid < (int)strlen(channelsuffixes[h->mode])) sprintf(chidstr = tmp, " (%c)", channelsuffixes[h->mode][chid]); // it's a mode-ish channel else chidstr = ""; // don't know } VERBOSE(" channel %2d: " LL_L("%7lld","%7ld") " bytes, id=%2d %s\n", j, li->chan[j].length, chid, chidstr); } fread(li->blend.sig, 1, 4, f); fread(li->blend.key, 1, 4, f); li->blend.opacity = fgetc(f); li->blend.clipping = fgetc(f); li->blend.flags = fgetc(f); fgetc(f); // padding // process layer's 'extra data' section extralen = get4B(f); extrastart = ftello(f); VERBOSE(" (extra data: " LL_L("%lld","%ld") " bytes @ " LL_L("%lld","%ld") ")\n", extralen, extrastart); // fetch layer mask data li->mask.size = get4B(f); if(li->mask.size >= 20){ off_t skip = li->mask.size; VERBOSE(" (has layer mask)\n"); li->mask.top = get4B(f); li->mask.left = get4B(f); li->mask.bottom = get4B(f); li->mask.right = get4B(f); li->mask.default_colour = fgetc(f); li->mask.flags = fgetc(f); skip -= 18; if(li->mask.size >= 36){ VERBOSE(" (has user layer mask)\n"); li->mask.real_flags = fgetc(f); li->mask.real_default_colour = fgetc(f); li->mask.real_top = get4B(f); li->mask.real_left = get4B(f); li->mask.real_bottom = get4B(f); li->mask.real_right = get4B(f); skip -= 18; } fseeko(f, skip, SEEK_CUR); // skip remainder }else VERBOSE(" (no layer mask)\n"); skipblock(f, "layer blending ranges"); // layer name li->nameno = checkmalloc(16); sprintf(li->nameno, "layer%d", i+1); namelen = fgetc(f); li->name = checkmalloc(PAD4(namelen+1)); fread(li->name, 1, PAD4(namelen+1)-1, f); li->name[namelen] = 0; if(namelen) UNQUIET(" name: \"%s\"\n", li->name); // process layer's 'additional info' li->additionalpos = ftello(f); li->additionallen = extrastart + extralen - li->additionalpos; // leave file positioned after extra data fseeko(f, extrastart + extralen, SEEK_SET); } }
static int envfs_load_data(struct envfs_super *super, void *buf, size_t size, const char *dir, unsigned flags) { int fd, ret = 0; char *str, *tmp; int headerlen_full; /* for envfs < 1.0 */ struct envfs_inode_end inode_end_dummy; inode_end_dummy.mode = ENVFS_32(S_IRWXU | S_IRWXG | S_IRWXO); inode_end_dummy.magic = ENVFS_32(ENVFS_INODE_END_MAGIC); while (size) { struct envfs_inode *inode; struct envfs_inode_end *inode_end; uint32_t inode_size, inode_headerlen, namelen; inode = buf; buf += sizeof(struct envfs_inode); if (ENVFS_32(inode->magic) != ENVFS_INODE_MAGIC) { printf("envfs: wrong magic\n"); ret = -EIO; goto out; } inode_size = ENVFS_32(inode->size); inode_headerlen = ENVFS_32(inode->headerlen); namelen = strlen(inode->data) + 1; if (super->major < 1) inode_end = &inode_end_dummy; else inode_end = buf + PAD4(namelen); debug("loading %s size %d namelen %d headerlen %d\n", inode->data, inode_size, namelen, inode_headerlen); str = concat_path_file(dir, inode->data); headerlen_full = PAD4(inode_headerlen); buf += headerlen_full; if (ENVFS_32(inode_end->magic) != ENVFS_INODE_END_MAGIC) { printf("envfs: wrong inode_end_magic\n"); ret = -EIO; goto out; } tmp = strdup(str); make_directory(dirname(tmp)); free(tmp); if (S_ISLNK(ENVFS_32(inode_end->mode))) { debug("symlink: %s -> %s\n", str, (char*)buf); if (!strcmp(buf, basename(str))) { unlink(str); } else { ret = symlink(buf, str); if (ret < 0) printf("symlink: %s -> %s : %s\n", str, (char*)buf, strerror(-errno)); } free(str); } else { struct stat s; if (flags & ENV_FLAG_NO_OVERWRITE && !stat(str, &s)) { printf("skip %s\n", str); goto skip; } fd = open(str, O_WRONLY | O_CREAT | O_TRUNC, 0644); free(str); if (fd < 0) { printf("Open %s\n", errno_str()); ret = fd; goto out; } ret = write(fd, buf, inode_size); if (ret < inode_size) { perror("write"); ret = -errno; close(fd); goto out; } close(fd); } skip: buf += PAD4(inode_size); size -= headerlen_full + PAD4(inode_size) + sizeof(struct envfs_inode); } recursive_action(dir, ACTION_RECURSE | ACTION_DEPTHFIRST, NULL, dir_remove_action, NULL, 0); ret = 0; out: return ret; }
/** * Make the current environment persistent * @param[in] filename where to store * @param[in] dirname what to store (all files in this dir) * @param[in] flags superblock flags (refer ENVFS_FLAGS_* macros) * @return 0 on success, anything else in case of failure * * Note: This function will also be used on the host! See note in the header * of this file. */ int envfs_save(const char *filename, const char *dirname, unsigned flags) { struct envfs_super *super; int envfd, size, ret; struct action_data data = {}; void *buf = NULL, *wbuf; struct envfs_entry *env; if (!filename) filename = default_environment_path_get(); if (!dirname) dirname = "/env"; data.writep = NULL; data.base = dirname; #ifdef __BAREBOX__ defaultenv_load(TMPDIR, 0); #endif if (flags & ENVFS_FLAGS_FORCE_BUILT_IN) { size = 0; /* force no content */ } else { /* first pass: calculate size */ recursive_action(dirname, ACTION_RECURSE, file_action, NULL, &data, 0); recursive_action("/.defaultenv", ACTION_RECURSE, file_remove_action, NULL, &data, 0); size = 0; for (env = data.env; env; env = env->next) { size += PAD4(env->size); size += sizeof(struct envfs_inode); size += PAD4(strlen(env->name) + 1); size += sizeof(struct envfs_inode_end); } } buf = xzalloc(size + sizeof(struct envfs_super)); data.writep = buf + sizeof(struct envfs_super); super = buf; super->magic = ENVFS_32(ENVFS_MAGIC); super->major = ENVFS_MAJOR; super->minor = ENVFS_MINOR; super->size = ENVFS_32(size); super->flags = ENVFS_32(flags); if (!(flags & ENVFS_FLAGS_FORCE_BUILT_IN)) { /* second pass: copy files to buffer */ env = data.env; while (env) { struct envfs_entry *next = env->next; envfs_save_inode(&data, env); free(env->buf); free(env->name); free(env); env = next; } } super->crc = ENVFS_32(crc32(0, buf + sizeof(struct envfs_super), size)); super->sb_crc = ENVFS_32(crc32(0, buf, sizeof(struct envfs_super) - 4)); envfd = open(filename, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); if (envfd < 0) { printf("could not open %s: %s\n", filename, errno_str()); ret = -errno; goto out1; } ret = protect(envfd, ~0, 0, 0); /* ENOSYS and EOPNOTSUPP aren't errors here, many devices don't need it */ if (ret && errno != ENOSYS && errno != EOPNOTSUPP) { printf("could not unprotect %s: %s\n", filename, errno_str()); goto out; } ret = erase(envfd, ~0, 0); /* ENOSYS and EOPNOTSUPP aren't errors here, many devices don't need it */ if (ret && errno != ENOSYS && errno != EOPNOTSUPP) { printf("could not erase %s: %s\n", filename, errno_str()); goto out; } size += sizeof(struct envfs_super); wbuf = buf; while (size) { ssize_t now = write(envfd, wbuf, size); if (now < 0) { ret = -errno; goto out; } wbuf += now; size -= now; } ret = protect(envfd, ~0, 0, 1); /* ENOSYS and EOPNOTSUPP aren't errors here, many devices don't need it */ if (ret && errno != ENOSYS && errno != EOPNOTSUPP) { printf("could not protect %s: %s\n", filename, errno_str()); goto out; } ret = 0; out: close(envfd); out1: free(buf); #ifdef __BAREBOX__ unlink_recursive(TMPDIR, NULL); #endif return ret; }
int es705_uart_dev_rdb(struct es705_priv *es705, void *buf, int id) { u32 cmd; u32 resp; u8 *dptr; int ret; int size; int rdcnt = 0; #if defined(CONFIG_MQ100_SENSOR_HUB) u8 pad; /* Take Mutex for the duration of this UART transaction. */ mutex_lock(&es705_priv.uart_transaction_mutex); #endif dptr = (u8 *)buf; /* Read voice sense keyword data block request. */ cmd = (ES705_RDB_CMD << 16) | (id & 0xFFFF); cmd = cpu_to_be32(cmd); ret = es705_uart_write(es705, (char *)&cmd, 4); if (ret < 0) { dev_err(es705->dev, "%s(): RDB cmd write err = %d\n", __func__, ret); goto rdb_err; } /* Refer to "ES705 Advanced API Guide" for details of interface */ usleep_range(10000, 10000); ret = es705_uart_read(es705, (char *)&resp, 4); if (ret < 0) { dev_err(es705->dev, "%s(): error sending request = %d\n", __func__, ret); goto rdb_err; } be32_to_cpus(&resp); size = resp & 0xffff; dev_dbg(es705->dev, "%s(): resp=0x%08x size=%d\n", __func__, resp, size); if ((resp & 0xffff0000) != (ES705_RDB_CMD << 16)) { dev_err(es705->dev, "%s(): invalid read v-s data block response = 0x%08x\n", __func__, resp); goto rdb_err; } if (size == 0) { dev_err(es705->dev, "%s(): read request return size of 0\n", __func__); goto rdb_err; } if (size > PARSE_BUFFER_SIZE) size = PARSE_BUFFER_SIZE; for (rdcnt = 0; rdcnt < size; rdcnt++, dptr++) { ret = es705_uart_read(es705, dptr, 1); if (ret < 0) { dev_err(es705->dev, "%s(): data block ed error %d bytes ret = %d\n", __func__, rdcnt, ret); goto rdb_err; } } es705->rdb_read_count = size; #if defined(CONFIG_MQ100_SENSOR_HUB) size = PAD4(size); dev_dbg(es705->dev, "%s: Discarding %d pad bytes\n", __func__, size); ret = 0; while ((size > 0) && (ret >= 0)) { ret = es705_uart_read(es705, &pad, 1); size--; } #endif ret = 0; goto exit; rdb_err: es705->rdb_read_count = 0; ret = -EIO; exit: #if defined(CONFIG_MQ100_SENSOR_HUB) /* release UART transaction mutex */ mutex_unlock(&es705_priv.uart_transaction_mutex); #endif return ret; }