Line 0
Link Here
|
|
|
1 |
--- ctm/ctm_pass3.c.ORI 2023-12-23 11:57:49.599008000 +0100 |
2 |
+++ ctm/ctm_pass3.c 2023-12-23 14:10:34.822327000 +0100 |
3 |
@@ -23,7 +23,7 @@ |
4 |
settime(const char *name, const struct timeval *times) |
5 |
{ |
6 |
if (SetTime) |
7 |
- if (utimes(name,times)) { |
8 |
+ if (lutimes(name,times)) { |
9 |
warn("utimes(): %s", name); |
10 |
return -1; |
11 |
} |
12 |
@@ -33,7 +33,7 @@ |
13 |
int |
14 |
setmodefromchar(const char *name, const u_char *mode) |
15 |
{ |
16 |
- return chmod(name, strtol(mode, NULL, 8)); |
17 |
+ return lchmod(name, strtol(mode, NULL, 8)); |
18 |
} |
19 |
|
20 |
int |
21 |
@@ -45,6 +45,7 @@ |
22 |
intmax_t cnt,rel; |
23 |
char *svn_command = NULL; |
24 |
u_char *md5=0,*md5before=0,*trash=0,*name=0,*uid=0,*gid=0,*mode=0; |
25 |
+ u_char* targetname = NULL; |
26 |
struct CTM_Syntax *sp; |
27 |
FILE *ed=0, *fd_to; |
28 |
struct stat st; |
29 |
@@ -124,6 +125,7 @@ |
30 |
Delete(md5before); |
31 |
Delete(trash); |
32 |
Delete(name); |
33 |
+ Delete( targetname ); |
34 |
cnt = -1; |
35 |
|
36 |
GETFIELD(p,' '); |
37 |
@@ -198,6 +200,10 @@ |
38 |
} |
39 |
} |
40 |
break; |
41 |
+ case CTM_F_Targetname: |
42 |
+ //GETNAMECOPY( targetname, sep, j, Verbose ); |
43 |
+ GETFIELDCOPY( targetname, sep ); |
44 |
+ break; |
45 |
default: WRONG |
46 |
} |
47 |
} |
48 |
@@ -337,6 +343,74 @@ |
49 |
} |
50 |
if(!strcmp(sp->Key,"TR") || !strcmp(sp->Key,"SV")) |
51 |
continue; |
52 |
+ |
53 |
+ |
54 |
+ if( strcmp( sp->Key, "LR" ) == 0 || strcmp( sp->Key, "LC" ) == 0 ) { |
55 |
+ |
56 |
+ /* Ignore KeepIt if this is a LINKCHANGE command. The whole |
57 |
+ * KeepIt option ist shitty and should go away... |
58 |
+ */ |
59 |
+ if( KeepIt && strcmp( sp->Key, "LC" ) != 0 ) { |
60 |
+ if( Verbose > 1 ) |
61 |
+ printf( " <%s> not removed\n", name ); |
62 |
+ |
63 |
+ } else { |
64 |
+ if( unlink( name )) { |
65 |
+ fprintf( stderr, "unlink %s: %s\n", name, strerror( errno )); |
66 |
+ WRONG |
67 |
+ } |
68 |
+ } |
69 |
+ |
70 |
+ if( strcmp( sp->Key, "LR" ) == 0 ) // done if it's no LC |
71 |
+ continue; |
72 |
+ } |
73 |
+ |
74 |
+ |
75 |
+ if( strcmp( sp->Key, "LM" ) == 0 || strcmp( sp->Key, "LC" ) == 0 ) { |
76 |
+ |
77 |
+ char* bn; // basename |
78 |
+ char cwd[ PATH_MAX ]; |
79 |
+ |
80 |
+ if( getcwd( cwd, sizeof cwd ) == NULL ) { |
81 |
+ fprintf( stderr, "getcwd: %s\n", strerror( errno ) ); |
82 |
+ WRONG |
83 |
+ } |
84 |
+ |
85 |
+ if( (bn = strrchr( name, '/' )) == NULL ) // no path component |
86 |
+ bn = name; // basename |
87 |
+ |
88 |
+ else { // have path component |
89 |
+ *bn++ = '\0'; // terminate path component |
90 |
+ if( chdir( name )) { |
91 |
+ fprintf( stderr, "chdir %s: %s\n", name, strerror( errno )); |
92 |
+ WRONG |
93 |
+ } |
94 |
+ } |
95 |
+ |
96 |
+ if( symlink( targetname, bn )) { |
97 |
+ fprintf( stderr, "symlink %s to %s: %s\n", targetname, bn, strerror( errno )); |
98 |
+ WRONG |
99 |
+ } |
100 |
+ |
101 |
+ if( chdir( cwd )) { // go back |
102 |
+ fprintf( stderr, "chdir %s: %s\n", cwd, strerror( errno )); |
103 |
+ WRONG |
104 |
+ } |
105 |
+ |
106 |
+ *--bn = '/'; // restore name with path |
107 |
+ if( lstat( name, &st )) { |
108 |
+ fprintf( stderr, "stat %s: %s\n", name, strerror( errno )); |
109 |
+ WRONG |
110 |
+ } else if( (st.st_mode & S_IFMT) != S_IFLNK ) { |
111 |
+ fprintf( stderr, "%s: no link\n", name ); |
112 |
+ WRONG |
113 |
+ } |
114 |
+ |
115 |
+ if( settime( name, times )) WRONG |
116 |
+ if( setmodefromchar( name, mode )) WRONG |
117 |
+ continue; |
118 |
+ } |
119 |
+ |
120 |
WRONG |
121 |
} |
122 |
|
123 |
--- ctm/ctm.h.ORI 2023-12-23 11:57:49.572644000 +0100 |
124 |
+++ ctm/ctm.h 2023-12-23 12:47:56.115821000 +0100 |
125 |
@@ -25,6 +25,7 @@ |
126 |
#include <sys/file.h> |
127 |
#include <sys/time.h> |
128 |
#include <stdint.h> |
129 |
+#include <limits.h> |
130 |
|
131 |
#define VERSION "2.0" |
132 |
|
133 |
@@ -43,6 +45,7 @@ |
134 |
#define CTM_F_Bytes 0x07 |
135 |
#define CTM_F_Release 0x08 |
136 |
#define CTM_F_Forward 0x09 |
137 |
+#define CTM_F_Targetname 0x0a |
138 |
|
139 |
/* The qualifiers... */ |
140 |
#define CTM_Q_MASK 0xff00 |
141 |
@@ -51,6 +54,7 @@ |
142 |
#define CTM_Q_Name_New 0x0400 |
143 |
#define CTM_Q_Name_Subst 0x0800 |
144 |
#define CTM_Q_Name_Svnbase 0x1000 |
145 |
+#define CTM_Q_Name_Link 0x2000 |
146 |
#define CTM_Q_MD5_After 0x0100 |
147 |
#define CTM_Q_MD5_Before 0x0200 |
148 |
#define CTM_Q_MD5_Chunk 0x0400 |
149 |
--- ctm/ctm_syntax.c.ORI 2023-12-23 11:57:49.601331000 +0100 |
150 |
+++ ctm/ctm_syntax.c 2023-12-23 13:52:50.585780000 +0100 |
151 |
@@ -68,6 +68,16 @@ |
152 |
static int ctmSV[] = /* Forward to svnadmin load */ |
153 |
{ Name|Dir|Svnbase, Release, Count, Forward|SVN, 0 }; |
154 |
|
155 |
+static int ctmLM[] = /* Link Make */ |
156 |
+ { Name|CTM_Q_Name_Link|New, Uid, Gid, Mode, CTM_F_Targetname, 0 }; |
157 |
+ |
158 |
+static int ctmLR[] = /* Link Remove */ |
159 |
+ { Name|CTM_Q_Name_Link, 0 }; |
160 |
+ |
161 |
+static int ctmLC[] = /* Link Change */ |
162 |
+ { Name|CTM_Q_Name_Link, Uid, Gid, Mode, CTM_F_Targetname, 0 }; |
163 |
+ |
164 |
+ |
165 |
struct CTM_Syntax Syntax[] = { |
166 |
{ "FM", ctmFM }, |
167 |
{ "FS", ctmFS }, |
168 |
@@ -79,4 +89,7 @@ |
169 |
{ "DR", ctmDR }, |
170 |
{ "TR", ctmTR }, |
171 |
{ "SV", ctmSV }, |
172 |
+ { "LM", ctmLM }, |
173 |
+ { "LR", ctmLR }, |
174 |
+ { "LC", ctmLC }, |
175 |
{ 0, 0} }; |
176 |
--- ctm/ctm_pass2.c.ORI 2023-12-24 08:26:35.301188000 +0100 |
177 |
+++ ctm/ctm_pass2.c 2023-12-24 08:28:13.320082000 +0100 |
178 |
@@ -105,14 +105,14 @@ |
179 |
/* XXX Check DR DM rec's for parent-dir */ |
180 |
if(j & CTM_Q_Name_New) { |
181 |
/* XXX Check DR FR rec's for item */ |
182 |
- if(-1 != stat(name,&st)) { |
183 |
+ if(-1 != lstat(name,&st)) { |
184 |
fprintf(stderr," %s: %s exists.\n", |
185 |
sp->Key,name); |
186 |
ret |= Exit_Forcible; |
187 |
} |
188 |
break; |
189 |
} |
190 |
- if(-1 == stat(name,&st)) { |
191 |
+ if(-1 == lstat(name,&st)) { |
192 |
fprintf(stderr," %s: %s doesn't exist.\n", |
193 |
sp->Key,name); |
194 |
if (sp->Key[1] == 'R') |
195 |
@@ -161,10 +161,18 @@ |
196 |
} |
197 |
break; |
198 |
} |
199 |
+ if( j & CTM_Q_Name_Link ) { |
200 |
+ if( ( st.st_mode & S_IFMT ) != S_IFLNK ) { |
201 |
+ fprintf( stderr, " %s: %s exist, but isn't link.\n", sp->Key,name ); |
202 |
+ ret |= Exit_NotOK; |
203 |
+ } |
204 |
+ break; |
205 |
+ } |
206 |
break; |
207 |
case CTM_F_Uid: |
208 |
case CTM_F_Gid: |
209 |
case CTM_F_Mode: |
210 |
+ case CTM_F_Targetname: |
211 |
GETFIELD(p,sep); |
212 |
break; |
213 |
case CTM_F_MD5: |
214 |
--- ctm/ctm_pass1.c.ORI 2023-12-23 11:57:49.594016000 +0100 |
215 |
+++ ctm/ctm_pass1.c 2023-12-23 14:10:21.518737000 +0100 |
216 |
@@ -27,6 +27,7 @@ |
217 |
int i,j,sep; |
218 |
intmax_t cnt, rel; |
219 |
u_char *md5=0,*name=0,*trash=0; |
220 |
+ u_char* targetname = NULL; |
221 |
struct CTM_Syntax *sp; |
222 |
int slashwarn=0, match=0, total_matches=0; |
223 |
unsigned current; |
224 |
@@ -71,6 +72,7 @@ |
225 |
Delete(md5); |
226 |
Delete(name); |
227 |
Delete(trash); |
228 |
+ Delete( targetname ); |
229 |
cnt = -1; |
230 |
/* if a filter list is defined we assume that all pathnames require |
231 |
an action opposite to that requested by the first filter in the |
232 |
@@ -224,6 +226,9 @@ |
233 |
return Exit_Garbage; |
234 |
} |
235 |
GETFORWARD(cnt,NULL); |
236 |
+ break; |
237 |
+ case CTM_F_Targetname: |
238 |
+ GETFIELDCOPY( targetname, sep ); |
239 |
break; |
240 |
default: |
241 |
fprintf(stderr,"List = 0x%x\n",j); |
242 |
--- ctm/ctm_passb.c.ORI 2023-04-25 21:04:20.000000000 +0200 |
243 |
+++ ctm/ctm_passb.c 2023-12-23 14:24:56.893291000 +0100 |
244 |
@@ -26,6 +26,7 @@ |
245 |
MD5_CTX ctx; |
246 |
int i,j,sep,cnt; |
247 |
u_char *md5=0,*md5before=0,*trash=0,*name=0,*uid=0,*gid=0,*mode=0; |
248 |
+ u_char* targetname = NULL; |
249 |
struct CTM_Syntax *sp; |
250 |
FILE *b = 0; /* backup command */ |
251 |
u_char buf[BUFSIZ]; |
252 |
@@ -57,6 +58,7 @@ |
253 |
Delete(md5before); |
254 |
Delete(trash); |
255 |
Delete(name); |
256 |
+ Delete( targetname ); |
257 |
cnt = -1; |
258 |
|
259 |
GETFIELD(p,' '); |
260 |
@@ -90,6 +92,7 @@ |
261 |
break; |
262 |
case CTM_F_Count: GETBYTECNT(cnt,sep); break; |
263 |
case CTM_F_Bytes: GETDATA(trash,cnt); break; |
264 |
+ case CTM_F_Targetname: GETFIELDCOPY( targetname, sep ); break; |
265 |
default: WRONG |
266 |
} |
267 |
} |
268 |
@@ -98,7 +101,7 @@ |
269 |
if(name[j] == '/') name[j] = '\0'; |
270 |
|
271 |
if (KeepIt && |
272 |
- (!strcmp(sp->Key,"DR") || !strcmp(sp->Key,"FR"))) |
273 |
+ (!strcmp(sp->Key,"DR") || !strcmp(sp->Key,"LR") || !strcmp(sp->Key,"FR"))) |
274 |
continue; |
275 |
|
276 |
/* match the name against the elements of the filter list. The |
277 |
@@ -113,7 +116,9 @@ |
278 |
if (CTM_FILTER_DISABLE == match) |
279 |
continue; |
280 |
|
281 |
+ // Do we have to backup symlinks??? |
282 |
if (!strcmp(sp->Key,"FS") || !strcmp(sp->Key,"FN") || |
283 |
+ !strcmp(sp->Key,"LR") || !strcmp(sp->Key,"LC") || |
284 |
!strcmp(sp->Key,"AS") || !strcmp(sp->Key,"DR") || |
285 |
!strcmp(sp->Key,"FR")) { |
286 |
/* send name to the archiver for a backup */ |
287 |
@@ -135,6 +140,7 @@ |
288 |
Delete(md5before); |
289 |
Delete(trash); |
290 |
Delete(name); |
291 |
+ Delete( targetname ); |
292 |
|
293 |
q = MD5End (&ctx,md5_1); |
294 |
GETFIELD(p,'\n'); /* <MD5> */ |