summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTim Peters <tim.peters@gmail.com>2001-03-01 18:12:00 (GMT)
committerTim Peters <tim.peters@gmail.com>2001-03-01 18:12:00 (GMT)
commitd1e87a8288b18541ab555fc95ab94d06758015a0 (patch)
treef3a16573a9d30b0d4a35f80fb720ca42f5df75cd
parent4f64c1358252836900bf3cd0f68c6f83a7ec4e44 (diff)
downloadcpython-d1e87a8288b18541ab555fc95ab94d06758015a0.zip
cpython-d1e87a8288b18541ab555fc95ab94d06758015a0.tar.gz
cpython-d1e87a8288b18541ab555fc95ab94d06758015a0.tar.bz2
More MacOSX fiddling. As noted in a comment, I believe all variations
of these "search the directory" schemes (including this one) are still prone to making mistakes.
-rw-r--r--Python/import.c55
1 files changed, 37 insertions, 18 deletions
diff --git a/Python/import.c b/Python/import.c
index b9637b2..86dd134 100644
--- a/Python/import.c
+++ b/Python/import.c
@@ -984,13 +984,24 @@ find_module(char *realname, PyObject *path, char *buf, size_t buflen,
return fdp;
}
-/* case_ok(buf, len, namelen, name)
- * We've already done a successful stat() or fopen() on buf (a path of length
- * len, exclusive of trailing null). name is the last component of that path
- * (a string of length namelen, exclusive of trailing null).
+/* case_ok(char* buf, int len, int namelen, char* name)
+ * The arguments here are tricky, best shown by example:
+ * /a/b/c/d/e/f/g/h/i/j/k/some_long_module_name.py\0
+ * ^ ^ ^ ^
+ * |--------------------- buf ---------------------|
+ * |------------------- len ------------------|
+ * |------ name -------|
+ * |----- namelen -----|
+ * buf is the full path, but len only counts up to (& exclusive of) the
+ * extension. name is the module name, also exclusive of extension.
+ *
+ * We've already done a successful stat() or fopen() on buf, so know that
+ * there's some match, possibly case-insensitive.
+ *
* case_ok() is to return 1 if there's a case-sensitive match for
* name, else 0. case_ok() is also to return 1 if envar PYTHONCASEOK
* exists.
+ *
* case_ok() is used to implement case-sensitive import semantics even
* on platforms with case-insensitive filesystems. It's trivial to implement
* for case-sensitive filesystems. It's pretty much a cross-platform
@@ -1015,7 +1026,7 @@ find_module(char *realname, PyObject *path, char *buf, size_t buflen,
#include "TFileSpec.h" /* for Path2FSSpec() */
#endif
-#elif defined(__MACH__) && defined(__APPLE__)
+#elif defined(__MACH__) && defined(__APPLE__) && defined(HAVE_DIRENT_H)
#include <sys/types.h>
#include <dirent.h>
@@ -1107,28 +1118,35 @@ case_ok(char *buf, int len, int namelen, char *name)
return fss.name[0] >= namelen &&
strncmp(name, (char *)fss.name+1, namelen) == 0;
-/* new-fangled macintosh */
-#elif defined(__MACH__) && defined(__APPLE__)
+/* new-fangled macintosh (macosx)
+ *
+ * XXX This seems prone to obscure errors, like suppose someone does
+ * XXX "import xyz", and in some directory there's both "XYZ.py" and
+ * XXX "xyz.txt". fopen("xyz.py") will open XYZ.py, but when marching thru
+ * XXX the directory we'll eventually "succeed" on "xyz.txt" because the
+ * XXX extension is never checked.
+ */
+#elif defined(__MACH__) && defined(__APPLE__) && defined(HAVE_DIRENT_H)
DIR *dirp;
struct dirent *dp;
- char pathname[MAXPATHLEN + 1];
- const int pathlen = len - namelen - 1; /* don't want trailing SEP */
+ char dirname[MAXPATHLEN + 1];
+ const int dirlen = len - namelen - 1; /* don't want trailing SEP */
if (getenv("PYTHONCASEOK") != NULL)
return 1;
- /* Copy the path component into pathname; substitute "." if empty */
- if (pathlen <= 0) {
- pathname[0] = '.';
- pathname[1] = '\0';
+ /* Copy the dir component into dirname; substitute "." if empty */
+ if (dirlen <= 0) {
+ dirname[0] = '.';
+ dirname[1] = '\0';
}
else {
- assert(pathlen <= MAXPATHLEN);
- memcpy(pathname, buf, pathlen);
- pathname[pathlen] = '\0';
+ assert(dirlen <= MAXPATHLEN);
+ memcpy(dirname, buf, dirlen);
+ dirname[dirlen] = '\0';
}
/* Open the directory and search the entries for an exact match. */
- dirp = opendir(pathname);
+ dirp = opendir(dirname);
if (dirp) {
while ((dp = readdir(dirp)) != NULL) {
const int thislen =
@@ -1137,7 +1155,8 @@ case_ok(char *buf, int len, int namelen, char *name)
#else
strlen(dp->d_name);
#endif
- if (thislen == namelen && !strcmp(dp->d_name, name)) {
+ if (thislen >= namelen &&
+ strncmp(dp->d_name, name, namelen) == 0) {
(void)closedir(dirp);
return 1; /* Found */
}