Bug Summary

File:src/system/libroot/os/find_paths.cpp
Warning:line 131, column 3
Potential leak of memory pointed to by 'locations'

Annotated Source Code

1/*
2 * Copyright 2015, Axel Dörfler, axeld@pinc-software.de.
3 * Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de.
4 * Distributed under the terms of the MIT License.
5 */
6
7
8#include <find_directory_private.h>
9
10#include <errno(*(_errnop())).h>
11#include <stdio.h>
12#include <string.h>
13#include <sys/stat.h>
14
15#include <algorithm>
16
17#include <fs_attr.h>
18
19#include <architecture_private.h>
20#include <AutoDeleter.h>
21#include <directories.h>
22#include <syscalls.h>
23
24#include "PathBuffer.h"
25
26
27static size_t kHomeInstallationLocationIndex = 1;
28
29static const path_base_directory kArchitectureSpecificBaseDirectories[] = {
30 B_FIND_PATH_ADD_ONS_DIRECTORY,
31 B_FIND_PATH_BIN_DIRECTORY,
32 B_FIND_PATH_DEVELOP_LIB_DIRECTORY,
33 B_FIND_PATH_HEADERS_DIRECTORY,
34};
35
36static size_t kArchitectureSpecificBaseDirectoryCount =
37 sizeof(kArchitectureSpecificBaseDirectories)
38 / sizeof(kArchitectureSpecificBaseDirectories[0]);
39
40
41namespace {
42
43
44struct InstallationLocations {
45public:
46 static const size_t kCount = 4;
47
48public:
49 InstallationLocations()
50 :
51 fReferenceCount(1)
52 {
53 fLocations[0] = kUserNonpackagedDirectory"/boot/home/config/non-packaged";
54 fLocations[1] = kUserConfigDirectory"/boot/home/config";
55 fLocations[2] = kSystemNonpackagedDirectory"/boot/system/non-packaged";
56 fLocations[3] = kSystemDirectory"/boot/system";
57 }
58
59 InstallationLocations(const char* home)
60 :
61 fReferenceCount(1)
62 {
63 static const char* const kNonPackagedSuffix = "/non-packaged";
64 char* homeNonPackaged
65 = (char*)malloc(strlen(home) + strlen(kNonPackagedSuffix) + 1);
66 fLocations[0] = homeNonPackaged;
67 if (homeNonPackaged != NULL__null) {
68 strcpy(homeNonPackaged, home);
69 strcat(homeNonPackaged, kNonPackagedSuffix);
70 }
71
72 fLocations[1] = strdup(home);
73
74 fLocations[2] = kSystemNonpackagedDirectory"/boot/system/non-packaged";
75 fLocations[3] = kSystemDirectory"/boot/system";
76 }
77
78 ~InstallationLocations()
79 {
80 free(const_cast<char*>(fLocations[0]));
81 free(const_cast<char*>(fLocations[1]));
82 }
83
84 bool IsValid() const
85 {
86 return fLocations[0] != NULL__null && fLocations[1] != NULL__null;
87 }
88
89 bool IsUserIndex(size_t index) const
90 {
91 return index==0 || index==1;
92 }
93
94 bool IsSystemIndex(size_t index) const
95 {
96 return index==2 || index==3;
97 }
98
99 static InstallationLocations* Default()
100 {
101 static char sBuffer[sizeof(InstallationLocations)];
102 static InstallationLocations* sDefaultLocations
103 = new(&sBuffer) InstallationLocations;
104 return sDefaultLocations;
105 }
106
107 static InstallationLocations* Get()
108 {
109 InstallationLocations* defaultLocations = Default();
110
111 // Get the home config installation location and create a new object,
112 // if it differs from the default.
113 char homeInstallationLocation[B_PATH_NAME_LENGTH(1024)];
114 if (__find_directory(B_USER_CONFIG_DIRECTORY, -1, false,
4
Assuming the condition is true
5
Taking true branch
115 homeInstallationLocation, sizeof(homeInstallationLocation))
116 == B_OK((int)0)) {
117 _kern_normalize_path(homeInstallationLocation, true,
118 homeInstallationLocation);
119 // failure is OK
120 if (strcmp(homeInstallationLocation,
6
Assuming the condition is true
7
Taking true branch
121 defaultLocations->At(kHomeInstallationLocationIndex))
122 != 0) {
123 InstallationLocations* locations
124 = new(std::nothrow) InstallationLocations(
8
Memory is allocated
125 homeInstallationLocation);
126 if (locations != NULL__null && locations->IsValid())
9
Assuming 'locations' is not equal to NULL
10
Taking false branch
127 return locations;
128 }
129 }
130
131 atomic_add(&defaultLocations->fReferenceCount, 1);
11
Potential leak of memory pointed to by 'locations'
132 return defaultLocations;
133 }
134
135 void Put()
136 {
137 if (atomic_add(&fReferenceCount, -1) == 1)
138 delete this;
139 }
140
141 const char* At(size_t index) const
142 {
143 return fLocations[index];
144 }
145
146 const char* LocationFor(const char* path, size_t& _index)
147 {
148 for (size_t i = 0; i < kCount; i++) {
149 size_t length = strlen(fLocations[i]);
150 if (strncmp(path, fLocations[i], length) == 0
151 && (path[length] == '/' || path[length] == '\0')) {
152 _index = i;
153 return fLocations[i];
154 }
155 }
156
157 return NULL__null;
158 }
159
160private:
161 int32 fReferenceCount;
162 const char* fLocations[kCount];
163};
164
165
166} // unnamed namespace
167
168
169/*! Returns the installation location relative path for the given base directory
170 constant and installation location index. A '%' in the returned path must be
171 replaced by "" for the primary architecture and by "/<arch>" for a secondary
172 architecture.
173 */
174static const char*
175get_relative_directory_path(size_t installationLocationIndex,
176 path_base_directory baseDirectory)
177{
178 switch (baseDirectory) {
179 case B_FIND_PATH_INSTALLATION_LOCATION_DIRECTORY:
180 return "";
181 case B_FIND_PATH_ADD_ONS_DIRECTORY:
182 return "/add-ons%";
183 case B_FIND_PATH_APPS_DIRECTORY:
184 return "/apps";
185 case B_FIND_PATH_BIN_DIRECTORY:
186 return "/bin%";
187 case B_FIND_PATH_BOOT_DIRECTORY:
188 return "/boot";
189 case B_FIND_PATH_CACHE_DIRECTORY:
190 return "/cache";
191 case B_FIND_PATH_DATA_DIRECTORY:
192 return "/data";
193 case B_FIND_PATH_DEVELOP_DIRECTORY:
194 return "/develop";
195 case B_FIND_PATH_DEVELOP_LIB_DIRECTORY:
196 return "/develop/lib%";
197 case B_FIND_PATH_DOCUMENTATION_DIRECTORY:
198 return "/documentation";
199 case B_FIND_PATH_ETC_DIRECTORY:
200 return "/settings/etc";
201 case B_FIND_PATH_FONTS_DIRECTORY:
202 return "/data/fonts";
203 case B_FIND_PATH_HEADERS_DIRECTORY:
204 return "/develop/headers%";
205 case B_FIND_PATH_LIB_DIRECTORY:
206 return "/lib%";
207 case B_FIND_PATH_LOG_DIRECTORY:
208 return "/log";
209 case B_FIND_PATH_MEDIA_NODES_DIRECTORY:
210 return "/add-ons%/media";
211 case B_FIND_PATH_PACKAGES_DIRECTORY:
212 return "/packages";
213 case B_FIND_PATH_PREFERENCES_DIRECTORY:
214 return "/preferences";
215 case B_FIND_PATH_SERVERS_DIRECTORY:
216 return "/servers";
217 case B_FIND_PATH_SETTINGS_DIRECTORY:
218 return installationLocationIndex == kHomeInstallationLocationIndex
219 ? "/settings/global" : "/settings";
220 case B_FIND_PATH_SOUNDS_DIRECTORY:
221 return "/data/sounds";
222 case B_FIND_PATH_SPOOL_DIRECTORY:
223 return "/var/spool";
224 case B_FIND_PATH_TRANSLATORS_DIRECTORY:
225 return "/add-ons%/Translators";
226 case B_FIND_PATH_VAR_DIRECTORY:
227 return "/var";
228
229 case B_FIND_PATH_IMAGE_PATH:
230 case B_FIND_PATH_PACKAGE_PATH:
231 default:
232 return NULL__null;
233 }
234}
235
236
237static status_t
238create_directory(char* path)
239{
240 // find the first directory that doesn't exist
241 char* slash = path;
242 bool found = false;
243 while (!found && (slash = strchr(slash + 1, '/')) != NULL__null) {
244 *slash = '\0';
245 struct stat st;
246 if (lstat(path, &st) != 0)
247 break;
248 *slash = '/';
249 }
250
251 if (found)
252 return B_OK((int)0);
253
254 // create directories
255 while (slash != NULL__null) {
256 *slash = '\0';
257 bool created = mkdir(path, 0755);
258 *slash = '/';
259
260 if (!created)
261 return errno(*(_errnop()));
262
263 slash = strchr(slash + 1, '/');
264 }
265
266 return B_OK((int)0);
267}
268
269
270static bool
271is_in_range(const void* pointer, const void* base, size_t size)
272{
273 return pointer >= base && (addr_t)pointer < (addr_t)base + size;
274}
275
276
277static status_t
278find_image(const void* codePointer, image_info& _info)
279{
280 int32 cookie = 0;
281
282 while (get_next_image_info(B_CURRENT_TEAM, &cookie, &_info)_get_next_image_info((0), (&cookie), (&_info), sizeof
(*(&_info)))
== B_OK((int)0)) {
283 if (codePointer == NULL__null ? _info.type == B_APP_IMAGE
284 : (is_in_range(codePointer, _info.text, _info.text_size)
285 || is_in_range(codePointer, _info.data, _info.data_size))) {
286 return B_OK((int)0);
287 }
288 }
289
290 return B_ENTRY_NOT_FOUND(((-2147483647 - 1) + 0x6000) + 3);
291}
292
293
294static status_t
295copy_path(const char* path, char* buffer, size_t bufferSize)
296{
297 if (strlcpy(buffer, path, bufferSize) >= bufferSize)
298 return B_BUFFER_OVERFLOW((((-2147483647 - 1) + 0x7000) + 41));
299 return B_OK((int)0);
300}
301
302
303static status_t
304normalize_path(const char* path, char* buffer, size_t bufferSize)
305{
306 status_t error;
307 if (bufferSize >= B_PATH_NAME_LENGTH(1024)) {
308 error = _kern_normalize_path(path, true, buffer);
309 } else {
310 char normalizedPath[B_PATH_NAME_LENGTH(1024)];
311 error = _kern_normalize_path(path, true, normalizedPath);
312 if (error == B_OK((int)0))
313 error = copy_path(path, buffer, bufferSize);
314 }
315
316 if (error != B_OK((int)0))
317 return error;
318
319 // make sure the path exists
320 struct stat st;
321 if (lstat(buffer, &st) != 0)
322 return errno(*(_errnop()));
323
324 return B_OK((int)0);
325}
326
327
328static status_t
329normalize_longest_existing_path_prefix(const char* path, char* buffer,
330 size_t bufferSize)
331{
332 if (strlcpy(buffer, path, bufferSize) >= bufferSize)
333 return B_NAME_TOO_LONG(((-2147483647 - 1) + 0x6000) + 4);
334
335 // Until we have an existing path, chop off leaf components.
336 for (;;) {
337 struct stat st;
338 if (lstat(buffer, &st) == 0)
339 break;
340
341 // Chop off the leaf, but fail, it it's "..", since then we'd actually
342 // construct a subpath.
343 char* lastSlash = strrchr(buffer, '/');
344 if (lastSlash == NULL__null || strcmp(lastSlash + 1, "..") == 0)
345 return B_ENTRY_NOT_FOUND(((-2147483647 - 1) + 0x6000) + 3);
346
347 *lastSlash = '\0';
348 }
349
350 // normalize the existing prefix path
351 size_t prefixLength = strlen(buffer);
352 status_t error = normalize_path(buffer, buffer, bufferSize);
353 if (error != B_OK((int)0))
354 return error;
355
356 // Re-append the non-existent suffix. Remove duplicate slashes and "."
357 // components.
358 const char* bufferEnd = buffer + bufferSize;
359 char* end = buffer + strlen(buffer);
360 const char* remainder = path + prefixLength + 1;
361 while (*remainder != '\0') {
362 // find component start
363 if (*remainder == '/') {
364 remainder++;
365 continue;
366 }
367
368 // find component end
369 const char* componentEnd = strchr(remainder, '/');
370 if (componentEnd == NULL__null)
371 componentEnd = remainder + strlen(remainder);
372
373 // skip "." components
374 size_t componentLength = componentEnd - remainder;
375 if (componentLength == 1 && *remainder == '.') {
376 remainder++;
377 continue;
378 }
379
380 // append the component
381 if (end + 1 + componentLength >= bufferEnd)
382 return B_BUFFER_OVERFLOW((((-2147483647 - 1) + 0x7000) + 41));
383
384 *end++ = '/';
385 memcpy(end, remainder, componentLength);
386 end += componentLength;
387 remainder += componentLength;
388 }
389
390 *end = '\0';
391 return B_OK((int)0);
392}
393
394
395static status_t
396get_file_attribute(const char* path, const char* attribute, char* nameBuffer,
397 size_t bufferSize)
398{
399 int fd = fs_open_attr(path, attribute, B_STRING_TYPE,
400 O_RDONLY0x0000 | O_NOTRAVERSE0x2000);
401 if (fd < 0)
402 return errno(*(_errnop()));
403
404 status_t error = B_OK((int)0);
405 ssize_t bytesRead = read(fd, nameBuffer, bufferSize - 1);
406 if (bytesRead < 0)
407 error = bytesRead;
408 else if (bytesRead == 0)
409 error = B_ENTRY_NOT_FOUND(((-2147483647 - 1) + 0x6000) + 3);
410 else
411 nameBuffer[bytesRead] = '\0';
412
413 fs_close_attr(fd);
414
415 return error;
416}
417
418
419static status_t
420normalize_dependency(const char* dependency, char* buffer, size_t bufferSize)
421{
422 if (strlcpy(buffer, dependency, bufferSize) >= bufferSize)
423 return B_NAME_TOO_LONG(((-2147483647 - 1) + 0x6000) + 4);
424
425 // replace all ':' with '~'
426 char* colon = buffer - 1;
427 while ((colon = strchr(colon + 1, ':')) != NULL__null)
428 *colon = '~';
429
430 return B_OK((int)0);
431}
432
433
434static ssize_t
435process_path(const char* installationLocation, const char* architecture,
436 const char* relativePath, const char* subPath, uint32 flags,
437 char* pathBuffer, size_t bufferSize)
438{
439 // copy the installation location
440 PathBuffer buffer(pathBuffer, bufferSize);
441 buffer.Append(installationLocation);
442
443 // append the relative path, expanding the architecture placeholder
444 if (const char* placeholder = strchr(relativePath, '%')) {
445 buffer.Append(relativePath, placeholder - relativePath);
446
447 if (architecture != NULL__null) {
448 buffer.Append("/", 1);
449 buffer.Append(architecture);
450 }
451
452 buffer.Append(placeholder + 1);
453 } else
454 buffer.Append(relativePath);
455
456 // append subpath, if given
457 if (subPath != NULL__null) {
458 buffer.Append("/", 1);
459 buffer.Append(subPath);
460 }
461
462 size_t totalLength = buffer.Length();
463 if (totalLength >= bufferSize)
464 return B_BUFFER_OVERFLOW((((-2147483647 - 1) + 0x7000) + 41));
465
466 // handle the flags
467 char* path = pathBuffer;
468
469 status_t error = B_OK((int)0);
470 if ((flags & B_FIND_PATH_CREATE_DIRECTORY) != 0) {
471 // create the directory
472 error = create_directory(path);
473 } else if ((flags & B_FIND_PATH_CREATE_PARENT_DIRECTORY) != 0) {
474 // create the parent directory
475 char* lastSlash = strrchr(path, '/');
476 *lastSlash = '\0';
477 error = create_directory(path);
478 *lastSlash = '/';
479 }
480
481 if (error != B_OK((int)0))
482 return error;
483
484 if ((flags & B_FIND_PATH_EXISTING_ONLY) != 0) {
485 // check if the entry exists
486 struct stat st;
487 if (lstat(path, &st) != 0)
488 return 0;
489 }
490
491 return totalLength + 1;
492}
493
494
495status_t
496internal_path_for_path(char* referencePath, size_t referencePathSize,
497 const char* dependency, const char* architecture,
498 path_base_directory baseDirectory, const char* subPath, uint32 flags,
499 char* pathBuffer, size_t bufferSize)
500{
501 if (strcmp(architecture, __get_primary_architecture()) == 0)
502 architecture = NULL__null;
503
504 // resolve dependency
505 char packageName[B_FILE_NAME_LENGTH(256)];
506 // Temporarily used here, permanently used below where
507 // B_FIND_PATH_PACKAGE_PATH is handled.
508 if (dependency != NULL__null) {
509 // get the versioned package name
510 status_t error = get_file_attribute(referencePath, "SYS:PACKAGE",
511 packageName, sizeof(packageName));
512 if (error != B_OK((int)0))
513 return error;
514
515 // normalize the dependency name
516 char normalizedDependency[B_FILE_NAME_LENGTH(256)];
517 error = normalize_dependency(dependency, normalizedDependency,
518 sizeof(normalizedDependency));
519 if (error != B_OK((int)0))
520 return error;
521
522 // Compute the path of the dependency symlink. This will yield the
523 // installation location path when normalized.
524 if (snprintf(referencePath, referencePathSize,
525 kSystemPackageLinksDirectory"/boot/system/package-links" "/%s/%s", packageName,
526 normalizedDependency)
527 >= (ssize_t)referencePathSize) {
528 return B_BUFFER_OVERFLOW((((-2147483647 - 1) + 0x7000) + 41));
529 }
530 }
531
532 // handle B_FIND_PATH_IMAGE_PATH
533 if (baseDirectory == B_FIND_PATH_IMAGE_PATH)
534 return copy_path(referencePath, pathBuffer, bufferSize);
535
536 // Handle B_FIND_PATH_PACKAGE_PATH: get the package file name and
537 // simply adjust our arguments to look the package file up in the packages
538 // directory.
539 if (baseDirectory == B_FIND_PATH_PACKAGE_PATH) {
540 status_t error = get_file_attribute(referencePath, "SYS:PACKAGE_FILE",
541 packageName, sizeof(packageName));
542 if (error != B_OK((int)0))
543 return error;
544
545 dependency = NULL__null;
546 subPath = packageName;
547 baseDirectory = B_FIND_PATH_PACKAGES_DIRECTORY;
548 flags = B_FIND_PATH_EXISTING_ONLY;
549 }
550
551 // normalize
552 status_t error = normalize_path(referencePath, referencePath,
553 referencePathSize);
554 if (error != B_OK((int)0))
555 return error;
556
557 // get the installation location
558 InstallationLocations* installationLocations = InstallationLocations::Get();
559 MethodDeleter<InstallationLocations> installationLocationsDeleter(
560 installationLocations, &InstallationLocations::Put);
561
562 size_t installationLocationIndex;
563 const char* installationLocation = installationLocations->LocationFor(
564 referencePath, installationLocationIndex);
565 if (installationLocation == NULL__null)
566 return B_ENTRY_NOT_FOUND(((-2147483647 - 1) + 0x6000) + 3);
567
568 // get base dir and process the path
569 const char* relativePath = get_relative_directory_path(
570 installationLocationIndex, baseDirectory);
571 if (relativePath == NULL__null)
572 return B_BAD_VALUE((-2147483647 - 1) + 5);
573
574 ssize_t pathSize = process_path(installationLocation, architecture,
575 relativePath, subPath, flags, pathBuffer, bufferSize);
576 if (pathSize <= 0)
577 return pathSize == 0 ? B_ENTRY_NOT_FOUND(((-2147483647 - 1) + 0x6000) + 3) : pathSize;
578 return B_OK((int)0);
579}
580
581
582// #pragma mark -
583
584
585status_t
586__find_path(const void* codePointer, path_base_directory baseDirectory,
587 const char* subPath, char* pathBuffer, size_t bufferSize)
588{
589 return __find_path_etc(codePointer, NULL__null, NULL__null, baseDirectory, subPath, 0,
590 pathBuffer, bufferSize);
591}
592
593
594status_t
595__find_path_etc(const void* codePointer, const char* dependency,
596 const char* architecture, path_base_directory baseDirectory,
597 const char* subPath, uint32 flags, char* pathBuffer, size_t bufferSize)
598{
599 if (pathBuffer == NULL__null)
600 return B_BAD_VALUE((-2147483647 - 1) + 5);
601
602 // resolve codePointer to image info
603 image_info imageInfo;
604 status_t error = find_image(codePointer, imageInfo);
605 if (error != B_OK((int)0))
606 return error;
607
608 if (architecture == NULL__null)
609 architecture = __get_architecture();
610
611 return internal_path_for_path(imageInfo.name, sizeof(imageInfo.name),
612 dependency, architecture, baseDirectory, subPath, flags, pathBuffer,
613 bufferSize);
614}
615
616
617status_t
618__find_path_for_path(const char* path, path_base_directory baseDirectory,
619 const char* subPath, char* pathBuffer, size_t bufferSize)
620{
621 return __find_path_for_path_etc(path, NULL__null, NULL__null, baseDirectory, subPath, 0,
622 pathBuffer, bufferSize);
623}
624
625
626status_t
627__find_path_for_path_etc(const char* path, const char* dependency,
628 const char* architecture, path_base_directory baseDirectory,
629 const char* subPath, uint32 flags, char* pathBuffer, size_t bufferSize)
630{
631 if (baseDirectory == B_FIND_PATH_IMAGE_PATH)
632 return B_BAD_VALUE((-2147483647 - 1) + 5);
633
634 char referencePath[B_PATH_NAME_LENGTH(1024)];
635 if (strlcpy(referencePath, path, sizeof(referencePath))
636 >= sizeof(referencePath)) {
637 return B_NAME_TOO_LONG(((-2147483647 - 1) + 0x6000) + 4);
638 }
639
640 if (architecture == NULL__null)
641 architecture = __guess_architecture_for_path(path);
642
643 return internal_path_for_path(referencePath, sizeof(referencePath),
644 dependency, architecture, baseDirectory, subPath, flags, pathBuffer,
645 bufferSize);
646}
647
648
649status_t
650__find_paths(path_base_directory baseDirectory, const char* subPath,
651 char*** _paths, size_t* _pathCount)
652{
653 return __find_paths_etc(NULL__null, baseDirectory, subPath, 0, _paths,
654 _pathCount);
655}
656
657
658status_t
659__find_paths_etc(const char* architecture, path_base_directory baseDirectory,
660 const char* subPath, uint32 flags, char*** _paths, size_t* _pathCount)
661{
662 if (_paths == NULL__null || _pathCount == NULL__null)
663 return B_BAD_VALUE((-2147483647 - 1) + 5);
664
665 // Analyze architecture. If NULL, use the caller's architecture. If the
666 // effective architecture is the primary one, set architecture to NULL to
667 // indicate that we don't need to insert an architecture subdirectory
668 // component.
669 if (architecture == NULL__null)
670 architecture = __get_architecture();
671 if (strcmp(architecture, __get_primary_architecture()) == 0)
672 architecture = NULL__null;
673 size_t architectureSize = architecture != NULL__null
674 ? strlen(architecture) + 1 : 0;
675
676 size_t subPathLength = subPath != NULL__null ? strlen(subPath) + 1 : 0;
677
678 // get the installation locations
679 InstallationLocations* installationLocations = InstallationLocations::Get();
680 MethodDeleter<InstallationLocations> installationLocationsDeleter(
681 installationLocations, &InstallationLocations::Put);
682
683 // Get the relative paths and compute the total size to allocate.
684 const char* relativePaths[InstallationLocations::kCount];
685 size_t totalSize = 0;
686
687 for (size_t i = 0; i < InstallationLocations::kCount; i++) {
688 if (((flags & B_FIND_PATHS_USER_ONLY) != 0
689 && !installationLocations->IsUserIndex(i))
690 || ((flags & B_FIND_PATHS_SYSTEM_ONLY) != 0
691 && !installationLocations->IsSystemIndex(i)))
692 continue;
693
694 relativePaths[i] = get_relative_directory_path(i, baseDirectory);
695 if (relativePaths[i] == NULL__null)
696 return B_BAD_VALUE((-2147483647 - 1) + 5);
697
698 totalSize += strlen(installationLocations->At(i))
699 + strlen(relativePaths[i]) + subPathLength + 1;
700 if (strchr(relativePaths[i], '%') != NULL__null)
701 totalSize += architectureSize - 1;
702 }
703
704 // allocate storage
705 char** paths = (char**)malloc(sizeof(char*) * InstallationLocations::kCount
706 + totalSize);
707 if (paths == NULL__null)
708 return B_NO_MEMORY((-2147483647 - 1) + 0);
709 MemoryDeleter pathsDeleter(paths);
710
711 // construct and process the paths
712 size_t count = 0;
713 char* pathBuffer = (char*)(paths + InstallationLocations::kCount);
714 const char* pathBufferEnd = pathBuffer + totalSize;
715 for (size_t i = 0; i < InstallationLocations::kCount; i++) {
716 if (((flags & B_FIND_PATHS_USER_ONLY) != 0
717 && !installationLocations->IsUserIndex(i))
718 || ((flags & B_FIND_PATHS_SYSTEM_ONLY) != 0
719 && !installationLocations->IsSystemIndex(i)))
720 continue;
721
722 ssize_t pathSize = process_path(installationLocations->At(i),
723 architecture, relativePaths[i], subPath, flags, pathBuffer,
724 pathBufferEnd - pathBuffer);
725 if (pathSize < 0)
726 return pathSize;
727 if (pathSize > 0) {
728 paths[count++] = pathBuffer;
729 pathBuffer += pathSize;
730 }
731 }
732
733 if (count == 0)
734 return B_ENTRY_NOT_FOUND(((-2147483647 - 1) + 0x6000) + 3);
735
736 *_paths = paths;
737 *_pathCount = count;
738 pathsDeleter.Detach();
739
740 return B_OK((int)0);
741}
742
743
744const char*
745__guess_secondary_architecture_from_path(const char* path,
746 const char* const* secondaryArchitectures,
747 size_t secondaryArchitectureCount)
748{
749 // Get the longest existing prefix path and normalize it.
750 char prefix[B_PATH_NAME_LENGTH(1024)];
751 if (normalize_longest_existing_path_prefix(path, prefix, sizeof(prefix))
1
Assuming the condition is false
2
Taking false branch
752 != B_OK((int)0)) {
753 return NULL__null;
754 }
755
756 // get an installation location relative path
757 InstallationLocations* installationLocations = InstallationLocations::Get();
3
Calling 'InstallationLocations::Get'
758 MethodDeleter<InstallationLocations> installationLocationsDeleter(
759 installationLocations, &InstallationLocations::Put);
760
761 size_t installationLocationIndex;
762 const char* installationLocation = installationLocations->LocationFor(
763 prefix, installationLocationIndex);
764 if (installationLocation == NULL__null)
765 return NULL__null;
766
767 const char* relativePath = prefix + strlen(installationLocation);
768 if (relativePath[0] != '/')
769 return NULL__null;
770
771 // Iterate through the known paths that would indicate a secondary
772 // architecture and try to match them with our given path.
773 for (size_t i = 0; i < kArchitectureSpecificBaseDirectoryCount; i++) {
774 const char* basePath = get_relative_directory_path(
775 installationLocationIndex, kArchitectureSpecificBaseDirectories[i]);
776 const char* placeholder = strchr(basePath, '%');
777 if (placeholder == NULL__null)
778 continue;
779
780 // match the part up to the architecture placeholder
781 size_t prefixLength = placeholder - basePath;
782 if (strncmp(relativePath, basePath, prefixLength) != 0
783 || relativePath[prefixLength] != '/') {
784 continue;
785 }
786
787 // match the architecture
788 const char* architecturePart = relativePath + prefixLength + 1;
789 for (size_t k = 0; k < secondaryArchitectureCount; k++) {
790 const char* architecture = secondaryArchitectures[k];
791 size_t architectureLength = strlen(architecture);
792 if (strncmp(architecturePart, architecture, architectureLength) == 0
793 && (architecturePart[architectureLength] == '/'
794 || architecturePart[architectureLength] == '\0')) {
795 return architecture;
796 }
797 }
798 }
799
800 return NULL__null;
801}
802
803
804B_DEFINE_WEAK_ALIAS(__find_path, find_path)extern "C" __typeof(__find_path) find_path __attribute__((weak
, alias("__find_path")))
;
805B_DEFINE_WEAK_ALIAS(__find_path_etc, find_path_etc)extern "C" __typeof(__find_path_etc) find_path_etc __attribute__
((weak, alias("__find_path_etc")))
;
806B_DEFINE_WEAK_ALIAS(__find_path_for_path, find_path_for_path)extern "C" __typeof(__find_path_for_path) find_path_for_path __attribute__
((weak, alias("__find_path_for_path")))
;
807B_DEFINE_WEAK_ALIAS(__find_path_for_path_etc, find_path_for_path_etc)extern "C" __typeof(__find_path_for_path_etc) find_path_for_path_etc
__attribute__((weak, alias("__find_path_for_path_etc")))
;
808B_DEFINE_WEAK_ALIAS(__find_paths, find_paths)extern "C" __typeof(__find_paths) find_paths __attribute__((weak
, alias("__find_paths")))
;
809B_DEFINE_WEAK_ALIAS(__find_paths_etc, find_paths_etc)extern "C" __typeof(__find_paths_etc) find_paths_etc __attribute__
((weak, alias("__find_paths_etc")))
;