Hello Louis Yung-Chieh Lo,
I'd like you to do a code review. Please visit
https://review.coreboot.org/22490
to review the following change.
Change subject: Add a file utility library ......................................................................
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);