* added support for extra inode attributes in volumes with an inodesize of 256 or more:
this brings nanoseconds for access, change and modification times, and also brings creation time. * switched off some debug output * HTreeEntryIterator: fCount can equal fLimit. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@38964 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -91,8 +91,9 @@ HTreeEntryIterator::Init()
|
|||||||
fCount = countLimit->Count();
|
fCount = countLimit->Count();
|
||||||
fLimit = countLimit->Limit();
|
fLimit = countLimit->Limit();
|
||||||
|
|
||||||
if (fCount >= fLimit) {
|
if (fCount > fLimit) {
|
||||||
ERROR("HTreeEntryIterator::Init() bad fCount %lu\n", (uint32)fCount);
|
ERROR("HTreeEntryIterator::Init() bad fCount %u (fLimit %u)\n",
|
||||||
|
fCount, fLimit);
|
||||||
fCount = fLimit = 0;
|
fCount = fLimit = 0;
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,6 +43,10 @@ Inode::Inode(Volume* volume, ino_t id)
|
|||||||
|
|
||||||
fInitStatus = UpdateNodeFromDisk();
|
fInitStatus = UpdateNodeFromDisk();
|
||||||
if (fInitStatus == B_OK) {
|
if (fInitStatus == B_OK) {
|
||||||
|
fHasExtraAttributes = (fNodeSize == sizeof(ext2_inode)
|
||||||
|
&& fNode.ExtraInodeSize() + EXT2_INODE_NORMAL_SIZE
|
||||||
|
== sizeof(ext2_inode));
|
||||||
|
|
||||||
if (IsDirectory() || (IsSymLink() && Size() < 60)) {
|
if (IsDirectory() || (IsSymLink() && Size() < 60)) {
|
||||||
TRACE("Inode::Inode(): Not creating the file cache\n");
|
TRACE("Inode::Inode(): Not creating the file cache\n");
|
||||||
fCached = false;
|
fCached = false;
|
||||||
@@ -342,7 +346,9 @@ Inode::WriteAt(Transaction& transaction, off_t pos, const uint8* buffer,
|
|||||||
WriteLocker writeLocker(fLock);
|
WriteLocker writeLocker(fLock);
|
||||||
|
|
||||||
TRACE("Inode::WriteAt(): Updating modification time\n");
|
TRACE("Inode::WriteAt(): Updating modification time\n");
|
||||||
fNode.SetModificationTime(real_time_clock());
|
struct timespec timespec;
|
||||||
|
_BigtimeToTimespec(real_time_clock_usecs(), ×pec);
|
||||||
|
SetModificationTime(×pec);
|
||||||
|
|
||||||
// NOTE: Debugging info to find why sometimes resize doesn't happen
|
// NOTE: Debugging info to find why sometimes resize doesn't happen
|
||||||
size_t length = *_length;
|
size_t length = *_length;
|
||||||
@@ -699,10 +705,14 @@ Inode::Create(Transaction& transaction, Inode* parent, const char* name,
|
|||||||
node.SetGroupID(parent != NULL ? parent->Node().GroupID() : getegid());
|
node.SetGroupID(parent != NULL ? parent->Node().GroupID() : getegid());
|
||||||
node.SetNumLinks(inode->IsDirectory() ? 2 : 1);
|
node.SetNumLinks(inode->IsDirectory() ? 2 : 1);
|
||||||
TRACE("Inode::Create(): Updating time\n");
|
TRACE("Inode::Create(): Updating time\n");
|
||||||
time_t creationTime = real_time_clock();
|
struct timespec timespec;
|
||||||
node.SetAccessTime(creationTime);
|
_BigtimeToTimespec(real_time_clock_usecs(), ×pec);
|
||||||
node.SetCreationTime(creationTime);
|
inode->SetAccessTime(×pec);
|
||||||
node.SetModificationTime(creationTime);
|
inode->SetCreationTime(×pec);
|
||||||
|
inode->SetModificationTime(×pec);
|
||||||
|
|
||||||
|
if (sizeof(ext2_inode) < volume->InodeSize())
|
||||||
|
node.SetExtraInodeSize(sizeof(ext2_inode) - EXT2_INODE_NORMAL_SIZE);
|
||||||
|
|
||||||
TRACE("Inode::Create(): Updating ID\n");
|
TRACE("Inode::Create(): Updating ID\n");
|
||||||
inode->fID = id;
|
inode->fID = id;
|
||||||
@@ -963,3 +973,4 @@ Inode::_SetNumBlocks(uint64 numBlocks)
|
|||||||
fNode.SetNumBlocks64(numBlocks);
|
fNode.SetNumBlocks64(numBlocks);
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,14 @@
|
|||||||
#include "Volume.h"
|
#include "Volume.h"
|
||||||
|
|
||||||
|
|
||||||
|
//#define TRACE_EXT2
|
||||||
|
#ifdef TRACE_EXT2
|
||||||
|
# define TRACEI(x...) dprintf("\33[34mext2:\33[0m " x)
|
||||||
|
#else
|
||||||
|
# define TRACEI(x...) ;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
class Inode : public TransactionListener {
|
class Inode : public TransactionListener {
|
||||||
public:
|
public:
|
||||||
Inode(Volume* volume, ino_t id);
|
Inode(Volume* volume, ino_t id);
|
||||||
@@ -38,17 +46,33 @@ public:
|
|||||||
status_t CheckPermissions(int accessMode) const;
|
status_t CheckPermissions(int accessMode) const;
|
||||||
|
|
||||||
bool IsDeleted() const { return fUnlinked; }
|
bool IsDeleted() const { return fUnlinked; }
|
||||||
|
bool HasExtraAttributes() const
|
||||||
|
{ return fHasExtraAttributes; }
|
||||||
|
|
||||||
mode_t Mode() const { return fNode.Mode(); }
|
mode_t Mode() const { return fNode.Mode(); }
|
||||||
int32 Flags() const { return fNode.Flags(); }
|
int32 Flags() const { return fNode.Flags(); }
|
||||||
|
|
||||||
off_t Size() const { return fNode.Size(); }
|
off_t Size() const { return fNode.Size(); }
|
||||||
time_t ModificationTime() const
|
void GetChangeTime(struct timespec *timespec) const
|
||||||
{ return fNode.ModificationTime(); }
|
{ fNode.GetChangeTime(timespec, fHasExtraAttributes); }
|
||||||
time_t CreationTime() const
|
void GetModificationTime(struct timespec *timespec) const
|
||||||
{ return fNode.CreationTime(); }
|
{ fNode.GetModificationTime(timespec,
|
||||||
time_t AccessTime() const
|
fHasExtraAttributes); }
|
||||||
{ return fNode.AccessTime(); }
|
void GetCreationTime(struct timespec *timespec) const
|
||||||
|
{ fNode.GetCreationTime(timespec,
|
||||||
|
fHasExtraAttributes); }
|
||||||
|
void GetAccessTime(struct timespec *timespec) const
|
||||||
|
{ fNode.GetAccessTime(timespec, fHasExtraAttributes); }
|
||||||
|
void SetChangeTime(const struct timespec *timespec)
|
||||||
|
{ fNode.SetChangeTime(timespec, fHasExtraAttributes); }
|
||||||
|
void SetModificationTime(const struct timespec *timespec)
|
||||||
|
{ fNode.SetModificationTime(timespec,
|
||||||
|
fHasExtraAttributes); }
|
||||||
|
void SetCreationTime(const struct timespec *timespec)
|
||||||
|
{ fNode.SetCreationTime(timespec,
|
||||||
|
fHasExtraAttributes); }
|
||||||
|
void SetAccessTime(const struct timespec *timespec)
|
||||||
|
{ fNode.SetAccessTime(timespec, fHasExtraAttributes); }
|
||||||
|
|
||||||
//::Volume* _Volume() const { return fVolume; }
|
//::Volume* _Volume() const { return fVolume; }
|
||||||
Volume* GetVolume() const { return fVolume; }
|
Volume* GetVolume() const { return fVolume; }
|
||||||
@@ -76,6 +100,10 @@ public:
|
|||||||
ino_t* _id = NULL, Inode** _inode = NULL,
|
ino_t* _id = NULL, Inode** _inode = NULL,
|
||||||
fs_vnode_ops* vnodeOps = NULL,
|
fs_vnode_ops* vnodeOps = NULL,
|
||||||
uint32 publishFlags = 0);
|
uint32 publishFlags = 0);
|
||||||
|
static void _BigtimeToTimespec(bigtime_t time,
|
||||||
|
struct timespec *timespec)
|
||||||
|
{ timespec->tv_sec = time / 1000000LL;
|
||||||
|
timespec->tv_nsec = (time % 1000000LL) * 1000; }
|
||||||
|
|
||||||
void* FileCache() const { return fCache; }
|
void* FileCache() const { return fCache; }
|
||||||
void* Map() const { return fMap; }
|
void* Map() const { return fMap; }
|
||||||
@@ -85,6 +113,8 @@ public:
|
|||||||
|
|
||||||
status_t Sync();
|
status_t Sync();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void TransactionDone(bool success);
|
virtual void TransactionDone(bool success);
|
||||||
virtual void RemovedFromTransaction();
|
virtual void RemovedFromTransaction();
|
||||||
@@ -98,7 +128,8 @@ private:
|
|||||||
|
|
||||||
status_t _EnlargeDataStream(Transaction& transaction,
|
status_t _EnlargeDataStream(Transaction& transaction,
|
||||||
off_t size);
|
off_t size);
|
||||||
status_t _ShrinkDataStream(Transaction& transaction, off_t size);
|
status_t _ShrinkDataStream(Transaction& transaction,
|
||||||
|
off_t size);
|
||||||
|
|
||||||
uint64 _NumBlocks();
|
uint64 _NumBlocks();
|
||||||
status_t _SetNumBlocks(uint64 numBlocks);
|
status_t _SetNumBlocks(uint64 numBlocks);
|
||||||
@@ -110,9 +141,10 @@ private:
|
|||||||
void* fMap;
|
void* fMap;
|
||||||
bool fCached;
|
bool fCached;
|
||||||
bool fUnlinked;
|
bool fUnlinked;
|
||||||
|
bool fHasExtraAttributes;
|
||||||
ext2_inode fNode;
|
ext2_inode fNode;
|
||||||
uint32 fNodeSize;
|
uint32 fNodeSize;
|
||||||
// Inodes have a varible size, but the important
|
// Inodes have a variable size, but the important
|
||||||
// information is always the same size (except in ext4)
|
// information is always the same size (except in ext4)
|
||||||
ext2_xattr_header* fAttributesBlock;
|
ext2_xattr_header* fAttributesBlock;
|
||||||
status_t fInitStatus;
|
status_t fInitStatus;
|
||||||
@@ -173,31 +205,31 @@ public:
|
|||||||
|
|
||||||
void Keep()
|
void Keep()
|
||||||
{
|
{
|
||||||
dprintf("Vnode::Keep()\n");
|
TRACEI("Vnode::Keep()\n");
|
||||||
fInode = NULL;
|
fInode = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
status_t Publish(Transaction& transaction, Inode* inode,
|
status_t Publish(Transaction& transaction, Inode* inode,
|
||||||
fs_vnode_ops* vnodeOps, uint32 publishFlags)
|
fs_vnode_ops* vnodeOps, uint32 publishFlags)
|
||||||
{
|
{
|
||||||
dprintf("Vnode::Publish()\n");
|
TRACEI("Vnode::Publish()\n");
|
||||||
Volume* volume = transaction.GetVolume();
|
Volume* volume = transaction.GetVolume();
|
||||||
|
|
||||||
status_t status = B_OK;
|
status_t status = B_OK;
|
||||||
|
|
||||||
if (!inode->IsSymLink() && volume->ID() >= 0) {
|
if (!inode->IsSymLink() && volume->ID() >= 0) {
|
||||||
dprintf("Vnode::Publish(): Publishing vnode: %d, %d, %p, %p, %x, "
|
TRACEI("Vnode::Publish(): Publishing vnode: %d, %d, %p, %p, %x, "
|
||||||
"%x\n", (int)volume->FSVolume(), (int)inode->ID(), inode,
|
"%x\n", (int)volume->FSVolume(), (int)inode->ID(), inode,
|
||||||
vnodeOps != NULL ? vnodeOps : &gExt2VnodeOps, (int)inode->Mode(),
|
vnodeOps != NULL ? vnodeOps : &gExt2VnodeOps, (int)inode->Mode(),
|
||||||
(int)publishFlags);
|
(int)publishFlags);
|
||||||
status = publish_vnode(volume->FSVolume(), inode->ID(), inode,
|
status = publish_vnode(volume->FSVolume(), inode->ID(), inode,
|
||||||
vnodeOps != NULL ? vnodeOps : &gExt2VnodeOps, inode->Mode(),
|
vnodeOps != NULL ? vnodeOps : &gExt2VnodeOps, inode->Mode(),
|
||||||
publishFlags);
|
publishFlags);
|
||||||
dprintf("Vnode::Publish(): Result: %s\n", strerror(status));
|
TRACEI("Vnode::Publish(): Result: %s\n", strerror(status));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status == B_OK) {
|
if (status == B_OK) {
|
||||||
dprintf("Vnode::Publish(): Preparing internal data\n");
|
TRACEI("Vnode::Publish(): Preparing internal data\n");
|
||||||
fInode = inode;
|
fInode = inode;
|
||||||
fStatus = B_OK;
|
fStatus = B_OK;
|
||||||
|
|
||||||
|
|||||||
@@ -210,19 +210,21 @@ struct ext2_data_stream {
|
|||||||
uint32 triple_indirect;
|
uint32 triple_indirect;
|
||||||
} _PACKED;
|
} _PACKED;
|
||||||
|
|
||||||
|
#define EXT2_INODE_NORMAL_SIZE 128
|
||||||
|
|
||||||
struct ext2_inode {
|
struct ext2_inode {
|
||||||
uint16 mode;
|
uint16 mode;
|
||||||
uint16 uid;
|
uint16 uid;
|
||||||
uint32 size;
|
uint32 size;
|
||||||
uint32 access_time;
|
uint32 access_time;
|
||||||
uint32 creation_time;
|
uint32 change_time;
|
||||||
uint32 modification_time;
|
uint32 modification_time;
|
||||||
uint32 deletion_time;
|
uint32 deletion_time;
|
||||||
uint16 gid;
|
uint16 gid;
|
||||||
uint16 num_links;
|
uint16 num_links;
|
||||||
uint32 num_blocks;
|
uint32 num_blocks;
|
||||||
uint32 flags;
|
uint32 flags;
|
||||||
uint32 _reserved1;
|
uint32 version;
|
||||||
union {
|
union {
|
||||||
ext2_data_stream stream;
|
ext2_data_stream stream;
|
||||||
char symlink[EXT2_SHORT_SYMLINK_LENGTH];
|
char symlink[EXT2_SHORT_SYMLINK_LENGTH];
|
||||||
@@ -246,8 +248,16 @@ struct ext2_inode {
|
|||||||
uint16 uid_high;
|
uint16 uid_high;
|
||||||
uint16 gid_high;
|
uint16 gid_high;
|
||||||
uint32 _reserved2;
|
uint32 _reserved2;
|
||||||
|
|
||||||
|
// extra attributes
|
||||||
uint16 extra_inode_size;
|
uint16 extra_inode_size;
|
||||||
uint16 _padding2;
|
uint16 _padding2;
|
||||||
|
uint32 change_time_extra;
|
||||||
|
uint32 modification_time_extra;
|
||||||
|
uint32 access_time_extra;
|
||||||
|
uint32 creation_time;
|
||||||
|
uint32 creation_time_extra;
|
||||||
|
uint32 version_high;
|
||||||
|
|
||||||
uint16 Mode() const { return B_LENDIAN_TO_HOST_INT16(mode); }
|
uint16 Mode() const { return B_LENDIAN_TO_HOST_INT16(mode); }
|
||||||
uint32 Flags() const { return B_LENDIAN_TO_HOST_INT32(flags); }
|
uint32 Flags() const { return B_LENDIAN_TO_HOST_INT32(flags); }
|
||||||
@@ -256,10 +266,77 @@ struct ext2_inode {
|
|||||||
uint64 NumBlocks64() const { return B_LENDIAN_TO_HOST_INT32(num_blocks)
|
uint64 NumBlocks64() const { return B_LENDIAN_TO_HOST_INT32(num_blocks)
|
||||||
| ((uint64)B_LENDIAN_TO_HOST_INT32(num_blocks_high) << 32); }
|
| ((uint64)B_LENDIAN_TO_HOST_INT32(num_blocks_high) << 32); }
|
||||||
|
|
||||||
time_t AccessTime() const { return B_LENDIAN_TO_HOST_INT32(access_time); }
|
static void _DecodeTime(struct timespec *timespec, uint32 time,
|
||||||
time_t CreationTime() const { return B_LENDIAN_TO_HOST_INT32(creation_time); }
|
uint32 time_extra, bool extra)
|
||||||
time_t ModificationTime() const { return B_LENDIAN_TO_HOST_INT32(modification_time); }
|
{
|
||||||
time_t DeletionTime() const { return B_LENDIAN_TO_HOST_INT32(deletion_time); }
|
timespec->tv_sec = B_LENDIAN_TO_HOST_INT32(time);
|
||||||
|
if (extra && sizeof(timespec->tv_sec) > 4)
|
||||||
|
timespec->tv_sec |=
|
||||||
|
(uint64)(B_LENDIAN_TO_HOST_INT32(time_extra) & 0x2) << 32;
|
||||||
|
if (extra)
|
||||||
|
timespec->tv_nsec = B_LENDIAN_TO_HOST_INT32(time_extra) >> 2;
|
||||||
|
else
|
||||||
|
timespec->tv_nsec = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GetModificationTime(struct timespec *timespec, bool extra) const
|
||||||
|
{ _DecodeTime(timespec, modification_time, modification_time_extra,
|
||||||
|
extra); }
|
||||||
|
void GetAccessTime(struct timespec *timespec, bool extra) const
|
||||||
|
{ _DecodeTime(timespec, access_time, access_time_extra, extra); }
|
||||||
|
void GetChangeTime(struct timespec *timespec, bool extra) const
|
||||||
|
{ _DecodeTime(timespec, change_time, change_time_extra, extra); }
|
||||||
|
void GetCreationTime(struct timespec *timespec, bool extra) const
|
||||||
|
{
|
||||||
|
if (extra)
|
||||||
|
_DecodeTime(timespec, creation_time, creation_time_extra, extra);
|
||||||
|
else {
|
||||||
|
timespec->tv_sec = 0;
|
||||||
|
timespec->tv_nsec = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
time_t DeletionTime() const
|
||||||
|
{ return B_LENDIAN_TO_HOST_INT32(deletion_time); }
|
||||||
|
|
||||||
|
static uint32 _EncodeTime(const struct timespec *timespec)
|
||||||
|
{
|
||||||
|
uint32 time = (timespec->tv_nsec << 2) & 0xfffffffc;
|
||||||
|
if (sizeof(timespec->tv_sec) > 4)
|
||||||
|
time |= (uint64)timespec->tv_sec >> 32;
|
||||||
|
return B_HOST_TO_LENDIAN_INT32(time);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetModificationTime(const struct timespec *timespec, bool extra)
|
||||||
|
{
|
||||||
|
modification_time = B_HOST_TO_LENDIAN_INT32((uint32)timespec->tv_sec);
|
||||||
|
if (extra)
|
||||||
|
modification_time_extra = _EncodeTime(timespec);
|
||||||
|
}
|
||||||
|
void SetAccessTime(const struct timespec *timespec, bool extra)
|
||||||
|
{
|
||||||
|
access_time = B_HOST_TO_LENDIAN_INT32((uint32)timespec->tv_sec);
|
||||||
|
if (extra)
|
||||||
|
access_time_extra = _EncodeTime(timespec);
|
||||||
|
}
|
||||||
|
void SetChangeTime(const struct timespec *timespec, bool extra)
|
||||||
|
{
|
||||||
|
change_time = B_HOST_TO_LENDIAN_INT32((uint32)timespec->tv_sec);
|
||||||
|
if (extra)
|
||||||
|
change_time_extra = _EncodeTime(timespec);
|
||||||
|
}
|
||||||
|
void SetCreationTime(const struct timespec *timespec, bool extra)
|
||||||
|
{
|
||||||
|
if (extra) {
|
||||||
|
creation_time = B_HOST_TO_LENDIAN_INT32((uint32)timespec->tv_sec);
|
||||||
|
creation_time_extra =
|
||||||
|
B_HOST_TO_LENDIAN_INT32((uint32)timespec->tv_nsec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void SetDeletionTime(time_t deletionTime)
|
||||||
|
{
|
||||||
|
deletion_time = B_HOST_TO_LENDIAN_INT32((uint32)deletionTime);
|
||||||
|
}
|
||||||
|
|
||||||
ino_t NextOrphan() const { return (ino_t)DeletionTime(); }
|
ino_t NextOrphan() const { return (ino_t)DeletionTime(); }
|
||||||
|
|
||||||
off_t Size() const
|
off_t Size() const
|
||||||
@@ -272,6 +349,9 @@ struct ext2_inode {
|
|||||||
return B_LENDIAN_TO_HOST_INT32(size);
|
return B_LENDIAN_TO_HOST_INT32(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint16 ExtraInodeSize() const
|
||||||
|
{ return B_LENDIAN_TO_HOST_INT16(extra_inode_size); }
|
||||||
|
|
||||||
uint32 UserID() const
|
uint32 UserID() const
|
||||||
{
|
{
|
||||||
return B_LENDIAN_TO_HOST_INT16(uid)
|
return B_LENDIAN_TO_HOST_INT16(uid)
|
||||||
@@ -325,26 +405,6 @@ struct ext2_inode {
|
|||||||
num_blocks_high = B_HOST_TO_LENDIAN_INT32(numBlocks >> 32);
|
num_blocks_high = B_HOST_TO_LENDIAN_INT32(numBlocks >> 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetAccessTime(time_t accessTime)
|
|
||||||
{
|
|
||||||
access_time = B_HOST_TO_LENDIAN_INT32((uint32)accessTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetCreationTime(time_t creationTime)
|
|
||||||
{
|
|
||||||
creation_time = B_HOST_TO_LENDIAN_INT32((uint32)creationTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetModificationTime(time_t modificationTime)
|
|
||||||
{
|
|
||||||
modification_time = B_HOST_TO_LENDIAN_INT32((uint32)modificationTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetDeletionTime(time_t deletionTime)
|
|
||||||
{
|
|
||||||
deletion_time = B_HOST_TO_LENDIAN_INT32((uint32)deletionTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetNextOrphan(ino_t id)
|
void SetNextOrphan(ino_t id)
|
||||||
{
|
{
|
||||||
deletion_time = B_HOST_TO_LENDIAN_INT32((uint32)id);
|
deletion_time = B_HOST_TO_LENDIAN_INT32((uint32)id);
|
||||||
@@ -373,6 +433,11 @@ struct ext2_inode {
|
|||||||
{
|
{
|
||||||
file_access_control = B_HOST_TO_LENDIAN_INT32(block);
|
file_access_control = B_HOST_TO_LENDIAN_INT32(block);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetExtraInodeSize(uint16 newSize)
|
||||||
|
{
|
||||||
|
extra_inode_size = B_HOST_TO_LENDIAN_INT16(newSize);
|
||||||
|
}
|
||||||
} _PACKED;
|
} _PACKED;
|
||||||
|
|
||||||
#define EXT2_SUPER_BLOCK_MAGIC 0xef53
|
#define EXT2_SUPER_BLOCK_MAGIC 0xef53
|
||||||
|
|||||||
@@ -550,9 +550,10 @@ ext2_read_stat(fs_volume* _volume, fs_vnode* _node, struct stat* stat)
|
|||||||
stat->st_mode = node.Mode();
|
stat->st_mode = node.Mode();
|
||||||
stat->st_type = 0;
|
stat->st_type = 0;
|
||||||
|
|
||||||
stat->st_atime = node.AccessTime();
|
inode->GetAccessTime(&stat->st_atim);
|
||||||
stat->st_mtime = stat->st_ctime = node.ModificationTime();
|
inode->GetModificationTime(&stat->st_mtim);
|
||||||
stat->st_crtime = node.CreationTime();
|
inode->GetChangeTime(&stat->st_ctim);
|
||||||
|
inode->GetCreationTime(&stat->st_crtim);
|
||||||
|
|
||||||
stat->st_size = inode->Size();
|
stat->st_size = inode->Size();
|
||||||
stat->st_blocks = (inode->Size() + 511) / 512;
|
stat->st_blocks = (inode->Size() + 511) / 512;
|
||||||
@@ -626,22 +627,22 @@ ext2_write_stat(fs_volume* _volume, fs_vnode* _node, const struct stat* stat,
|
|||||||
|
|
||||||
if ((mask & B_STAT_MODIFICATION_TIME) != 0 || updateTime
|
if ((mask & B_STAT_MODIFICATION_TIME) != 0 || updateTime
|
||||||
|| (mask & B_STAT_CHANGE_TIME) != 0) {
|
|| (mask & B_STAT_CHANGE_TIME) != 0) {
|
||||||
time_t newTime = 0;
|
struct timespec newTimespec = { 0, 0};
|
||||||
|
|
||||||
if ((mask & B_STAT_MODIFICATION_TIME) != 0)
|
if ((mask & B_STAT_MODIFICATION_TIME) != 0)
|
||||||
newTime = stat->st_mtim.tv_sec;
|
newTimespec = stat->st_mtim;
|
||||||
|
|
||||||
if ((mask & B_STAT_CHANGE_TIME) != 0)
|
if ((mask & B_STAT_CHANGE_TIME) != 0
|
||||||
newTime = newTime > stat->st_ctim.tv_sec ? newTime
|
&& stat->st_ctim.tv_sec > newTimespec.tv_sec)
|
||||||
: stat->st_ctim.tv_sec;
|
newTimespec = stat->st_ctim;
|
||||||
|
|
||||||
if (newTime == 0)
|
if (newTimespec.tv_sec == 0)
|
||||||
newTime = real_time_clock();
|
Inode::_BigtimeToTimespec(real_time_clock_usecs(), &newTimespec);
|
||||||
|
|
||||||
node.SetModificationTime(newTime);
|
inode->SetModificationTime(&newTimespec);
|
||||||
}
|
}
|
||||||
if ((mask & B_STAT_CREATION_TIME) != 0)
|
if ((mask & B_STAT_CREATION_TIME) != 0)
|
||||||
node.SetCreationTime(stat->st_crtim.tv_sec);
|
inode->SetCreationTime(&stat->st_crtim);
|
||||||
|
|
||||||
status = inode->WriteBack(transaction);
|
status = inode->WriteBack(transaction);
|
||||||
if (status == B_OK)
|
if (status == B_OK)
|
||||||
|
|||||||
Reference in New Issue
Block a user