summaryrefslogtreecommitdiff
path: root/src/tool_findfile.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/tool_findfile.c')
-rw-r--r--src/tool_findfile.c134
1 files changed, 134 insertions, 0 deletions
diff --git a/src/tool_findfile.c b/src/tool_findfile.c
new file mode 100644
index 000000000..cda8c8ed8
--- /dev/null
+++ b/src/tool_findfile.c
@@ -0,0 +1,134 @@
+/***************************************************************************
+ * _ _ ____ _
+ * Project ___| | | | _ \| |
+ * / __| | | | |_) | |
+ * | (__| |_| | _ <| |___
+ * \___|\___/|_| \_\_____|
+ *
+ * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al.
+ *
+ * This software is licensed as described in the file COPYING, which
+ * you should have received as part of this distribution. The terms
+ * are also available at https://curl.se/docs/copyright.html.
+ *
+ * You may opt to use, copy, modify, merge, publish, distribute and/or sell
+ * copies of the Software, and permit persons to whom the Software is
+ * furnished to do so, under the terms of the COPYING file.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ***************************************************************************/
+#include "tool_setup.h"
+
+#ifdef HAVE_PWD_H
+# undef __NO_NET_API /* required for building for AmigaOS */
+# include <pwd.h>
+#endif
+
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+#include <curl/mprintf.h>
+
+#include "tool_findfile.h"
+
+#include "memdebug.h" /* keep this as LAST include */
+
+struct finder {
+ const char *env;
+ const char *append;
+};
+
+static const struct finder list[] = {
+ { "CURL_HOME", NULL },
+ { "XDG_CONFIG_HOME", NULL },
+ { "HOME", NULL },
+#ifdef WIN32
+ { "USERPROFILE", NULL },
+ { "APPDATA", NULL },
+ { "USERPROFILE", "\\Application Data"},
+#endif
+ { NULL, NULL }
+};
+
+static char *checkhome(const char *home, const char *fname, bool dotscore)
+{
+ const char pref[2] = { '.', '_' };
+ int i;
+ for(i = 0; i < (dotscore ? 2 : 1); i++) {
+ char *c;
+ if(dotscore)
+ c = curl_maprintf("%s" DIR_CHAR "%c%s", home, pref[i], &fname[1]);
+ else
+ c = curl_maprintf("%s" DIR_CHAR "%s", home, fname);
+ if(c) {
+ int fd = open(c, O_RDONLY);
+ if(fd >= 0) {
+ char *path = strdup(c);
+ close(fd);
+ curl_free(c);
+ return path;
+ }
+ curl_free(c);
+ }
+ }
+ return NULL;
+}
+
+/*
+ * findfile() - return the full path name of the file.
+ *
+ * If 'dotscore' is TRUE, then check for the file first with a leading dot
+ * and then with a leading underscore.
+ *
+ * 1. Iterate over the environment variables in order, and if set, check for
+ * the given file to be accessed there, then it is a match.
+ * 2. Non-windows: try getpwuid
+ */
+char *findfile(const char *fname, bool dotscore)
+{
+ int i;
+ DEBUGASSERT(fname && fname[0]);
+ DEBUGASSERT(!dotscore || (fname[0] == '.'));
+
+ if(!fname[0])
+ return NULL;
+
+ for(i = 0; list[i].env; i++) {
+ char *home = curl_getenv(list[i].env);
+ if(home) {
+ char *path;
+ if(!home[0]) {
+ curl_free(home);
+ continue;
+ }
+ if(list[i].append) {
+ char *c = curl_maprintf("%s%s", home, list[i].append);
+ curl_free(home);
+ if(!c)
+ return NULL;
+ home = c;
+ }
+ path = checkhome(home, fname, dotscore);
+ curl_free(home);
+ if(path)
+ return path;
+ }
+ }
+#if defined(HAVE_GETPWUID) && defined(HAVE_GETEUID)
+ {
+ struct passwd *pw = getpwuid(geteuid());
+ if(pw) {
+ char *home = pw->pw_dir;
+ if(home && home[0])
+ return checkhome(home, fname, FALSE);
+ }
+ }
+#endif /* PWD-stuff */
+ return NULL;
+}