Bug Summary

File:src/system/boot/loader/vfs.cpp
Warning:line 1207, column 3
Use of memory after it is freed

Annotated Source Code

1/*
2 * Copyright 2003-2013, Axel Dörfler, axeld@pinc-software.de.
3 * Copyright 2014, Ingo Weinhold, ingo_weinhold@gmx.de.
4 * Copyright 2017, Jessica Hamilton, jessica.l.hamilton@gmail.com.
5 * Distributed under the terms of the MIT License.
6 */
7
8
9#include <boot/vfs.h>
10
11#include <errno(*(_errnop())).h>
12#include <fcntl.h>
13#include <string.h>
14#include <sys/uio.h>
15#include <unistd.h>
16
17#include <StorageDefs.h>
18
19#include <AutoDeleter.h>
20
21#include <boot/platform.h>
22#include <boot/partitions.h>
23#include <boot/stdio.h>
24#include <boot/stage2.h>
25#include <syscall_utils.h>
26
27#include "package_support.h"
28#include "RootFileSystem.h"
29#include "file_systems/packagefs/packagefs.h"
30
31
32using namespace boot;
33
34//#define TRACE_VFS
35#ifdef TRACE_VFS
36# define TRACE(x); dprintf x
37#else
38# define TRACE(x); ;
39#endif
40
41
42struct __DIR {
43 Directory* directory;
44 void* cookie;
45 dirent entry;
46 char nameBuffer[B_FILE_NAME_LENGTH(256) - 1];
47};
48
49
50class Descriptor {
51 public:
52 Descriptor(Node *node, void *cookie);
53 ~Descriptor();
54
55 ssize_t ReadAt(off_t pos, void *buffer, size_t bufferSize);
56 ssize_t Read(void *buffer, size_t bufferSize);
57 ssize_t WriteAt(off_t pos, const void *buffer, size_t bufferSize);
58 ssize_t Write(const void *buffer, size_t bufferSize);
59
60 void Stat(struct stat &stat);
61 status_t Seek(off_t position, int mode);
62
63 off_t Offset() const { return fOffset; }
64 int32 RefCount() const { return fRefCount; }
65
66 status_t Acquire();
67 status_t Release();
68
69 Node *GetNode() const { return fNode; }
70
71 private:
72 Node *fNode;
73 void *fCookie;
74 off_t fOffset;
75 int32 fRefCount;
76};
77
78#define MAX_VFS_DESCRIPTORS64 64
79
80NodeList gBootDevices;
81NodeList gPartitions;
82RootFileSystem *gRoot;
83static Descriptor *sDescriptors[MAX_VFS_DESCRIPTORS64];
84static Node *sBootDevice;
85
86
87Node::Node()
88 :
89 fRefCount(1)
90{
91}
92
93
94Node::~Node()
95{
96}
97
98
99status_t
100Node::Open(void **_cookie, int mode)
101{
102 TRACE(("%p::Open()\n", this));;
103 return Acquire();
104}
105
106
107status_t
108Node::Close(void *cookie)
109{
110 TRACE(("%p::Close()\n", this));;
111 return Release();
4
Calling 'Node::Release'
8
Returning; memory was released
112}
113
114
115status_t
116Node::ReadLink(char* buffer, size_t bufferSize)
117{
118 return B_BAD_VALUE((-2147483647 - 1) + 5);
119}
120
121
122status_t
123Node::GetName(char *nameBuffer, size_t bufferSize) const
124{
125 return B_ERROR(-1);
126}
127
128
129status_t
130Node::GetFileMap(struct file_map_run *runs, int32 *count)
131{
132 return B_ERROR(-1);
133}
134
135
136int32
137Node::Type() const
138{
139 return 0;
140}
141
142
143off_t
144Node::Size() const
145{
146 return 0LL;
147}
148
149
150ino_t
151Node::Inode() const
152{
153 return 0;
154}
155
156
157void
158Node::Stat(struct stat& stat)
159{
160 stat.st_mode = Type();
161 stat.st_size = Size();
162 stat.st_ino = Inode();
163}
164
165
166status_t
167Node::Acquire()
168{
169 fRefCount++;
170 TRACE(("%p::Acquire(), fRefCount = %ld\n", this, fRefCount));;
171 return B_OK((int)0);
172}
173
174
175status_t
176Node::Release()
177{
178 TRACE(("%p::Release(), fRefCount = %ld\n", this, fRefCount));;
179 if (--fRefCount == 0) {
5
Assuming the condition is true
6
Taking true branch
180 TRACE(("delete node: %p\n", this));;
181 delete this;
7
Memory is released
182 return 1;
183 }
184
185 return B_OK((int)0);
186}
187
188
189// #pragma mark -
190
191
192ConsoleNode::ConsoleNode()
193 : Node()
194{
195}
196
197
198ssize_t
199ConsoleNode::Read(void *buffer, size_t bufferSize)
200{
201 return ReadAt(NULL__null, -1, buffer, bufferSize);
202}
203
204
205ssize_t
206ConsoleNode::Write(const void *buffer, size_t bufferSize)
207{
208 return WriteAt(NULL__null, -1, buffer, bufferSize);
209}
210
211
212// #pragma mark -
213
214
215Directory::Directory()
216 : Node()
217{
218}
219
220
221ssize_t
222Directory::ReadAt(void *cookie, off_t pos, void *buffer, size_t bufferSize)
223{
224 return B_ERROR(-1);
225}
226
227
228ssize_t
229Directory::WriteAt(void *cookie, off_t pos, const void *buffer, size_t bufferSize)
230{
231 return B_ERROR(-1);
232}
233
234
235int32
236Directory::Type() const
237{
238 return S_IFDIR00000040000;
239}
240
241
242Node*
243Directory::Lookup(const char* name, bool traverseLinks)
244{
245 Node* node = LookupDontTraverse(name);
246 if (node == NULL__null)
247 return NULL__null;
248
249 if (!traverseLinks || !S_ISLNK(node->Type())(((node->Type()) & 00000170000) == 00000120000))
250 return node;
251
252 // the node is a symbolic link, so we have to resolve the path
253 char linkPath[B_PATH_NAME_LENGTH(1024)];
254 status_t error = node->ReadLink(linkPath, sizeof(linkPath));
255
256 node->Release();
257 // we don't need this one anymore
258
259 if (error != B_OK((int)0))
260 return NULL__null;
261
262 // let open_from() do the real work
263 int fd = open_from(this, linkPath, O_RDONLY0x0000);
264 if (fd < 0)
265 return NULL__null;
266
267 node = get_node_from(fd);
268 if (node != NULL__null)
269 node->Acquire();
270
271 close(fd);
272 return node;
273}
274
275
276status_t
277Directory::CreateFile(const char *name, mode_t permissions, Node **_node)
278{
279 return EROFS((((-2147483647 - 1) + 0x6000) + 8));
280}
281
282
283// #pragma mark -
284
285
286MemoryDisk::MemoryDisk(const uint8* data, size_t size, const char* name)
287 : Node(),
288 fData(data),
289 fSize(size)
290{
291 strlcpy(fName, name, sizeof(fName));
292}
293
294
295ssize_t
296MemoryDisk::ReadAt(void* cookie, off_t pos, void* buffer, size_t bufferSize)
297{
298 if (pos < 0)
299 return B_BAD_VALUE((-2147483647 - 1) + 5);
300 if ((size_t)pos >= fSize)
301 return 0;
302
303 if (pos + bufferSize > fSize)
304 bufferSize = fSize - pos;
305
306 memcpy(buffer, fData + pos, bufferSize);
307 return bufferSize;
308}
309
310
311ssize_t
312MemoryDisk::WriteAt(void* cookie, off_t pos, const void* buffer,
313 size_t bufferSize)
314{
315 return B_NOT_ALLOWED((-2147483647 - 1) + 15);
316}
317
318
319off_t
320MemoryDisk::Size() const
321{
322 return fSize;
323}
324
325
326status_t
327MemoryDisk::GetName(char *nameBuffer, size_t bufferSize) const
328{
329 if (!nameBuffer)
330 return B_BAD_VALUE((-2147483647 - 1) + 5);
331
332 strlcpy(nameBuffer, fName, bufferSize);
333 return B_OK((int)0);
334}
335
336
337// #pragma mark -
338
339
340Descriptor::Descriptor(Node *node, void *cookie)
341 :
342 fNode(node),
343 fCookie(cookie),
344 fOffset(0),
345 fRefCount(1)
346{
347}
348
349
350Descriptor::~Descriptor()
351{
352}
353
354
355ssize_t
356Descriptor::Read(void *buffer, size_t bufferSize)
357{
358 ssize_t bytesRead = fNode->ReadAt(fCookie, fOffset, buffer, bufferSize);
359 if (bytesRead > B_OK((int)0))
360 fOffset += bytesRead;
361
362 return bytesRead;
363}
364
365
366ssize_t
367Descriptor::ReadAt(off_t pos, void *buffer, size_t bufferSize)
368{
369 return fNode->ReadAt(fCookie, pos, buffer, bufferSize);
370}
371
372
373ssize_t
374Descriptor::Write(const void *buffer, size_t bufferSize)
375{
376 ssize_t bytesWritten = fNode->WriteAt(fCookie, fOffset, buffer, bufferSize);
377 if (bytesWritten > B_OK((int)0))
378 fOffset += bytesWritten;
379
380 return bytesWritten;
381}
382
383
384ssize_t
385Descriptor::WriteAt(off_t pos, const void *buffer, size_t bufferSize)
386{
387 return fNode->WriteAt(fCookie, pos, buffer, bufferSize);
388}
389
390
391void
392Descriptor::Stat(struct stat &stat)
393{
394 fNode->Stat(stat);
395}
396
397
398status_t
399Descriptor::Seek(off_t position, int mode)
400{
401 off_t newPosition;
402 switch (mode)
403 {
404 case SEEK_SET0:
405 newPosition = position;
406 break;
407 case SEEK_CUR1:
408 newPosition = fOffset + position;
409 break;
410 case SEEK_END2:
411 {
412 struct stat st;
413 Stat(st);
414 newPosition = st.st_size + position;
415 break;
416 }
417 default:
418 return B_BAD_VALUE((-2147483647 - 1) + 5);
419 }
420
421 if (newPosition < 0)
422 return B_BAD_VALUE((-2147483647 - 1) + 5);
423
424 fOffset = newPosition;
425 return B_OK((int)0);
426}
427
428
429status_t
430Descriptor::Acquire()
431{
432 fRefCount++;
433 return B_OK((int)0);
434}
435
436
437status_t
438Descriptor::Release()
439{
440 if (--fRefCount == 0) {
441 status_t status = fNode->Close(fCookie);
442 if (status != B_OK((int)0))
443 return status;
444 }
445
446 return B_OK((int)0);
447}
448
449
450// #pragma mark -
451
452
453BootVolume::BootVolume()
454 :
455 fRootDirectory(NULL__null),
456 fSystemDirectory(NULL__null),
457 fPackageVolumeInfo(NULL__null),
458 fPackageVolumeState(NULL__null)
459{
460}
461
462
463BootVolume::~BootVolume()
464{
465 Unset();
466}
467
468
469status_t
470BootVolume::SetTo(Directory* rootDirectory,
471 PackageVolumeInfo* packageVolumeInfo,
472 PackageVolumeState* packageVolumeState)
473{
474 Unset();
475
476 status_t error = _SetTo(rootDirectory, packageVolumeInfo,
477 packageVolumeState);
478 if (error != B_OK((int)0))
479 Unset();
480
481 return error;
482}
483
484
485void
486BootVolume::Unset()
487{
488 if (fRootDirectory != NULL__null) {
489 fRootDirectory->Release();
490 fRootDirectory = NULL__null;
491 }
492
493 if (fSystemDirectory != NULL__null) {
494 fSystemDirectory->Release();
495 fSystemDirectory = NULL__null;
496 }
497
498 if (fPackageVolumeInfo != NULL__null) {
499 fPackageVolumeInfo->ReleaseReference();
500 fPackageVolumeInfo = NULL__null;
501 fPackageVolumeState = NULL__null;
502 }
503}
504
505
506status_t
507BootVolume::_SetTo(Directory* rootDirectory,
508 PackageVolumeInfo* packageVolumeInfo,
509 PackageVolumeState* packageVolumeState)
510{
511 Unset();
512
513 if (rootDirectory == NULL__null)
514 return B_BAD_VALUE((-2147483647 - 1) + 5);
515
516 fRootDirectory = rootDirectory;
517 fRootDirectory->Acquire();
518
519 // find the system directory
520 Node* systemNode = fRootDirectory->Lookup("system", true);
521 if (systemNode == NULL__null || !S_ISDIR(systemNode->Type())(((systemNode->Type()) & 00000170000) == 00000040000)) {
522 if (systemNode != NULL__null)
523 systemNode->Release();
524 Unset();
525 return B_ENTRY_NOT_FOUND(((-2147483647 - 1) + 0x6000) + 3);
526 }
527
528 fSystemDirectory = static_cast<Directory*>(systemNode);
529
530 if (packageVolumeInfo == NULL__null) {
531 // get a package volume info
532 BReference<PackageVolumeInfo> packageVolumeInfoReference(
533 new(std::nothrow) PackageVolumeInfo);
534 status_t error = packageVolumeInfoReference->SetTo(fSystemDirectory,
535 "packages");
536 if (error != B_OK((int)0)) {
537 // apparently not packaged
538 return B_OK((int)0);
539 }
540
541 fPackageVolumeInfo = packageVolumeInfoReference.Detach();
542 } else {
543 fPackageVolumeInfo = packageVolumeInfo;
544 fPackageVolumeInfo->AcquireReference();
545 }
546
547 fPackageVolumeState = packageVolumeState != NULL__null
548 ? packageVolumeState : fPackageVolumeInfo->States().Head();
549
550 // try opening the system package
551 int packageFD = _OpenSystemPackage();
552 if (packageFD < 0)
553 return packageFD;
554
555 // mount packagefs
556 Directory* packageRootDirectory;
557 status_t error = packagefs_mount_file(packageFD, fSystemDirectory,
558 packageRootDirectory);
559 close(packageFD);
560 if (error != B_OK((int)0)) {
561 Unset();
562 return error;
563 }
564
565 fSystemDirectory->Release();
566 fSystemDirectory = packageRootDirectory;
567
568 return B_OK((int)0);
569}
570
571
572int
573BootVolume::_OpenSystemPackage()
574{
575 // open the packages directory
576 Node* packagesNode = fSystemDirectory->Lookup("packages", false);
577 if (packagesNode == NULL__null)
578 return -1;
579 MethodDeleter<Node, status_t> packagesNodeReleaser(packagesNode,
580 &Node::Release);
581
582 if (!S_ISDIR(packagesNode->Type())(((packagesNode->Type()) & 00000170000) == 00000040000
)
)
583 return -1;
584 Directory* packageDirectory = (Directory*)packagesNode;
585
586 // open the system package
587 return open_from(packageDirectory, fPackageVolumeState->SystemPackage(),
588 O_RDONLY0x0000);
589}
590
591
592// #pragma mark -
593
594
595status_t
596vfs_init(stage2_args *args)
597{
598 gRoot = new(nothrow) RootFileSystem();
599 if (gRoot == NULL__null)
600 return B_NO_MEMORY((-2147483647 - 1) + 0);
601
602 return B_OK((int)0);
603}
604
605
606status_t
607register_boot_file_system(BootVolume& bootVolume)
608{
609 Directory* rootDirectory = bootVolume.RootDirectory();
610 gRoot->AddLink("boot", rootDirectory);
611
612 Partition *partition;
613 status_t status = gRoot->GetPartitionFor(rootDirectory, &partition);
614 if (status != B_OK((int)0)) {
615 dprintf("register_boot_file_system(): could not locate boot volume in "
616 "root!\n");
617 return status;
618 }
619
620 gBootVolume.SetInt64(BOOT_VOLUME_PARTITION_OFFSET"partition offset",
621 partition->offset);
622
623 if (bootVolume.IsPackaged()) {
624 gBootVolume.SetBool(BOOT_VOLUME_PACKAGED"packaged", true);
625 PackageVolumeState* state = bootVolume.GetPackageVolumeState();
626 if (state->Name() != NULL__null)
627 gBootVolume.AddString(BOOT_VOLUME_PACKAGES_STATE"packages state", state->Name());
628 }
629
630 Node *device = get_node_from(partition->FD());
631 if (device == NULL__null) {
632 dprintf("register_boot_file_system(): could not get boot device!\n");
633 return B_ERROR(-1);
634 }
635
636 return platform_register_boot_device(device);
637}
638
639
640/*! Gets the boot device, scans all of its partitions, gets the
641 boot partition, and mounts its file system.
642
643 \param args The stage 2 arguments.
644 \param _bootVolume On success set to the boot volume.
645 \return \c B_OK on success, another error code otherwise.
646*/
647status_t
648get_boot_file_system(stage2_args* args, BootVolume& _bootVolume)
649{
650 status_t error = platform_add_boot_device(args, &gBootDevices);
651 if (error != B_OK((int)0))
652 return error;
653
654 NodeIterator iterator = gBootDevices.GetIterator();
655 while (iterator.HasNext()) {
656 Node *device = iterator.Next();
657
658 error = add_partitions_for(device, false, true);
659 if (error != B_OK((int)0))
660 continue;
661
662 Partition *partition;
663 error = platform_get_boot_partition(args, device, &gPartitions, &partition);
664 if (error != B_OK((int)0))
665 continue;
666
667 Directory *fileSystem;
668 error = partition->Mount(&fileSystem, true);
669 if (error != B_OK((int)0)) {
670 // this partition doesn't contain any known file system; we
671 // don't need it anymore
672 gPartitions.Remove(partition);
673 delete partition;
674 continue;
675 }
676
677 // init the BootVolume
678 error = _bootVolume.SetTo(fileSystem);
679 if (error != B_OK((int)0))
680 continue;
681
682 sBootDevice = device;
683 return B_OK((int)0);
684 }
685
686 return B_ERROR(-1);
687}
688
689
690/** Mounts all file systems recognized on the given device by
691 * calling the add_partitions_for() function on them.
692 */
693
694status_t
695mount_file_systems(stage2_args *args)
696{
697 // mount other partitions on boot device (if any)
698 NodeIterator iterator = gPartitions.GetIterator();
699
700 Partition *partition = NULL__null;
701 while ((partition = (Partition *)iterator.Next()) != NULL__null) {
702 // don't scan known partitions again
703 if (partition->IsFileSystem())
704 continue;
705
706 // remove the partition if it doesn't contain a (known) file system
707 if (partition->Scan(true) != B_OK((int)0) && !partition->IsFileSystem()) {
708 gPartitions.Remove(partition);
709 delete partition;
710 }
711 }
712
713 // add all block devices the platform has for us
714
715 status_t status = platform_add_block_devices(args, &gBootDevices);
716 if (status < B_OK((int)0))
717 return status;
718
719 iterator = gBootDevices.GetIterator();
720 Node *device = NULL__null, *last = NULL__null;
721 while ((device = iterator.Next()) != NULL__null) {
722 // don't scan former boot device again
723 if (device == sBootDevice)
724 continue;
725
726 if (add_partitions_for(device, true) == B_OK((int)0)) {
727 // ToDo: we can't delete the object here, because it must
728 // be removed from the list before we know that it was
729 // deleted.
730
731/* // if the Release() deletes the object, we need to skip it
732 if (device->Release() > 0) {
733 list_remove_item(&gBootDevices, device);
734 device = last;
735 }
736*/
737(void)last;
738 }
739 last = device;
740 }
741
742 if (gPartitions.IsEmpty())
743 return B_ENTRY_NOT_FOUND(((-2147483647 - 1) + 0x6000) + 3);
744
745#if 0
746 void *cookie;
747 if (gRoot->Open(&cookie, O_RDONLY0x0000) == B_OK((int)0)) {
748 Directory *directory;
749 while (gRoot->GetNextNode(cookie, (Node **)&directory) == B_OK((int)0)) {
750 char name[256];
751 if (directory->GetName(name, sizeof(name)) == B_OK((int)0))
752 printf(":: %s (%p)\n", name, directory);
753
754 void *subCookie;
755 if (directory->Open(&subCookie, O_RDONLY0x0000) == B_OK((int)0)) {
756 while (directory->GetNextEntry(subCookie, name, sizeof(name)) == B_OK((int)0)) {
757 printf("\t%s\n", name);
758 }
759 directory->Close(subCookie);
760 }
761 }
762 gRoot->Close(cookie);
763 }
764#endif
765
766 return B_OK((int)0);
767}
768
769
770/*! Resolves \a directory + \a path to a node.
771 Note that \a path will be modified by the function.
772*/
773static status_t
774get_node_for_path(Directory *directory, char *path, Node **_node)
775{
776 directory->Acquire();
777 // balance Acquire()/Release() calls
778
779 while (true) {
780 Node *nextNode;
781 char *nextPath;
782
783 // walk to find the next path component ("path" will point to a single
784 // path component), and filter out multiple slashes
785 for (nextPath = path + 1; nextPath[0] != '\0' && nextPath[0] != '/'; nextPath++);
786
787 if (*nextPath == '/') {
788 *nextPath = '\0';
789 do
790 nextPath++;
791 while (*nextPath == '/');
792 }
793
794 nextNode = directory->Lookup(path, true);
795 directory->Release();
796
797 if (nextNode == NULL__null)
798 return B_ENTRY_NOT_FOUND(((-2147483647 - 1) + 0x6000) + 3);
799
800 path = nextPath;
801 if (S_ISDIR(nextNode->Type())(((nextNode->Type()) & 00000170000) == 00000040000))
802 directory = (Directory *)nextNode;
803 else if (path[0])
804 return B_NOT_ALLOWED((-2147483647 - 1) + 15);
805
806 // are we done?
807 if (path[0] == '\0') {
808 *_node = nextNode;
809 return B_OK((int)0);
810 }
811 }
812
813 return B_ENTRY_NOT_FOUND(((-2147483647 - 1) + 0x6000) + 3);
814}
815
816
817/*! Version of get_node_for_path() not modifying \a path.
818 */
819static status_t
820get_node_for_path(Directory* directory, const char* path, Node** _node)
821{
822 char* mutablePath = strdup(path);
823 if (mutablePath == NULL__null)
824 return B_NO_MEMORY((-2147483647 - 1) + 0);
825 MemoryDeleter mutablePathDeleter(mutablePath);
826
827 return get_node_for_path(directory, mutablePath, _node);
828}
829
830// #pragma mark -
831
832
833static Descriptor *
834get_descriptor(int fd)
835{
836 if (fd < 0 || fd >= MAX_VFS_DESCRIPTORS64)
837 return NULL__null;
838
839 return sDescriptors[fd];
840}
841
842
843static void
844free_descriptor(int fd)
845{
846 if (fd >= MAX_VFS_DESCRIPTORS64)
847 return;
848
849 delete sDescriptors[fd];
850 sDescriptors[fd] = NULL__null;
851}
852
853
854/** Reserves an entry of the descriptor table and
855 * assigns the given node to it.
856 */
857
858int
859open_node(Node *node, int mode)
860{
861 if (node == NULL__null)
862 return B_ERROR(-1);
863
864 // get free descriptor
865
866 int fd = 0;
867 for (; fd < MAX_VFS_DESCRIPTORS64; fd++) {
868 if (sDescriptors[fd] == NULL__null)
869 break;
870 }
871 if (fd == MAX_VFS_DESCRIPTORS64)
872 return B_ERROR(-1);
873
874 TRACE(("got descriptor %d for node %p\n", fd, node));;
875
876 // we got a free descriptor entry, now try to open the node
877
878 void *cookie;
879 status_t status = node->Open(&cookie, mode);
880 if (status < B_OK((int)0))
881 return status;
882
883 TRACE(("could open node at %p\n", node));;
884
885 Descriptor *descriptor = new(nothrow) Descriptor(node, cookie);
886 if (descriptor == NULL__null)
887 return B_NO_MEMORY((-2147483647 - 1) + 0);
888
889 sDescriptors[fd] = descriptor;
890
891 return fd;
892}
893
894
895int
896dup(int fd)
897{
898 Descriptor *descriptor = get_descriptor(fd);
899 if (descriptor == NULL__null)
900 RETURN_AND_SET_ERRNO(B_FILE_ERROR)do { __typeof((((-2147483647 - 1) + 0x6000) + 0)) __result = (
(((-2147483647 - 1) + 0x6000) + 0)); if (__result < 0) { (
*(_errnop())) = __result; return -1; } return __result; } while
(0)
;
901
902 descriptor->Acquire();
903 RETURN_AND_SET_ERRNO(fd)do { __typeof(fd) __result = (fd); if (__result < 0) { (*(
_errnop())) = __result; return -1; } return __result; } while
(0)
;
904}
905
906
907off_t
908lseek(int fd, off_t offset, int whence)
909{
910 Descriptor* descriptor = get_descriptor(fd);
911 if (descriptor == NULL__null)
912 RETURN_AND_SET_ERRNO(B_FILE_ERROR)do { __typeof((((-2147483647 - 1) + 0x6000) + 0)) __result = (
(((-2147483647 - 1) + 0x6000) + 0)); if (__result < 0) { (
*(_errnop())) = __result; return -1; } return __result; } while
(0)
;
913
914 status_t error = descriptor->Seek(offset, whence);
915 if (error != B_OK((int)0))
916 RETURN_AND_SET_ERRNO(B_FILE_ERROR)do { __typeof((((-2147483647 - 1) + 0x6000) + 0)) __result = (
(((-2147483647 - 1) + 0x6000) + 0)); if (__result < 0) { (
*(_errnop())) = __result; return -1; } return __result; } while
(0)
;
917
918 return descriptor->Offset();
919}
920
921
922int
923ftruncate(int fd, off_t newSize)
924{
925 dprintf("ftruncate() not implemented!\n");
926 RETURN_AND_SET_ERRNO(B_FILE_ERROR)do { __typeof((((-2147483647 - 1) + 0x6000) + 0)) __result = (
(((-2147483647 - 1) + 0x6000) + 0)); if (__result < 0) { (
*(_errnop())) = __result; return -1; } return __result; } while
(0)
;
927}
928
929
930ssize_t
931read_pos(int fd, off_t offset, void *buffer, size_t bufferSize)
932{
933 Descriptor *descriptor = get_descriptor(fd);
934 if (descriptor == NULL__null)
935 RETURN_AND_SET_ERRNO(B_FILE_ERROR)do { __typeof((((-2147483647 - 1) + 0x6000) + 0)) __result = (
(((-2147483647 - 1) + 0x6000) + 0)); if (__result < 0) { (
*(_errnop())) = __result; return -1; } return __result; } while
(0)
;
936
937 RETURN_AND_SET_ERRNO(descriptor->ReadAt(offset, buffer, bufferSize))do { __typeof(descriptor->ReadAt(offset, buffer, bufferSize
)) __result = (descriptor->ReadAt(offset, buffer, bufferSize
)); if (__result < 0) { (*(_errnop())) = __result; return -
1; } return __result; } while (0)
;
938}
939
940
941ssize_t
942pread(int fd, void* buffer, size_t bufferSize, off_t offset)
943{
944 return read_pos(fd, offset, buffer, bufferSize);
945}
946
947
948ssize_t
949read(int fd, void *buffer, size_t bufferSize)
950{
951 Descriptor *descriptor = get_descriptor(fd);
952 if (descriptor == NULL__null)
953 RETURN_AND_SET_ERRNO(B_FILE_ERROR)do { __typeof((((-2147483647 - 1) + 0x6000) + 0)) __result = (
(((-2147483647 - 1) + 0x6000) + 0)); if (__result < 0) { (
*(_errnop())) = __result; return -1; } return __result; } while
(0)
;
954
955 RETURN_AND_SET_ERRNO(descriptor->Read(buffer, bufferSize))do { __typeof(descriptor->Read(buffer, bufferSize)) __result
= (descriptor->Read(buffer, bufferSize)); if (__result <
0) { (*(_errnop())) = __result; return -1; } return __result
; } while (0)
;
956}
957
958
959ssize_t
960write_pos(int fd, off_t offset, const void *buffer, size_t bufferSize)
961{
962 Descriptor *descriptor = get_descriptor(fd);
963 if (descriptor == NULL__null)
964 RETURN_AND_SET_ERRNO(B_FILE_ERROR)do { __typeof((((-2147483647 - 1) + 0x6000) + 0)) __result = (
(((-2147483647 - 1) + 0x6000) + 0)); if (__result < 0) { (
*(_errnop())) = __result; return -1; } return __result; } while
(0)
;
965
966 RETURN_AND_SET_ERRNO(descriptor->WriteAt(offset, buffer, bufferSize))do { __typeof(descriptor->WriteAt(offset, buffer, bufferSize
)) __result = (descriptor->WriteAt(offset, buffer, bufferSize
)); if (__result < 0) { (*(_errnop())) = __result; return -
1; } return __result; } while (0)
;
967}
968
969
970ssize_t
971pwrite(int fd, const void* buffer, size_t bufferSize, off_t offset)
972{
973 return write_pos(fd, offset, buffer, bufferSize);
974}
975
976
977ssize_t
978write(int fd, const void *buffer, size_t bufferSize)
979{
980 Descriptor *descriptor = get_descriptor(fd);
981 if (descriptor == NULL__null)
982 RETURN_AND_SET_ERRNO(B_FILE_ERROR)do { __typeof((((-2147483647 - 1) + 0x6000) + 0)) __result = (
(((-2147483647 - 1) + 0x6000) + 0)); if (__result < 0) { (
*(_errnop())) = __result; return -1; } return __result; } while
(0)
;
983
984 RETURN_AND_SET_ERRNO(descriptor->Write(buffer, bufferSize))do { __typeof(descriptor->Write(buffer, bufferSize)) __result
= (descriptor->Write(buffer, bufferSize)); if (__result <
0) { (*(_errnop())) = __result; return -1; } return __result
; } while (0)
;
985}
986
987
988ssize_t
989writev(int fd, const struct iovec* vecs, size_t count)
990{
991 size_t totalWritten = 0;
992
993 for (size_t i = 0; i < count; i++) {
994 ssize_t written = write(fd, vecs[i].iov_base, vecs[i].iov_len);
995 if (written < 0)
996 return totalWritten == 0 ? written : totalWritten;
997
998 totalWritten += written;
999
1000 if ((size_t)written != vecs[i].iov_len)
1001 break;
1002 }
1003
1004 return totalWritten;
1005}
1006
1007
1008int
1009open(const char *name, int mode, ...)
1010{
1011 mode_t permissions = 0;
1012 if ((mode & O_CREAT0x0200) != 0) {
1013 va_list args;
1014 va_start(args, mode)__builtin_va_start(args,mode);
1015 permissions = va_arg(args, int)__builtin_va_arg(args,int) /*& ~__gUmask*/;
1016 // adapt the permissions as required by POSIX
1017 va_end(args)__builtin_va_end(args);
1018 }
1019
1020 // we always start at the top (there is no notion of a current directory (yet?))
1021 RETURN_AND_SET_ERRNO(open_from(gRoot, name, mode, permissions))do { __typeof(open_from(gRoot, name, mode, permissions)) __result
= (open_from(gRoot, name, mode, permissions)); if (__result <
0) { (*(_errnop())) = __result; return -1; } return __result
; } while (0)
;
1022}
1023
1024
1025int
1026open_from(Directory *directory, const char *name, int mode, mode_t permissions)
1027{
1028 if (name[0] == '/') {
1029 // ignore the directory and start from root if we are asked to do that
1030 directory = gRoot;
1031 name++;
1032 }
1033
1034 char path[B_PATH_NAME_LENGTH(1024)];
1035 if (strlcpy(path, name, sizeof(path)) >= sizeof(path))
1036 return B_NAME_TOO_LONG(((-2147483647 - 1) + 0x6000) + 4);
1037
1038 Node *node;
1039 status_t error = get_node_for_path(directory, path, &node);
1040 if (error != B_OK((int)0)) {
1041 if (error != B_ENTRY_NOT_FOUND(((-2147483647 - 1) + 0x6000) + 3))
1042 return error;
1043
1044 if ((mode & O_CREAT0x0200) == 0)
1045 return B_ENTRY_NOT_FOUND(((-2147483647 - 1) + 0x6000) + 3);
1046
1047 // try to resolve the parent directory
1048 strlcpy(path, name, sizeof(path));
1049 if (char* lastSlash = strrchr(path, '/')) {
1050 if (lastSlash[1] == '\0')
1051 return B_ENTRY_NOT_FOUND(((-2147483647 - 1) + 0x6000) + 3);
1052
1053 *lastSlash = '\0';
1054 name = lastSlash + 1;
1055
1056 // resolve the directory
1057 if (get_node_for_path(directory, path, &node) != B_OK((int)0))
1058 return B_ENTRY_NOT_FOUND(((-2147483647 - 1) + 0x6000) + 3);
1059
1060 if (node->Type() != S_IFDIR00000040000) {
1061 node->Release();
1062 return B_NOT_A_DIRECTORY(((-2147483647 - 1) + 0x6000) + 5);
1063 }
1064
1065 directory = static_cast<Directory*>(node);
1066 } else
1067 directory->Acquire();
1068
1069 // create the file
1070 error = directory->CreateFile(name, permissions, &node);
1071 directory->Release();
1072
1073 if (error != B_OK((int)0))
1074 return error;
1075 } else if ((mode & O_EXCL0x0100) != 0) {
1076 node->Release();
1077 return B_FILE_EXISTS(((-2147483647 - 1) + 0x6000) + 2);
1078 }
1079
1080 int fd = open_node(node, mode);
1081
1082 node->Release();
1083 return fd;
1084}
1085
1086
1087/** Since we don't have directory functions yet, this
1088 * function is needed to get the contents of a directory.
1089 * It should be removed once readdir() & co. are in place.
1090 */
1091
1092Node *
1093get_node_from(int fd)
1094{
1095 Descriptor *descriptor = get_descriptor(fd);
1096 if (descriptor == NULL__null)
1097 return NULL__null;
1098
1099 return descriptor->GetNode();
1100}
1101
1102
1103status_t
1104get_stat(Directory* directory, const char* path, struct stat& st)
1105{
1106 Node* node;
1107 status_t error = get_node_for_path(directory, path, &node);
1108 if (error != B_OK((int)0))
1109 return error;
1110
1111 node->Stat(st);
1112 node->Release();
1113 return B_OK((int)0);
1114}
1115
1116
1117Directory*
1118directory_from(DIR* dir)
1119{
1120 return dir != NULL__null ? dir->directory : NULL__null;
1121}
1122
1123
1124int
1125close(int fd)
1126{
1127 Descriptor *descriptor = get_descriptor(fd);
1128 if (descriptor == NULL__null)
1129 RETURN_AND_SET_ERRNO(B_FILE_ERROR)do { __typeof((((-2147483647 - 1) + 0x6000) + 0)) __result = (
(((-2147483647 - 1) + 0x6000) + 0)); if (__result < 0) { (
*(_errnop())) = __result; return -1; } return __result; } while
(0)
;
1130
1131 status_t status = descriptor->Release();
1132 if (!descriptor->RefCount())
1133 free_descriptor(fd);
1134
1135 RETURN_AND_SET_ERRNO(status)do { __typeof(status) __result = (status); if (__result < 0
) { (*(_errnop())) = __result; return -1; } return __result; }
while (0)
;
1136}
1137
1138
1139// ToDo: remove this kludge when possible
1140int
1141#if defined(fstat) && !defined(main)
1142_fstat(int fd, struct stat *stat, size_t /*statSize*/)
1143#else
1144fstat(int fd, struct stat *stat)
1145#endif
1146{
1147 if (stat == NULL__null)
1148 RETURN_AND_SET_ERRNO(B_BAD_VALUE)do { __typeof(((-2147483647 - 1) + 5)) __result = (((-2147483647
- 1) + 5)); if (__result < 0) { (*(_errnop())) = __result
; return -1; } return __result; } while (0)
;
1149
1150 Descriptor *descriptor = get_descriptor(fd);
1151 if (descriptor == NULL__null)
1152 RETURN_AND_SET_ERRNO(B_FILE_ERROR)do { __typeof((((-2147483647 - 1) + 0x6000) + 0)) __result = (
(((-2147483647 - 1) + 0x6000) + 0)); if (__result < 0) { (
*(_errnop())) = __result; return -1; } return __result; } while
(0)
;
1153
1154 descriptor->Stat(*stat);
1155 return 0;
1156}
1157
1158
1159DIR*
1160open_directory(Directory* baseDirectory, const char* path)
1161{
1162 DIR* dir = new(std::nothrow) DIR;
1163 if (dir == NULL__null) {
1164 errno(*(_errnop())) = B_NO_MEMORY((-2147483647 - 1) + 0);
1165 return NULL__null;
1166 }
1167 ObjectDeleter<DIR> dirDeleter(dir);
1168
1169 Node* node;
1170 status_t error = get_node_for_path(baseDirectory, path, &node);
1171 if (error != B_OK((int)0)) {
1172 errno(*(_errnop())) = error;
1173 return NULL__null;
1174 }
1175 MethodDeleter<Node, status_t> nodeReleaser(node, &Node::Release);
1176
1177 if (!S_ISDIR(node->Type())(((node->Type()) & 00000170000) == 00000040000)) {
1178 errno(*(_errnop())) = error;
1179 return NULL__null;
1180 }
1181
1182 dir->directory = static_cast<Directory*>(node);
1183
1184 error = dir->directory->Open(&dir->cookie, O_RDONLY0x0000);
1185 if (error != B_OK((int)0)) {
1186 errno(*(_errnop())) = error;
1187 return NULL__null;
1188 }
1189
1190 nodeReleaser.Detach();
1191 return dirDeleter.Detach();
1192}
1193
1194
1195DIR*
1196opendir(const char* dirName)
1197{
1198 return open_directory(gRoot, dirName);
1199}
1200
1201
1202int
1203closedir(DIR* dir)
1204{
1205 if (dir != NULL__null) {
1
Assuming 'dir' is not equal to NULL
2
Taking true branch
1206 dir->directory->Close(dir->cookie);
3
Calling 'Node::Close'
9
Returning; memory was released
1207 dir->directory->Release();
10
Use of memory after it is freed
1208 delete dir;
1209 }
1210
1211 return 0;
1212}
1213
1214
1215struct dirent*
1216readdir(DIR* dir)
1217{
1218 if (dir == NULL__null) {
1219 errno(*(_errnop())) = B_BAD_VALUE((-2147483647 - 1) + 5);
1220 return NULL__null;
1221 }
1222
1223 for (;;) {
1224 status_t error = dir->directory->GetNextEntry(dir->cookie,
1225 dir->entry.d_name, B_FILE_NAME_LENGTH(256));
1226 if (error != B_OK((int)0)) {
1227 errno(*(_errnop())) = error;
1228 return NULL__null;
1229 }
1230
1231 dir->entry.d_pdev = 0;
1232 // not supported
1233 dir->entry.d_pino = dir->directory->Inode();
1234 dir->entry.d_dev = dir->entry.d_pdev;
1235 // not supported
1236
1237 if (strcmp(dir->entry.d_name, ".") == 0
1238 || strcmp(dir->entry.d_name, "..") == 0) {
1239 // Note: That's obviously not correct for "..", but we can't
1240 // retrieve that information.
1241 dir->entry.d_ino = dir->entry.d_pino;
1242 } else {
1243 Node* node = dir->directory->Lookup(dir->entry.d_name, false);
1244 if (node == NULL__null)
1245 continue;
1246
1247 dir->entry.d_ino = node->Inode();
1248 node->Release();
1249 }
1250
1251 return &dir->entry;
1252 }
1253}
1254
1255
1256void
1257rewinddir(DIR* dir)
1258{
1259 if (dir == NULL__null) {
1260 errno(*(_errnop())) = B_BAD_VALUE((-2147483647 - 1) + 5);
1261 return;
1262 }
1263
1264 status_t error = dir->directory->Rewind(dir->cookie);
1265 if (error != B_OK((int)0))
1266 errno(*(_errnop())) = error;
1267}