+
+int setrlimit_closest(int resource, const struct rlimit *rlim) {
+ struct rlimit highest, fixed;
+
+ assert(rlim);
+
+ if (setrlimit(resource, rlim) >= 0)
+ return 0;
+
+ if (errno != EPERM)
+ return -errno;
+
+ /* So we failed to set the desired setrlimit, then let's try
+ * to get as close as we can */
+ assert_se(getrlimit(resource, &highest) == 0);
+
+ fixed.rlim_cur = MIN(rlim->rlim_cur, highest.rlim_max);
+ fixed.rlim_max = MIN(rlim->rlim_max, highest.rlim_max);
+
+ if (setrlimit(resource, &fixed) < 0)
+ return -errno;
+
+ return 0;
+}
+
+int path_is_read_only_fs(const char *path) {
+ struct statvfs st;
+
+ assert(path);
+
+ if (statvfs(path, &st) < 0)
+ return -errno;
+
+ return !!(st.f_flag & ST_RDONLY);
+}
+
+int getenv_for_pid(pid_t pid, const char *field, char **_value) {
+ char path[sizeof("/proc/")-1+10+sizeof("/environ")], *value = NULL;
+ int r;
+ FILE *f;
+ bool done = false;
+ size_t l;
+
+ assert(field);
+ assert(_value);
+
+ if (pid == 0)
+ pid = getpid();
+
+ snprintf(path, sizeof(path), "/proc/%lu/environ", (unsigned long) pid);
+ char_array_0(path);
+
+ f = fopen(path, "re");
+ if (!f)
+ return -errno;
+
+ l = strlen(field);
+ r = 0;
+
+ do {
+ char line[LINE_MAX];
+ unsigned i;
+
+ for (i = 0; i < sizeof(line)-1; i++) {
+ int c;
+
+ c = getc(f);
+ if (_unlikely_(c == EOF)) {
+ done = true;
+ break;
+ } else if (c == 0)
+ break;
+
+ line[i] = c;
+ }
+ line[i] = 0;
+
+ if (memcmp(line, field, l) == 0 && line[l] == '=') {
+ value = strdup(line + l + 1);
+ if (!value) {
+ r = -ENOMEM;
+ break;
+ }
+
+ r = 1;
+ break;
+ }
+
+ } while (!done);
+
+ fclose(f);
+
+ if (r >= 0)
+ *_value = value;
+
+ return r;
+}