-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathsetfname.cpp
87 lines (69 loc) · 2.18 KB
/
setfname.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#include <cstdio>
#include <cstring>
#include <cctype>
#include <ctime> // borland needs this
#include <sys/stat.h>
#if defined(_MSC_VER)
# include <sys/utime.h>
#else
# include <utime.h>
#endif
#if defined(_WIN32)
# include <io.h>
# define F_OK 0
#else
# include <unistd.h>
#endif
#include "sedit.h"
#include "setfname.h"
/*
copyright (c) 2004-2006 squell <[email protected]>
use, modification, copying and distribution of this software is permitted
under the conditions described in the file 'COPYING'.
*/
using namespace std;
using tag::write::file;
// checks if a character is a member of the portable set
namespace {
// \/?*":|<> are special char (fat)
const char allowed[] = " !#$%&'()+,-.;=@[]^_`{}~";
bool portable_fn(char c)
{
return isalnum(c) || (c & 0x80) || strchr(allowed, c);
}
utimbuf* get_utime(const char* fname, utimbuf* buf)
{
struct stat file_info;
if( stat(fname, &file_info) == 0 ) {
buf->actime = file_info.st_atime;
buf->modtime = file_info.st_mtime;
return buf;
}
return 0;
}
}
bool file::vmodify(const char* fname, const function& edit) const
{
utimbuf buf, *stamp = get_utime(fname, &buf);
function::result edited = edit(m_template); // use pre-values
if(m_template.empty() || !edited.good()) {
bool ok = combined<interface>::vmodify(fname, edit);
if(m_preserve) utime(fname, stamp);
return ok;
}
string name = edited;
for(string::iterator p = name.begin(); p != name.end(); ++p) {
if(!portable_fn(*p)) *p = '_'; // replace ill. chars
}
if(const char* psep = strrchr(fname, '/')) {
name.insert(0, fname, psep-fname+1); // copy path prefix
}
const char* newfn = name.c_str();
if(name != fname && access(newfn, F_OK) == 0) // check if already exists
throw failure(newfn, ": file already exists");
bool ok = combined<interface>::vmodify(fname, edit);
if(m_preserve) utime(fname, stamp);
if(ok && std::rename(fname, newfn) != 0)
throw failure("could not rename ", fname);
return ok;
}