diff --git a/src/EmbeddedFiles.cpp b/src/EmbeddedFiles.cpp index 2e8fc0516f..d8756b1d9e 100644 --- a/src/EmbeddedFiles.cpp +++ b/src/EmbeddedFiles.cpp @@ -134,15 +134,21 @@ bool EmbeddedFile::extract(Buffer const * buf) const // need to make directory? FileName path = ext.onlyPath(); - if (!path.isDirectory()) - makedir(const_cast(path.absFilename().c_str()), 0755); - if (emb.copyTo(ext)) + if (!path.createPath()) { + Alert::error(_("Copy file failure"), + bformat(_("Cannot create file path '%1$s'.\n" + "Please check whether the path is writeable."), + from_utf8(path.absFilename()))); + return false; + } + + if (emb.copyTo(ext, true)) return true; + Alert::error(_("Copy file failure"), bformat(_("Cannot copy file %1$s to %2$s.\n" "Please check whether the directory exists and is writeable."), from_utf8(emb_file), from_utf8(ext_file))); - //LYXERR(Debug::DEBUG, "Fs error: " << fe.what()); return false; } @@ -177,8 +183,8 @@ bool EmbeddedFile::updateFromExternalFile(Buffer const * buf) const // need to make directory? FileName path = emb.onlyPath(); if (!path.isDirectory()) - makedir(const_cast(path.absFilename().c_str()), 0755); - if (ext.copyTo(emb)) + path.createPath(); + if (ext.copyTo(emb, true)) return true; Alert::error(_("Copy file failure"), bformat(_("Cannot copy file %1$s to %2$s.\n" @@ -281,7 +287,7 @@ bool EmbeddedFiles::writeFile(DocFileName const & filename) ::zipFiles(zipfile.toFilesystemEncoding(), filenames); // copy file back - if (!zipfile.copyTo(filename)) { + if (!zipfile.copyTo(filename, true)) { Alert::error(_("Save failure"), bformat(_("Cannot create file %1$s.\n" "Please check whether the directory exists and is writeable."), diff --git a/src/support/FileName.cpp b/src/support/FileName.cpp index a596463a88..e35546860d 100644 --- a/src/support/FileName.cpp +++ b/src/support/FileName.cpp @@ -40,8 +40,18 @@ #ifdef HAVE_SYS_STAT_H # include #endif -#include +#ifdef HAVE_UNISTD_H +# include +#endif +#ifdef HAVE_DIRECT_H +# include +#endif +#ifdef _WIN32 +# include +#endif + #include +#include using namespace std; @@ -397,10 +407,91 @@ bool FileName::destroyDirectory() const } +static int mymkdir(char const * pathname, unsigned long int mode) +{ + // FIXME: why don't we have mode_t in lyx::mkdir prototype ?? +#if HAVE_MKDIR +# if MKDIR_TAKES_ONE_ARG + // MinGW32 + return ::mkdir(pathname); + // FIXME: "Permissions of created directories are ignored on this system." +# else + // POSIX + return ::mkdir(pathname, mode_t(mode)); +# endif +#elif defined(_WIN32) + // plain Windows 32 + return CreateDirectory(pathname, 0) != 0 ? 0 : -1; + // FIXME: "Permissions of created directories are ignored on this system." +#elif HAVE__MKDIR + return ::_mkdir(pathname); + // FIXME: "Permissions of created directories are ignored on this system." +#else +# error "Don't know how to create a directory on this system." +#endif + +} + + bool FileName::createDirectory(int permission) const { BOOST_ASSERT(!empty()); - return mkdir(*this, permission) == 0; + return mymkdir(toFilesystemEncoding().c_str(), permission) == 0; +} + + +// adapted from zlib-1.2.3/contrib/minizip/miniunz.c +static int makedir(char * newdir, unsigned long int mode) +{ + char *buffer; + char *p; + int len = (int)strlen(newdir); + + if (len <= 0) + return 1; + + buffer = (char*)malloc(len+1); + strcpy(buffer,newdir); + + if (buffer[len-1] == '/') + buffer[len-1] = '\0'; + if (mymkdir(buffer, mode) == 0) { + free(buffer); + return 0; + } + + p = buffer + 1; + while (1) { + char hold; + + while(*p && *p != '\\' && *p != '/') + p++; + hold = *p; + *p = 0; + if (mymkdir(buffer, mode) != 0) { + free(buffer); + return 1; + } + if (hold == 0) + break; + *p++ = hold; + } + free(buffer); + return 0; +} + + +bool FileName::createPath() const +{ + BOOST_ASSERT(!empty()); + if (isDirectory()) + return true; + + QDir dir; + bool success = dir.mkpath(d->fi.absoluteFilePath()); + if (!success) + LYXERR0("Cannot create path '" << *this << "'!"); + return success; } diff --git a/src/support/FileName.h b/src/support/FileName.h index 16de028ccb..fd63ce5e53 100644 --- a/src/support/FileName.h +++ b/src/support/FileName.h @@ -120,6 +120,9 @@ public: /// Creates pointed directory. /// \return true on success. bool createDirectory(int permissions) const; + /// Creates pointed path. + /// \return true on success. + bool createPath() const; /// Get the contents of a file as a huge docstring. /// \param encoding defines the encoding of the file contents. diff --git a/src/support/Makefile.am b/src/support/Makefile.am index 934d10051d..2e7f13293d 100644 --- a/src/support/Makefile.am +++ b/src/support/Makefile.am @@ -78,7 +78,6 @@ liblyxsupport_la_SOURCES = \ lyxsum.cpp \ Messages.cpp \ Messages.h \ - mkdir.cpp \ os.cpp \ os.h \ Path.cpp \ diff --git a/src/support/lyxlib.h b/src/support/lyxlib.h index 4096bc8d94..74abd7fefa 100644 --- a/src/support/lyxlib.h +++ b/src/support/lyxlib.h @@ -30,13 +30,7 @@ FileName const getcwd(); int kill(int pid, int sig); /// FIXME: same here void abort(); -/// create the given directory with the given mode -/// \ret return 0 if the directory is successfully created -int mkdir(FileName const & pathname, unsigned long int mode); -/// create the given directory with the given mode, create all -/// intermediate directories if necessary -/// \ret return 0 if the directory is successfully created -int makedir(char * pathname, unsigned long int mode=0755); + /// (securely) create a temporary file in the given dir with the given mask /// \p mask must be in filesystem encoding FileName const tempName(FileName const & dir = FileName(), diff --git a/src/support/mkdir.cpp b/src/support/mkdir.cpp deleted file mode 100644 index d96dca007b..0000000000 --- a/src/support/mkdir.cpp +++ /dev/null @@ -1,112 +0,0 @@ -/** - * \file mkdir.cpp - * This file is part of LyX, the document processor. - * Licence details can be found in the file COPYING. - * - * \author Lars Gullik Bjønnes - * - * Full author contact details are available in file CREDITS. - */ - -#include - -#include "support/lyxlib.h" -#include "support/debug.h" -#include "support/FileName.h" - -#ifdef HAVE_SYS_STAT_H -# include -#endif -#ifdef HAVE_SYS_TYPES_H -# include -#endif -#include -#ifdef HAVE_UNISTD_H -# include -#endif -#ifdef HAVE_DIRECT_H -# include -#endif -#ifdef _WIN32 -# include -#endif - -namespace lyx { -namespace support { - - -int mymkdir(char const * pathname, unsigned long int mode) -{ - LYXERR0("MKDIR" << pathname); - // FIXME: why don't we have mode_t in lyx::mkdir prototype ?? -#if HAVE_MKDIR -# if MKDIR_TAKES_ONE_ARG - // MinGW32 - return ::mkdir(pathname); - // FIXME: "Permissions of created directories are ignored on this system." -# else - // POSIX - return ::mkdir(pathname, mode_t(mode)); -# endif -#elif defined(_WIN32) - // plain Windows 32 - return CreateDirectory(pathname, 0) != 0 ? 0 : -1; - // FIXME: "Permissions of created directories are ignored on this system." -#elif HAVE__MKDIR - return ::_mkdir(pathname); - // FIXME: "Permissions of created directories are ignored on this system." -#else -# error "Don't know how to create a directory on this system." -#endif - -} - -int mkdir(FileName const & pathname, unsigned long int mode) -{ - return mymkdir(pathname.toFilesystemEncoding().c_str(), mode); -} - - -// adapted from zlib-1.2.3/contrib/minizip/miniunz.c -int makedir(char * newdir, unsigned long int mode) -{ - char *buffer; - char *p; - int len = (int)strlen(newdir); - - if (len <= 0) - return 1; - - buffer = (char*)malloc(len+1); - strcpy(buffer,newdir); - - if (buffer[len-1] == '/') - buffer[len-1] = '\0'; - if (mymkdir(buffer, mode) == 0) { - free(buffer); - return 0; - } - - p = buffer + 1; - while (1) { - char hold; - - while(*p && *p != '\\' && *p != '/') - p++; - hold = *p; - *p = 0; - if (mymkdir(buffer, mode) != 0) { - free(buffer); - return 1; - } - if (hold == 0) - break; - *p++ = hold; - } - free(buffer); - return 0; -} - - -} // namespace support -} // namespace lyx