Salome HOME
Copyright update 2021
[tools/libbatch.git] / src / Core / CommunicationProtocolRSH.cxx
1 // Copyright (C) 2007-2021  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 /*
23  *  CommunicationProtocolRSH.cxx :
24  *
25  *  Created on: 14 sept. 2009
26  *  Author : Renaud BARATE - EDF R&D
27  */
28
29 #ifdef WIN32
30 #include <direct.h>
31 #include <iostream>
32
33 #include <RunTimeException.hxx>
34 #endif
35
36 #include <libbatch_config.h>
37
38 #include "CommunicationProtocolRSH.hxx"
39 #include "Log.hxx"
40
41 using namespace std;
42
43 namespace Batch {
44
45   CommunicationProtocolRSH::CommunicationProtocolRSH()
46   : CommunicationProtocol(RSH)
47   {
48   }
49
50   vector<string> CommunicationProtocolRSH::getExecCommandArgs(const string & subCommand,
51                                                               const string & host,
52                                                               const string & user) const
53   {
54     vector<string> cmd;
55
56     cmd.push_back(RSH_COMMAND);
57     cmd.push_back(host);
58
59     if (user.size() > 0) {
60       cmd.push_back("-l");
61       cmd.push_back(user);
62     }
63
64 #ifdef WIN32
65     cmd.push_back("-n");
66 #endif
67
68     cmd.push_back(subCommand);
69
70     return cmd;
71   }
72
73   vector<string> CommunicationProtocolRSH::getCopyCommandArgs(const string & sourcePath,
74                                                               const string & sourceHost,
75                                                               const string & sourceUser,
76                                                               const string & destinationPath,
77                                                               const string & destinationHost,
78                                                               const string & destinationUser) const
79   {
80     vector<string> cmd;
81
82     string fullSource;
83     if (sourceHost.size() != 0) {
84       if (sourceUser.size() != 0) {
85 #ifdef WIN32
86         fullSource += sourceHost + "." + sourceUser + ":";
87 #else
88         fullSource += sourceUser + "@" + sourceHost + ":";
89 #endif
90       } else {
91         fullSource += sourceHost + ":";
92       }
93     }
94     fullSource += sourcePath;
95
96     string fullDestination;
97     if (destinationHost.size() != 0) {
98       if (destinationUser.size() != 0) {
99 #ifdef WIN32
100         fullDestination += destinationHost + "." + destinationUser + ":";
101 #else
102         fullDestination += destinationUser + "@" + destinationHost + ":";
103 #endif
104       } else {
105         fullDestination += destinationHost + ":";
106       }
107     }
108     fullDestination += destinationPath;
109
110     cmd.push_back(RCP_COMMAND);
111     cmd.push_back("-r");
112     cmd.push_back(fullSource);
113     cmd.push_back(fullDestination);
114
115     return cmd;
116   }
117
118 #ifdef WIN32
119   int CommunicationProtocolRSH::copyFile(const std::string & sourcePath,
120                                          const std::string & sourceHost,
121                                          const std::string & sourceUser,
122                                          const std::string & destinationPath,
123                                          const std::string & destinationHost,
124                                          const std::string & destinationUser) const
125   {
126     // On Windows, we can't use drive letters in the paths of rcp command because they
127     // are confused with host names. So we must first change the working directory and
128     // then copy the file using its path without the drive letter.
129
130     // Extract the drive letter from the source path
131     string sourcePathWithoutDrive;
132     char sourceDriveLetter = getDriveLetter(sourcePath, &sourcePathWithoutDrive);
133     // Error if we have a drive letter and it is a remote path
134     if (sourceDriveLetter != '\0' && sourceHost.size() != 0)
135       throw RunTimeException(string("Invalid path: ") + sourcePath + " for host " + sourceHost);
136
137     // Extract the drive letter from the destination path
138     string destinationPathWithoutDrive;
139     char destinationDriveLetter = getDriveLetter(destinationPath, &destinationPathWithoutDrive);
140     // Error if we have a drive letter and it is a remote path
141     if (destinationDriveLetter != '\0' && destinationHost.size() != 0)
142       throw RunTimeException(string("Invalid path: ") + destinationPath + " for host " + destinationHost);
143
144     // Error if we have two drive letters and they are different
145     if (sourceDriveLetter != '\0' && destinationDriveLetter != '\0' &&
146         sourceDriveLetter != destinationDriveLetter)
147       throw RunTimeException(string("Can't use RCP to copy files between different drives: ") +
148                              sourcePath + (", ") + destinationPath);
149
150     // Now get the drive letter to use if there is one
151     char driveLetter = (sourceDriveLetter != '\0') ? sourceDriveLetter : destinationDriveLetter;
152
153     // Get the drive of the current working directory
154     char cwd[_MAX_PATH];
155     _getcwd(cwd, _MAX_PATH);
156     char currentDrive = getDriveLetter(cwd);
157
158     // Change working directory if necessary
159     if (driveLetter != '\0' && driveLetter != currentDrive) {
160       char newdir[3];
161       newdir[0] = driveLetter;
162       newdir[1] = ':';
163       newdir[2] = '\0';
164       LOG("Changing directory: " << newdir);
165       _chdir(newdir);
166     }
167
168     int status = CommunicationProtocol::copyFile(sourcePathWithoutDrive, sourceHost, sourceUser,
169                                                  destinationPathWithoutDrive, destinationHost, destinationUser);
170
171     // Go back to previous directory if necessary
172     if (driveLetter != '\0' && driveLetter != currentDrive) {
173       LOG("Changing directory: " << cwd);
174       _chdir(cwd);
175     }
176
177     return status;
178   }
179
180   char CommunicationProtocolRSH::getDriveLetter(const string & path, string * pathWithoutDrive) const
181   {
182     if (path.find(':') != string::npos) {
183       // Error if the colon is not the second character
184       if (path.size() < 2 || path[1] != ':')
185         throw RunTimeException(string("Invalid path: ") + path);
186       else {
187         if (pathWithoutDrive != NULL) *pathWithoutDrive = path.substr(2);
188         return path[0];
189       }
190     } else {
191       if (pathWithoutDrive != NULL) *pathWithoutDrive = path;
192       return '\0';
193     }
194   }
195
196 #endif
197
198 }