Initial commit of the platform independent part of the new stage2 boot loader.
Not yet complete, of course, but already scans amiga partitions :-) git-svn-id: file:///srv/svn/repos/haiku/trunk/current@4461 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
9b890bf17f
commit
f659db057c
58
src/kernel/boot/loader/Jamfile
Normal file
58
src/kernel/boot/loader/Jamfile
Normal file
@ -0,0 +1,58 @@
|
||||
SubDir OBOS_TOP src kernel boot loader ;
|
||||
|
||||
SubDirHdrs $(OBOS_TOP) src add-ons kernel partitioning_systems amiga ;
|
||||
UsePrivateHeaders [ FDirName kernel boot platform $(OBOS_BOOT_PLATFORM) ] ;
|
||||
UsePrivateHeaders [ FDirName kernel disk_device_manager ] ;
|
||||
UsePrivateHeaders [ FDirName storage ] ;
|
||||
|
||||
{
|
||||
local defines =
|
||||
_BOOT_MODE
|
||||
BOOT_SUPPORT_PARTITION_AMIGA
|
||||
;
|
||||
|
||||
defines = [ FDefines $(defines) ] ;
|
||||
SubDirCcFlags $(defines) -Wall -Wno-multichar ;
|
||||
SubDirC++Flags $(defines) -Wall -Wno-multichar ;
|
||||
}
|
||||
|
||||
KernelStaticLibrary boot_loader :
|
||||
main.cpp
|
||||
vfs.cpp
|
||||
partitions.cpp
|
||||
heap.cpp
|
||||
stdio.cpp
|
||||
list.c
|
||||
|
||||
amiga_rdb.cpp
|
||||
|
||||
kernel_cpp.cpp
|
||||
:
|
||||
-fno-builtin
|
||||
;
|
||||
|
||||
# The following is a try to make the actual partition support
|
||||
# really configurable somewhere and let the build independent
|
||||
# from it:
|
||||
|
||||
#local boot_partition_support =
|
||||
# amiga_rdb.cpp
|
||||
# ;
|
||||
#
|
||||
#KernelStaticLibrary boot_loader_partition :
|
||||
# $(boot_partition_support)
|
||||
# :
|
||||
# ;
|
||||
|
||||
# Tell Jam where to find the utility sources
|
||||
SEARCH on [ FGristFiles kernel_cpp.cpp list.c ]
|
||||
= [ FDirName $(OBOS_TOP) src kernel core util ] ;
|
||||
|
||||
SEARCH on [ FGristFiles amiga_rdb.cpp ]
|
||||
= [ FDirName $(OBOS_TOP) src add-ons kernel partitioning_systems amiga ] ;
|
||||
|
||||
SEARCH on [ FGristFiles stage2_crt0.S ]
|
||||
= [ FDirName $(OBOS_TOP) src kernel boot arch $(OBOS_ARCH) ] ;
|
||||
|
||||
# SubInclude OBOS_TOP src kernel boot loader partition ;
|
||||
|
79
src/kernel/boot/loader/main.cpp
Normal file
79
src/kernel/boot/loader/main.cpp
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
** Distributed under the terms of the OpenBeOS License.
|
||||
*/
|
||||
|
||||
|
||||
#include <boot/stage2.h>
|
||||
#include <boot/vfs.h>
|
||||
#include <boot/platform.h>
|
||||
#include <boot/heap.h>
|
||||
#include <boot/stdio.h>
|
||||
|
||||
#include <util/kernel_cpp.h>
|
||||
|
||||
|
||||
extern "C" int
|
||||
boot(stage2_args *args)
|
||||
{
|
||||
puts("Oh yes, we are\n");
|
||||
if (heap_init(args) < B_OK)
|
||||
panic("Could not initialize heap!\n");
|
||||
|
||||
puts("heap initialized...");
|
||||
|
||||
// the main platform dependent initialisation
|
||||
// has already taken place at this point.
|
||||
|
||||
if (vfs_init(args) < B_OK)
|
||||
panic("Could not initialize VFS!\n");
|
||||
|
||||
puts("Welcome to the OpenBeOS boot loader!");
|
||||
|
||||
if (mount_boot_file_systems() < B_OK)
|
||||
panic("Could not locate any supported boot devices!\n");
|
||||
|
||||
heap_release();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
void *get_boot_device(stage2_args *args);
|
||||
void *user_menu();
|
||||
void load_boot_drivers(void *device);
|
||||
void load_boot_modules(void *device);
|
||||
void load_driver_settings(void *device);
|
||||
|
||||
|
||||
void
|
||||
load_kernel(void *deviceHandle)
|
||||
{
|
||||
void *handle = open(deviceHandle, "system/kernel");
|
||||
if (handle == NULL)
|
||||
panic("Could not open kernel from boot device!\n");
|
||||
|
||||
/* load kernel into memory and relocate it */
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
main(stage2_args *args)
|
||||
{
|
||||
/* pre-state2 initialization is already done at this point */
|
||||
|
||||
void *device = get_boot_device(args);
|
||||
if (device == NULL)
|
||||
device = user_menu();
|
||||
|
||||
if (device == NULL)
|
||||
panic("No boot partition found");
|
||||
|
||||
load_kernel(device);
|
||||
load_boot_drivers(device);
|
||||
load_boot_modules(device);
|
||||
load_driver_settings(device);
|
||||
|
||||
start_kernel();
|
||||
}
|
||||
#endif
|
||||
|
124
src/kernel/boot/loader/partitions.cpp
Normal file
124
src/kernel/boot/loader/partitions.cpp
Normal file
@ -0,0 +1,124 @@
|
||||
/*
|
||||
** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
** Distributed under the terms of the OpenBeOS License.
|
||||
*/
|
||||
|
||||
|
||||
#include <boot/partitions.h>
|
||||
#include <boot/vfs.h>
|
||||
#include <boot/stdio.h>
|
||||
#include <ddm_modules.h>
|
||||
#include <util/kernel_cpp.h>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
static partition_module_info *sPartitionModules[] = {
|
||||
#ifdef BOOT_SUPPORT_PARTITION_AMIGA
|
||||
&gAmigaPartitionModule,
|
||||
#endif
|
||||
#ifdef BOOT_SUPPORT_PARTITION_INTEL
|
||||
&gIntelPartitionModule,
|
||||
#endif
|
||||
#ifdef BOOT_SUPPORT_PARTITION_APPLE
|
||||
&gApplePartitionModule,
|
||||
#endif
|
||||
};
|
||||
static const int32 sNumPartitionModules = sizeof(sPartitionModules) / sizeof(partition_module_info *);
|
||||
|
||||
extern list gPartitions;
|
||||
|
||||
|
||||
Partition::Partition(int fd)
|
||||
{
|
||||
// it's safe to close the file
|
||||
fFD = dup(fd);
|
||||
}
|
||||
|
||||
|
||||
Partition::~Partition()
|
||||
{
|
||||
close(fFD);
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
Partition::ReadAt(void *cookie, off_t position, void *buffer, size_t bufferSize)
|
||||
{
|
||||
if (position > this->size)
|
||||
return 0;
|
||||
if (position < 0)
|
||||
position = 0;
|
||||
|
||||
if (position + bufferSize > this->size)
|
||||
bufferSize = this->size - position;
|
||||
|
||||
return read_pos(fFD, this->offset + position, buffer, bufferSize);
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
Partition::WriteAt(void *cookie, off_t position, const void *buffer, size_t bufferSize)
|
||||
{
|
||||
if (position > this->size)
|
||||
return 0;
|
||||
if (position < 0)
|
||||
position = 0;
|
||||
|
||||
if (position + bufferSize > this->size)
|
||||
bufferSize = this->size - position;
|
||||
|
||||
return write_pos(fFD, this->offset + position, buffer, bufferSize);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
status_t
|
||||
add_partitions_for(int fd)
|
||||
{
|
||||
struct partition_data partition;
|
||||
memset(&partition, 0, sizeof(partition_data));
|
||||
|
||||
// set some magic/default values
|
||||
partition.id = (partition_id)&partition;
|
||||
partition.block_size = 512;
|
||||
partition.size = 1024*1024*1024; // ToDo: fix this!
|
||||
partition.volume = (dev_t)fd;
|
||||
|
||||
for (int32 i = 0; i < sNumPartitionModules; i++) {
|
||||
partition_module_info *module = sPartitionModules[i];
|
||||
void *cookie;
|
||||
|
||||
puts(module->pretty_name);
|
||||
if (module->identify_partition(fd, &partition, &cookie) <= 0.0)
|
||||
continue;
|
||||
|
||||
status_t status = module->scan_partition(fd, &partition, cookie);
|
||||
module->free_identify_partition_cookie(&partition, cookie);
|
||||
|
||||
if (status == B_OK)
|
||||
return B_OK;
|
||||
}
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
}
|
||||
|
||||
|
||||
partition_data *
|
||||
create_child_partition(partition_id id, int32 index, partition_id childID)
|
||||
{
|
||||
partition_data &partition = *(partition_data *)id;
|
||||
Partition *child = new Partition(partition.volume);
|
||||
if (child == NULL) {
|
||||
printf("creating partition failed: no memory\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
list_add_item(&gPartitions, (void *)child);
|
||||
|
||||
return child;
|
||||
}
|
||||
|
||||
|
142
src/kernel/boot/loader/stdio.cpp
Normal file
142
src/kernel/boot/loader/stdio.cpp
Normal file
@ -0,0 +1,142 @@
|
||||
/*
|
||||
** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
** Distributed under the terms of the OpenBeOS License.
|
||||
*/
|
||||
|
||||
|
||||
#include <boot/vfs.h>
|
||||
#include <boot/stdio.h>
|
||||
#include <util/kernel_cpp.h>
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
|
||||
//#undef stdout
|
||||
//#undef stdin
|
||||
//extern FILE *stdout;
|
||||
//extern FILE *stdin;
|
||||
|
||||
|
||||
// ToDo: does it make sense to have the extra "\r\n" handling in here?
|
||||
// or should this be done by the platform dependent part?
|
||||
|
||||
|
||||
int
|
||||
vfprintf(FILE *file, const char *format, va_list list)
|
||||
{
|
||||
ConsoleNode *node = (ConsoleNode *)file;
|
||||
char buffer[1024];
|
||||
// the buffer handling could (or should) be done better...
|
||||
// we should have a vsprintf() version that accepts a
|
||||
// maximum buffer size (for the kernel as well!)
|
||||
|
||||
int length = vsprintf(buffer, format, list);
|
||||
if (length > 0) {
|
||||
int pos = 0;
|
||||
char *c;
|
||||
|
||||
// be nice to our audience and replace single "\n" with "\r\n"
|
||||
|
||||
for (c = buffer; c[0] && (size_t)length < sizeof(buffer) - 1; c++, pos++) {
|
||||
if (c[0] == '\r' && c[1] == '\n') {
|
||||
c++;
|
||||
pos++;
|
||||
continue;
|
||||
}
|
||||
if (c[0] == '\n') {
|
||||
// insert a '\r' here
|
||||
memmove(c + 1, c, length - pos);
|
||||
c[0] = '\r';
|
||||
length++;
|
||||
}
|
||||
}
|
||||
node->Write(buffer, length);
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
printf(const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
int status = vfprintf(stdout, format, args);
|
||||
va_end(args);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
fprintf(FILE *file, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
int status = vfprintf(file, format, args);
|
||||
va_end(args);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
fputc(int character, FILE *file)
|
||||
{
|
||||
if (file == NULL)
|
||||
return B_FILE_ERROR;
|
||||
|
||||
status_t status;
|
||||
|
||||
// we only support direct console output right now...
|
||||
if (character == '\n')
|
||||
status = ((ConsoleNode *)file)->Write("\r\n", 2);
|
||||
else
|
||||
status = ((ConsoleNode *)file)->Write(&character, 1);
|
||||
|
||||
if (status > 0)
|
||||
return character;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
fputs(const char *string, FILE *file)
|
||||
{
|
||||
if (file == NULL)
|
||||
return B_FILE_ERROR;
|
||||
|
||||
// ToDo: for consistency, we should replace "\n" with "\r\n" here, too.
|
||||
|
||||
status_t status = ((ConsoleNode *)file)->Write(string, strlen(string));
|
||||
fputc('\n', file);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
putc(int character)
|
||||
{
|
||||
return fputc(character, stdout);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
putchar(int character)
|
||||
{
|
||||
return fputc(character, stdout);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
puts(const char *string)
|
||||
{
|
||||
return fputs(string, stdout);
|
||||
}
|
||||
|
||||
|
364
src/kernel/boot/loader/vfs.cpp
Normal file
364
src/kernel/boot/loader/vfs.cpp
Normal file
@ -0,0 +1,364 @@
|
||||
/*
|
||||
** Copyright 2003, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
** Distributed under the terms of the OpenBeOS License.
|
||||
*/
|
||||
|
||||
|
||||
#include <boot/vfs.h>
|
||||
#include <boot/platform.h>
|
||||
#include <boot/stdio.h>
|
||||
#include <util/kernel_cpp.h>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
|
||||
#if 0
|
||||
struct vfs_ops {
|
||||
int (*open)(void **_cookie);
|
||||
int (*close)(void *cookie);
|
||||
int (*read)(void *cookie, off_t pos, void *buffer, size_t bytes);
|
||||
int (*write)(void *cookie, off_t pos, const void *buffer, size_t bytes);
|
||||
};
|
||||
|
||||
struct vfs_node {
|
||||
struct vfs_node *next;
|
||||
off_t offset;
|
||||
off_t size;
|
||||
int32 ref_count;
|
||||
struct vfs_ops *ops;
|
||||
};
|
||||
|
||||
struct vfs_descriptor {
|
||||
struct vfs_node *node;
|
||||
struct vfs_ops *ops;
|
||||
void *cookie;
|
||||
off_t offset;
|
||||
int32 ref_count;
|
||||
};
|
||||
#endif
|
||||
|
||||
#define MAX_VFS_DESCRIPTORS 32
|
||||
|
||||
list gBootDevices;
|
||||
list gPartitions;
|
||||
Descriptor *gDescriptors[MAX_VFS_DESCRIPTORS];
|
||||
|
||||
|
||||
Node::Node()
|
||||
:
|
||||
fRefCount(0)
|
||||
{
|
||||
fLink.next = fLink.prev = NULL;
|
||||
}
|
||||
|
||||
|
||||
Node::~Node()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Node::Open(void **_cookie, int mode)
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Node::Close(void *cookie)
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
|
||||
|
||||
ConsoleNode::ConsoleNode()
|
||||
: Node()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
ConsoleNode::Read(void *buffer, size_t bufferSize)
|
||||
{
|
||||
return ReadAt(NULL, -1, buffer, bufferSize);
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
ConsoleNode::Write(const void *buffer, size_t bufferSize)
|
||||
{
|
||||
return WriteAt(NULL, -1, buffer, bufferSize);
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
|
||||
|
||||
Descriptor::Descriptor(Node *node, void *cookie)
|
||||
:
|
||||
fNode(node),
|
||||
fCookie(cookie),
|
||||
fOffset(0),
|
||||
fRefCount(1)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Descriptor::~Descriptor()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
Descriptor::Read(void *buffer, size_t bufferSize)
|
||||
{
|
||||
ssize_t bytesRead = fNode->ReadAt(fCookie, fOffset, buffer, bufferSize);
|
||||
if (bytesRead > B_OK)
|
||||
fOffset += bytesRead;
|
||||
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
Descriptor::Read(off_t pos, void *buffer, size_t bufferSize)
|
||||
{
|
||||
return fNode->ReadAt(fCookie, pos, buffer, bufferSize);
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
Descriptor::Write(const void *buffer, size_t bufferSize)
|
||||
{
|
||||
ssize_t bytesWritten = fNode->WriteAt(fCookie, fOffset, buffer, bufferSize);
|
||||
if (bytesWritten > B_OK)
|
||||
fOffset += bytesWritten;
|
||||
|
||||
return bytesWritten;
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
Descriptor::Write(off_t pos, const void *buffer, size_t bufferSize)
|
||||
{
|
||||
return fNode->WriteAt(fCookie, pos, buffer, bufferSize);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Descriptor::Acquire()
|
||||
{
|
||||
fRefCount++;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
Descriptor::Release()
|
||||
{
|
||||
if (--fRefCount == 1) {
|
||||
status_t status = fNode->Close(fCookie);
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
|
||||
|
||||
static Descriptor *
|
||||
get_descriptor(int fd)
|
||||
{
|
||||
if (fd >= MAX_VFS_DESCRIPTORS)
|
||||
return NULL;
|
||||
|
||||
return gDescriptors[fd];
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
free_descriptor(int fd)
|
||||
{
|
||||
if (fd >= MAX_VFS_DESCRIPTORS)
|
||||
return;
|
||||
|
||||
delete gDescriptors[fd];
|
||||
gDescriptors[fd] = NULL;
|
||||
}
|
||||
|
||||
|
||||
/** Reserves an entry of the descriptor table and
|
||||
* assigns the given node to it.
|
||||
*/
|
||||
|
||||
int
|
||||
open_node(Node *node, int mode)
|
||||
{
|
||||
if (node == NULL)
|
||||
return B_ERROR;
|
||||
|
||||
// get free descriptor
|
||||
|
||||
int fd = 0;
|
||||
for (; fd < MAX_VFS_DESCRIPTORS; fd++) {
|
||||
if (gDescriptors[fd] == NULL)
|
||||
break;
|
||||
}
|
||||
if (fd == MAX_VFS_DESCRIPTORS)
|
||||
return B_ERROR;
|
||||
|
||||
printf("got descriptor %d\n", fd);
|
||||
|
||||
// we got a free descriptor entry, now try to open the node
|
||||
|
||||
void *cookie;
|
||||
status_t status = node->Open(&cookie, mode);
|
||||
if (status < B_OK)
|
||||
return status;
|
||||
|
||||
printf("could open node at %p\n", node);
|
||||
|
||||
Descriptor *descriptor = new Descriptor(node, cookie);
|
||||
if (descriptor == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
gDescriptors[fd] = descriptor;
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
vfs_init(stage2_args *args)
|
||||
{
|
||||
list_init(&gBootDevices);
|
||||
list_init(&gPartitions);
|
||||
|
||||
status_t status = platform_get_boot_devices(args, &gBootDevices);
|
||||
if (status < B_OK)
|
||||
return status;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
mount_boot_file_systems()
|
||||
{
|
||||
Node *device = NULL;
|
||||
while ((device = (Node *)list_get_next_item(&gBootDevices, (void *)device)) != NULL) {
|
||||
int fd = open_node(device, O_RDONLY);
|
||||
if (fd < B_OK)
|
||||
continue;
|
||||
|
||||
puts("add partitions");
|
||||
add_partitions_for(fd);
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
||||
if (list_is_empty(&gPartitions))
|
||||
panic("Could not find any partitions on the boot devices");
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
void *
|
||||
mount(void *from, const char *name)
|
||||
{
|
||||
ops *op = (ops *)handle;
|
||||
|
||||
if (op->mount != NULL)
|
||||
return op->mount(from, name);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
int
|
||||
dup(int fd)
|
||||
{
|
||||
Descriptor *descriptor = get_descriptor(fd);
|
||||
if (descriptor == NULL)
|
||||
return B_FILE_ERROR;
|
||||
|
||||
descriptor->Acquire();
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
read_pos(int fd, off_t offset, void *buffer, size_t bufferSize)
|
||||
{
|
||||
Descriptor *descriptor = get_descriptor(fd);
|
||||
if (descriptor == NULL)
|
||||
return B_FILE_ERROR;
|
||||
|
||||
return descriptor->Read(offset, buffer, bufferSize);
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
read(int fd, void *buffer, size_t bufferSize)
|
||||
{
|
||||
Descriptor *descriptor = get_descriptor(fd);
|
||||
if (descriptor == NULL)
|
||||
return B_FILE_ERROR;
|
||||
|
||||
return descriptor->Read(buffer, bufferSize);
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
write_pos(int fd, off_t offset, const void *buffer, size_t bufferSize)
|
||||
{
|
||||
Descriptor *descriptor = get_descriptor(fd);
|
||||
if (descriptor == NULL)
|
||||
return B_FILE_ERROR;
|
||||
|
||||
return descriptor->Write(offset, buffer, bufferSize);
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
write(int fd, const void *buffer, size_t bufferSize)
|
||||
{
|
||||
Descriptor *descriptor = get_descriptor(fd);
|
||||
if (descriptor == NULL)
|
||||
return B_FILE_ERROR;
|
||||
|
||||
return descriptor->Write(buffer, bufferSize);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
open(const char *name, int mode)
|
||||
{
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
close(int fd)
|
||||
{
|
||||
Descriptor *descriptor = get_descriptor(fd);
|
||||
if (descriptor == NULL)
|
||||
return B_FILE_ERROR;
|
||||
|
||||
status_t status = descriptor->Release();
|
||||
if (!descriptor->RefCount())
|
||||
free_descriptor(fd);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user