]>
sourceware.org Git - systemtap.git/blob - util.cxx
1 // Copyright (C) Andrew Tridgell 2002 (original file)
2 // Copyright (C) 2006, 2009 Red Hat Inc. (systemtap changes)
4 // This program is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU General Public License as
6 // published by the Free Software Foundation; either version 2 of the
7 // License, or (at your option) any later version.
9 // This program is distributed in the hope that it will be useful, but
10 // WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the GNU
12 // General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
30 #include <sys/types.h>
38 // Return current users home directory or die.
40 get_home_directory(void)
42 const char *p
= getenv("HOME");
46 struct passwd
*pwd
= getpwuid(getuid());
50 throw runtime_error("Unable to determine home directory");
55 // Get the size of a file in bytes
57 get_file_size(const string
&path
)
59 struct stat file_info
;
61 if (stat(path
.c_str(), &file_info
) == 0)
62 return file_info
.st_size
;
67 // Get the size of a file in bytes
69 file_exists (const string
&path
)
71 struct stat file_info
;
73 if (stat(path
.c_str(), &file_info
) == 0)
79 // Copy a file. The copy is done via a temporary file and atomic
82 copy_file(const string
& src
, const string
& dest
, bool verbose
)
92 clog
<< "Copying " << src
<< " to " << dest
<< endl
;
95 fd1
= open(src
.c_str(), O_RDONLY
);
99 // Open the temporary output file.
100 tmp
= dest
+ string(".XXXXXX");
101 tmp_name
= (char *)tmp
.c_str();
102 fd2
= mkstemp(tmp_name
);
109 // Copy the src file to the temporary output file.
110 while ((n
= read(fd1
, buf
, sizeof(buf
))) > 0)
112 if (write(fd2
, buf
, n
) != n
)
122 // Set the permissions on the temporary output file.
124 fchmod(fd2
, 0666 & ~mask
);
127 // Close the temporary output file. The close can fail on NFS if
129 if (close(fd2
) == -1)
135 // Rename the temporary output file to the destination file.
136 unlink(dest
.c_str());
137 if (rename(tmp_name
, dest
.c_str()) == -1)
146 cerr
<< "Copy failed (\"" << src
<< "\" to \"" << dest
<< "\"): "
147 << strerror(errno
) << endl
;
152 // Make sure a directory exists.
154 create_dir(const char *dir
)
157 if (stat(dir
, &st
) == 0)
159 if (S_ISDIR(st
.st_mode
))
165 if (mkdir(dir
, 0777) != 0 && errno
!= EEXIST
)
171 // Remove a file or directory
173 remove_file_or_dir (const char *name
)
178 if ((rc
= stat(name
, &st
)) != 0)
185 if (remove (name
) != 0)
187 cerr
<< "remove returned 0" << endl
;
192 tokenize(const string
& str
, vector
<string
>& tokens
,
193 const string
& delimiters
= " ")
195 // Skip delimiters at beginning.
196 string::size_type lastPos
= str
.find_first_not_of(delimiters
, 0);
197 // Find first "non-delimiter".
198 string::size_type pos
= str
.find_first_of(delimiters
, lastPos
);
200 while (pos
!= string::npos
|| lastPos
!= string::npos
)
202 // Found a token, add it to the vector.
203 tokens
.push_back(str
.substr(lastPos
, pos
- lastPos
));
204 // Skip delimiters. Note the "not_of"
205 lastPos
= str
.find_first_not_of(delimiters
, pos
);
206 // Find next "non-delimiter"
207 pos
= str
.find_first_of(delimiters
, lastPos
);
212 // Resolve an executable name to a canonical full path name, with the
213 // same policy as execvp(). A program name not containing a slash
214 // will be searched along the $PATH.
216 string
find_executable(const string
& name
)
220 if (name
.size() == 0)
225 if (name
.find('/') != string::npos
) // slash in the path already?
229 else // Nope, search $PATH.
231 char *path
= getenv("PATH");
236 tokenize(string(path
), dirs
, string(":"));
238 // Search the path looking for the first executable of the right name.
239 for (vector
<string
>::iterator i
= dirs
.begin(); i
!= dirs
.end(); i
++)
241 string fname
= *i
+ "/" + name
;
242 const char *f
= fname
.c_str();
244 // Look for a normal executable file.
245 if (access(f
, X_OK
) == 0
247 && S_ISREG(st
.st_mode
))
257 // Could not find the program on the $PATH. We'll just fall back to
258 // the unqualified name, which our caller will probably fail with.
262 // Canonicalize the path name.
263 char *cf
= canonicalize_file_name (retpath
.c_str());
266 retpath
= string(cf
);
275 const string
cmdstr_quoted(const string
& cmd
)
277 // original cmd : substr1
278 // or : substr1'substr2
279 // or : substr1'substr2'substr3......
281 // every substr(even it's empty) is quoted by ''
282 // every single-quote(') is quoted by ""
283 // examples: substr1 --> 'substr1'
284 // substr1'substr2 --> 'substr1'"'"'substr2'
288 string
replace("'\"'\"'");
289 string::size_type pos
= 0;
292 for (string::size_type quote_pos
= cmd
.find(quote
, pos
);
293 quote_pos
!= string::npos
;
294 quote_pos
= cmd
.find(quote
, pos
)) {
295 quoted_cmd
+= cmd
.substr(pos
, quote_pos
- pos
);
296 quoted_cmd
+= replace
;
299 quoted_cmd
+= cmd
.substr(pos
, cmd
.length() - pos
);
307 git_revision(const string
& path
)
309 string revision
= "(not-a-git-repository)";
310 string git_dir
= path
+ "/.git/";
313 if (stat(git_dir
.c_str(), &st
) == 0)
315 string command
= "git --git-dir=\"" + git_dir
316 + "\" rev-parse HEAD 2>/dev/null";
319 FILE *fp
= popen(command
.c_str(), "r");
322 char *bufp
= fgets(buf
, sizeof(buf
), fp
);
324 if (bufp
!= NULL
&& rc
== 0)
333 static pid_t spawned_pid
= 0;
335 // Runs a command with a saved PID, so we can kill it from the signal handler
337 stap_system(int verbose
, const std::string
& command
)
339 const char *cmd
= command
.c_str();
340 STAP_PROBE1(stap
, stap_system__start
, cmd
);
341 char const * const argv
[] = { "sh", "-c", cmd
, NULL
};
347 clog
<< "Running " << command
<< endl
;
349 ret
= posix_spawn(&spawned_pid
, "/bin/sh", NULL
, NULL
, const_cast<char * const *>(argv
), environ
);
350 STAP_PROBE2(stap
, stap_system__spawn
, ret
, spawned_pid
);
353 ret
= waitpid(spawned_pid
, &status
, 0);
354 if (ret
== spawned_pid
)
356 ret
= WIFEXITED(status
) ? WEXITSTATUS(status
) : 128 + WTERMSIG(status
);
358 clog
<< "Spawn waitpid result (0x" << ios::hex
<< status
<< ios::dec
<< "): " << ret
<< endl
;
363 clog
<< "Spawn waitpid error (" << ret
<< "): " << strerror(errno
) << endl
;
370 clog
<< "Spawn error (" << ret
<< "): " << strerror(ret
) << endl
;
373 STAP_PROBE1(stap
, stap_system__complete
, ret
);
378 // Send a signal to our spawned command
380 kill_stap_spawn(int sig
)
382 return spawned_pid
? kill(spawned_pid
, sig
) : 0;
385 /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
This page took 0.053278 seconds and 5 git commands to generate.