|
1 diff --git a/include/dirtree.h b/include/dirtree.h |
|
2 index 0f41986..fe7b14b 100644 |
|
3 --- a/include/dirtree.h |
|
4 +++ b/include/dirtree.h |
|
5 @@ -126,6 +126,10 @@ typedef struct cmd_struc { |
|
6 pr_table_t *notes; /* Private data for passing/retaining between handlers */ |
|
7 |
|
8 int cmd_id; /* Index into commands list, for faster comparisons */ |
|
9 + |
|
10 + int error_code; /* Stores errno of failed file transfer |
|
11 + * commands. Required for Solaris auditing. |
|
12 + */ |
|
13 } cmd_rec; |
|
14 |
|
15 struct config_struc { |
|
16 diff --git a/modules/mod_core.c b/modules/mod_core.c |
|
17 index e33ee11..f680748 100644 |
|
18 --- a/modules/mod_core.c |
|
19 +++ b/modules/mod_core.c |
|
20 @@ -4775,6 +4775,7 @@ MODRET core_rmd(cmd_rec *cmd) { |
|
21 dir = dir_canonical_path(cmd->tmp_pool, dir); |
|
22 if (dir == NULL) { |
|
23 int xerrno = EINVAL; |
|
24 + cmd->error_code = EINVAL; |
|
25 |
|
26 pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno)); |
|
27 |
|
28 @@ -4784,6 +4785,7 @@ MODRET core_rmd(cmd_rec *cmd) { |
|
29 |
|
30 if (!dir_check_canon(cmd->tmp_pool, cmd, cmd->group, dir, NULL)) { |
|
31 int xerrno = EACCES; |
|
32 + cmd->error_code = EACCES; |
|
33 |
|
34 pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno)); |
|
35 |
|
36 @@ -4793,6 +4795,7 @@ MODRET core_rmd(cmd_rec *cmd) { |
|
37 |
|
38 if (pr_fsio_rmdir(dir) < 0) { |
|
39 int xerrno = errno; |
|
40 + cmd->error_code = errno; |
|
41 |
|
42 (void) pr_trace_msg("fileperms", 1, "%s, user '%s' (UID %lu, GID %lu): " |
|
43 "error removing directory '%s': %s", cmd->argv[0], session.user, |
|
44 @@ -4849,6 +4852,7 @@ MODRET core_mkd(cmd_rec *cmd) { |
|
45 dir = dir_canonical_path(cmd->tmp_pool, dir); |
|
46 if (dir == NULL) { |
|
47 int xerrno = EINVAL; |
|
48 + cmd->error_code = EINVAL; |
|
49 |
|
50 pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno)); |
|
51 |
|
52 @@ -4858,6 +4862,7 @@ MODRET core_mkd(cmd_rec *cmd) { |
|
53 |
|
54 if (!dir_check_canon(cmd->tmp_pool, cmd, cmd->group, dir, NULL)) { |
|
55 int xerrno = EACCES; |
|
56 + cmd->error_code = EACCES; |
|
57 |
|
58 pr_log_debug(DEBUG8, "%s command denied by <Limit> config", cmd->argv[0]); |
|
59 pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno)); |
|
60 @@ -4869,6 +4874,7 @@ MODRET core_mkd(cmd_rec *cmd) { |
|
61 if (pr_fsio_smkdir(cmd->tmp_pool, dir, 0777, session.fsuid, |
|
62 session.fsgid) < 0) { |
|
63 int xerrno = errno; |
|
64 + cmd->error_code = errno; |
|
65 |
|
66 (void) pr_trace_msg("fileperms", 1, "%s, user '%s' (UID %lu, GID %lu): " |
|
67 "error making directory '%s': %s", cmd->argv[0], session.user, |
|
68 @@ -4915,6 +4921,7 @@ MODRET core_mdtm(cmd_rec *cmd) { |
|
69 !dir_check(cmd->tmp_pool, cmd, cmd->group, path, NULL) || |
|
70 pr_fsio_stat(path, &st) == -1) { |
|
71 int xerrno = errno; |
|
72 + cmd->error_code = errno; |
|
73 |
|
74 pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno)); |
|
75 |
|
76 @@ -5026,6 +5033,7 @@ MODRET core_dele(cmd_rec *cmd) { |
|
77 path = dir_canonical_path(cmd->tmp_pool, path); |
|
78 if (path == NULL) { |
|
79 int xerrno = ENOENT; |
|
80 + cmd->error_code = ENOENT; |
|
81 |
|
82 pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno)); |
|
83 |
|
84 @@ -5035,6 +5043,7 @@ MODRET core_dele(cmd_rec *cmd) { |
|
85 |
|
86 if (!dir_check(cmd->tmp_pool, cmd, cmd->group, path, NULL)) { |
|
87 int xerrno = errno; |
|
88 + cmd->error_code = errno; |
|
89 |
|
90 pr_log_debug(DEBUG7, "deleting '%s' denied by <Limit> configuration", path); |
|
91 pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno)); |
|
92 @@ -5051,6 +5060,7 @@ MODRET core_dele(cmd_rec *cmd) { |
|
93 pr_fs_clear_cache(); |
|
94 if (pr_fsio_lstat(path, &st) < 0) { |
|
95 int xerrno = errno; |
|
96 + cmd->error_code = errno; |
|
97 |
|
98 pr_log_debug(DEBUG3, "unable to lstat '%s': %s", path, strerror(xerrno)); |
|
99 pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno)); |
|
100 @@ -5065,6 +5075,7 @@ MODRET core_dele(cmd_rec *cmd) { |
|
101 */ |
|
102 if (S_ISDIR(st.st_mode)) { |
|
103 int xerrno = EISDIR; |
|
104 + cmd->error_code = EISDIR; |
|
105 |
|
106 (void) pr_trace_msg("fileperms", 1, "%s, user '%s' (UID %lu, GID %lu): " |
|
107 "error deleting '%s': %s", cmd->argv[0], session.user, |
|
108 @@ -5081,6 +5092,7 @@ MODRET core_dele(cmd_rec *cmd) { |
|
109 |
|
110 if (pr_fsio_unlink(path) < 0) { |
|
111 int xerrno = errno; |
|
112 + cmd->error_code = errno; |
|
113 |
|
114 (void) pr_trace_msg("fileperms", 1, "%s, user '%s' (UID %lu, GID %lu): " |
|
115 "error deleting '%s': %s", cmd->argv[0], session.user, |
|
116 @@ -5165,6 +5177,7 @@ MODRET core_rnto(cmd_rec *cmd) { |
|
117 pr_log_debug(DEBUG6, "AllowOverwrite denied permission for %s", path); |
|
118 pr_response_add_err(R_550, _("%s: Rename permission denied"), cmd->arg); |
|
119 errno = EACCES; |
|
120 + cmd->error_code = EACCES; |
|
121 return PR_ERROR(cmd); |
|
122 } |
|
123 |
|
124 @@ -5172,6 +5185,7 @@ MODRET core_rnto(cmd_rec *cmd) { |
|
125 !dir_check_canon(cmd->tmp_pool, cmd, cmd->group, path, NULL) || |
|
126 pr_fsio_rename(session.xfer.path, path) == -1) { |
|
127 int xerrno = errno; |
|
128 + cmd->error_code = errno; |
|
129 |
|
130 if (xerrno != EXDEV) { |
|
131 (void) pr_trace_msg("fileperms", 1, "%s, user '%s' (UID %lu, GID %lu): " |
|
132 @@ -5223,6 +5237,7 @@ MODRET core_rnto(cmd_rec *cmd) { |
|
133 */ |
|
134 if (pr_fs_copy_file(session.xfer.path, path) < 0) { |
|
135 xerrno = errno; |
|
136 + cmd->error_code = errno; |
|
137 |
|
138 (void) pr_trace_msg("fileperms", 1, "%s, user '%s' (UID %lu, GID %lu): " |
|
139 "error copying '%s' to '%s': %s", cmd->argv[0], session.user, |
|
140 @@ -5238,6 +5253,8 @@ MODRET core_rnto(cmd_rec *cmd) { |
|
141 |
|
142 /* Once copied, unlink the original file. */ |
|
143 if (pr_fsio_unlink(session.xfer.path) < 0) { |
|
144 + cmd->error_code = errno; |
|
145 + |
|
146 pr_log_debug(DEBUG0, "error unlinking '%s': %s", session.xfer.path, |
|
147 strerror(errno)); |
|
148 } |
|
149 @@ -5295,6 +5312,7 @@ MODRET core_rnfr(cmd_rec *cmd) { |
|
150 !dir_check(cmd->tmp_pool, cmd, cmd->group, path, NULL) || |
|
151 !exists(path)) { |
|
152 int xerrno = errno; |
|
153 + cmd->error_code = errno; |
|
154 |
|
155 pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno)); |
|
156 |
|
157 diff --git a/modules/mod_xfer.c b/modules/mod_xfer.c |
|
158 index bcfb487..41c597e 100644 |
|
159 --- a/modules/mod_xfer.c |
|
160 +++ b/modules/mod_xfer.c |
|
161 @@ -1190,6 +1190,7 @@ MODRET xfer_pre_stor(cmd_rec *cmd) { |
|
162 if (cmd->argc < 2) { |
|
163 pr_response_add_err(R_500, _("'%s' not understood"), |
|
164 pr_cmd_get_displayable_str(cmd, NULL)); |
|
165 + cmd->error_code = EINVAL; |
|
166 errno = EINVAL; |
|
167 return PR_ERROR(cmd); |
|
168 } |
|
169 @@ -1200,6 +1201,7 @@ MODRET xfer_pre_stor(cmd_rec *cmd) { |
|
170 if (!path || |
|
171 !dir_check(cmd->tmp_pool, cmd, cmd->group, path, NULL)) { |
|
172 int xerrno = errno; |
|
173 + cmd->error_code = errno; |
|
174 |
|
175 pr_log_debug(DEBUG8, "%s %s denied by <Limit> configuration", cmd->argv[0], |
|
176 cmd->arg); |
|
177 @@ -1232,6 +1234,7 @@ MODRET xfer_pre_stor(cmd_rec *cmd) { |
|
178 if (xfer_check_limit(cmd) < 0) { |
|
179 pr_response_add_err(R_451, _("%s: Too many transfers"), cmd->arg); |
|
180 errno = EPERM; |
|
181 + cmd->error_code = EPERM; |
|
182 return PR_ERROR(cmd); |
|
183 } |
|
184 |
|
185 @@ -1244,6 +1247,7 @@ MODRET xfer_pre_stor(cmd_rec *cmd) { |
|
186 pr_log_debug(DEBUG6, "AllowOverwrite denied permission for %s", cmd->arg); |
|
187 pr_response_add_err(R_550, _("%s: Overwrite permission denied"), cmd->arg); |
|
188 errno = EACCES; |
|
189 + cmd->error_code = EACCES; |
|
190 return PR_ERROR(cmd); |
|
191 } |
|
192 |
|
193 @@ -1267,6 +1271,7 @@ MODRET xfer_pre_stor(cmd_rec *cmd) { |
|
194 |
|
195 /* Deliberately use EISDIR for anything non-file (e.g. directories). */ |
|
196 errno = EISDIR; |
|
197 + cmd->error_code = EISDIR; |
|
198 return PR_ERROR(cmd); |
|
199 } |
|
200 } |
|
201 @@ -1285,6 +1290,7 @@ MODRET xfer_pre_stor(cmd_rec *cmd) { |
|
202 session.restart_pos = 0L; |
|
203 session.xfer.xfer_type = STOR_DEFAULT; |
|
204 errno = EPERM; |
|
205 + cmd->error_code = EPERM; |
|
206 return PR_ERROR(cmd); |
|
207 } |
|
208 |
|
209 @@ -1306,6 +1312,7 @@ MODRET xfer_pre_stor(cmd_rec *cmd) { |
|
210 /* Otherwise everthing is good */ |
|
211 if (pr_table_add(cmd->notes, "mod_xfer.store-path", |
|
212 pstrdup(cmd->pool, path), 0) < 0) { |
|
213 + cmd->error_code = errno; |
|
214 if (errno != EEXIST) { |
|
215 pr_log_pri(PR_LOG_NOTICE, |
|
216 "notice: error adding 'mod_xfer.store-path': %s", strerror(errno)); |
|
217 @@ -1326,6 +1333,7 @@ MODRET xfer_pre_stor(cmd_rec *cmd) { |
|
218 pr_response_add_err(R_501, |
|
219 _("REST not compatible with server configuration")); |
|
220 errno = EINVAL; |
|
221 + cmd->error_code = EINVAL; |
|
222 return PR_ERROR(cmd); |
|
223 } |
|
224 |
|
225 @@ -1335,6 +1343,7 @@ MODRET xfer_pre_stor(cmd_rec *cmd) { |
|
226 pr_response_add_err(R_550, |
|
227 _("APPE not compatible with server configuration")); |
|
228 errno = EINVAL; |
|
229 + cmd->error_code = EINVAL; |
|
230 return PR_ERROR(cmd); |
|
231 } |
|
232 |
|
233 @@ -1400,6 +1409,7 @@ MODRET xfer_pre_stou(cmd_rec *cmd) { |
|
234 tmpfd = mkstemp(filename); |
|
235 if (tmpfd < 0) { |
|
236 int xerrno = errno; |
|
237 + cmd->error_code = errno; |
|
238 |
|
239 pr_log_pri(PR_LOG_WARNING, "error: unable to use mkstemp(): %s", |
|
240 strerror(xerrno)); |
|
241 @@ -1428,6 +1438,7 @@ MODRET xfer_pre_stou(cmd_rec *cmd) { |
|
242 if (!filename || |
|
243 !dir_check(cmd->tmp_pool, cmd, cmd->group, filename, NULL)) { |
|
244 int xerrno = errno; |
|
245 + cmd->error_code = errno; |
|
246 |
|
247 /* Do not forget to delete the file created by mkstemp(3) if there is |
|
248 * an error. |
|
249 @@ -1461,12 +1472,14 @@ MODRET xfer_pre_stou(cmd_rec *cmd) { |
|
250 |
|
251 /* Deliberately use EISDIR for anything non-file (e.g. directories). */ |
|
252 errno = EISDIR; |
|
253 + cmd->error_code = errno; |
|
254 return PR_ERROR(cmd); |
|
255 } |
|
256 |
|
257 /* Otherwise everthing is good */ |
|
258 if (pr_table_add(cmd->notes, "mod_xfer.store-path", |
|
259 pstrdup(cmd->pool, filename), 0) < 0) { |
|
260 + cmd->error_code = errno; |
|
261 if (errno != EEXIST) { |
|
262 pr_log_pri(PR_LOG_NOTICE, |
|
263 "notice: error adding 'mod_xfer.store-path': %s", strerror(errno)); |
|
264 @@ -1492,6 +1505,7 @@ MODRET xfer_post_stou(cmd_rec *cmd) { |
|
265 mode_t mode = 0666; |
|
266 |
|
267 if (pr_fsio_chmod(cmd->arg, mode) < 0) { |
|
268 + cmd->error_code = errno; |
|
269 |
|
270 /* Not much to do but log the error. */ |
|
271 pr_log_pri(PR_LOG_NOTICE, "error: unable to chmod '%s' to %04o: %s", |
|
272 @@ -1510,6 +1524,7 @@ MODRET xfer_pre_appe(cmd_rec *cmd) { |
|
273 if (xfer_check_limit(cmd) < 0) { |
|
274 pr_response_add_err(R_451, _("%s: Too many transfers"), cmd->arg); |
|
275 errno = EPERM; |
|
276 + cmd->error_code = EPERM; |
|
277 return PR_ERROR(cmd); |
|
278 } |
|
279 |
|
280 @@ -1580,6 +1595,7 @@ MODRET xfer_stor(cmd_rec *cmd) { |
|
281 |
|
282 if (stor_fh) { |
|
283 if (pr_fsio_lseek(stor_fh, 0, SEEK_END) == (off_t) -1) { |
|
284 + cmd->error_code = errno; |
|
285 pr_log_debug(DEBUG4, "unable to seek to end of '%s' for appending: %s", |
|
286 cmd->arg, strerror(errno)); |
|
287 (void) pr_fsio_close(stor_fh); |
|
288 @@ -1588,6 +1604,7 @@ MODRET xfer_stor(cmd_rec *cmd) { |
|
289 |
|
290 } else { |
|
291 ferrno = errno; |
|
292 + cmd->error_code = errno; |
|
293 |
|
294 (void) pr_trace_msg("fileperms", 1, "%s, user '%s' (UID %lu, GID %lu): " |
|
295 "error opening '%s': %s", cmd->argv[0], session.user, |
|
296 @@ -1601,6 +1618,7 @@ MODRET xfer_stor(cmd_rec *cmd) { |
|
297 O_WRONLY|(session.restart_pos ? 0 : O_TRUNC|O_CREAT)); |
|
298 if (stor_fh == NULL) { |
|
299 ferrno = errno; |
|
300 + cmd->error_code = errno; |
|
301 |
|
302 (void) pr_trace_msg("fileperms", 1, "%s, user '%s' (UID %lu, GID %lu): " |
|
303 "error opening '%s': %s", cmd->argv[0], session.user, |
|
304 @@ -1614,11 +1632,13 @@ MODRET xfer_stor(cmd_rec *cmd) { |
|
305 int xerrno = 0; |
|
306 |
|
307 if (pr_fsio_lseek(stor_fh, session.restart_pos, SEEK_SET) == -1) { |
|
308 + cmd->error_code = errno; |
|
309 pr_log_debug(DEBUG4, "unable to seek to position %" PR_LU " of '%s': %s", |
|
310 (pr_off_t) session.restart_pos, cmd->arg, strerror(errno)); |
|
311 xerrno = errno; |
|
312 |
|
313 } else if (pr_fsio_stat(path, &st) == -1) { |
|
314 + cmd->error_code = errno; |
|
315 pr_log_debug(DEBUG4, "unable to stat '%s': %s", cmd->arg, |
|
316 strerror(errno)); |
|
317 xerrno = errno; |
|
318 @@ -1755,6 +1775,7 @@ MODRET xfer_stor(cmd_rec *cmd) { |
|
319 pr_data_abort(EPERM, FALSE); |
|
320 errno = EPERM; |
|
321 #endif |
|
322 + cmd->error_code = errno; |
|
323 return PR_ERROR(cmd); |
|
324 } |
|
325 |
|
326 @@ -1766,6 +1787,7 @@ MODRET xfer_stor(cmd_rec *cmd) { |
|
327 res = pr_fsio_write(stor_fh, lbuf, len); |
|
328 if (res != len) { |
|
329 int xerrno = EIO; |
|
330 + cmd->error_code = errno; |
|
331 |
|
332 if (res < 0) |
|
333 xerrno = errno; |
|
334 @@ -1795,6 +1817,7 @@ MODRET xfer_stor(cmd_rec *cmd) { |
|
335 |
|
336 /* default abort errno, in case session.d et al has already gone away */ |
|
337 int xerrno = ECONNABORTED; |
|
338 + cmd->error_code = ECONNABORTED; |
|
339 |
|
340 stor_abort(); |
|
341 |
|
342 @@ -1814,6 +1837,7 @@ MODRET xfer_stor(cmd_rec *cmd) { |
|
343 |
|
344 if (stor_complete() < 0) { |
|
345 int xerrno = errno; |
|
346 + cmd->error_code = errno; |
|
347 |
|
348 _log_transfer('i', 'i'); |
|
349 |
|
350 @@ -1826,12 +1850,14 @@ MODRET xfer_stor(cmd_rec *cmd) { |
|
351 if (xerrno == EDQUOT) { |
|
352 pr_response_add_err(R_552, "%s: %s", cmd->arg, strerror(xerrno)); |
|
353 errno = xerrno; |
|
354 + cmd->error_code = errno; |
|
355 return PR_ERROR(cmd); |
|
356 } |
|
357 #elif defined(EFBIG) |
|
358 if (xerrno == EFBIG) { |
|
359 pr_response_add_err(R_552, "%s: %s", cmd->arg, strerror(xerrno)); |
|
360 errno = xerrno; |
|
361 + cmd->error_code = errno; |
|
362 return PR_ERROR(cmd); |
|
363 } |
|
364 #endif |
|
365 @@ -1845,6 +1871,7 @@ MODRET xfer_stor(cmd_rec *cmd) { |
|
366 session.xfer.path_hidden) { |
|
367 if (pr_fsio_rename(session.xfer.path_hidden, session.xfer.path) != 0) { |
|
368 int xerrno = errno; |
|
369 + cmd->error_code = errno; |
|
370 |
|
371 /* This should only fail on a race condition with a chmod/chown |
|
372 * or if STOR_APPEND is on and the permissions are squirrely. |
|
373 @@ -1947,6 +1974,7 @@ MODRET xfer_pre_retr(cmd_rec *cmd) { |
|
374 pr_response_add_err(R_500, _("'%s' not understood"), |
|
375 pr_cmd_get_displayable_str(cmd, NULL)); |
|
376 errno = EINVAL; |
|
377 + cmd->error_code = EINVAL; |
|
378 return PR_ERROR(cmd); |
|
379 } |
|
380 |
|
381 @@ -1956,6 +1984,7 @@ MODRET xfer_pre_retr(cmd_rec *cmd) { |
|
382 if (!dir || |
|
383 !dir_check(cmd->tmp_pool, cmd, cmd->group, dir, NULL)) { |
|
384 int xerrno = errno; |
|
385 + cmd->error_code; |
|
386 |
|
387 pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno)); |
|
388 |
|
389 @@ -1978,12 +2007,14 @@ MODRET xfer_pre_retr(cmd_rec *cmd) { |
|
390 if (xfer_check_limit(cmd) < 0) { |
|
391 pr_response_add_err(R_451, _("%s: Too many transfers"), cmd->arg); |
|
392 errno = EPERM; |
|
393 + cmd->error_code = EPERM; |
|
394 return PR_ERROR(cmd); |
|
395 } |
|
396 |
|
397 fmode = file_mode(dir); |
|
398 if (fmode == 0) { |
|
399 int xerrno = errno; |
|
400 + cmd->error_code = errno; |
|
401 |
|
402 pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(xerrno)); |
|
403 |
|
404 @@ -2000,6 +2031,7 @@ MODRET xfer_pre_retr(cmd_rec *cmd) { |
|
405 |
|
406 /* Deliberately use EISDIR for anything non-file (e.g. directories). */ |
|
407 errno = EISDIR; |
|
408 + cmd->error_code = EISDIR; |
|
409 return PR_ERROR(cmd); |
|
410 } |
|
411 |
|
412 @@ -2014,12 +2046,14 @@ MODRET xfer_pre_retr(cmd_rec *cmd) { |
|
413 cmd->arg); |
|
414 session.restart_pos = 0L; |
|
415 errno = EPERM; |
|
416 + cmd->error_code = EPERM; |
|
417 return PR_ERROR(cmd); |
|
418 } |
|
419 |
|
420 /* Otherwise everthing is good */ |
|
421 if (pr_table_add(cmd->notes, "mod_xfer.retr-path", |
|
422 pstrdup(cmd->pool, dir), 0) < 0) { |
|
423 + cmd->error_code = errno; |
|
424 if (errno != EEXIST) { |
|
425 pr_log_pri(PR_LOG_NOTICE, "notice: error adding 'mod_xfer.retr-path': %s", |
|
426 strerror(errno)); |
|
427 @@ -2046,6 +2080,7 @@ MODRET xfer_retr(cmd_rec *cmd) { |
|
428 retr_fh = pr_fsio_open(dir, O_RDONLY); |
|
429 if (retr_fh == NULL) { |
|
430 int xerrno = errno; |
|
431 + cmd->error_code = errno; |
|
432 |
|
433 (void) pr_trace_msg("fileperms", 1, "%s, user '%s' (UID %lu, GID %lu): " |
|
434 "error opening '%s': %s", cmd->argv[0], session.user, |
|
435 @@ -2059,6 +2094,7 @@ MODRET xfer_retr(cmd_rec *cmd) { |
|
436 if (pr_fsio_stat(dir, &st) < 0) { |
|
437 /* Error stat'ing the file. */ |
|
438 int xerrno = errno; |
|
439 + cmd->error_code = errno; |
|
440 pr_fsio_close(retr_fh); |
|
441 errno = xerrno; |
|
442 |
|
443 @@ -2083,6 +2119,7 @@ MODRET xfer_retr(cmd_rec *cmd) { |
|
444 if (pr_fsio_lseek(retr_fh, session.restart_pos, |
|
445 SEEK_SET) == (off_t) -1) { |
|
446 int xerrno = errno; |
|
447 + cmd->error_code = errno; |
|
448 pr_fsio_close(retr_fh); |
|
449 errno = xerrno; |
|
450 retr_fh = NULL; |
|
451 @@ -2143,6 +2180,7 @@ MODRET xfer_retr(cmd_rec *cmd) { |
|
452 retr_abort(); |
|
453 |
|
454 /* Set errno to EPERM ("Operation not permitted") */ |
|
455 + cmd->error_code = EPERM; |
|
456 pr_data_abort(EPERM, FALSE); |
|
457 return PR_ERROR(cmd); |
|
458 } |
|
459 @@ -2174,6 +2212,7 @@ MODRET xfer_retr(cmd_rec *cmd) { |
|
460 * is preserved; errno itself might be overwritten in retr_abort(). |
|
461 */ |
|
462 int xerrno = errno; |
|
463 + cmd->error_code = errno; |
|
464 |
|
465 retr_abort(); |
|
466 pr_data_abort(xerrno, FALSE); |