summaryrefslogtreecommitdiffstats
path: root/libblkid/lib/path.c
diff options
context:
space:
mode:
Diffstat (limited to 'libblkid/lib/path.c')
-rw-r--r--libblkid/lib/path.c258
1 files changed, 258 insertions, 0 deletions
diff --git a/libblkid/lib/path.c b/libblkid/lib/path.c
new file mode 100644
index 000000000..fc90c0a16
--- /dev/null
+++ b/libblkid/lib/path.c
@@ -0,0 +1,258 @@
+/*
+ * Simple functions to access files, paths maybe be globally prefixed by a
+ * global prefix to read data from alternative destination (e.g. /proc dump for
+ * regression tests).
+ *
+ * Taken from lscpu.c
+ *
+ * Copyright (C) 2008 Cai Qian <qcai@redhat.com>
+ * Copyright (C) 2008-2012 Karel Zak <kzak@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdarg.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <inttypes.h>
+#include <errno.h>
+
+#include "all-io.h"
+#include "path.h"
+#include "nls.h"
+#include "c.h"
+
+static size_t prefixlen;
+static char pathbuf[PATH_MAX];
+
+static const char *
+path_vcreate(const char *path, va_list ap)
+{
+ if (prefixlen)
+ vsnprintf(pathbuf + prefixlen,
+ sizeof(pathbuf) - prefixlen, path, ap);
+ else
+ vsnprintf(pathbuf, sizeof(pathbuf), path, ap);
+ return pathbuf;
+}
+
+char *
+path_strdup(const char *path, ...)
+{
+ const char *p;
+ va_list ap;
+
+ va_start(ap, path);
+ p = path_vcreate(path, ap);
+ va_end(ap);
+
+ return p ? strdup(p) : NULL;
+}
+
+static FILE *
+path_vfopen(const char *mode, int exit_on_error, const char *path, va_list ap)
+{
+ FILE *f;
+ const char *p = path_vcreate(path, ap);
+
+ f = fopen(p, mode);
+ if (!f && exit_on_error)
+ err(EXIT_FAILURE, _("cannot open %s"), p);
+ return f;
+}
+
+static int
+path_vopen(int flags, const char *path, va_list ap)
+{
+ int fd;
+ const char *p = path_vcreate(path, ap);
+
+ fd = open(p, flags);
+ if (fd == -1)
+ err(EXIT_FAILURE, _("cannot open %s"), p);
+ return fd;
+}
+
+FILE *
+path_fopen(const char *mode, int exit_on_error, const char *path, ...)
+{
+ FILE *fd;
+ va_list ap;
+
+ va_start(ap, path);
+ fd = path_vfopen(mode, exit_on_error, path, ap);
+ va_end(ap);
+
+ return fd;
+}
+
+void
+path_read_str(char *result, size_t len, const char *path, ...)
+{
+ FILE *fd;
+ va_list ap;
+
+ va_start(ap, path);
+ fd = path_vfopen("r", 1, path, ap);
+ va_end(ap);
+
+ if (!fgets(result, len, fd))
+ err(EXIT_FAILURE, _("cannot read %s"), pathbuf);
+ fclose(fd);
+
+ len = strlen(result);
+ if (result[len - 1] == '\n')
+ result[len - 1] = '\0';
+}
+
+int
+path_read_s32(const char *path, ...)
+{
+ FILE *fd;
+ va_list ap;
+ int result;
+
+ va_start(ap, path);
+ fd = path_vfopen("r", 1, path, ap);
+ va_end(ap);
+
+ if (fscanf(fd, "%d", &result) != 1) {
+ if (ferror(fd))
+ err(EXIT_FAILURE, _("cannot read %s"), pathbuf);
+ else
+ errx(EXIT_FAILURE, _("parse error: %s"), pathbuf);
+ }
+ fclose(fd);
+ return result;
+}
+
+uint64_t
+path_read_u64(const char *path, ...)
+{
+ FILE *fd;
+ va_list ap;
+ uint64_t result;
+
+ va_start(ap, path);
+ fd = path_vfopen("r", 1, path, ap);
+ va_end(ap);
+
+ if (fscanf(fd, "%"SCNu64, &result) != 1) {
+ if (ferror(fd))
+ err(EXIT_FAILURE, _("cannot read %s"), pathbuf);
+ else
+ errx(EXIT_FAILURE, _("parse error: %s"), pathbuf);
+ }
+ fclose(fd);
+ return result;
+}
+
+int
+path_write_str(const char *str, const char *path, ...)
+{
+ int fd, result;
+ va_list ap;
+
+ va_start(ap, path);
+ fd = path_vopen(O_WRONLY|O_CLOEXEC, path, ap);
+ va_end(ap);
+ result = write_all(fd, str, strlen(str));
+ close(fd);
+ return result;
+}
+
+int
+path_exist(const char *path, ...)
+{
+ va_list ap;
+ const char *p;
+
+ va_start(ap, path);
+ p = path_vcreate(path, ap);
+ va_end(ap);
+
+ return access(p, F_OK) == 0;
+}
+
+#ifdef HAVE_CPU_SET_T
+
+static cpu_set_t *
+path_cpuparse(int maxcpus, int islist, const char *path, va_list ap)
+{
+ FILE *fd;
+ cpu_set_t *set;
+ size_t setsize, len = maxcpus * 7;
+ char buf[len];
+
+ fd = path_vfopen("r", 1, path, ap);
+
+ if (!fgets(buf, len, fd))
+ err(EXIT_FAILURE, _("cannot read %s"), pathbuf);
+ fclose(fd);
+
+ len = strlen(buf);
+ if (buf[len - 1] == '\n')
+ buf[len - 1] = '\0';
+
+ set = cpuset_alloc(maxcpus, &setsize, NULL);
+ if (!set)
+ err(EXIT_FAILURE, _("failed to callocate cpu set"));
+
+ if (islist) {
+ if (cpulist_parse(buf, set, setsize, 0))
+ errx(EXIT_FAILURE, _("failed to parse CPU list %s"), buf);
+ } else {
+ if (cpumask_parse(buf, set, setsize))
+ errx(EXIT_FAILURE, _("failed to parse CPU mask %s"), buf);
+ }
+ return set;
+}
+
+cpu_set_t *
+path_read_cpuset(int maxcpus, const char *path, ...)
+{
+ va_list ap;
+ cpu_set_t *set;
+
+ va_start(ap, path);
+ set = path_cpuparse(maxcpus, 0, path, ap);
+ va_end(ap);
+
+ return set;
+}
+
+cpu_set_t *
+path_read_cpulist(int maxcpus, const char *path, ...)
+{
+ va_list ap;
+ cpu_set_t *set;
+
+ va_start(ap, path);
+ set = path_cpuparse(maxcpus, 1, path, ap);
+ va_end(ap);
+
+ return set;
+}
+
+#endif /* HAVE_CPU_SET_T */
+
+void
+path_set_prefix(const char *prefix)
+{
+ prefixlen = strlen(prefix);
+ strncpy(pathbuf, prefix, sizeof(pathbuf));
+ pathbuf[sizeof(pathbuf) - 1] = '\0';
+}