16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 #include "precompiled.hpp" 25 #include "gc/z/zArray.inline.hpp" 26 #include "gc/z/zBackingPath_linux_x86.hpp" 27 #include "gc/z/zErrno.hpp" 28 #include "logging/log.hpp" 29 30 #include <stdio.h> 31 #include <unistd.h> 32 33 // Mount information, see proc(5) for more details. 34 #define PROC_SELF_MOUNTINFO "/proc/self/mountinfo" 35 36 ZBackingPath::ZBackingPath(const char* filesystem, const char* preferred_path) { 37 if (ZPath != NULL) { 38 // Use specified path 39 _path = strdup(ZPath); 40 } else { 41 // Find suitable path 42 _path = find_mountpoint(filesystem, preferred_path); 43 } 44 } 45 46 ZBackingPath::~ZBackingPath() { 47 free(_path); 48 _path = NULL; 49 } 50 51 char* ZBackingPath::get_mountpoint(const char* line, const char* filesystem) const { 52 char* line_mountpoint = NULL; 53 char* line_filesystem = NULL; 54 55 // Parse line and return a newly allocated string containing the mountpoint if 56 // the line contains a matching filesystem and the mountpoint is accessible by 57 // the current user. 58 if (sscanf(line, "%*u %*u %*u:%*u %*s %ms %*[^-]- %ms", &line_mountpoint, &line_filesystem) != 2 || 59 strcmp(line_filesystem, filesystem) != 0 || 60 access(line_mountpoint, R_OK|W_OK|X_OK) != 0) { 61 // Not a matching or accessible filesystem 62 free(line_mountpoint); 63 line_mountpoint = NULL; 64 } 65 66 free(line_filesystem); 67 68 return line_mountpoint; 69 } 70 71 void ZBackingPath::get_mountpoints(ZArray<char*>* mountpoints, const char* filesystem) const { 72 FILE* fd = fopen(PROC_SELF_MOUNTINFO, "r"); 73 if (fd == NULL) { 74 ZErrno err; 75 log_error(gc, init)("Failed to open %s: %s", PROC_SELF_MOUNTINFO, err.to_string()); 76 return; 77 } 78 79 char* line = NULL; 80 size_t length = 0; 81 82 while (getline(&line, &length, fd) != -1) { 83 char* const mountpoint = get_mountpoint(line, filesystem); 84 if (mountpoint != NULL) { 85 mountpoints->add(mountpoint); 86 } 87 } 88 89 free(line); 90 fclose(fd); 91 } 92 93 void ZBackingPath::free_mountpoints(ZArray<char*>* mountpoints) const { 94 ZArrayIterator<char*> iter(mountpoints); 95 for (char* mountpoint; iter.next(&mountpoint);) { 96 free(mountpoint); 97 } 98 mountpoints->clear(); 99 } 100 101 char* ZBackingPath::find_mountpoint(const char* filesystem, const char* preferred_mountpoint) const { 102 char* path = NULL; 103 ZArray<char*> mountpoints; 104 105 get_mountpoints(&mountpoints, filesystem); 106 107 if (mountpoints.size() == 0) { 108 // No filesystem found 109 log_error(gc, init)("Failed to find an accessible %s filesystem", filesystem); 110 } else if (mountpoints.size() == 1) { 111 // One filesystem found 112 path = strdup(mountpoints.at(0)); 113 } else if (mountpoints.size() > 1) { 114 // More than one filesystem found 115 ZArrayIterator<char*> iter(&mountpoints); 116 for (char* mountpoint; iter.next(&mountpoint);) { 117 if (!strcmp(mountpoint, preferred_mountpoint)) { 118 // Preferred mount point found 119 path = strdup(mountpoint); 120 break; 121 } 122 } 123 124 if (path == NULL) { 125 // Preferred mount point not found 126 log_error(gc, init)("More than one %s filesystem found:", filesystem); 127 ZArrayIterator<char*> iter2(&mountpoints); 128 for (char* mountpoint; iter2.next(&mountpoint);) { 129 log_error(gc, init)(" %s", mountpoint); 130 } 131 } 132 } 133 134 free_mountpoints(&mountpoints); 135 136 return path; 137 } 138 139 const char* ZBackingPath::get() const { 140 return _path; 141 } | 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 #include "precompiled.hpp" 25 #include "gc/z/zArray.inline.hpp" 26 #include "gc/z/zBackingPath_linux_x86.hpp" 27 #include "gc/z/zErrno.hpp" 28 #include "logging/log.hpp" 29 30 #include <stdio.h> 31 #include <unistd.h> 32 33 // Mount information, see proc(5) for more details. 34 #define PROC_SELF_MOUNTINFO "/proc/self/mountinfo" 35 36 ZBackingPath::ZBackingPath(const char* filesystem, const char** preferred_mountpoints) { 37 if (ZPath != NULL) { 38 // Use specified path 39 _path = strdup(ZPath); 40 } else { 41 // Find suitable path 42 _path = find_mountpoint(filesystem, preferred_mountpoints); 43 } 44 } 45 46 ZBackingPath::~ZBackingPath() { 47 free(_path); 48 _path = NULL; 49 } 50 51 char* ZBackingPath::get_mountpoint(const char* line, const char* filesystem) const { 52 char* line_mountpoint = NULL; 53 char* line_filesystem = NULL; 54 55 // Parse line and return a newly allocated string containing the mountpoint if 56 // the line contains a matching filesystem and the mountpoint is accessible by 57 // the current user. 58 if (sscanf(line, "%*u %*u %*u:%*u %*s %ms %*[^-]- %ms", &line_mountpoint, &line_filesystem) != 2 || 59 strcmp(line_filesystem, filesystem) != 0 || 60 access(line_mountpoint, R_OK|W_OK|X_OK) != 0) { 61 // Not a matching or accessible filesystem 62 free(line_mountpoint); 63 line_mountpoint = NULL; 64 } 65 66 free(line_filesystem); 67 68 return line_mountpoint; 69 } 70 71 void ZBackingPath::get_mountpoints(const char* filesystem, ZArray<char*>* mountpoints) const { 72 FILE* fd = fopen(PROC_SELF_MOUNTINFO, "r"); 73 if (fd == NULL) { 74 ZErrno err; 75 log_error(gc, init)("Failed to open %s: %s", PROC_SELF_MOUNTINFO, err.to_string()); 76 return; 77 } 78 79 char* line = NULL; 80 size_t length = 0; 81 82 while (getline(&line, &length, fd) != -1) { 83 char* const mountpoint = get_mountpoint(line, filesystem); 84 if (mountpoint != NULL) { 85 mountpoints->add(mountpoint); 86 } 87 } 88 89 free(line); 90 fclose(fd); 91 } 92 93 void ZBackingPath::free_mountpoints(ZArray<char*>* mountpoints) const { 94 ZArrayIterator<char*> iter(mountpoints); 95 for (char* mountpoint; iter.next(&mountpoint);) { 96 free(mountpoint); 97 } 98 mountpoints->clear(); 99 } 100 101 char* ZBackingPath::find_preferred_mountpoint(const char* filesystem, 102 ZArray<char*>* mountpoints, 103 const char** preferred_mountpoints) const { 104 // Among the found mountpoints, return the first that is on the list of preferred mountpoints 105 ZArrayIterator<char*> iter1(mountpoints); 106 for (char* mountpoint; iter1.next(&mountpoint);) { 107 for (const char** preferred = preferred_mountpoints; *preferred != NULL; preferred++) { 108 if (!strcmp(mountpoint, *preferred)) { 109 // Preferred mountpoint found 110 return strdup(mountpoint); 111 } 112 } 113 } 114 115 // Preferred mountpoint not found 116 log_error(gc, init)("More than one %s filesystem found:", filesystem); 117 ZArrayIterator<char*> iter2(mountpoints); 118 for (char* mountpoint; iter2.next(&mountpoint);) { 119 log_error(gc, init)(" %s", mountpoint); 120 } 121 122 return NULL; 123 } 124 125 char* ZBackingPath::find_mountpoint(const char* filesystem, const char** preferred_mountpoints) const { 126 char* path = NULL; 127 ZArray<char*> mountpoints; 128 129 get_mountpoints(filesystem, &mountpoints); 130 131 if (mountpoints.size() == 0) { 132 // No mountpoint found 133 log_error(gc, init)("Failed to find an accessible %s filesystem", filesystem); 134 } else if (mountpoints.size() == 1) { 135 // One mountpoint found 136 path = strdup(mountpoints.at(0)); 137 } else { 138 // More than one mountpoint found 139 path = find_preferred_mountpoint(filesystem, &mountpoints, preferred_mountpoints); 140 } 141 142 free_mountpoints(&mountpoints); 143 144 return path; 145 } 146 147 const char* ZBackingPath::get() const { 148 return _path; 149 } |