Fsutil: allow truncate to arbitrary length.
This commit is contained in:
@@ -84,7 +84,7 @@ int fs_block_free (fs_t *fs, unsigned int bno)
|
|||||||
/*
|
/*
|
||||||
* Free an indirect block.
|
* Free an indirect block.
|
||||||
*/
|
*/
|
||||||
int fs_indirect_block_free (fs_t *fs, unsigned int bno)
|
int fs_indirect_block_free (fs_t *fs, unsigned int bno, int nblk)
|
||||||
{
|
{
|
||||||
unsigned nb;
|
unsigned nb;
|
||||||
unsigned char data [BSDFS_BSIZE];
|
unsigned char data [BSDFS_BSIZE];
|
||||||
@@ -94,8 +94,13 @@ int fs_indirect_block_free (fs_t *fs, unsigned int bno)
|
|||||||
fprintf (stderr, "inode_clear: read error at block %d\n", bno);
|
fprintf (stderr, "inode_clear: read error at block %d\n", bno);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
for (i=BSDFS_BSIZE-2; i>=0; i-=2) {
|
for (i=BSDFS_BSIZE-4; i>=0; i-=4) {
|
||||||
nb = data [i+1] << 8 | data [i];
|
if (i/4 < nblk) {
|
||||||
|
/* Truncate up to required size. */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
nb = data [i+3] << 24 | data [i+2] << 16 |
|
||||||
|
data [i+1] << 8 | data [i];
|
||||||
if (nb)
|
if (nb)
|
||||||
fs_block_free (fs, nb);
|
fs_block_free (fs, nb);
|
||||||
}
|
}
|
||||||
@@ -106,7 +111,7 @@ int fs_indirect_block_free (fs_t *fs, unsigned int bno)
|
|||||||
/*
|
/*
|
||||||
* Free a double indirect block.
|
* Free a double indirect block.
|
||||||
*/
|
*/
|
||||||
int fs_double_indirect_block_free (fs_t *fs, unsigned int bno)
|
int fs_double_indirect_block_free (fs_t *fs, unsigned int bno, int nblk)
|
||||||
{
|
{
|
||||||
unsigned nb;
|
unsigned nb;
|
||||||
unsigned char data [BSDFS_BSIZE];
|
unsigned char data [BSDFS_BSIZE];
|
||||||
@@ -116,10 +121,16 @@ int fs_double_indirect_block_free (fs_t *fs, unsigned int bno)
|
|||||||
fprintf (stderr, "inode_clear: read error at block %d\n", bno);
|
fprintf (stderr, "inode_clear: read error at block %d\n", bno);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
for (i=BSDFS_BSIZE-2; i>=0; i-=2) {
|
for (i=BSDFS_BSIZE-4; i>=0; i-=4) {
|
||||||
nb = data [i+1] << 8 | data [i];
|
if (i/4 * BSDFS_BSIZE/4 < nblk) {
|
||||||
|
/* Truncate up to required size. */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
nb = data [i+3] << 24 | data [i+2] << 16 |
|
||||||
|
data [i+1] << 8 | data [i];
|
||||||
if (nb)
|
if (nb)
|
||||||
fs_indirect_block_free (fs, nb);
|
fs_indirect_block_free (fs, nb,
|
||||||
|
nblk - i/4 * BSDFS_BSIZE/4);
|
||||||
}
|
}
|
||||||
fs_block_free (fs, bno);
|
fs_block_free (fs, bno);
|
||||||
return 1;
|
return 1;
|
||||||
@@ -128,7 +139,7 @@ int fs_double_indirect_block_free (fs_t *fs, unsigned int bno)
|
|||||||
/*
|
/*
|
||||||
* Free a triple indirect block.
|
* Free a triple indirect block.
|
||||||
*/
|
*/
|
||||||
int fs_triple_indirect_block_free (fs_t *fs, unsigned int bno)
|
int fs_triple_indirect_block_free (fs_t *fs, unsigned int bno, int nblk)
|
||||||
{
|
{
|
||||||
unsigned nb;
|
unsigned nb;
|
||||||
unsigned char data [BSDFS_BSIZE];
|
unsigned char data [BSDFS_BSIZE];
|
||||||
@@ -138,10 +149,16 @@ int fs_triple_indirect_block_free (fs_t *fs, unsigned int bno)
|
|||||||
fprintf (stderr, "inode_clear: read error at block %d\n", bno);
|
fprintf (stderr, "inode_clear: read error at block %d\n", bno);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
for (i=BSDFS_BSIZE-2; i>=0; i-=2) {
|
for (i=BSDFS_BSIZE-4; i>=0; i-=4) {
|
||||||
nb = data [i+1] << 8 | data [i];
|
if (i/4 * BSDFS_BSIZE/4 * BSDFS_BSIZE/4 < nblk) {
|
||||||
|
/* Truncate up to required size. */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
nb = data [i+3] << 24 | data [i+2] << 16 |
|
||||||
|
data [i+1] << 8 | data [i];
|
||||||
if (nb)
|
if (nb)
|
||||||
fs_double_indirect_block_free (fs, nb);
|
fs_double_indirect_block_free (fs, nb,
|
||||||
|
nblk - i/4 * BSDFS_BSIZE/4 * BSDFS_BSIZE/4);
|
||||||
}
|
}
|
||||||
fs_block_free (fs, bno);
|
fs_block_free (fs, bno);
|
||||||
return 1;
|
return 1;
|
||||||
|
|||||||
@@ -169,7 +169,7 @@ int fs_mount(fs_t *fs, char *dirname);
|
|||||||
int fs_inode_get (fs_t *fs, fs_inode_t *inode, unsigned inum);
|
int fs_inode_get (fs_t *fs, fs_inode_t *inode, unsigned inum);
|
||||||
int fs_inode_save (fs_inode_t *inode, int force);
|
int fs_inode_save (fs_inode_t *inode, int force);
|
||||||
void fs_inode_clear (fs_inode_t *inode);
|
void fs_inode_clear (fs_inode_t *inode);
|
||||||
void fs_inode_truncate (fs_inode_t *inode);
|
void fs_inode_truncate (fs_inode_t *inode, unsigned long size);
|
||||||
void fs_inode_print (fs_inode_t *inode, FILE *out);
|
void fs_inode_print (fs_inode_t *inode, FILE *out);
|
||||||
int fs_inode_read (fs_inode_t *inode, unsigned long offset,
|
int fs_inode_read (fs_inode_t *inode, unsigned long offset,
|
||||||
unsigned char *data, unsigned long bytes);
|
unsigned char *data, unsigned long bytes);
|
||||||
@@ -184,9 +184,9 @@ int fs_write_block (fs_t *fs, unsigned bnum, unsigned char *data);
|
|||||||
int fs_read_block (fs_t *fs, unsigned bnum, unsigned char *data);
|
int fs_read_block (fs_t *fs, unsigned bnum, unsigned char *data);
|
||||||
int fs_block_free (fs_t *fs, unsigned int bno);
|
int fs_block_free (fs_t *fs, unsigned int bno);
|
||||||
int fs_block_alloc (fs_t *fs, unsigned int *bno);
|
int fs_block_alloc (fs_t *fs, unsigned int *bno);
|
||||||
int fs_indirect_block_free (fs_t *fs, unsigned int bno);
|
int fs_indirect_block_free (fs_t *fs, unsigned int bno, int nblk);
|
||||||
int fs_double_indirect_block_free (fs_t *fs, unsigned int bno);
|
int fs_double_indirect_block_free (fs_t *fs, unsigned int bno, int nblk);
|
||||||
int fs_triple_indirect_block_free (fs_t *fs, unsigned int bno);
|
int fs_triple_indirect_block_free (fs_t *fs, unsigned int bno, int nblk);
|
||||||
|
|
||||||
void fs_directory_scan (fs_inode_t *inode, char *dirname,
|
void fs_directory_scan (fs_inode_t *inode, char *dirname,
|
||||||
fs_directory_scanner_t scanner, void *arg);
|
fs_directory_scanner_t scanner, void *arg);
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ int fs_file_create (fs_t *fs, fs_file_t *file, const char *name, int mode)
|
|||||||
/* Cannot open directory on write. */
|
/* Cannot open directory on write. */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
fs_inode_truncate (&file->inode);
|
fs_inode_truncate (&file->inode, 0);
|
||||||
fs_inode_save (&file->inode, 0);
|
fs_inode_save (&file->inode, 0);
|
||||||
file->writable = 1;
|
file->writable = 1;
|
||||||
file->offset = 0;
|
file->offset = 0;
|
||||||
|
|||||||
@@ -90,35 +90,46 @@ int fs_inode_get (fs_t *fs, fs_inode_t *inode, unsigned inum)
|
|||||||
* a contiguous free list much longer
|
* a contiguous free list much longer
|
||||||
* than FIFO.
|
* than FIFO.
|
||||||
*/
|
*/
|
||||||
void fs_inode_truncate (fs_inode_t *inode)
|
void fs_inode_truncate (fs_inode_t *inode, unsigned long size)
|
||||||
{
|
{
|
||||||
|
int i, nblk;
|
||||||
unsigned *blk;
|
unsigned *blk;
|
||||||
|
|
||||||
if ((inode->mode & INODE_MODE_FMT) == INODE_MODE_FCHR ||
|
if ((inode->mode & INODE_MODE_FMT) == INODE_MODE_FCHR ||
|
||||||
(inode->mode & INODE_MODE_FMT) == INODE_MODE_FBLK)
|
(inode->mode & INODE_MODE_FMT) == INODE_MODE_FBLK)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
#define SINGLE 4 /* index of single indirect block */
|
#define SINGLE NDADDR /* index of single indirect block */
|
||||||
#define DOUBLE 5 /* index of double indirect block */
|
#define DOUBLE (SINGLE+1) /* index of double indirect block */
|
||||||
#define TRIPLE 6 /* index of triple indirect block */
|
#define TRIPLE (DOUBLE+1) /* index of triple indirect block */
|
||||||
|
|
||||||
for (blk = &inode->addr[TRIPLE]; blk >= &inode->addr[0]; --blk) {
|
nblk = (size + BSDFS_BSIZE - 1) / BSDFS_BSIZE;
|
||||||
|
for (i=TRIPLE; i>=0; --i) {
|
||||||
|
blk = &inode->addr[i];
|
||||||
if (*blk == 0)
|
if (*blk == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (blk == &inode->addr [TRIPLE])
|
if (i == TRIPLE) {
|
||||||
fs_triple_indirect_block_free (inode->fs, *blk);
|
if (! fs_triple_indirect_block_free (inode->fs, *blk,
|
||||||
else if (blk == &inode->addr [DOUBLE])
|
nblk - (NDADDR + BSDFS_BSIZE/4 + BSDFS_BSIZE/4*BSDFS_BSIZE/4)))
|
||||||
fs_double_indirect_block_free (inode->fs, *blk);
|
break;
|
||||||
else if (blk == &inode->addr [SINGLE])
|
} else if (i == DOUBLE) {
|
||||||
fs_indirect_block_free (inode->fs, *blk);
|
if (! fs_double_indirect_block_free (inode->fs, *blk,
|
||||||
else
|
nblk - (NDADDR + BSDFS_BSIZE/4)))
|
||||||
|
break;
|
||||||
|
} else if (i == SINGLE) {
|
||||||
|
if (! fs_indirect_block_free (inode->fs, *blk, nblk - NDADDR))
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
if (i * BSDFS_BSIZE < size)
|
||||||
|
break;
|
||||||
fs_block_free (inode->fs, *blk);
|
fs_block_free (inode->fs, *blk);
|
||||||
|
}
|
||||||
|
|
||||||
*blk = 0;
|
*blk = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inode->size = 0;
|
inode->size = size;
|
||||||
inode->dirty = 1;
|
inode->dirty = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -743,7 +754,7 @@ delete_file:
|
|||||||
inode->dirty = 1;
|
inode->dirty = 1;
|
||||||
inode->nlink--;
|
inode->nlink--;
|
||||||
if (inode->nlink <= 0) {
|
if (inode->nlink <= 0) {
|
||||||
fs_inode_truncate (inode);
|
fs_inode_truncate (inode, 0);
|
||||||
fs_inode_clear (inode);
|
fs_inode_clear (inode);
|
||||||
if (inode->fs->ninode < NICINOD) {
|
if (inode->fs->ninode < NICINOD) {
|
||||||
inode->fs->inode [inode->fs->ninode++] = dirent.inum;
|
inode->fs->inode [inode->fs->ninode++] = dirent.inum;
|
||||||
|
|||||||
@@ -173,6 +173,12 @@ int op_open(const char *path, struct fuse_file_info *fi)
|
|||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((file.inode.mode & INODE_MODE_FMT) != INODE_MODE_FREG) {
|
||||||
|
/* Cannot open special files. */
|
||||||
|
file.inode.mode = 0;
|
||||||
|
return -ENXIO;
|
||||||
|
}
|
||||||
|
|
||||||
if (fi->flags & O_APPEND) {
|
if (fi->flags & O_APPEND) {
|
||||||
file.offset = file.inode.size;
|
file.offset = file.inode.size;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user