1 /*
2 * Copyright (c) 2007 Cisco Systems, Inc. All rights reserved.
3 * $COPYRIGHT$
4 *
5 * Additional copyrights may follow
6 *
7 * $HEADER$
8 */
9
10 #include "opal_config.h"
11
12 #include <stdio.h>
13 #include <stdlib.h>
14 #ifdef HAVE_SYS_TYPES_H
15 #include <sys/types.h>
16 #endif
17 #ifdef HAVE_SYS_STAT_H
18 #include <sys/stat.h>
19 #endif
20 #ifdef HAVE_UNISTD_H
21 #include <unistd.h>
22 #endif
23 #include <string.h>
24
25 #include "opal/util/basename.h"
26 #include "opal/util/opal_getcwd.h"
27 #include "opal/util/string_copy.h"
28 #include "opal/constants.h"
29
30
31 /*
32 * Use $PWD instead of getcwd() a) if $PWD exists and b) is a valid
33 * synonym for the results from getcwd(). If both of these conditions
34 * are not met, just fall back and use the results of getcwd().
35 */
36 int opal_getcwd(char *buf, size_t size)
37 {
38 char cwd[OPAL_PATH_MAX];
39 char *pwd = getenv("PWD");
40 struct stat a, b;
41 char *shortened;
42
43 /* Bozo checks (e.g., if someone accidentally passed -1 to the
44 unsigned "size" param) */
45 if (NULL == buf || size > INT_MAX) {
46 return OPAL_ERR_BAD_PARAM;
47 }
48
49 /* Call getcwd() to get a baseline result */
50 if (NULL == getcwd(cwd, sizeof(cwd))) {
51 return OPAL_ERR_IN_ERRNO;
52 }
53
54 #if !defined(HAVE_SYS_STAT_H)
55 /* If we don't have stat(), then we can't tell if the $PWD and cwd
56 are the same, so just fall back to getcwd(). */
57 pwd = cwd;
58 #else
59 if (NULL == pwd) {
60 pwd = cwd;
61 } else {
62 /* If the two are not the same value, figure out if they are
63 pointing to the same place */
64 if (0 != strcmp(pwd, cwd)) {
65 /* If we can't stat() what getcwd() gave us, give up */
66 if (0 != stat(cwd, &a)) {
67 return OPAL_ERR_IN_ERRNO;
68 }
69 /* If we can't stat() $PWD, then $PWD could just be stale
70 -- so ignore it. */
71 else if (0 != stat(pwd, &b)) {
72 pwd = cwd;
73 }
74 /* Otherwise, we successfully stat()'ed them both, so
75 compare. If either the device or inode is not the
76 same, then fallback to getcwd(). */
77 else {
78 if (a.st_dev != b.st_dev || a.st_ino != b.st_ino) {
79 pwd = cwd;
80 }
81 }
82 }
83 }
84 #endif
85
86 /* If we got here, pwd is pointing to the result that we want to
87 give. Ensure the user's buffer is long enough. If it is, copy
88 in the value and be done. */
89 if (strlen(pwd) > size) {
90 /* if it isn't big enough, give them as much
91 * of the basename as possible
92 */
93 shortened = opal_basename(pwd);
94 opal_string_copy(buf, shortened, size);
95 free(shortened);
96 /* indicate that it isn't the full path */
97 return OPAL_ERR_TEMP_OUT_OF_RESOURCE;
98 }
99 opal_string_copy(buf, pwd, size);
100 return OPAL_SUCCESS;
101 }