- for (std::string::size_type pos = 0; (pos = inDir.find('/', pos + 1)) != std::string::npos;)
- {
- std::string path = inDir.substr(0, pos);
- const char *cpath = path.c_str();
- struct stat sb;
- if (::stat(cpath, &sb))
- {
- // if we are creating a path in the user's home directory, override the user's mode
- std::string homedir = getenv("HOME");
-
- // canonicalize the path (remove double slashes)
- string canonPath = RemoveDoubleSlashes(cpath);
-
- if (canonPath.find(homedir, 0) == 0)
- {
- mode = 0700;
- }
-
- if (errno != ENOENT || ::mkdir(cpath, mode))
- UnixError::throwMe(errno);
- }
- else if (!S_ISDIR(sb.st_mode))
- CssmError::throwMe(CSSM_ERRCODE_OS_ACCESS_DENIED); // @@@ Should be is a directory
- }
+ // see if the file already exists and is a directory
+ struct stat st;
+ int result = stat(inDir.c_str(), &st);
+
+ if (result == 0) // file exists
+ {
+ if ((st.st_mode & S_IFDIR) == 0)
+ {
+ // whatever was there, it wasn't a directory. That's really bad, so complain
+ syslog(LOG_ALERT, "Needed a directory at %s, but the file that was there was not one.\n", inDir.c_str());
+ UnixError::throwMe(ENOTDIR);
+ }
+ }
+ else
+ {
+ // the file did not exist, try to create it
+ result = mkpath_np(inDir.c_str(), 0777); // make the directory with umask
+ if (result != 0)
+ {
+ // mkpath_np does not set errno, you have to look at the result.
+ UnixError::throwMe(result);
+ }
+ }
+
+ // Double check and see if we got what we hoped for
+ result = stat(inDir.c_str(), &st);
+ if (result != 0)
+ {
+ UnixError::throwMe(errno);
+ }
+
+ if ((st.st_mode & S_IFDIR) == 0)
+ {
+ // we didn't create a dictionary? That's curious...
+ syslog(LOG_ALERT, "Failed to create a directory when we asked for one to be created at %s\n", inDir.c_str());
+ UnixError::throwMe(ENOTDIR);
+ }