6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 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.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 mount point if 56 // the line contains a matching filesystem and the mount point 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)("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 // Find preferred mount point 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 mount point found 110 return strdup(mountpoint); 111 } 112 } 113 } 114 115 // Preferred mount point not found 116 log_error(gc)("More than one %s filesystem found:", filesystem); 117 ZArrayIterator<char*> iter2(mountpoints); 118 for (char* mountpoint; iter2.next(&mountpoint);) { 119 log_error(gc)(" %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 mount point found 133 log_error(gc)("Failed to find an accessible %s filesystem", filesystem); 134 } else if (mountpoints.size() == 1) { 135 // One mount point found 136 path = strdup(mountpoints.at(0)); 137 } else { 138 // More than one mount point 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 } | 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 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/zErrno.hpp" 27 #include "gc/z/zMountPoint_linux.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 ZMountPoint::ZMountPoint(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 ZMountPoint::~ZMountPoint() { 47 free(_path); 48 _path = NULL; 49 } 50 51 char* ZMountPoint::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 mount point if 56 // the line contains a matching filesystem and the mount point 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 ZMountPoint::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)("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 ZMountPoint::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* ZMountPoint::find_preferred_mountpoint(const char* filesystem, 102 ZArray<char*>* mountpoints, 103 const char** preferred_mountpoints) const { 104 // Find preferred mount point 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 mount point found 110 return strdup(mountpoint); 111 } 112 } 113 } 114 115 // Preferred mount point not found 116 log_error(gc)("More than one %s filesystem found:", filesystem); 117 ZArrayIterator<char*> iter2(mountpoints); 118 for (char* mountpoint; iter2.next(&mountpoint);) { 119 log_error(gc)(" %s", mountpoint); 120 } 121 122 return NULL; 123 } 124 125 char* ZMountPoint::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 mount point found 133 log_error(gc)("Failed to find an accessible %s filesystem", filesystem); 134 } else if (mountpoints.size() == 1) { 135 // One mount point found 136 path = strdup(mountpoints.at(0)); 137 } else { 138 // More than one mount point 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* ZMountPoint::get() const { 148 return _path; 149 } |