* Fix missing initialization of the entry size on SetSize() that'd cause some
attribute writes to not be visible. * Don't read past the current node size when emulating write support. * Fix writing calculations so that writing actually works as intended. * Actually follow the linked list when joining write_buffers instead of using the same pointer that becomes invalid after the first iteration. * Small optimizations. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@29251 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -422,6 +422,11 @@ 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 (fVolume->WriteSupport()) {
|
if (fVolume->WriteSupport()) {
|
||||||
|
if (position >= fCurrentNodeLength) {
|
||||||
|
*length = 0;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
if (position < fOriginalNodeLength) {
|
if (position < fOriginalNodeLength) {
|
||||||
open_cookie *cookie = (open_cookie *)_cookie;
|
open_cookie *cookie = (open_cookie *)_cookie;
|
||||||
size_t readLength = MIN(fOriginalNodeLength - position, *length);
|
size_t readLength = MIN(fOriginalNodeLength - position, *length);
|
||||||
@@ -436,8 +441,11 @@ OverlayInode::Read(void *_cookie, off_t position, void *buffer, size_t *length)
|
|||||||
*length = MIN(fCurrentNodeLength - position, *length);
|
*length = MIN(fCurrentNodeLength - position, *length);
|
||||||
off_t end = position + *length;
|
off_t end = position + *length;
|
||||||
while (element) {
|
while (element) {
|
||||||
|
if (element->position > end)
|
||||||
|
break;
|
||||||
|
|
||||||
off_t elementEnd = element->position + element->length;
|
off_t elementEnd = element->position + element->length;
|
||||||
if (elementEnd > position && element->position < end) {
|
if (elementEnd > position) {
|
||||||
off_t copyPosition = MAX(position, element->position);
|
off_t copyPosition = MAX(position, element->position);
|
||||||
size_t copyLength = MIN(elementEnd - position, *length);
|
size_t copyLength = MIN(elementEnd - position, *length);
|
||||||
memcpy((uint8 *)buffer + (copyPosition - position),
|
memcpy((uint8 *)buffer + (copyPosition - position),
|
||||||
@@ -473,7 +481,7 @@ OverlayInode::Write(void *_cookie, off_t position, const void *buffer,
|
|||||||
off_t newEnd = newPosition + newLength;
|
off_t newEnd = newPosition + newLength;
|
||||||
off_t otherEnd = other->position + other->length;
|
off_t otherEnd = other->position + other->length;
|
||||||
if (otherEnd < newPosition) {
|
if (otherEnd < newPosition) {
|
||||||
// other completely before us
|
// other is completely before us
|
||||||
link = &other->next;
|
link = &other->next;
|
||||||
other = other->next;
|
other = other->next;
|
||||||
continue;
|
continue;
|
||||||
@@ -489,20 +497,21 @@ OverlayInode::Write(void *_cookie, off_t position, const void *buffer,
|
|||||||
swallow = other;
|
swallow = other;
|
||||||
|
|
||||||
if (other->position <= newPosition) {
|
if (other->position <= newPosition) {
|
||||||
// other chunk overlaps us or is adjacent
|
if (swallowCount == 1 && otherEnd >= newEnd) {
|
||||||
if (otherEnd < newEnd) {
|
// other chunk completely covers us, just copy
|
||||||
// extend the chunk to completely overlap us
|
memcpy(other->buffer + (newPosition - other->position),
|
||||||
newPosition = other->position;
|
buffer, *length);
|
||||||
newLength = other->length + (newEnd - otherEnd);
|
|
||||||
} else {
|
fModificationTime = time(NULL);
|
||||||
// other chunk completely overlaps us already
|
notify_stat_changed(SuperVolume()->id, fInodeNumber,
|
||||||
|
B_STAT_MODIFICATION_TIME);
|
||||||
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
other = other->next;
|
newLength += newPosition - other->position;
|
||||||
continue;
|
newPosition = other->position;
|
||||||
}
|
}
|
||||||
|
|
||||||
// we overlap the other chunk - swallow it
|
|
||||||
if (otherEnd > newEnd)
|
if (otherEnd > newEnd)
|
||||||
newLength += otherEnd - newEnd;
|
newLength += otherEnd - newEnd;
|
||||||
|
|
||||||
@@ -529,14 +538,12 @@ OverlayInode::Write(void *_cookie, off_t position, const void *buffer,
|
|||||||
// populate the buffer with the existing chunks
|
// populate the buffer with the existing chunks
|
||||||
if (swallowCount > 0) {
|
if (swallowCount > 0) {
|
||||||
while (swallowCount-- > 0) {
|
while (swallowCount-- > 0) {
|
||||||
off_t swallowEnd = swallow->position + swallow->length;
|
memcpy(element->buffer + (swallow->position - newPosition),
|
||||||
if (swallow->position < position || swallowEnd > newEnd) {
|
swallow->buffer, swallow->length);
|
||||||
memcpy(element->buffer + (swallow->position - newPosition),
|
|
||||||
swallow->buffer, swallow->length);
|
|
||||||
}
|
|
||||||
|
|
||||||
element->next = swallow->next;
|
element->next = swallow->next;
|
||||||
free(swallow);
|
free(swallow);
|
||||||
|
swallow = element->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1148,6 +1155,7 @@ AttributeEntry::SetSize(size_t size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
memcpy(newData, fData, min_c(fEntry->size, size));
|
memcpy(newData, fData, min_c(fEntry->size, size));
|
||||||
|
fEntry->size = size;
|
||||||
fAllocatedData = true;
|
fAllocatedData = true;
|
||||||
fData = newData;
|
fData = newData;
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|||||||
Reference in New Issue
Block a user