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