diff options
author | Brad King <brad.king@kitware.com> | 2006-03-03 23:44:32 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2006-03-03 23:44:32 (GMT) |
commit | a2e136fd17b693765a4961220433bdf207930583 (patch) | |
tree | b785101e7a9fe7bed52a05e3d483216b500a4d70 /Source/cmFileCommand.cxx | |
parent | 5792dc8da8a567ece9fd231e9844a5b1cd30ddc2 (diff) | |
download | CMake-a2e136fd17b693765a4961220433bdf207930583.zip CMake-a2e136fd17b693765a4961220433bdf207930583.tar.gz CMake-a2e136fd17b693765a4961220433bdf207930583.tar.bz2 |
ENH: Added PERMISSIONS and RENAME options to the INSTALL command's FILES and PROGRAMS mode, and corresponding support to FILE(INSTALL). Default permissions for shared libraries on non-Windows/non-OSX platforms no longer has the execute bit set.
Diffstat (limited to 'Source/cmFileCommand.cxx')
-rw-r--r-- | Source/cmFileCommand.cxx | 394 |
1 files changed, 273 insertions, 121 deletions
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index 36d309e..3c45d66 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -276,6 +276,7 @@ bool cmFileCommand::HandleInstallCommand( return false; } + std::string rename = ""; std::string destination = ""; std::string stype = "FILES"; const char* build_type = m_Makefile->GetDefinition("BUILD_TYPE"); @@ -298,8 +299,38 @@ bool cmFileCommand::HandleInstallCommand( std::map<cmStdString, const char*> properties; + // Build a table of permissions flags. +#if defined(_WIN32) && !defined(__CYGWIN__) + mode_t mode_owner_read = S_IREAD; + mode_t mode_owner_write = S_IWRITE; + mode_t mode_owner_execute = S_IEXEC; + mode_t mode_group_read = 0; + mode_t mode_group_write = 0; + mode_t mode_group_execute = 0; + mode_t mode_world_read = 0; + mode_t mode_world_write = 0; + mode_t mode_world_execute = 0; + mode_t mode_setuid = 0; + mode_t mode_setgid = 0; +#else + mode_t mode_owner_read = S_IRUSR; + mode_t mode_owner_write = S_IWUSR; + mode_t mode_owner_execute = S_IXUSR; + mode_t mode_group_read = S_IRGRP; + mode_t mode_group_write = S_IWGRP; + mode_t mode_group_execute = S_IXGRP; + mode_t mode_world_read = S_IROTH; + mode_t mode_world_write = S_IWOTH; + mode_t mode_world_execute = S_IXOTH; + mode_t mode_setuid = S_ISUID; + mode_t mode_setgid = S_ISGID; +#endif + bool in_files = false; bool in_properties = false; + bool in_permissions = false; + bool use_given_permissions = false; + mode_t permissions = 0; bool optional = false; for ( ; i != args.size(); ++i ) { @@ -310,6 +341,7 @@ bool cmFileCommand::HandleInstallCommand( destination = args[i]; in_files = false; in_properties = false; + in_permissions = false; } else if ( *cstr == "TYPE" && i < args.size()-1 ) { @@ -322,16 +354,34 @@ bool cmFileCommand::HandleInstallCommand( } in_properties = false; in_files = false; + in_permissions = false; + } + else if ( *cstr == "RENAME" && i < args.size()-1 ) + { + i++; + rename = args[i]; + in_properties = false; + in_files = false; + in_permissions = false; } else if ( *cstr == "PROPERTIES" ) { in_properties = true; in_files = false; + in_permissions = false; + } + else if ( *cstr == "PERMISSIONS" ) + { + use_given_permissions = true; + in_properties = false; + in_files = false; + in_permissions = true; } else if ( *cstr == "FILES" && !in_files) { in_files = true; in_properties = false; + in_permissions = false; } else if ( in_properties && i < args.size()-1 ) { @@ -342,6 +392,50 @@ bool cmFileCommand::HandleInstallCommand( { files.push_back(*cstr); } + else if(in_permissions && args[i] == "OWNER_READ") + { + permissions |= mode_owner_read; + } + else if(in_permissions && args[i] == "OWNER_WRITE") + { + permissions |= mode_owner_write; + } + else if(in_permissions && args[i] == "OWNER_EXECUTE") + { + permissions |= mode_owner_execute; + } + else if(in_permissions && args[i] == "GROUP_READ") + { + permissions |= mode_group_read; + } + else if(in_permissions && args[i] == "GROUP_WRITE") + { + permissions |= mode_group_write; + } + else if(in_permissions && args[i] == "GROUP_EXECUTE") + { + permissions |= mode_group_execute; + } + else if(in_permissions && args[i] == "WORLD_READ") + { + permissions |= mode_world_read; + } + else if(in_permissions && args[i] == "WORLD_WRITE") + { + permissions |= mode_world_write; + } + else if(in_permissions && args[i] == "WORLD_EXECUTE") + { + permissions |= mode_world_execute; + } + else if(in_permissions && args[i] == "SETUID") + { + permissions |= mode_setuid; + } + else if(in_permissions && args[i] == "SETGID") + { + permissions |= mode_setgid; + } else { this->SetError("called with inappropriate arguments"); @@ -458,6 +552,61 @@ bool cmFileCommand::HandleInstallCommand( return false; } + // Check rename form. + if(!rename.empty()) + { + if(itype != cmTarget::INSTALL_FILES) + { + this->SetError("INSTALL option RENAME may be used only with FILES."); + return false; + } + if(files.size() > 1) + { + this->SetError("INSTALL option RENAME may be used only with one file."); + return false; + } + } + + // If permissions were not specified set default permissions for + // this target type. + bool use_source_permissions = false; + if(!use_given_permissions) + { + switch(itype) + { + case cmTarget::SHARED_LIBRARY: + case cmTarget::MODULE_LIBRARY: +#if !defined(_WIN32) && !defined(__APPLE_CC__) + // Use read/write permissions. + use_given_permissions = true; + permissions = 0; + permissions |= mode_owner_read; + permissions |= mode_owner_write; + permissions |= mode_group_read; + permissions |= mode_world_read; + break; +#endif + case cmTarget::EXECUTABLE: + case cmTarget::INSTALL_PROGRAMS: + // Use read/write/executable permissions. + use_given_permissions = true; + permissions = 0; + permissions |= mode_owner_read; + permissions |= mode_owner_write; + permissions |= mode_owner_execute; + permissions |= mode_group_read; + permissions |= mode_group_execute; + permissions |= mode_world_read; + permissions |= mode_world_execute; + break; + default: + // Use the permissions of the file being copied. + use_source_permissions = true; + break; + } + } + + // Get the current manifest. const char* manifest_files = m_Makefile->GetDefinition("CMAKE_INSTALL_MANIFEST_FILES"); std::string smanifest_files; @@ -466,26 +615,24 @@ bool cmFileCommand::HandleInstallCommand( smanifest_files = manifest_files; } + // Handle each file listed. for ( i = 0; i < files.size(); i ++ ) { - std::string destfilewe - = destination + "/" - + cmSystemTools::GetFilenameWithoutExtension(files[i]); - std::string ctarget = files[i].c_str(); - std::string fname = cmSystemTools::GetFilenameName(ctarget); - std::string ext = cmSystemTools::GetFilenameExtension(ctarget); - std::string fnamewe - = cmSystemTools::GetFilenameWithoutExtension(ctarget); - std::string destfile = destfilewe; - if ( ext.size() ) - { - destfile += ext; - } - switch( itype ) + // Split the input file into its directory and name components. + std::string fromDir = cmSystemTools::GetFilenamePath(files[i]); + std::string fromName = cmSystemTools::GetFilenameName(files[i]); + + // Compute the full path to the destination file. + std::string toFile = destination; + toFile += "/"; + toFile += rename.empty()? fromName : rename; + + // Handle type-specific installation details. + switch(itype) { - case cmTarget::MODULE_LIBRARY: - case cmTarget::STATIC_LIBRARY: - case cmTarget::SHARED_LIBRARY: + case cmTarget::MODULE_LIBRARY: + case cmTarget::STATIC_LIBRARY: + case cmTarget::SHARED_LIBRARY: { // Handle shared library versioning const char* lib_version = 0; @@ -508,18 +655,18 @@ bool cmFileCommand::HandleInstallCommand( } if ( lib_version && lib_soversion ) { - std::string libname = destfile; - std::string soname = destfile; - std::string soname_nopath = fname; + std::string libname = toFile; + std::string soname = toFile; + std::string soname_nopath = fromName; soname += "."; soname += lib_soversion; soname_nopath += "."; soname_nopath += lib_soversion; - fname += "."; - fname += lib_version; - destfile += "."; - destfile += lib_version; + fromName += "."; + fromName += lib_version; + toFile += "."; + toFile += lib_version; cmSystemTools::RemoveFile(soname.c_str()); cmSystemTools::RemoveFile(libname.c_str()); @@ -532,11 +679,11 @@ bool cmFileCommand::HandleInstallCommand( } smanifest_files += ";"; smanifest_files += libname.substr(destDirLength);; - if ( destfile != soname ) + if ( toFile != soname ) { - if ( !cmSystemTools::CreateSymlink(fname.c_str(), soname.c_str()) ) + if ( !cmSystemTools::CreateSymlink(fromName.c_str(), soname.c_str()) ) { - std::string errstring = "error when creating symlink from: " + soname + " to " + fname; + std::string errstring = "error when creating symlink from: " + soname + " to " + fromName; this->SetError(errstring.c_str()); return false; } @@ -544,129 +691,134 @@ bool cmFileCommand::HandleInstallCommand( smanifest_files += soname.substr(destDirLength); } } - - // Reconstruct the source file path taking into account the - // possibly new file name. - cmOStringStream str; - str << cmSystemTools::GetFilenamePath(ctarget) << "/" << fname; - ctarget = str.str(); - } - break; - case cmTarget::EXECUTABLE: - { - // Handle executable versioning - const char* exe_version = 0; - if ( properties.find("VERSION") != properties.end() ) - { - exe_version = properties["VERSION"]; } - if ( exe_version ) + break; + case cmTarget::EXECUTABLE: { - std::string exename = destfile; - std::string exename_nopath = fname; - exename_nopath += "-"; - exename_nopath += exe_version; + // Handle executable versioning + const char* exe_version = 0; + if ( properties.find("VERSION") != properties.end() ) + { + exe_version = properties["VERSION"]; + } + if ( exe_version ) + { + std::string exename = toFile; + std::string exename_nopath = fromName; + exename_nopath += "-"; + exename_nopath += exe_version; - fname += "-"; - fname += exe_version; - destfile += "-"; - destfile += exe_version; + fromName += "-"; + fromName += exe_version; + toFile += "-"; + toFile += exe_version; - cmSystemTools::RemoveFile(exename.c_str()); + cmSystemTools::RemoveFile(exename.c_str()); - if (!cmSystemTools::CreateSymlink(exename_nopath.c_str(), exename.c_str()) ) - { - std::string errstring = "error when creating symlink from: " + exename + " to " + exename_nopath; - this->SetError(errstring.c_str()); - return false; + if (!cmSystemTools::CreateSymlink(exename_nopath.c_str(), exename.c_str()) ) + { + std::string errstring = "error when creating symlink from: " + exename + " to " + exename_nopath; + this->SetError(errstring.c_str()); + return false; + } + smanifest_files += ";"; + smanifest_files += exename.substr(destDirLength); } - smanifest_files += ";"; - smanifest_files += exename.substr(destDirLength); } - - // Reconstruct the source file path taking into account the - // possibly new file name. - cmOStringStream str; - str << cmSystemTools::GetFilenamePath(ctarget) << "/" << fname; - ctarget = str.str(); - } - break; + break; } + // Construct the full path to the source file. The file name may + // have been changed above. + std::string fromFile = fromDir; + fromFile += "/"; + fromFile += fromName; + std::string message; - if ( !cmSystemTools::SameFile(ctarget.c_str(), destfile.c_str()) ) + if(!cmSystemTools::SameFile(fromFile.c_str(), toFile.c_str())) { - if ( cmSystemTools::FileExists(ctarget.c_str()) ) + if(cmSystemTools::FileExists(fromFile.c_str())) { + // We will install this file. Display the information. message = "Installing "; - message += destfile.c_str(); + message += toFile.c_str(); m_Makefile->DisplayStatus(message.c_str(), -1); - cmSystemTools::RemoveFile(destfile.c_str()); - if ( !cmSystemTools::CopyFileAlways(ctarget.c_str(), - destination.c_str()) ) + + // If no permissions were already given use the permissions of + // the file being copied. + if(!use_given_permissions && + (!use_source_permissions || + !cmSystemTools::GetPermissions(fromFile.c_str(), permissions))) { - std::string errstring = "cannot copy file: " + ctarget + - " to directory : " + destination + "."; - this->SetError(errstring.c_str()); - return false; + // Set default permissions. + permissions = 0; + permissions |= mode_owner_read; + permissions |= mode_owner_write; + permissions |= mode_group_read; + permissions |= mode_world_read; } - switch( itype ) + + // Remove the original file and try copying the new file. + // TODO: This should be copy-if-different. Don't forget to + // edit the destination file permissions, or compare files + // first. This would need a new SystemTools::FilesDiffer that + // does not read all of the files at once. + cmSystemTools::RemoveFile(toFile.c_str()); + if(!cmSystemTools::CopyFileAlways(fromFile.c_str(), toFile.c_str())) { - case cmTarget::STATIC_LIBRARY: + cmOStringStream e; + e << "INSTALL cannot copy file \"" << fromFile + << "\" to \"" << toFile + "\"."; + this->SetError(e.str().c_str()); + return false; + } + + // Perform post-installation processing on the file depending + // on its type. #if defined(__APPLE_CC__) + // Static libraries need ranlib on this platform. + if(itype == cmTarget::STATIC_LIBRARY) + { + std::string ranlib = "ranlib "; + ranlib += cmSystemTools::ConvertToOutputPath(toFile.c_str()); + if(!cmSystemTools::RunSingleCommand(ranlib.c_str())) { - std::string ranlib = "ranlib "; - ranlib += cmSystemTools::ConvertToOutputPath(destfile.c_str()); - if(!cmSystemTools::RunSingleCommand(ranlib.c_str())) - { - std::string err = "ranlib failed: "; - err += ranlib; - this->SetError(err.c_str()); - } + std::string err = "ranlib failed: "; + err += ranlib; + this->SetError(err.c_str()); + return false; } + } #endif - break; - - case cmTarget::MODULE_LIBRARY: - case cmTarget::SHARED_LIBRARY: - case cmTarget::EXECUTABLE: - case cmTarget::INSTALL_PROGRAMS: - - if ( !cmSystemTools::SetPermissions(destfile.c_str(), -#if defined( _MSC_VER ) || defined( __MINGW32__ ) - S_IREAD | S_IWRITE | S_IEXEC -#elif defined( __BORLANDC__ ) - S_IRUSR | S_IWUSR | S_IXUSR -#else - S_IRUSR | S_IWUSR | S_IXUSR | - S_IRGRP | S_IXGRP | - S_IROTH | S_IXOTH -#endif - ) ) - { - cmOStringStream err; - err << "Problem setting permissions on file: " - << destfile.c_str(); - perror(err.str().c_str()); - } + + // Set permissions of the destination file. + if(!cmSystemTools::SetPermissions(toFile.c_str(), permissions)) + { + cmOStringStream e; + e << "Problem setting permissions on file \"" + << toFile.c_str() << "\""; + this->SetError(e.str().c_str()); + return false; } + + // Add the file to the manifest. smanifest_files += ";"; - smanifest_files += destfile.substr(destDirLength); + smanifest_files += toFile.substr(destDirLength); } - else + else if(!optional) { - if ( !optional ) - { - std::string errstring = "cannot find file: " + - ctarget + " to install."; - this->SetError(errstring.c_str()); - return false; - } + // The input file does not exist and installation is not optional. + cmOStringStream e; + e << "INSTALL cannot find file \"" << fromFile << "\" to install."; + this->SetError(e.str().c_str()); + return false; } } } + + // Save the updated install manifest. m_Makefile->AddDefinition("CMAKE_INSTALL_MANIFEST_FILES", - smanifest_files.c_str()); + smanifest_files.c_str()); return true; } |