1 /* 2 * Copyright 2004, François Revol. 3 * Copyright 2007-2010, Axel Dörfler, axeld@pinc-software.de. 4 * Copyright 2011, Oliver Tappe, zooey@hirschkaefer.de. 5 * Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de. 6 * 7 * Distributed under the terms of the MIT license. 8 */ 9 10 // TODO: this call is currently compiled for the kernel and libroot separately; 11 // they may not always return the same directory right now! 12 13 #ifdef _KERNEL_MODE 14 # include <vfs.h> 15 #else 16 # include <syscalls.h> 17 #endif 18 19 #include <directories.h> 20 #include <FindDirectory.h> 21 #include <fs_info.h> 22 #include <StackOrHeapArray.h> 23 24 #include <errno.h> 25 #include <pwd.h> 26 #include <string.h> 27 #include <sys/stat.h> 28 #include <stdlib.h> 29 #include <unistd.h> 30 31 #include <architecture_private.h> 32 #include <errno_private.h> 33 #include <find_directory_private.h> 34 #include <stdlib_private.h> 35 #include <symbol_versioning.h> 36 #include <user_group.h> 37 38 #include <AutoDeleter.h> 39 40 #include "PathBuffer.h" 41 42 43 /* use pwents to find home */ 44 #define USE_PWENTS 45 46 47 /* 48 * If you change any of the directories below, please have a look at 49 * headers/private/libroot/directories.h and adjust that accordingly! 50 */ 51 52 #define SYSTEM "system" 53 #define COMMON "system/data/empty" 54 #define NON_PACKAGED "/non-packaged" 55 56 enum { 57 // obsolete common directories 58 B_COMMON_DIRECTORY = 2000, 59 B_COMMON_SYSTEM_DIRECTORY, 60 B_COMMON_ADDONS_DIRECTORY, 61 B_COMMON_BOOT_DIRECTORY, 62 B_COMMON_FONTS_DIRECTORY, 63 B_COMMON_LIB_DIRECTORY, 64 B_COMMON_SERVERS_DIRECTORY, 65 B_COMMON_BIN_DIRECTORY, 66 _B_COMMON_ETC_DIRECTORY, 67 B_COMMON_DOCUMENTATION_DIRECTORY, 68 _B_COMMON_SETTINGS_DIRECTORY, 69 B_COMMON_DEVELOP_DIRECTORY, 70 _B_COMMON_LOG_DIRECTORY, 71 _B_COMMON_SPOOL_DIRECTORY, 72 _B_COMMON_TEMP_DIRECTORY, 73 _B_COMMON_VAR_DIRECTORY, 74 B_COMMON_TRANSLATORS_DIRECTORY, 75 B_COMMON_MEDIA_NODES_DIRECTORY, 76 B_COMMON_SOUNDS_DIRECTORY, 77 B_COMMON_DATA_DIRECTORY, 78 _B_COMMON_CACHE_DIRECTORY, 79 B_COMMON_PACKAGES_DIRECTORY, 80 B_COMMON_HEADERS_DIRECTORY, 81 }; 82 83 84 /* Haiku system directories */ 85 86 static const char *kSystemDirectories[] = { 87 SYSTEM, // B_SYSTEM_DIRECTORY 88 SYSTEM, // B_BEOS_SYSTEM_DIRECTORY 89 SYSTEM "/add-ons$a", 90 SYSTEM "/boot", 91 SYSTEM "/data/fonts", 92 SYSTEM "/lib$a", 93 SYSTEM "/servers", 94 SYSTEM "/apps", 95 SYSTEM "/bin$a", 96 SYSTEM "/settings/etc", 97 SYSTEM "/documentation", 98 SYSTEM "/preferences", 99 SYSTEM "/add-ons$a/Translators", 100 SYSTEM "/add-ons$a/media", 101 SYSTEM "/data/sounds", 102 SYSTEM "/data", 103 SYSTEM "/develop", 104 SYSTEM "/packages", 105 SYSTEM "/develop/headers$a", 106 }; 107 108 /* Common directories, shared among users */ 109 110 static const char *kCommonDirectories[] = { 111 COMMON, // B_COMMON_DIRECTORY 112 COMMON, // B_COMMON_SYSTEM_DIRECTORY 113 COMMON "/add-ons$a", 114 COMMON "/boot", 115 COMMON "/data/fonts", 116 COMMON "/lib$a", 117 COMMON "/servers", 118 COMMON "/bin$a", 119 SYSTEM "/settings/etc", // B_SYSTEM_ETC_DIRECTORY 120 COMMON "/documentation", 121 SYSTEM "/settings", // B_SYSTEM_SETTINGS_DIRECTORY 122 COMMON "/develop", 123 SYSTEM "/var/log", // B_SYSTEM_LOG_DIRECTORY 124 SYSTEM "/var/spool", // B_SYSTEM_SPOOL_DIRECTORY 125 SYSTEM "/cache/tmp", // B_SYSTEM_TEMP_DIRECTORY 126 SYSTEM "/var", // B_SYSTEM_VAR_DIRECTORY 127 COMMON "/add-ons$a/Translators", 128 COMMON "/add-ons$a/media", 129 COMMON "/data/sounds", 130 COMMON "/data", 131 SYSTEM "/cache", // B_SYSTEM_CACHE_DIRECTORY 132 COMMON "/packages", 133 COMMON "/develop/headers$a", 134 SYSTEM NON_PACKAGED, 135 SYSTEM NON_PACKAGED "/add-ons$a", 136 SYSTEM NON_PACKAGED "/add-ons$a/Translators", 137 SYSTEM NON_PACKAGED "/add-ons$a/media", 138 SYSTEM NON_PACKAGED "/bin$a", 139 SYSTEM NON_PACKAGED "/data", 140 SYSTEM NON_PACKAGED "/data/fonts", 141 SYSTEM NON_PACKAGED "/data/sounds", 142 SYSTEM NON_PACKAGED "/documentation", 143 SYSTEM NON_PACKAGED "/lib$a", 144 SYSTEM NON_PACKAGED "/develop/headers$a", 145 SYSTEM NON_PACKAGED "/develop", 146 }; 147 148 /* User directories */ 149 150 #define HOME "$h" 151 #define CONFIG "/config" 152 153 static const char *kUserDirectories[] = { 154 HOME, // B_USER_DIRECTORY 155 HOME CONFIG, // B_USER_CONFIG_DIRECTORY 156 HOME CONFIG "/add-ons$a", 157 HOME CONFIG "/settings/boot", 158 HOME CONFIG "/data/fonts", 159 HOME CONFIG "/lib$a", 160 HOME CONFIG "/settings", 161 HOME CONFIG "/settings/deskbar/menu", 162 HOME CONFIG "/settings/printers", 163 HOME CONFIG "/add-ons$a/Translators", 164 HOME CONFIG "/add-ons$a/media", 165 HOME CONFIG "/data/sounds", 166 HOME CONFIG "/data", 167 HOME CONFIG "/cache", 168 HOME CONFIG "/packages", 169 HOME CONFIG "/develop/headers$a", 170 HOME CONFIG NON_PACKAGED, 171 HOME CONFIG NON_PACKAGED "/add-ons$a", 172 HOME CONFIG NON_PACKAGED "/add-ons$a/Translators", 173 HOME CONFIG NON_PACKAGED "/add-ons$a/media", 174 HOME CONFIG NON_PACKAGED "/bin$a", 175 HOME CONFIG NON_PACKAGED "/data", 176 HOME CONFIG NON_PACKAGED "/data/fonts", 177 HOME CONFIG NON_PACKAGED "/data/sounds", 178 HOME CONFIG NON_PACKAGED "/documentation", 179 HOME CONFIG NON_PACKAGED "/lib$a", 180 HOME CONFIG NON_PACKAGED "/develop/headers$a", 181 HOME CONFIG NON_PACKAGED "/develop", 182 HOME CONFIG "/develop", 183 HOME CONFIG "/documentation", 184 HOME CONFIG "/servers", 185 HOME CONFIG "/apps", 186 HOME CONFIG "/bin$a", 187 HOME CONFIG "/preferences", 188 HOME CONFIG "/settings/etc", 189 HOME CONFIG "/var/log", 190 HOME CONFIG "/var/spool", 191 HOME CONFIG "/var", 192 }; 193 194 #ifndef _LOADER_MODE 195 /*! make dir and its parents if needed */ 196 static int 197 create_path(const char *path, mode_t mode) 198 { 199 int pathLength; 200 int i = 0; 201 202 if (path == NULL || ((pathLength = strlen(path)) > B_PATH_NAME_LENGTH)) 203 return EINVAL; 204 205 BStackOrHeapArray<char, 128> buffer(pathLength + 1); 206 if (!buffer.IsValid()) 207 return B_NO_MEMORY; 208 209 while (++i < pathLength) { 210 char *slash = strchr(&path[i], '/'); 211 struct stat st; 212 213 if (slash == NULL) 214 i = pathLength; 215 else if (i != slash - path) 216 i = slash - path; 217 else 218 continue; 219 220 strlcpy(buffer, path, i + 1); 221 if (stat(buffer, &st) < 0) { 222 __set_errno(0); 223 if (mkdir(buffer, mode) < 0) 224 return errno; 225 } 226 } 227 228 return 0; 229 } 230 231 232 static size_t 233 get_user_home_path(char* buffer, size_t bufferSize) 234 { 235 const char* home = NULL; 236 #ifndef _KERNEL_MODE 237 #ifdef USE_PWENTS 238 uid_t user = geteuid(); 239 if (user == 0) { 240 // TODO: this is a work-around as the launch_daemon, and the registrar 241 // must not call getpwuid_r(). 242 return strlcpy(buffer, kUserDirectory, bufferSize); 243 } 244 245 struct passwd pwBuffer; 246 char pwStringBuffer[MAX_PASSWD_BUFFER_SIZE]; 247 struct passwd* pw; 248 249 if (getpwuid_r(user, &pwBuffer, pwStringBuffer, 250 sizeof(pwStringBuffer), &pw) == 0 251 && pw != NULL) { 252 home = pw->pw_dir; 253 } 254 #endif // USE_PWENTS 255 if (home == NULL) { 256 /* use env var */ 257 ssize_t result = __getenv_reentrant("HOME", buffer, bufferSize); 258 if (result >= 0) 259 return result; 260 } 261 #endif // !_KERNEL_MODE 262 if (home == NULL) 263 home = kUserDirectory; 264 265 return strlcpy(buffer, home, bufferSize); 266 } 267 268 269 // #pragma mark - 270 271 272 status_t 273 __find_directory(directory_which which, dev_t device, bool createIt, 274 char *returnedPath, int32 _pathLength) 275 { 276 if (_pathLength <= 0) 277 return E2BIG; 278 size_t pathLength = _pathLength; 279 280 status_t err = B_OK; 281 dev_t bootDevice = -1; 282 struct fs_info fsInfo; 283 struct stat st; 284 const char *templatePath = NULL; 285 286 /* as with the R5 version, no on-stack buffer */ 287 char *buffer = (char*)malloc(pathLength); 288 if (buffer == NULL) 289 return B_NO_MEMORY; 290 MemoryDeleter bufferDeleter(buffer); 291 292 memset(buffer, 0, pathLength); 293 294 /* fiddle with non-boot volume for items that need it */ 295 switch (which) { 296 case B_DESKTOP_DIRECTORY: 297 case B_TRASH_DIRECTORY: 298 bootDevice = dev_for_path("/boot"); 299 if (device <= 0) 300 device = bootDevice; 301 if (fs_stat_dev(device, &fsInfo) != B_OK) 302 return ENODEV; 303 if (device != bootDevice) { 304 #ifdef _KERNEL_MODE 305 err = _user_entry_ref_to_path(device, fsInfo.root, /*"."*/ 306 NULL, buffer, pathLength); 307 #else 308 err = _kern_entry_ref_to_path(device, fsInfo.root, /*"."*/ 309 NULL, buffer, pathLength); 310 #endif 311 if (err != B_OK) 312 return err; 313 } else { 314 /* use the user id to find the home folder */ 315 /* done later */ 316 strlcat(buffer, "/boot", pathLength); 317 } 318 break; 319 case B_PACKAGE_LINKS_DIRECTORY: 320 // this is a directory living in rootfs 321 break; 322 default: 323 strlcat(buffer, "/boot", pathLength); 324 break; 325 } 326 327 switch ((int)which) { 328 /* Per volume directories */ 329 case B_DESKTOP_DIRECTORY: 330 if (device == bootDevice || !strcmp(fsInfo.fsh_name, "bfs")) 331 templatePath = "$h/Desktop"; 332 break; 333 case B_TRASH_DIRECTORY: 334 // TODO: eventually put that into the file system API? 335 if (device == bootDevice || !strcmp(fsInfo.fsh_name, "bfs")) 336 templatePath = "trash"; // TODO: add suffix for current user 337 else if (!strcmp(fsInfo.fsh_name, "fat")) 338 templatePath = "RECYCLED/_BEOS_"; 339 break; 340 341 /* Haiku system directories */ 342 case B_SYSTEM_DIRECTORY: 343 case B_BEOS_SYSTEM_DIRECTORY: 344 case B_SYSTEM_ADDONS_DIRECTORY: 345 case B_SYSTEM_BOOT_DIRECTORY: 346 case B_SYSTEM_FONTS_DIRECTORY: 347 case B_SYSTEM_LIB_DIRECTORY: 348 case B_SYSTEM_SERVERS_DIRECTORY: 349 case B_SYSTEM_APPS_DIRECTORY: 350 case B_SYSTEM_BIN_DIRECTORY: 351 case B_BEOS_ETC_DIRECTORY: 352 case B_SYSTEM_DOCUMENTATION_DIRECTORY: 353 case B_SYSTEM_PREFERENCES_DIRECTORY: 354 case B_SYSTEM_TRANSLATORS_DIRECTORY: 355 case B_SYSTEM_MEDIA_NODES_DIRECTORY: 356 case B_SYSTEM_SOUNDS_DIRECTORY: 357 case B_SYSTEM_DATA_DIRECTORY: 358 case B_SYSTEM_DEVELOP_DIRECTORY: 359 case B_SYSTEM_PACKAGES_DIRECTORY: 360 case B_SYSTEM_HEADERS_DIRECTORY: 361 templatePath = kSystemDirectories[which - B_SYSTEM_DIRECTORY]; 362 break; 363 364 /* Obsolete common directories and writable system directories */ 365 case B_COMMON_DIRECTORY: 366 case B_COMMON_SYSTEM_DIRECTORY: 367 case B_COMMON_ADDONS_DIRECTORY: 368 case B_COMMON_BOOT_DIRECTORY: 369 case B_COMMON_FONTS_DIRECTORY: 370 case B_COMMON_LIB_DIRECTORY: 371 case B_COMMON_SERVERS_DIRECTORY: 372 case B_COMMON_BIN_DIRECTORY: 373 case B_SYSTEM_ETC_DIRECTORY: 374 case B_COMMON_DOCUMENTATION_DIRECTORY: 375 case B_SYSTEM_SETTINGS_DIRECTORY: 376 case B_COMMON_DEVELOP_DIRECTORY: 377 case B_SYSTEM_LOG_DIRECTORY: 378 case B_SYSTEM_SPOOL_DIRECTORY: 379 case B_SYSTEM_TEMP_DIRECTORY: 380 case B_SYSTEM_VAR_DIRECTORY: 381 case B_COMMON_TRANSLATORS_DIRECTORY: 382 case B_COMMON_MEDIA_NODES_DIRECTORY: 383 case B_COMMON_SOUNDS_DIRECTORY: 384 case B_COMMON_DATA_DIRECTORY: 385 case B_SYSTEM_CACHE_DIRECTORY: 386 case B_COMMON_PACKAGES_DIRECTORY: 387 case B_COMMON_HEADERS_DIRECTORY: 388 case B_SYSTEM_NONPACKAGED_DIRECTORY: 389 case B_SYSTEM_NONPACKAGED_ADDONS_DIRECTORY: 390 case B_SYSTEM_NONPACKAGED_TRANSLATORS_DIRECTORY: 391 case B_SYSTEM_NONPACKAGED_MEDIA_NODES_DIRECTORY: 392 case B_SYSTEM_NONPACKAGED_BIN_DIRECTORY: 393 case B_SYSTEM_NONPACKAGED_DATA_DIRECTORY: 394 case B_SYSTEM_NONPACKAGED_FONTS_DIRECTORY: 395 case B_SYSTEM_NONPACKAGED_SOUNDS_DIRECTORY: 396 case B_SYSTEM_NONPACKAGED_DOCUMENTATION_DIRECTORY: 397 case B_SYSTEM_NONPACKAGED_LIB_DIRECTORY: 398 case B_SYSTEM_NONPACKAGED_HEADERS_DIRECTORY: 399 case B_SYSTEM_NONPACKAGED_DEVELOP_DIRECTORY: 400 templatePath = kCommonDirectories[which - B_COMMON_DIRECTORY]; 401 break; 402 403 /* User directories */ 404 case B_USER_DIRECTORY: 405 case B_USER_CONFIG_DIRECTORY: 406 case B_USER_ADDONS_DIRECTORY: 407 case B_USER_BOOT_DIRECTORY: 408 case B_USER_FONTS_DIRECTORY: 409 case B_USER_LIB_DIRECTORY: 410 case B_USER_SETTINGS_DIRECTORY: 411 case B_USER_DESKBAR_DIRECTORY: 412 case B_USER_PRINTERS_DIRECTORY: 413 case B_USER_TRANSLATORS_DIRECTORY: 414 case B_USER_MEDIA_NODES_DIRECTORY: 415 case B_USER_SOUNDS_DIRECTORY: 416 case B_USER_DATA_DIRECTORY: 417 case B_USER_CACHE_DIRECTORY: 418 case B_USER_PACKAGES_DIRECTORY: 419 case B_USER_HEADERS_DIRECTORY: 420 case B_USER_DEVELOP_DIRECTORY: 421 case B_USER_DOCUMENTATION_DIRECTORY: 422 case B_USER_NONPACKAGED_DIRECTORY: 423 case B_USER_NONPACKAGED_ADDONS_DIRECTORY: 424 case B_USER_NONPACKAGED_TRANSLATORS_DIRECTORY: 425 case B_USER_NONPACKAGED_MEDIA_NODES_DIRECTORY: 426 case B_USER_NONPACKAGED_BIN_DIRECTORY: 427 case B_USER_NONPACKAGED_DATA_DIRECTORY: 428 case B_USER_NONPACKAGED_FONTS_DIRECTORY: 429 case B_USER_NONPACKAGED_SOUNDS_DIRECTORY: 430 case B_USER_NONPACKAGED_DOCUMENTATION_DIRECTORY: 431 case B_USER_NONPACKAGED_LIB_DIRECTORY: 432 case B_USER_NONPACKAGED_HEADERS_DIRECTORY: 433 case B_USER_NONPACKAGED_DEVELOP_DIRECTORY: 434 case B_USER_SERVERS_DIRECTORY: 435 case B_USER_APPS_DIRECTORY: 436 case B_USER_BIN_DIRECTORY: 437 case B_USER_PREFERENCES_DIRECTORY: 438 case B_USER_ETC_DIRECTORY: 439 case B_USER_LOG_DIRECTORY: 440 case B_USER_SPOOL_DIRECTORY: 441 case B_USER_VAR_DIRECTORY: 442 templatePath = kUserDirectories[which - B_USER_DIRECTORY]; 443 break; 444 445 /* Global directories */ 446 case B_APPS_DIRECTORY: 447 case B_UTILITIES_DIRECTORY: 448 templatePath = SYSTEM "/apps"; 449 break; 450 case B_PREFERENCES_DIRECTORY: 451 templatePath = SYSTEM "/preferences"; 452 break; 453 case B_PACKAGE_LINKS_DIRECTORY: 454 templatePath = "packages"; 455 break; 456 457 default: 458 return EINVAL; 459 } 460 461 if (templatePath == NULL) 462 return ENOENT; 463 464 PathBuffer pathBuffer(buffer, pathLength, strlen(buffer)); 465 466 // resolve "$h" placeholder to the user's home directory 467 if (!strncmp(templatePath, "$h", 2)) { 468 if (bootDevice > -1 && device != bootDevice) { 469 pathBuffer.Append("/home"); 470 } else { 471 size_t length = get_user_home_path(buffer, pathLength); 472 if (length >= pathLength) 473 return E2BIG; 474 pathBuffer.SetTo(buffer, pathLength, length); 475 } 476 templatePath += 2; 477 } else if (templatePath[0] != '\0') 478 pathBuffer.Append('/'); 479 480 // resolve "$a" placeholder to the architecture subdirectory, if not 481 // primary 482 if (char* dollar = strchr(templatePath, '$')) { 483 if (dollar[1] == 'a') { 484 pathBuffer.Append(templatePath, dollar - templatePath); 485 #ifndef _KERNEL_MODE 486 const char* architecture = __get_architecture(); 487 if (strcmp(architecture, __get_primary_architecture()) != 0) { 488 pathBuffer.Append('/'); 489 pathBuffer.Append(architecture); 490 } 491 #endif 492 templatePath = dollar + 2; 493 } 494 } 495 496 // append (remainder of) template path 497 pathBuffer.Append(templatePath); 498 499 if (pathBuffer.Length() >= pathLength) 500 return E2BIG; 501 502 if (createIt && stat(buffer, &st) < 0) { 503 err = create_path(buffer, 0755); 504 if (err != B_OK) 505 return err; 506 } 507 508 strlcpy(returnedPath, buffer, pathLength); 509 return B_OK; 510 } 511 512 513 extern "C" status_t 514 __find_directory_alpha4(directory_which which, dev_t device, bool createIt, 515 char *returnedPath, int32 pathLength) 516 { 517 return __find_directory(which, device, createIt, returnedPath, pathLength); 518 } 519 520 521 DEFINE_LIBROOT_KERNEL_SYMBOL_VERSION("__find_directory_alpha4", 522 "find_directory@", "BASE"); 523 524 DEFINE_LIBROOT_KERNEL_SYMBOL_VERSION("__find_directory", "find_directory@@", 525 "1_ALPHA5"); 526 #else // _LOADER_MODE 527 status_t 528 __find_directory(directory_which which, dev_t device, bool createIt, 529 char *returnedPath, int32 _pathLength) 530 { 531 if (_pathLength <= 0) 532 return E2BIG; 533 size_t pathLength = _pathLength; 534 535 const char *templatePath = NULL; 536 537 /* as with the R5 version, no on-stack buffer */ 538 char *buffer = (char*)malloc(pathLength); 539 if (buffer == NULL) 540 return B_NO_MEMORY; 541 MemoryDeleter bufferDeleter(buffer); 542 543 memset(buffer, 0, pathLength); 544 545 strlcat(buffer, "/boot", pathLength); 546 547 switch ((int)which) { 548 /* Haiku system directories */ 549 case B_SYSTEM_DIRECTORY: 550 case B_BEOS_SYSTEM_DIRECTORY: 551 case B_SYSTEM_ADDONS_DIRECTORY: 552 case B_SYSTEM_BOOT_DIRECTORY: 553 case B_SYSTEM_FONTS_DIRECTORY: 554 case B_SYSTEM_LIB_DIRECTORY: 555 case B_SYSTEM_SERVERS_DIRECTORY: 556 case B_SYSTEM_APPS_DIRECTORY: 557 case B_SYSTEM_BIN_DIRECTORY: 558 case B_BEOS_ETC_DIRECTORY: 559 case B_SYSTEM_DOCUMENTATION_DIRECTORY: 560 case B_SYSTEM_PREFERENCES_DIRECTORY: 561 case B_SYSTEM_TRANSLATORS_DIRECTORY: 562 case B_SYSTEM_MEDIA_NODES_DIRECTORY: 563 case B_SYSTEM_SOUNDS_DIRECTORY: 564 case B_SYSTEM_DATA_DIRECTORY: 565 case B_SYSTEM_DEVELOP_DIRECTORY: 566 case B_SYSTEM_PACKAGES_DIRECTORY: 567 case B_SYSTEM_HEADERS_DIRECTORY: 568 templatePath = kSystemDirectories[which - B_SYSTEM_DIRECTORY]; 569 break; 570 571 /* Obsolete common directories and writable system directories */ 572 case B_COMMON_DIRECTORY: 573 case B_COMMON_SYSTEM_DIRECTORY: 574 case B_COMMON_ADDONS_DIRECTORY: 575 case B_COMMON_BOOT_DIRECTORY: 576 case B_COMMON_FONTS_DIRECTORY: 577 case B_COMMON_LIB_DIRECTORY: 578 case B_COMMON_SERVERS_DIRECTORY: 579 case B_COMMON_BIN_DIRECTORY: 580 case B_SYSTEM_ETC_DIRECTORY: 581 case B_COMMON_DOCUMENTATION_DIRECTORY: 582 case B_SYSTEM_SETTINGS_DIRECTORY: 583 case B_COMMON_DEVELOP_DIRECTORY: 584 case B_SYSTEM_LOG_DIRECTORY: 585 case B_SYSTEM_SPOOL_DIRECTORY: 586 case B_SYSTEM_TEMP_DIRECTORY: 587 case B_SYSTEM_VAR_DIRECTORY: 588 case B_COMMON_TRANSLATORS_DIRECTORY: 589 case B_COMMON_MEDIA_NODES_DIRECTORY: 590 case B_COMMON_SOUNDS_DIRECTORY: 591 case B_COMMON_DATA_DIRECTORY: 592 case B_SYSTEM_CACHE_DIRECTORY: 593 case B_COMMON_PACKAGES_DIRECTORY: 594 case B_COMMON_HEADERS_DIRECTORY: 595 case B_SYSTEM_NONPACKAGED_DIRECTORY: 596 case B_SYSTEM_NONPACKAGED_ADDONS_DIRECTORY: 597 case B_SYSTEM_NONPACKAGED_TRANSLATORS_DIRECTORY: 598 case B_SYSTEM_NONPACKAGED_MEDIA_NODES_DIRECTORY: 599 case B_SYSTEM_NONPACKAGED_BIN_DIRECTORY: 600 case B_SYSTEM_NONPACKAGED_DATA_DIRECTORY: 601 case B_SYSTEM_NONPACKAGED_FONTS_DIRECTORY: 602 case B_SYSTEM_NONPACKAGED_SOUNDS_DIRECTORY: 603 case B_SYSTEM_NONPACKAGED_DOCUMENTATION_DIRECTORY: 604 case B_SYSTEM_NONPACKAGED_LIB_DIRECTORY: 605 case B_SYSTEM_NONPACKAGED_HEADERS_DIRECTORY: 606 case B_SYSTEM_NONPACKAGED_DEVELOP_DIRECTORY: 607 templatePath = kCommonDirectories[which - B_COMMON_DIRECTORY]; 608 break; 609 610 /* User directories */ 611 case B_USER_DIRECTORY: 612 case B_USER_CONFIG_DIRECTORY: 613 case B_USER_ADDONS_DIRECTORY: 614 case B_USER_BOOT_DIRECTORY: 615 case B_USER_FONTS_DIRECTORY: 616 case B_USER_LIB_DIRECTORY: 617 case B_USER_SETTINGS_DIRECTORY: 618 case B_USER_DESKBAR_DIRECTORY: 619 case B_USER_PRINTERS_DIRECTORY: 620 case B_USER_TRANSLATORS_DIRECTORY: 621 case B_USER_MEDIA_NODES_DIRECTORY: 622 case B_USER_SOUNDS_DIRECTORY: 623 case B_USER_DATA_DIRECTORY: 624 case B_USER_CACHE_DIRECTORY: 625 case B_USER_PACKAGES_DIRECTORY: 626 case B_USER_HEADERS_DIRECTORY: 627 case B_USER_DEVELOP_DIRECTORY: 628 case B_USER_DOCUMENTATION_DIRECTORY: 629 case B_USER_NONPACKAGED_DIRECTORY: 630 case B_USER_NONPACKAGED_ADDONS_DIRECTORY: 631 case B_USER_NONPACKAGED_TRANSLATORS_DIRECTORY: 632 case B_USER_NONPACKAGED_MEDIA_NODES_DIRECTORY: 633 case B_USER_NONPACKAGED_BIN_DIRECTORY: 634 case B_USER_NONPACKAGED_DATA_DIRECTORY: 635 case B_USER_NONPACKAGED_FONTS_DIRECTORY: 636 case B_USER_NONPACKAGED_SOUNDS_DIRECTORY: 637 case B_USER_NONPACKAGED_DOCUMENTATION_DIRECTORY: 638 case B_USER_NONPACKAGED_LIB_DIRECTORY: 639 case B_USER_NONPACKAGED_HEADERS_DIRECTORY: 640 case B_USER_NONPACKAGED_DEVELOP_DIRECTORY: 641 case B_USER_SERVERS_DIRECTORY: 642 case B_USER_APPS_DIRECTORY: 643 case B_USER_BIN_DIRECTORY: 644 case B_USER_PREFERENCES_DIRECTORY: 645 case B_USER_ETC_DIRECTORY: 646 case B_USER_LOG_DIRECTORY: 647 case B_USER_SPOOL_DIRECTORY: 648 case B_USER_VAR_DIRECTORY: 649 templatePath = kUserDirectories[which - B_USER_DIRECTORY]; 650 break; 651 652 default: 653 return EINVAL; 654 } 655 656 if (templatePath == NULL) 657 return ENOENT; 658 659 PathBuffer pathBuffer(buffer, pathLength, strlen(buffer)); 660 661 // resolve "$h" placeholder to the user's home directory 662 if (!strncmp(templatePath, "$h", 2)) { 663 pathBuffer.Append("/home"); 664 templatePath += 2; 665 } else if (templatePath[0] != '\0') 666 pathBuffer.Append('/'); 667 668 // resolve "$a" placeholder to the architecture subdirectory, if not 669 // primary 670 if (char* dollar = strchr(templatePath, '$')) { 671 if (dollar[1] == 'a') { 672 pathBuffer.Append(templatePath, dollar - templatePath); 673 templatePath = dollar + 2; 674 } 675 } 676 677 // append (remainder of) template path 678 pathBuffer.Append(templatePath); 679 680 if (pathBuffer.Length() >= pathLength) 681 return E2BIG; 682 683 strlcpy(returnedPath, buffer, pathLength); 684 return B_OK; 685 } 686 #endif // _LOADER_MODE 687