* Added stat::st_blocks field as required by POSIX. This also closes ticket
#2261. * Made at least BFS report it more or less correctly (the attributes are ignored, though). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@27791 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -10,15 +10,15 @@
|
|||||||
|
|
||||||
|
|
||||||
struct stat {
|
struct stat {
|
||||||
dev_t st_dev; /* "device" that this file resides on */
|
dev_t st_dev; /* device ID that this file resides on */
|
||||||
ino_t st_ino; /* this file's inode #, unique per device */
|
ino_t st_ino; /* this file's serial inode ID */
|
||||||
mode_t st_mode; /* mode bits (rwx for user, group, etc) */
|
mode_t st_mode; /* file mode (rwx for user, group, etc) */
|
||||||
nlink_t st_nlink; /* number of hard links to this file */
|
nlink_t st_nlink; /* number of hard links to this file */
|
||||||
uid_t st_uid; /* user id of the owner of this file */
|
uid_t st_uid; /* user ID of the owner of this file */
|
||||||
gid_t st_gid; /* group id of the owner of this file */
|
gid_t st_gid; /* group ID of the owner of this file */
|
||||||
off_t st_size; /* size in bytes of this file */
|
off_t st_size; /* size in bytes of this file */
|
||||||
dev_t st_rdev; /* device type (not used) */
|
dev_t st_rdev; /* device type (not used) */
|
||||||
size_t st_blksize; /* preferred block size for i/o */
|
blksize_t st_blksize; /* preferred block size for I/O */
|
||||||
time_t st_atime; /* last access time */
|
time_t st_atime; /* last access time */
|
||||||
time_t st_mtime; /* last modification time */
|
time_t st_mtime; /* last modification time */
|
||||||
time_t st_ctime; /* last change time, not creation time */
|
time_t st_ctime; /* last change time, not creation time */
|
||||||
@@ -29,6 +29,7 @@ struct stat {
|
|||||||
* TODO: we should find another solution for this, as BStatable::GetStat()
|
* TODO: we should find another solution for this, as BStatable::GetStat()
|
||||||
* can only retrieve the R5 stat structure */
|
* can only retrieve the R5 stat structure */
|
||||||
unsigned int st_type; /* attribute/index type */
|
unsigned int st_type; /* attribute/index type */
|
||||||
|
blkcnt_t st_blocks; /* number of blocks allocated for object */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* extended file types */
|
/* extended file types */
|
||||||
|
|||||||
@@ -1224,6 +1224,7 @@
|
|||||||
#define st_ctime fssh_st_ctime
|
#define st_ctime fssh_st_ctime
|
||||||
#define st_crtime fssh_st_crtime
|
#define st_crtime fssh_st_crtime
|
||||||
#define st_type fssh_st_type
|
#define st_type fssh_st_type
|
||||||
|
#define st_blocks fssh_st_blocks
|
||||||
|
|
||||||
/* extended file types */
|
/* extended file types */
|
||||||
#define S_ATTR_DIR FSSH_S_ATTR_DIR
|
#define S_ATTR_DIR FSSH_S_ATTR_DIR
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ struct fssh_stat {
|
|||||||
// TODO: we should find another solution for this, as BStatable::GetStat()
|
// TODO: we should find another solution for this, as BStatable::GetStat()
|
||||||
// can only retrieve the R5 stat structure
|
// can only retrieve the R5 stat structure
|
||||||
unsigned int fssh_st_type; /* attribute/index type */
|
unsigned int fssh_st_type; /* attribute/index type */
|
||||||
|
fssh_off_t fssh_st_blocks; /* number of blocks allocated for object */
|
||||||
};
|
};
|
||||||
typedef struct fssh_stat fssh_struct_stat;
|
typedef struct fssh_stat fssh_struct_stat;
|
||||||
|
|
||||||
|
|||||||
@@ -1275,6 +1275,48 @@ Inode::IsEmpty()
|
|||||||
// #pragma mark - data stream
|
// #pragma mark - data stream
|
||||||
|
|
||||||
|
|
||||||
|
/*! Computes the number of bytes this inode occupies in the file system.
|
||||||
|
This includes the file meta blocks used for maintaining its data stream.
|
||||||
|
|
||||||
|
TODO: However, the attributes in extra files are not really accounted for;
|
||||||
|
depending on the speed penalty, this should be changed, though (the value
|
||||||
|
could be cached in the inode structure or Inode object, though).
|
||||||
|
*/
|
||||||
|
off_t
|
||||||
|
Inode::AllocatedSize() const
|
||||||
|
{
|
||||||
|
if (IsSymLink() && (Flags() & INODE_LONG_SYMLINK) == 0) {
|
||||||
|
// This symlink does not have a data stream
|
||||||
|
return Node().InodeSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
const data_stream& data = Node().data;
|
||||||
|
uint32 blockSize = fVolume->BlockSize();
|
||||||
|
off_t size = blockSize;
|
||||||
|
|
||||||
|
if (data.MaxDoubleIndirectRange() != 0) {
|
||||||
|
off_t doubleIndirectSize = data.MaxDoubleIndirectRange()
|
||||||
|
- data.MaxIndirectRange();
|
||||||
|
int32 indirectSize = (1L << (INDIRECT_BLOCKS_SHIFT
|
||||||
|
+ fVolume->BlockShift())) * (blockSize / sizeof(block_run));
|
||||||
|
|
||||||
|
size += (2 * NUM_ARRAY_BLOCKS + doubleIndirectSize / indirectSize)
|
||||||
|
* blockSize + data.MaxDoubleIndirectRange();
|
||||||
|
} else if (data.MaxIndirectRange() != 0)
|
||||||
|
size += NUM_ARRAY_BLOCKS + data.MaxIndirectRange();
|
||||||
|
else
|
||||||
|
size += data.MaxDirectRange();
|
||||||
|
|
||||||
|
if (!Node().attributes.IsZero()) {
|
||||||
|
// TODO: to make this exact, we'd had to count all attributes
|
||||||
|
size += 2 * blockSize;
|
||||||
|
// 2 blocks, one for the attributes inode, one for its B+tree
|
||||||
|
}
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! Finds the block_run where "pos" is located in the data_stream of
|
/*! Finds the block_run where "pos" is located in the data_stream of
|
||||||
the inode.
|
the inode.
|
||||||
If successful, "offset" will then be set to the file offset
|
If successful, "offset" will then be set to the file offset
|
||||||
|
|||||||
@@ -76,8 +76,9 @@ public:
|
|||||||
int32 Flags() const { return fNode.Flags(); }
|
int32 Flags() const { return fNode.Flags(); }
|
||||||
|
|
||||||
off_t Size() const { return fNode.data.Size(); }
|
off_t Size() const { return fNode.data.Size(); }
|
||||||
|
off_t AllocatedSize() const;
|
||||||
off_t LastModified() const
|
off_t LastModified() const
|
||||||
{ return fNode.last_modified_time; }
|
{ return fNode.LastModifiedTime(); }
|
||||||
|
|
||||||
const block_run& BlockRun() const
|
const block_run& BlockRun() const
|
||||||
{ return fNode.inode_num; }
|
{ return fNode.inode_num; }
|
||||||
|
|||||||
@@ -50,11 +50,14 @@ fill_stat_buffer(Inode* inode, struct stat& stat)
|
|||||||
stat.st_mtime = stat.st_ctime = (time_t)(node.LastModifiedTime() >> INODE_TIME_SHIFT);
|
stat.st_mtime = stat.st_ctime = (time_t)(node.LastModifiedTime() >> INODE_TIME_SHIFT);
|
||||||
stat.st_crtime = (time_t)(node.CreateTime() >> INODE_TIME_SHIFT);
|
stat.st_crtime = (time_t)(node.CreateTime() >> INODE_TIME_SHIFT);
|
||||||
|
|
||||||
if (inode->IsSymLink() && (node.Flags() & INODE_LONG_SYMLINK) == 0) {
|
if (inode->IsSymLink() && (inode->Flags() & INODE_LONG_SYMLINK) == 0) {
|
||||||
// symlinks report the size of the link here
|
// symlinks report the size of the link here
|
||||||
stat.st_size = strlen(node.short_symlink);
|
stat.st_size = strlen(node.short_symlink);
|
||||||
} else
|
} else
|
||||||
stat.st_size = inode->Size();
|
stat.st_size = inode->Size();
|
||||||
|
|
||||||
|
stat.st_blocks = inode->AllocatedSize() / node.InodeSize();
|
||||||
|
// TODO: decide for a unit to use for st_blocks!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user