Implemented write stat.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@29260 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Lotz
2009-02-19 22:40:30 +00:00
parent 77b26c3221
commit 66728ad8b8
@@ -76,6 +76,7 @@ public:
ino_t InodeNumber() { return fInodeNumber; } ino_t InodeNumber() { return fInodeNumber; }
status_t ReadStat(struct stat *stat); status_t ReadStat(struct stat *stat);
status_t WriteStat(const struct stat *stat, uint32 statMask);
status_t Open(int openMode, void **cookie); status_t Open(int openMode, void **cookie);
status_t Close(void *cookie); status_t Close(void *cookie);
@@ -91,8 +92,8 @@ private:
ino_t fInodeNumber; ino_t fInodeNumber;
write_buffer * fWriteBuffers; write_buffer * fWriteBuffers;
off_t fOriginalNodeLength; off_t fOriginalNodeLength;
off_t fCurrentNodeLength; struct stat fStat;
time_t fModificationTime; bool fHasStat;
}; };
@@ -120,7 +121,7 @@ OverlayInode::OverlayInode(OverlayVolume *volume, fs_vnode *superVnode,
fInodeNumber(inodeNumber), fInodeNumber(inodeNumber),
fWriteBuffers(NULL), fWriteBuffers(NULL),
fOriginalNodeLength(-1), fOriginalNodeLength(-1),
fCurrentNodeLength(-1) fHasStat(false)
{ {
TRACE("inode created\n"); TRACE("inode created\n");
} }
@@ -148,21 +149,55 @@ OverlayInode::InitCheck()
status_t status_t
OverlayInode::ReadStat(struct stat *stat) OverlayInode::ReadStat(struct stat *stat)
{ {
if (fSuperVnode.ops->read_stat == NULL) if (!fHasStat) {
return B_UNSUPPORTED; if (fSuperVnode.ops->read_stat == NULL)
return B_UNSUPPORTED;
status_t result = fSuperVnode.ops->read_stat(SuperVolume(), &fSuperVnode, status_t result = fSuperVnode.ops->read_stat(SuperVolume(),
stat); &fSuperVnode, &fStat);
if (result != B_OK) if (result != B_OK)
return result; return result;
if (fCurrentNodeLength >= 0) { fHasStat = true;
stat->st_size = fCurrentNodeLength;
stat->st_blocks = (stat->st_size + stat->st_blksize - 1)
/ stat->st_blksize;
stat->st_mtime = fModificationTime;
} }
if (stat == NULL)
return B_OK;
memcpy(stat, &fStat, sizeof(struct stat));
stat->st_blocks = (stat->st_size + stat->st_blksize - 1) / stat->st_blksize;
return B_OK;
}
status_t
OverlayInode::WriteStat(const struct stat *stat, uint32 statMask)
{
if (!fHasStat)
ReadStat(NULL);
if (statMask & B_STAT_SIZE)
fStat.st_size = stat->st_size;
if (statMask & B_STAT_MODE)
fStat.st_mode = stat->st_mode;
if (statMask & B_STAT_UID)
fStat.st_uid = stat->st_uid;
if (statMask & B_STAT_GID)
fStat.st_gid = stat->st_gid;
if (statMask & B_STAT_MODIFICATION_TIME)
fStat.st_mtime = stat->st_mtime;
if (statMask & B_STAT_CREATION_TIME)
fStat.st_crtime = stat->st_crtime;
if ((statMask & (B_STAT_MODE | B_STAT_UID | B_STAT_GID)) != 0
&& (statMask & B_STAT_MODIFICATION_TIME) == 0) {
fStat.st_mtime = time(NULL);
statMask |= B_STAT_MODIFICATION_TIME;
}
notify_stat_changed(SuperVolume()->id, fInodeNumber, statMask);
return B_OK; return B_OK;
} }
@@ -181,21 +216,17 @@ OverlayInode::Open(int openMode, void **_cookie)
struct stat stat; struct stat stat;
status_t result = fSuperVnode.ops->read_stat(SuperVolume(), status_t result = fSuperVnode.ops->read_stat(SuperVolume(),
&fSuperVnode, &stat); &fSuperVnode, &stat);
if (result != B_OK) { if (result != B_OK)
free(cookie);
return result; return result;
}
fOriginalNodeLength = stat.st_size; fOriginalNodeLength = stat.st_size;
fCurrentNodeLength = stat.st_size;
fModificationTime = stat.st_mtime;
} }
cookie->open_mode = openMode; cookie->open_mode = openMode;
*_cookie = cookie; *_cookie = cookie;
if (openMode & O_TRUNC) if (openMode & O_TRUNC)
fCurrentNodeLength = 0; fStat.st_size = 0;
openMode &= ~(O_RDWR | O_WRONLY | O_TRUNC | O_CREAT); openMode &= ~(O_RDWR | O_WRONLY | O_TRUNC | O_CREAT);
status_t result = fSuperVnode.ops->open(SuperVolume(), &fSuperVnode, status_t result = fSuperVnode.ops->open(SuperVolume(), &fSuperVnode,
@@ -232,7 +263,7 @@ OverlayInode::FreeCookie(void *_cookie)
status_t status_t
OverlayInode::Read(void *_cookie, off_t position, void *buffer, size_t *length) OverlayInode::Read(void *_cookie, off_t position, void *buffer, size_t *length)
{ {
if (position >= fCurrentNodeLength) { if (position >= fStat.st_size) {
*length = 0; *length = 0;
return B_OK; return B_OK;
} }
@@ -244,11 +275,15 @@ OverlayInode::Read(void *_cookie, off_t position, void *buffer, size_t *length)
cookie->super_cookie, position, buffer, &readLength); cookie->super_cookie, position, buffer, &readLength);
if (result != B_OK) if (result != B_OK)
return result; return result;
}
if (readLength < *length)
memset((uint8 *)buffer + readLength, 0, *length - readLength);
} else
memset(buffer, 0, *length);
// overlay the read with whatever chunks we have written // overlay the read with whatever chunks we have written
write_buffer *element = fWriteBuffers; write_buffer *element = fWriteBuffers;
*length = MIN(fCurrentNodeLength - position, *length); *length = MIN(fStat.st_size - position, *length);
off_t end = position + *length; off_t end = position + *length;
while (element) { while (element) {
if (element->position > end) if (element->position > end)
@@ -307,7 +342,7 @@ OverlayInode::Write(void *_cookie, off_t position, const void *buffer,
memcpy(other->buffer + (newPosition - other->position), memcpy(other->buffer + (newPosition - other->position),
buffer, *length); buffer, *length);
fModificationTime = time(NULL); fStat.st_mtime = time(NULL);
notify_stat_changed(SuperVolume()->id, fInodeNumber, notify_stat_changed(SuperVolume()->id, fInodeNumber,
B_STAT_MODIFICATION_TIME); B_STAT_MODIFICATION_TIME);
return B_OK; return B_OK;
@@ -335,8 +370,8 @@ OverlayInode::Write(void *_cookie, off_t position, const void *buffer,
bool sizeChanged = false; bool sizeChanged = false;
off_t newEnd = newPosition + newLength; off_t newEnd = newPosition + newLength;
if (newEnd > fCurrentNodeLength) { if (newEnd > fStat.st_size) {
fCurrentNodeLength = newEnd; fStat.st_size = newEnd;
sizeChanged = true; sizeChanged = true;
} }
@@ -354,10 +389,9 @@ OverlayInode::Write(void *_cookie, off_t position, const void *buffer,
memcpy(element->buffer + (position - newPosition), buffer, *length); memcpy(element->buffer + (position - newPosition), buffer, *length);
fModificationTime = time(NULL); fStat.st_mtime = time(NULL);
notify_stat_changed(SuperVolume()->id, fInodeNumber, notify_stat_changed(SuperVolume()->id, fInodeNumber,
B_STAT_MODIFICATION_TIME | (sizeChanged ? B_STAT_SIZE : 0)); B_STAT_MODIFICATION_TIME | (sizeChanged ? B_STAT_SIZE : 0));
return B_OK; return B_OK;
} }
@@ -613,8 +647,7 @@ static status_t
overlay_write_stat(fs_volume *volume, fs_vnode *vnode, const struct stat *stat, overlay_write_stat(fs_volume *volume, fs_vnode *vnode, const struct stat *stat,
uint32 statMask) uint32 statMask)
{ {
OVERLAY_CALL(write_stat, stat, statMask) return ((OverlayInode *)vnode->private_node)->WriteStat(stat, statMask);
return B_UNSUPPORTED;
} }
@@ -974,7 +1007,7 @@ overlay_read_fs_info(fs_volume *volume, struct fs_info *info)
if (result != B_OK) if (result != B_OK)
return result; return result;
info->flags &= ~(B_FS_IS_READONLY | B_FS_IS_PERSISTENT); info->flags &= ~B_FS_IS_READONLY;
return B_OK; return B_OK;
} }