David Hendricks would like Louis Yung-Chieh Lo to review this change.

View Change

Add a file utility library

This adds a library for BSD-licensed helper functions for dealing
with files.

Currently the library only has scanft() which was ported over from
mosys. This function recursively scans files in a filesystem tree
and can optionally match the beginning content. This is particularly
useful for searching for devices in sysfs, which may be infinitely
recursive (due to symlinks) and typically contain single values, such
as a module alias.

BUG=none
TEST=used in follow-up CLs to find I2C and SPI buses and addresses

Example test output using /sys/bus/i2c/devices/ as root path,
following 2 levels of symbolic links, physical i2c bus is 4 but
got shifted to 6:
gec_i2c_probe_programmer: probing for GEC on I2C...
gec_i2c_probe_programmer: chromeos-ec found in \
"/sys/bus/i2c/devices/i2c-6/6-001e/name"
gec_i2c_probe_programmer: bus: 6, addr: 0x1e

Change-Id: I6c86ad3a50748e6bdbaa6675b05e75ef714b3994
Reviewed-on: https://gerrit.chromium.org/gerrit/23466
Reviewed-by: Yung-Chieh Lo <yjlou%chromium.org@gtempaccount.com>
Commit-Ready: David Hendricks <dhendrix@chromium.org>
Tested-by: David Hendricks <dhendrix@chromium.org>
---
M Makefile
A file.c
A file.h
3 files changed, 175 insertions(+), 1 deletion(-)

git pull ssh://review.coreboot.org:29418/flashrom refs/changes/90/22490/1
diff --git a/Makefile b/Makefile
index 5bd7158..26bf343 100644
--- a/Makefile
+++ b/Makefile
@@ -519,7 +519,7 @@
###############################################################################
# Library code.

-LIB_OBJS = libflashrom.o layout.o flashrom.o udelay.o programmer.o helpers.o ich_descriptors.o
+LIB_OBJS = libflashrom.o layout.o flashrom.o udelay.o programmer.o helpers.o ich_descriptors.o file.o

###############################################################################
# Frontend related stuff.
diff --git a/file.c b/file.c
new file mode 100644
index 0000000..6f15ff9
--- /dev/null
+++ b/file.c
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2012, The Chromium OS Authors
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * scanft() is derived from mosys source,s which were released under the
+ * BSD license
+ */
+
+#include <dirent.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "flash.h"
+
+/*returns 1 if contents matches, 0 if not, and <0 to indicate error */
+static int file_contents_match(const char *path, const char *str)
+{
+ FILE *fp;
+ char *content;
+ int len = strlen(str);
+ int ret = -1;
+
+ content = malloc(len);
+ if (!content)
+ return -1;
+
+ if ((fp = fopen(path, "r")) == NULL) {
+ msg_pdbg("Error opening %s: %s\n", path, strerror(errno));
+ goto file_contents_match_done;
+ }
+ if (fread(content, 1, len, fp) < 1) {
+ msg_pdbg("Error reading %s: %s\n", path, strerror(ferror(fp)));
+ goto file_contents_match_done;
+ }
+
+ if (!strncmp(str, content, len))
+ ret = 1;
+ else
+ ret = 0;
+
+file_contents_match_done:
+ fclose(fp);
+ free(content);
+ return ret;
+}
+
+ /*
+ * scanft - scan filetree for file with option to parse some content
+ *
+ * @root: Where to begin search
+ * @filename: Name of file to search for
+ * @str: Optional NULL terminated string to check at the beginning
+ * of the file
+ * @symdepth: Maximum depth of symlinks to follow. A negative value means
+ * follow indefinitely. Zero means do not follow symlinks.
+ *
+ * The caller should be specific enough with root and symdepth arguments
+ * to avoid finding duplicate information (especially in sysfs).
+ *
+ * returns allocated string with path of matching file if successful
+ * returns NULL to indicate failure
+ */
+const char *scanft(const char *root, const char *filename,
+ const char *str, int symdepth)
+{
+ DIR *dp;
+ struct dirent *d;
+ struct stat s;
+ const char *ret = NULL;
+
+ if (lstat(root, &s) < 0) {
+ msg_pdbg("%s: Error stat'ing %s: %s\n",
+ __func__, root, strerror(errno));
+ return NULL;
+ }
+
+ if (S_ISLNK(s.st_mode)) {
+ if (symdepth == 0) /* Leaf has been reached */
+ return NULL;
+ else if (symdepth > 0) /* Follow if not too deep in */
+ symdepth--;
+ }
+
+ if ((dp = opendir(root)) == NULL)
+ return NULL;
+
+ while (!ret && (d = readdir(dp))) {
+ char newpath[PATH_MAX];
+
+ /* Skip "." and ".." */
+ if (!(strcmp(d->d_name, ".")) ||
+ !(strcmp(d->d_name, "..")))
+ continue;
+
+ snprintf(newpath, sizeof(newpath), "%s/%s", root, d->d_name);
+
+ if (!strcmp(d->d_name, filename)) {
+ if (!str || file_contents_match(newpath, str))
+ ret = strdup(newpath);
+ }
+
+ if (!ret)
+ ret = scanft(newpath, filename, str, symdepth);
+ }
+
+ closedir(dp);
+ return ret;
+}
diff --git a/file.h b/file.h
new file mode 100644
index 0000000..ea37084
--- /dev/null
+++ b/file.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2012, The Chromium OS Authors
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+const char *scanft(const char *root, const char *filename,
+ const char *str, int symdepth);

To view, visit change 22490. To unsubscribe, visit settings.

Gerrit-Project: flashrom
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: I6c86ad3a50748e6bdbaa6675b05e75ef714b3994
Gerrit-Change-Number: 22490
Gerrit-PatchSet: 1
Gerrit-Owner: David Hendricks <david.hendricks@gmail.com>
Gerrit-Reviewer: Louis Yung-Chieh Lo <yjlou@chromium.org>