summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--commands/ubi.c2
-rw-r--r--drivers/mtd/ubi/barebox.c19
-rw-r--r--fs/devfs.c5
-rw-r--r--fs/fs.c2
-rw-r--r--include/driver.h1
-rw-r--r--lib/libfile.c22
6 files changed, 40 insertions, 11 deletions
diff --git a/commands/ubi.c b/commands/ubi.c
index 4c445d2216..5e2758400a 100644
--- a/commands/ubi.c
+++ b/commands/ubi.c
@@ -42,7 +42,7 @@ static int do_ubiupdatevol(int argc, char *argv[])
return 1;
}
- fd_vol = open(argv[optind], O_WRONLY);
+ fd_vol = open(argv[optind], O_WRONLY | O_TRUNC);
if (fd_vol < 0) {
perror("open volume");
ret = 1;
diff --git a/drivers/mtd/ubi/barebox.c b/drivers/mtd/ubi/barebox.c
index 329cf4564a..d67e566db6 100644
--- a/drivers/mtd/ubi/barebox.c
+++ b/drivers/mtd/ubi/barebox.c
@@ -162,6 +162,21 @@ static loff_t ubi_volume_cdev_lseek(struct cdev *cdev, loff_t ofs)
return ofs;
}
+static int ubi_volume_cdev_truncate(struct cdev *cdev, size_t size)
+{
+ struct ubi_volume_cdev_priv *priv = cdev->priv;
+ struct ubi_device *ubi = priv->ubi;
+ struct ubi_volume *vol = priv->vol;
+ uint64_t rsvd_bytes;
+
+ rsvd_bytes = (long long)vol->reserved_pebs *
+ ubi->leb_size - vol->data_pad;
+ if (size > rsvd_bytes)
+ return -ENOSPC;
+
+ return 0;
+}
+
static int ubi_volume_cdev_ioctl(struct cdev *cdev, int cmd, void *buf)
{
struct ubi_volume_cdev_priv *priv = cdev->priv;
@@ -210,6 +225,7 @@ static struct file_operations ubi_volume_fops = {
.write = ubi_volume_cdev_write,
.lseek = ubi_volume_cdev_lseek,
.ioctl = ubi_volume_cdev_ioctl,
+ .truncate = ubi_volume_cdev_truncate,
};
int ubi_volume_cdev_add(struct ubi_device *ubi, struct ubi_volume *vol)
@@ -228,9 +244,6 @@ int ubi_volume_cdev_add(struct ubi_device *ubi, struct ubi_volume *vol)
cdev->priv = priv;
cdev->size = vol->used_bytes;
- if (vol->vol_type == UBI_STATIC_VOLUME)
- cdev->flags = DEVFS_IS_CHARACTER_DEV;
-
cdev->dev = &vol->dev;
ubi_msg(ubi, "registering %s as /dev/%s", vol->name, cdev->name);
ret = devfs_create(cdev);
diff --git a/fs/devfs.c b/fs/devfs.c
index 6fabcf8ffa..2a7b1b3466 100644
--- a/fs/devfs.c
+++ b/fs/devfs.c
@@ -168,6 +168,11 @@ static int devfs_ioctl(struct device_d *_dev, FILE *f, int request, void *buf)
static int devfs_truncate(struct device_d *dev, FILE *f, ulong size)
{
+ struct cdev *cdev = f->priv;
+
+ if (cdev->ops->truncate)
+ return cdev->ops->truncate(cdev, size);
+
if (f->fsdev->dev.num_resources < 1)
return -ENOSPC;
if (size > resource_size(&f->fsdev->dev.resource[0]))
diff --git a/fs/fs.c b/fs/fs.c
index b7e7c63ffe..2b4659cfbb 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -682,7 +682,7 @@ int open(const char *pathname, int flags, ...)
if (ret)
goto out;
- if (!(s.st_mode & S_IFCHR) && (flags & O_TRUNC)) {
+ if (flags & O_TRUNC) {
ret = fsdrv->truncate(&fsdev->dev, f, 0);
f->size = 0;
if (ret)
diff --git a/include/driver.h b/include/driver.h
index 80aa8d821c..6abaaad8b4 100644
--- a/include/driver.h
+++ b/include/driver.h
@@ -434,6 +434,7 @@ struct file_operations {
int (*erase)(struct cdev*, loff_t count, loff_t offset);
int (*protect)(struct cdev*, size_t count, loff_t offset, int prot);
int (*memmap)(struct cdev*, void **map, int flags);
+ int (*truncate)(struct cdev*, size_t size);
};
#define MAX_PARTUUID_STR sizeof("00112233-4455-6677-8899-AABBCCDDEEFF")
diff --git a/lib/libfile.c b/lib/libfile.c
index cba2f02a23..049ec32d77 100644
--- a/lib/libfile.c
+++ b/lib/libfile.c
@@ -263,9 +263,10 @@ int copy_file(const char *src, const char *dst, int verbose)
int srcfd = 0, dstfd = 0;
int r, w;
int ret = 1, err1 = 0;
+ int mode;
void *buf;
int total = 0;
- struct stat statbuf;
+ struct stat srcstat, dststat;
rw_buf = xmalloc(RW_BUF_SIZE);
@@ -275,17 +276,26 @@ int copy_file(const char *src, const char *dst, int verbose)
goto out;
}
- dstfd = open(dst, O_WRONLY | O_CREAT | O_TRUNC);
+ ret = stat(dst, &dststat);
+ if (ret)
+ goto out;
+
+ mode = O_WRONLY | O_CREAT;
+
+ if (S_ISREG(dststat.st_mode))
+ mode |= O_TRUNC;
+
+ dstfd = open(dst, mode);
if (dstfd < 0) {
printf("could not open %s: %s\n", dst, errno_str());
goto out;
}
if (verbose) {
- if (stat(src, &statbuf) < 0)
- statbuf.st_size = 0;
+ if (stat(src, &srcstat) < 0)
+ srcstat.st_size = 0;
- init_progression_bar(statbuf.st_size);
+ init_progression_bar(srcstat.st_size);
}
while (1) {
@@ -310,7 +320,7 @@ int copy_file(const char *src, const char *dst, int verbose)
}
if (verbose) {
- if (statbuf.st_size && statbuf.st_size != FILESIZE_MAX)
+ if (srcstat.st_size && srcstat.st_size != FILESIZE_MAX)
show_progress(total);
else
show_progress(total / 16384);