Kernel interface abstraction for attribute access
* Introduce interface AttributeCookie and currently only implementation UnpackingAttributeCookie. This is an interface for reading/stat()ing an attribute. * Add abstract virtual Node::OpenAttribute() method that returns an AttributeCookie and implemented it for derived classes. * In the kernel interface attribute hooks use AttributeCookie now. The attribute directory hooks are unchanged.
This commit is contained in:
@@ -0,0 +1,12 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011, Ingo Weinhold, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "AttributeCookie.h"
|
||||||
|
|
||||||
|
|
||||||
|
AttributeCookie::~AttributeCookie()
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011, Ingo Weinhold, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef ATTRIBUTE_COOKIE_H
|
||||||
|
#define ATTRIBUTE_COOKIE_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
|
||||||
|
class AttributeCookie {
|
||||||
|
public:
|
||||||
|
virtual ~AttributeCookie();
|
||||||
|
|
||||||
|
virtual status_t Close() = 0;
|
||||||
|
virtual status_t ReadAttribute(off_t offset, void* buffer,
|
||||||
|
size_t* bufferSize) = 0;
|
||||||
|
virtual status_t ReadAttributeStat(struct stat* st) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // ATTRIBUTE_COOKIE_H
|
||||||
@@ -7,6 +7,7 @@
|
|||||||
#include "Directory.h"
|
#include "Directory.h"
|
||||||
|
|
||||||
#include "DebugSupport.h"
|
#include "DebugSupport.h"
|
||||||
|
#include "UnpackingAttributeCookie.h"
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -171,6 +172,15 @@ Directory::ReadSymlink(void* buffer, size_t* bufferSize)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
Directory::OpenAttribute(const char* name, int openMode,
|
||||||
|
AttributeCookie*& _cookie)
|
||||||
|
{
|
||||||
|
return UnpackingAttributeCookie::Open(fPackageDirectories.Head(), name,
|
||||||
|
openMode, _cookie);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Directory::AddChild(Node* node)
|
Directory::AddChild(Node* node)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -51,6 +51,9 @@ public:
|
|||||||
virtual status_t ReadSymlink(void* buffer,
|
virtual status_t ReadSymlink(void* buffer,
|
||||||
size_t* bufferSize);
|
size_t* bufferSize);
|
||||||
|
|
||||||
|
virtual status_t OpenAttribute(const char* name, int openMode,
|
||||||
|
AttributeCookie*& _cookie);
|
||||||
|
|
||||||
void AddChild(Node* node);
|
void AddChild(Node* node);
|
||||||
void RemoveChild(Node* node);
|
void RemoveChild(Node* node);
|
||||||
Node* FindChild(const char* name);
|
Node* FindChild(const char* name);
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ UsePrivateHeaders shared ;
|
|||||||
|
|
||||||
|
|
||||||
HAIKU_PACKAGE_FS_SOURCES =
|
HAIKU_PACKAGE_FS_SOURCES =
|
||||||
|
AttributeCookie.cpp
|
||||||
BlockBufferCacheKernel.cpp
|
BlockBufferCacheKernel.cpp
|
||||||
DebugSupport.cpp
|
DebugSupport.cpp
|
||||||
Dependency.cpp
|
Dependency.cpp
|
||||||
@@ -26,6 +27,7 @@ HAIKU_PACKAGE_FS_SOURCES =
|
|||||||
PackageNodeAttribute.cpp
|
PackageNodeAttribute.cpp
|
||||||
PackageSymlink.cpp
|
PackageSymlink.cpp
|
||||||
Resolvable.cpp
|
Resolvable.cpp
|
||||||
|
UnpackingAttributeCookie.cpp
|
||||||
Version.cpp
|
Version.cpp
|
||||||
Volume.cpp
|
Volume.cpp
|
||||||
;
|
;
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include "UnpackingAttributeCookie.h"
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -193,6 +194,15 @@ LeafNode::ReadSymlink(void* buffer, size_t* bufferSize)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
LeafNode::OpenAttribute(const char* name, int openMode,
|
||||||
|
AttributeCookie*& _cookie)
|
||||||
|
{
|
||||||
|
return UnpackingAttributeCookie::Open(fPackageNodes.Head(), name, openMode,
|
||||||
|
_cookie);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const char*
|
const char*
|
||||||
LeafNode::SymlinkPath() const
|
LeafNode::SymlinkPath() const
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -38,6 +38,9 @@ public:
|
|||||||
virtual status_t ReadSymlink(void* buffer,
|
virtual status_t ReadSymlink(void* buffer,
|
||||||
size_t* bufferSize);
|
size_t* bufferSize);
|
||||||
|
|
||||||
|
virtual status_t OpenAttribute(const char* name, int openMode,
|
||||||
|
AttributeCookie*& _cookie);
|
||||||
|
|
||||||
const char* SymlinkPath() const;
|
const char* SymlinkPath() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
#include <util/OpenHashTable.h>
|
#include <util/OpenHashTable.h>
|
||||||
|
|
||||||
|
|
||||||
|
class AttributeCookie;
|
||||||
class Directory;
|
class Directory;
|
||||||
class PackageNode;
|
class PackageNode;
|
||||||
|
|
||||||
@@ -63,6 +64,9 @@ public:
|
|||||||
virtual status_t ReadSymlink(void* buffer,
|
virtual status_t ReadSymlink(void* buffer,
|
||||||
size_t* bufferSize) = 0;
|
size_t* bufferSize) = 0;
|
||||||
|
|
||||||
|
virtual status_t OpenAttribute(const char* name, int openMode,
|
||||||
|
AttributeCookie*& _cookie) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
rw_lock fLock;
|
rw_lock fLock;
|
||||||
ino_t fID;
|
ino_t fID;
|
||||||
|
|||||||
@@ -0,0 +1,142 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "UnpackingAttributeCookie.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <new>
|
||||||
|
|
||||||
|
#include <package/hpkg/DataReader.h>
|
||||||
|
#include <package/hpkg/PackageData.h>
|
||||||
|
#include <package/hpkg/PackageDataReader.h>
|
||||||
|
|
||||||
|
#include <AutoDeleter.h>
|
||||||
|
|
||||||
|
#include "DebugSupport.h"
|
||||||
|
#include "GlobalFactory.h"
|
||||||
|
#include "Package.h"
|
||||||
|
#include "PackageNode.h"
|
||||||
|
|
||||||
|
|
||||||
|
using BPackageKit::BHPKG::BBufferDataReader;
|
||||||
|
//using BPackageKit::BHPKG::BDataReader;
|
||||||
|
using BPackageKit::BHPKG::BFDDataReader;
|
||||||
|
//using BPackageKit::BHPKG::BPackageData;
|
||||||
|
//using BPackageKit::BHPKG::BPackageDataReader;
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
read_package_data(const BPackageData& data, BDataReader* dataReader,
|
||||||
|
off_t offset, void* buffer, size_t* bufferSize)
|
||||||
|
{
|
||||||
|
// create a BPackageDataReader
|
||||||
|
BPackageDataReader* reader;
|
||||||
|
status_t error = GlobalFactory::Default()->CreatePackageDataReader(
|
||||||
|
dataReader, data, reader);
|
||||||
|
if (error != B_OK)
|
||||||
|
RETURN_ERROR(error);
|
||||||
|
ObjectDeleter<BPackageDataReader> readerDeleter(reader);
|
||||||
|
|
||||||
|
// check the offset
|
||||||
|
if (offset < 0 || (uint64)offset > data.UncompressedSize())
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
// clamp the size
|
||||||
|
size_t toRead = std::min((uint64)*bufferSize,
|
||||||
|
data.UncompressedSize() - offset);
|
||||||
|
|
||||||
|
// read
|
||||||
|
if (toRead > 0) {
|
||||||
|
status_t error = reader->ReadData(offset, buffer, toRead);
|
||||||
|
if (error != B_OK)
|
||||||
|
RETURN_ERROR(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
*bufferSize = toRead;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
UnpackingAttributeCookie::UnpackingAttributeCookie(PackageNode* packageNode,
|
||||||
|
PackageNodeAttribute* attribute, int openMode)
|
||||||
|
:
|
||||||
|
fPackageNode(packageNode),
|
||||||
|
fPackage(packageNode->GetPackage()),
|
||||||
|
fAttribute(attribute),
|
||||||
|
fOpenMode(openMode)
|
||||||
|
{
|
||||||
|
fPackageNode->AcquireReference();
|
||||||
|
fPackage->AcquireReference();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
UnpackingAttributeCookie::~UnpackingAttributeCookie()
|
||||||
|
{
|
||||||
|
fPackageNode->ReleaseReference();
|
||||||
|
fPackage->ReleaseReference();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*static*/ status_t
|
||||||
|
UnpackingAttributeCookie::Open(PackageNode* packageNode, const char* name,
|
||||||
|
int openMode, AttributeCookie*& _cookie)
|
||||||
|
{
|
||||||
|
if (packageNode == NULL)
|
||||||
|
return B_ENTRY_NOT_FOUND;
|
||||||
|
|
||||||
|
// get the attribute
|
||||||
|
PackageNodeAttribute* attribute = packageNode->FindAttribute(name);
|
||||||
|
if (attribute == NULL)
|
||||||
|
return B_ENTRY_NOT_FOUND;
|
||||||
|
|
||||||
|
// allocate the cookie
|
||||||
|
UnpackingAttributeCookie* cookie = new(std::nothrow)
|
||||||
|
UnpackingAttributeCookie(packageNode, attribute, openMode);
|
||||||
|
if (cookie == NULL)
|
||||||
|
RETURN_ERROR(B_NO_MEMORY);
|
||||||
|
|
||||||
|
_cookie = cookie;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
UnpackingAttributeCookie::Close()
|
||||||
|
{
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
UnpackingAttributeCookie::ReadAttribute(off_t offset, void* buffer,
|
||||||
|
size_t* bufferSize)
|
||||||
|
{
|
||||||
|
const BPackageData& data = fAttribute->Data();
|
||||||
|
if (data.IsEncodedInline()) {
|
||||||
|
// inline data
|
||||||
|
BBufferDataReader dataReader(data.InlineData(), data.CompressedSize());
|
||||||
|
return read_package_data(data, &dataReader, offset, buffer, bufferSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
// data not inline -- open the package
|
||||||
|
int fd = fPackage->Open();
|
||||||
|
if (fd < 0)
|
||||||
|
RETURN_ERROR(fd);
|
||||||
|
PackageCloser packageCloser(fPackage);
|
||||||
|
|
||||||
|
BFDDataReader dataReader(fd);
|
||||||
|
return read_package_data(data, &dataReader, offset, buffer, bufferSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
UnpackingAttributeCookie::ReadAttributeStat(struct stat* st)
|
||||||
|
{
|
||||||
|
st->st_size = fAttribute->Data().UncompressedSize();
|
||||||
|
st->st_type = fAttribute->Type();
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef UNPACKING_ATTRIBUTE_COOKIE_H
|
||||||
|
#define UNPACKING_ATTRIBUTE_COOKIE_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "AttributeCookie.h"
|
||||||
|
|
||||||
|
|
||||||
|
class Package;
|
||||||
|
class PackageNode;
|
||||||
|
class PackageNodeAttribute;
|
||||||
|
|
||||||
|
|
||||||
|
class UnpackingAttributeCookie : public AttributeCookie {
|
||||||
|
public:
|
||||||
|
UnpackingAttributeCookie(
|
||||||
|
PackageNode* packageNode,
|
||||||
|
PackageNodeAttribute* attribute,
|
||||||
|
int openMode);
|
||||||
|
virtual ~UnpackingAttributeCookie();
|
||||||
|
|
||||||
|
static status_t Open(PackageNode* packageNode, const char* name,
|
||||||
|
int openMode, AttributeCookie*& _cookie);
|
||||||
|
|
||||||
|
virtual status_t Close();
|
||||||
|
virtual status_t ReadAttribute(off_t offset, void* buffer,
|
||||||
|
size_t* bufferSize);
|
||||||
|
virtual status_t ReadAttributeStat(struct stat* st);
|
||||||
|
|
||||||
|
private:
|
||||||
|
PackageNode* fPackageNode;
|
||||||
|
Package* fPackage;
|
||||||
|
PackageNodeAttribute* fAttribute;
|
||||||
|
int fOpenMode;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // UNPACKING_ATTRIBUTE_COOKIE_H
|
||||||
@@ -8,7 +8,6 @@
|
|||||||
|
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <new>
|
#include <new>
|
||||||
|
|
||||||
#include <fs_info.h>
|
#include <fs_info.h>
|
||||||
@@ -18,6 +17,7 @@
|
|||||||
|
|
||||||
#include <AutoDeleter.h>
|
#include <AutoDeleter.h>
|
||||||
|
|
||||||
|
#include "AttributeCookie.h"
|
||||||
#include "DebugSupport.h"
|
#include "DebugSupport.h"
|
||||||
#include "Directory.h"
|
#include "Directory.h"
|
||||||
#include "GlobalFactory.h"
|
#include "GlobalFactory.h"
|
||||||
@@ -25,10 +25,6 @@
|
|||||||
#include "Volume.h"
|
#include "Volume.h"
|
||||||
|
|
||||||
|
|
||||||
using BPackageKit::BHPKG::BBufferDataReader;
|
|
||||||
using BPackageKit::BHPKG::BFDDataReader;
|
|
||||||
|
|
||||||
|
|
||||||
static const uint32 kOptimalIOSize = 64 * 1024;
|
static const uint32 kOptimalIOSize = 64 * 1024;
|
||||||
|
|
||||||
|
|
||||||
@@ -860,32 +856,6 @@ packagefs_rewind_attr_dir(fs_volume* fsVolume, fs_vnode* fsNode, void* _cookie)
|
|||||||
// #pragma mark - Attribute Operations
|
// #pragma mark - Attribute Operations
|
||||||
|
|
||||||
|
|
||||||
struct AttributeCookie {
|
|
||||||
PackageNode* packageNode;
|
|
||||||
Package* package;
|
|
||||||
PackageNodeAttribute* attribute;
|
|
||||||
int openMode;
|
|
||||||
|
|
||||||
AttributeCookie(PackageNode* packageNode, PackageNodeAttribute* attribute,
|
|
||||||
int openMode)
|
|
||||||
:
|
|
||||||
packageNode(packageNode),
|
|
||||||
package(packageNode->GetPackage()),
|
|
||||||
attribute(attribute),
|
|
||||||
openMode(openMode)
|
|
||||||
{
|
|
||||||
packageNode->AcquireReference();
|
|
||||||
package->AcquireReference();
|
|
||||||
}
|
|
||||||
|
|
||||||
~AttributeCookie()
|
|
||||||
{
|
|
||||||
packageNode->ReleaseReference();
|
|
||||||
package->ReleaseReference();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
packagefs_open_attr(fs_volume* fsVolume, fs_vnode* fsNode, const char* name,
|
packagefs_open_attr(fs_volume* fsVolume, fs_vnode* fsNode, const char* name,
|
||||||
int openMode, void** _cookie)
|
int openMode, void** _cookie)
|
||||||
@@ -907,21 +877,12 @@ packagefs_open_attr(fs_volume* fsVolume, fs_vnode* fsNode, const char* name,
|
|||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
// get the package node and the respectively named attribute
|
AttributeCookie* cookie;
|
||||||
PackageNode* packageNode = node->GetPackageNode();
|
error = node->OpenAttribute(name, openMode, cookie);
|
||||||
PackageNodeAttribute* attribute = packageNode != NULL
|
if (error != B_OK)
|
||||||
? packageNode->FindAttribute(name) : NULL;
|
return error;
|
||||||
if (attribute == NULL)
|
|
||||||
return B_ENTRY_NOT_FOUND;
|
|
||||||
|
|
||||||
// allocate the cookie
|
|
||||||
AttributeCookie* cookie = new(std::nothrow) AttributeCookie(packageNode,
|
|
||||||
attribute, openMode);
|
|
||||||
if (cookie == NULL)
|
|
||||||
RETURN_ERROR(B_NO_MEMORY);
|
|
||||||
|
|
||||||
*_cookie = cookie;
|
*_cookie = cookie;
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -929,7 +890,8 @@ packagefs_open_attr(fs_volume* fsVolume, fs_vnode* fsNode, const char* name,
|
|||||||
status_t
|
status_t
|
||||||
packagefs_close_attr(fs_volume* fsVolume, fs_vnode* fsNode, void* _cookie)
|
packagefs_close_attr(fs_volume* fsVolume, fs_vnode* fsNode, void* _cookie)
|
||||||
{
|
{
|
||||||
return B_OK;
|
AttributeCookie* cookie = (AttributeCookie*)_cookie;
|
||||||
|
RETURN_ERROR(cookie->Close());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -951,38 +913,6 @@ packagefs_free_attr_cookie(fs_volume* fsVolume, fs_vnode* fsNode, void* _cookie)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
|
||||||
read_package_data(const BPackageData& data, BDataReader* dataReader, off_t offset,
|
|
||||||
void* buffer, size_t* bufferSize)
|
|
||||||
{
|
|
||||||
// create a BPackageDataReader
|
|
||||||
BPackageDataReader* reader;
|
|
||||||
status_t error = GlobalFactory::Default()->CreatePackageDataReader(
|
|
||||||
dataReader, data, reader);
|
|
||||||
if (error != B_OK)
|
|
||||||
RETURN_ERROR(error);
|
|
||||||
ObjectDeleter<BPackageDataReader> readerDeleter(reader);
|
|
||||||
|
|
||||||
// check the offset
|
|
||||||
if (offset < 0 || (uint64)offset > data.UncompressedSize())
|
|
||||||
return B_BAD_VALUE;
|
|
||||||
|
|
||||||
// clamp the size
|
|
||||||
size_t toRead = std::min((uint64)*bufferSize,
|
|
||||||
data.UncompressedSize() - offset);
|
|
||||||
|
|
||||||
// read
|
|
||||||
if (toRead > 0) {
|
|
||||||
status_t error = reader->ReadData(offset, buffer, toRead);
|
|
||||||
if (error != B_OK)
|
|
||||||
RETURN_ERROR(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
*bufferSize = toRead;
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
packagefs_read_attr(fs_volume* fsVolume, fs_vnode* fsNode, void* _cookie,
|
packagefs_read_attr(fs_volume* fsVolume, fs_vnode* fsNode, void* _cookie,
|
||||||
off_t offset, void* buffer, size_t* bufferSize)
|
off_t offset, void* buffer, size_t* bufferSize)
|
||||||
@@ -996,21 +926,7 @@ packagefs_read_attr(fs_volume* fsVolume, fs_vnode* fsNode, void* _cookie,
|
|||||||
TOUCH(volume);
|
TOUCH(volume);
|
||||||
TOUCH(node);
|
TOUCH(node);
|
||||||
|
|
||||||
const BPackageData& data = cookie->attribute->Data();
|
return cookie->ReadAttribute(offset, buffer, bufferSize);
|
||||||
if (data.IsEncodedInline()) {
|
|
||||||
// inline data
|
|
||||||
BBufferDataReader dataReader(data.InlineData(), data.CompressedSize());
|
|
||||||
return read_package_data(data, &dataReader, offset, buffer, bufferSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
// data not inline -- open the package
|
|
||||||
int fd = cookie->package->Open();
|
|
||||||
if (fd < 0)
|
|
||||||
RETURN_ERROR(fd);
|
|
||||||
PackageCloser packageCloser(cookie->package);
|
|
||||||
|
|
||||||
BFDDataReader dataReader(fd);
|
|
||||||
return read_package_data(data, &dataReader, offset, buffer, bufferSize);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1027,10 +943,7 @@ packagefs_read_attr_stat(fs_volume* fsVolume, fs_vnode* fsNode,
|
|||||||
TOUCH(volume);
|
TOUCH(volume);
|
||||||
TOUCH(node);
|
TOUCH(node);
|
||||||
|
|
||||||
st->st_size = cookie->attribute->Data().UncompressedSize();
|
return cookie->ReadAttributeStat(st);
|
||||||
st->st_type = cookie->attribute->Type();
|
|
||||||
|
|
||||||
return B_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user