Skip to content
Snippets Groups Projects
Commit e832ed98 authored by Ronny Nilsson's avatar Ronny Nilsson
Browse files

Support for writing data into a fresh new UBI volume.

parent 3642686e
No related branches found
No related tags found
No related merge requests found
......@@ -15,6 +15,7 @@
#include <time.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/sysmacros.h>
#include <fcntl.h>
#define __EXPORTED_HEADERS__
......@@ -174,6 +175,137 @@ int ubi_create_volume(int volId, long long size)
//-------------------------------------------------------------
// Write fresh data from <srcPath>, from beginning
// to the end of a static UBI volume. Any remainging
// space in the volume will be padded.
static int ubi_write_volume(int volId, const char *srcPath)
{
int srcFd, dstFd, res, readChunk, writtenChunk;
char dstPath[UBI_MAX_VOLUME_NAME], *buf;
struct stat srcStat, dstStat;
struct ubi_vol_info volInfo;
long long writtenTot;
res = 0;
errno = 0;
srcFd = -1;
dstFd = -1;
writtenTot = 0ll;
buf = malloc(devInfo.leb_size);
// Sanity check the volume before overwriting it.
if(ubi_get_vol_info1(libubi, devInfo.dev_num, volId, &volInfo)) {
fprintf(stderr, "Error reading UBI volume %d: %s\n",
volId, strerror(errno));
res = -1;
goto out;
}
else if(volInfo.type != UBI_STATIC_VOLUME || volInfo.vol_id != volId) {
fprintf(stderr, "Wrong data in to write UBI volume %d\n", volId);
res = -1;
goto out;
}
/* Open the source data file and the destination volume
* character device. Further sanity check them and prepare
* them for work. */
srcFd = open(srcPath, O_RDONLY);
if(srcFd == -1) {
fprintf(stderr, "Error opening file %s: %s", srcPath, strerror(errno));
res = -1;
goto out;
}
else if(fstat(srcFd, &srcStat)) {
fprintf(stderr, "Error investigating file %s: %s", srcPath, strerror(errno));
res = -1;
goto out;
}
else if(srcStat.st_size > volInfo.rsvd_bytes) {
fprintf(stderr, "Error; source is to big!\n");
res = -1;
goto out;
}
snprintf(dstPath, UBI_MAX_VOLUME_NAME, "/dev/ubi%d_%d",
devInfo.dev_num, volId);
dstFd = open(dstPath, O_WRONLY);
if(dstFd == -1) {
fprintf(stderr, "Error opening file %s: %s", dstPath, strerror(errno));
res = -1;
goto out;
}
else if(fstat(dstFd, &dstStat)) {
fprintf(stderr, "Error investigating file %s: %s", dstPath, strerror(errno));
res = -1;
goto out;
}
else if(!S_ISCHR(dstStat.st_mode) || volInfo.major != major(dstStat.st_rdev) ||
volInfo.minor != minor(dstStat.st_rdev)) {
fprintf(stderr, "BUG: wrong choice of destination! %s %d %u %d %u\n",
dstPath, volInfo.major, major(dstStat.st_rdev), volInfo.minor,
minor(dstStat.st_rdev));
res = -1;
goto out;
}
if(volInfo.rsvd_bytes % volInfo.leb_size || volInfo.data_bytes) {
fprintf(stderr, "Error volume %s to write isn't empty!", dstPath);
res = -1;
goto out;
}
if(ubi_update_start(libubi, dstFd, volInfo.rsvd_bytes)) {
fprintf(stderr, "Error preparing volume %s: %s", dstPath, strerror(errno));
res = -1;
goto out;
}
// Loop copying source into destination volume.
while(writtenTot < volInfo.rsvd_bytes && res >= 0) {
writtenChunk = 0;
// Read a chunk of data from source file.
readChunk = (volInfo.rsvd_bytes - writtenTot > devInfo.leb_size) ?
devInfo.leb_size : volInfo.rsvd_bytes - writtenTot;
res = read(srcFd, buf, readChunk);
if(res == -1) {
fprintf(stderr, "Error reading file %s: %s", srcPath, strerror(errno));
}
else if(res > 0) {
readChunk = res;
}
else if(!res) {
// End of source data file. Pad the rest.
memset(buf, 0xffu, devInfo.leb_size);
readChunk = (volInfo.rsvd_bytes - writtenTot > devInfo.leb_size) ?
devInfo.leb_size : volInfo.rsvd_bytes - writtenTot;
}
// Write the chunk of data to the destination UBI volume.
while(writtenChunk < readChunk && res >= 0) {
res = write(dstFd, buf, readChunk - writtenChunk);
if(res == -1) {
fprintf(stderr, "Error writing volume %s: %s",
dstPath, strerror(errno));
}
else if(res > 0) {
writtenChunk += res;
writtenTot += (long long) res;
if(writtenTot == volInfo.rsvd_bytes) res = 0;
}
}
}
out:
if(srcFd != -1) close(srcFd);
if(dstFd != -1) close(dstFd);
free(buf);
return res;
}
//-------------------------------------------------------------
// Init the UBI library and query system for info.
static int ubi_probe(void)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment