• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

proftpd / proftpd / 26182518137

20 May 2026 06:49PM UTC coverage: 93.024% (+0.4%) from 92.635%
26182518137

push

github

51329 of 55178 relevant lines covered (93.02%)

226.63 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

99.22
/src/error.c
1
/*
2
 * ProFTPD - FTP server daemon
3
 * Copyright (c) 2016-2026 The ProFTPD Project team
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation; either version 2 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, see <https://www.gnu.org/licenses/>.
17
 *
18
 * As a special exemption, The ProFTPD Project team and other respective
19
 * copyright holders give permission to link this program with OpenSSL, and
20
 * distribute the resulting executable, without including the source code for
21
 * OpenSSL in the source distribution.
22
 */
23

24
/* Error API */
25

26
#include "error.h"
27
#include "proftpd.h"
28
#include "str.h"
29
#include "support.h"
30
#include "session.h"
31
#include "trace.h"
32

33
#define PR_ERROR_BUFSZ                32
34

35
struct err_rec {
36
  pool *err_pool;
37

38
  /* Actual errno value, or -1 if unknown */
39
  int err_errno;
40

41
  /* String of errno name, e.g. "EINVAL" */
42
  const char *err_name;
43

44
  /* strerror(3) value, or NULL if unknown. */
45
  const char *err_desc;
46

47
  /* Module where the error occurred, if known. */
48
  module *err_module;
49

50
  /* File location of the error, e.g. __FILE__. */
51
  const char *err_file;
52

53
  /* Line number in file of the error, e.g. __LINE__. */
54
  unsigned int err_lineno;
55

56
  /* Process identity at time of error. */
57
  const char *err_user;
58
  uid_t err_uid;
59
  gid_t err_gid;
60

61
  /* Components for use in a more detailed error message:
62
   *
63
   * goal (the why)
64
   * operation (the what)
65
   */
66
  const char *err_goal;
67
  const char *err_oper;
68
  const char *err_args;
69
  const char *err_explained;
70
};
71

72
static unsigned int error_details = PR_ERROR_DETAILS_DEFAULT;
73
static unsigned int error_formats = PR_ERROR_FORMAT_DEFAULT;
74

75
struct err_explainer {
76
  struct err_explainer *next, *prev;
77

78
  module *m;
79
  const char *name;
80
  pr_error_explainer_t *explainer;
81
};
82

83
/* List of registered explainers. */
84
static struct err_explainer *error_explainers = NULL;
85

86
/* Currently selected explainers. */
87
static struct err_explainer *error_explainer = NULL;
88

89
struct errno_info {
90
  int error_number;
91
  const char *name;
92
};
93

94
static struct errno_info errno_names[] = {
95
#ifdef E2BIG
96
  { E2BIG, "E2BIG" },
97
#endif /* E2BIG */
98
#ifdef EACCES
99
  { EACCES, "EACCES" },
100
#endif /* EACCES */
101
#ifdef EADDRINUSE
102
  { EADDRINUSE, "EADDRINUSE" },
103
#endif /* EADDRINUSE */
104
#ifdef EADDRNOTAVAIL
105
  { EADDRNOTAVAIL, "EADDRNOTAVAIL" },
106
#endif /* EADDRNOTAVAIL */
107
#ifdef EAFNOSUPPORT
108
  { EAFNOSUPPORT, "EAFNOSUPPORT" },
109
#endif /* EAFNOSUPPORT */
110
#ifdef EAGAIN
111
  { EAGAIN, "EAGAIN" },
112
#endif /* EAGAIN */
113
#ifdef EALREADY
114
  { EALREADY, "EALREADY" },
115
#endif /* EALREADY */
116
#ifdef EBADF
117
  { EBADF, "EBADF" },
118
#endif /* EBADF */
119
#ifdef EBADFD
120
  { EBADFD, "EBADFD" },
121
#endif /* EBADFD */
122
#ifdef EBUSY
123
  { EBUSY, "EBUSY" },
124
#endif /* EBUSY */
125
#ifdef ECANCELED
126
  { ECANCELED, "ECANCELED" },
127
#endif /* ECANCELED */
128
#ifdef ECOMM
129
  { ECOMM, "ECOMM" },
130
#endif /* ECOMM */
131
#ifdef ECONNABORTED
132
  { ECONNABORTED, "ECONNABORTED" },
133
#endif /* ECONNABORTED */
134
#ifdef ECONNREFUSED
135
  { ECONNREFUSED, "ECONNREFUSED" },
136
#endif /* ECONNREFUSED */
137
#ifdef ECONNRESET
138
  { ECONNRESET, "ECONNRESET" },
139
#endif /* ECONNRESET */
140
#ifdef EDEADLK
141
  { EDEADLK, "EDEADLK" },
142
#endif /* EDEADLK */
143
#ifdef EDEADLOCK
144
  { EDEADLOCK, "EDEADLOCK" },
145
#endif /* EDEADLOCK */
146
#ifdef EDQUOT
147
  { EDQUOT, "EDQUOT" },
148
#endif /* EDQUOT */
149
#ifdef EEXIST
150
  { EEXIST, "EEXIST" },
151
#endif /* EEXIST */
152
#ifdef EFAULT
153
  { EFAULT, "EFAULT" },
154
#endif /* EFAULT */
155
#ifdef EFBIG
156
  { EFBIG, "EFBIG" },
157
#endif /* EFBIG */
158
#ifdef EHOSTDOWN
159
  { EHOSTDOWN, "EHOSTDOWN" },
160
#endif /* EHOSTDOWN */
161
#ifdef EHOSTUNREACH
162
  { EHOSTUNREACH, "EHOSTUNREACH" },
163
#endif /* EHOSTUNREACH */
164
#ifdef EILSEQ
165
  { EILSEQ, "EILSEQ" },
166
#endif /* EILSEQ */
167
#ifdef EINPROGRESS
168
  { EINPROGRESS, "EINPROGRESS" },
169
#endif /* EINPROGRESS */
170
#ifdef EINTR
171
  { EINTR, "EINTR" },
172
#endif /* EINTR */
173
#ifdef EINVAL
174
  { EINVAL, "EINVAL" },
175
#endif /* EINVAL */
176
#ifdef EISCONN
177
  { EISCONN, "EISCONN" },
178
#endif /* EISCONN */
179
#ifdef EISDIR
180
  { EISDIR, "EISDIR" },
181
#endif /* EISDIR */
182
#ifdef EIO
183
  { EIO, "EIO" },
184
#endif /* EIO */
185
#ifdef ELOOP
186
  { ELOOP, "ELOOP" },
187
#endif /* ELOOP */
188
#ifdef EMFILE
189
  { EMFILE, "EMFILE" },
190
#endif /* EMFILE */
191
#ifdef EMLINK
192
  { EMLINK, "EMLINK" },
193
#endif /* EMLINK */
194
#ifdef EMSGSIZE
195
  { EMSGSIZE, "EMSGSIZE" },
196
#endif /* EMSGSIZE */
197
#ifdef ENAMETOOLONG
198
  { ENAMETOOLONG, "ENAMETOOLONG" },
199
#endif /* ENAMETOOLONG */
200
#ifdef ENFILE
201
  { ENFILE, "ENFILE" },
202
#endif /* ENFILE */
203
#ifdef ENETDOWN
204
  { ENETDOWN, "ENETDOWN" },
205
#endif /* ENETDOWN */
206
#ifdef ENETRESET
207
  { ENETRESET, "ENETRESET" },
208
#endif /* ENETRESET */
209
#ifdef ENETUNREACH
210
  { ENETUNREACH, "ENETUNREACH" },
211
#endif /* ENETUNREACH */
212
#ifdef ENOBUFS
213
  { ENOBUFS, "ENOBUFS" },
214
#endif /* ENOBUFS */
215
#ifdef ENODATA
216
  { ENODATA, "ENODATA" },
217
#endif /* ENODATA */
218
#ifdef ENOATTR
219
  { ENOATTR, "ENOATTR" },
220
#endif /* ENOATTR */
221
#ifdef ENOLCK
222
  { ENOLCK, "ENOLCK" },
223
#endif /* ENOLCK */
224
#ifdef ENOLINK
225
  { ENOLINK, "ENOLINK" },
226
#endif /* ENOLINK */
227
#ifdef ENOMEDIUM
228
  { ENOMEDIUM, "ENOMEDIUM" },
229
#endif /* ENOMEDIUM */
230
#ifdef ENOMEM
231
  { ENOMEM, "ENOMEM" },
232
#endif /* ENOMEM */
233
#ifdef ENONET
234
  { ENONET, "ENONET" },
235
#endif /* ENONET */
236
#ifdef ENOTCONN
237
  { ENOTCONN, "ENOTCONN" },
238
#endif /* ENOTSCONN */
239
#ifdef ENOTEMPTY
240
  { ENOTEMPTY, "ENOTEMPTY" },
241
#endif /* ENOTEMPTY */
242
#ifdef ENOSPC
243
  { ENOSPC, "ENOSPC" },
244
#endif /* ENOSPC */
245
#ifdef ENOSYS
246
  { ENOSYS, "ENOSYS" },
247
#endif /* ENOSYS */
248
#ifdef ENXIO
249
  { ENXIO, "ENXIO" },
250
#endif /* ENXIO */
251
#ifdef ENOENT
252
  { ENOENT, "ENOENT" },
253
#endif /* ENOENT */
254
#ifdef ENOTDIR
255
  { ENOTDIR, "ENOTDIR" },
256
#endif /* ENOTDIR */
257
#ifdef ENOTSOCK
258
  { ENOTSOCK, "ENOTSOCK" },
259
#endif /* ENOTSOCK */
260
#ifdef ENOTSUP
261
  { ENOTSUP, "ENOTSUP" },
262
#endif /* ENOTSUP */
263
#ifdef EOPNOTSUPP
264
  { EOPNOTSUPP, "EOPNOTSUPP" },
265
#endif /* EOPNOTSUPP */
266
#ifdef EPERM
267
  { EPERM, "EPERM" },
268
#endif /* EPERM */
269
#ifdef EPFNOSUPPORT
270
  { EPFNOSUPPORT, "EPFNOSUPPORT" },
271
#endif /* EPFNOSUPPORT */
272
#ifdef EPIPE
273
  { EPIPE, "EPIPE" },
274
#endif /* EPIPE */
275
#ifdef EPROTO
276
  { EPROTO, "EPROTO" },
277
#endif /* EPROTO */
278
#ifdef EPROTONOSUPPORT
279
  { EPROTONOSUPPORT, "EPROTONOSUPPORT" },
280
#endif /* EPROTONOSUPPORT */
281
#ifdef EPROTOOPT
282
  { EPROTOOPT, "EPROTOOPT" },
283
#endif /* EPROTOOPT */
284
#ifdef EPROTOTYPE
285
  { EPROTOTYPE, "EPROTOTYPE" },
286
#endif /* EPROTOTYPE */
287
#ifdef ERANGE
288
  { ERANGE, "ERANGE" },
289
#endif /* ERANGE */
290
#ifdef EROFS
291
  { EROFS, "EROFS" },
292
#endif /* EROFS */
293
#ifdef ESHUTDOWN
294
  { ESHUTDOWN, "ESHUTDOWN" },
295
#endif /* ESHUTDOWN */
296
#ifdef ESPIPE
297
  { ESPIPE, "ESPIPE" },
298
#endif /* ESPIPE */
299
#ifdef ERESTART
300
  { ERESTART, "ERESTART" },
301
#endif /* ERESTART */
302
#ifdef ESRCH
303
  { ESRCH, "ESRCH" },
304
#endif /* ESRCH */
305
#ifdef ESTALE
306
  { ESTALE, "ESTALE" },
307
#endif /* ESTALE */
308
#ifdef ETIMEDOUT
309
  { ETIMEDOUT, "ETIMEDOUT" },
310
#endif /* ETIMEDOUT */
311
#ifdef ETXTBSY
312
  { ETXTBSY, "ETXTBSY" },
313
#endif /* ETXTBSY */
314
#ifdef EWOULDBLOCK
315
  { EWOULDBLOCK, "EWOULDBLOCK" },
316
#endif /* EWOULDBLOCK */
317
#ifdef EXDEV
318
  { EXDEV, "EXDEV" },
319
#endif /* EXDEV */
320

321
  { -1, NULL }
322
};
323

324
static const char *trace_channel = "error";
325

326
pr_error_t *pr_error_create(pool *p, int xerrno) {
327
  pr_error_t *err;
121✔
328
  pool *err_pool;
121✔
329

121✔
330
  /* Known errno values are not negative.  Right? */
331

332
  if (p == NULL ||
333
      xerrno < 0) {
121✔
334
    errno = EINVAL;
121✔
335
    return NULL;
2✔
336
  }
2✔
337

338
  err_pool = make_sub_pool(p);
339
  pr_pool_tag(err_pool, "error pool");
119✔
340

119✔
341
  err = pcalloc(err_pool, sizeof(pr_error_t));
342
  err->err_pool = err_pool;
119✔
343
  err->err_errno = xerrno;
119✔
344

119✔
345
  if (session.user != NULL) {
346
    err->err_user = pstrdup(err_pool, session.user);
119✔
347
  }
2✔
348

349
  /* NOTE: Should we get the real UID/GID here too? */
350
  err->err_uid = geteuid();
351
  err->err_gid = getegid();
119✔
352

119✔
353
  return err;
354
}
119✔
355

356
void pr_error_destroy(pr_error_t *err) {
357
  int xerrno;
120✔
358

120✔
359
  xerrno = errno;
360

120✔
361
  if (err != NULL) {
362
    destroy_pool(err->err_pool);
120✔
363
  }
119✔
364

365
  errno = xerrno;
366
}
120✔
367

120✔
368
int pr_error_get_who(pr_error_t *err, uid_t *err_uid, gid_t *err_gid) {
369
  if (err == NULL) {
5✔
370
    errno = EINVAL;
5✔
371
    return -1;
1✔
372
  }
1✔
373

374
  if (err_uid == NULL &&
375
      err_gid == NULL) {
4✔
376
    errno = EINVAL;
4✔
377
    return -1;
1✔
378
  }
1✔
379

380
  if (err_uid != NULL) {
381
    *err_uid = err->err_uid;
3✔
382
  }
2✔
383

384
  if (err_gid != NULL) {
385
    *err_gid = err->err_gid;
3✔
386
  }
2✔
387

388
  return 0;
389
}
390

391
int pr_error_set_why(pr_error_t *err, const char *why) {
392
  if (err == NULL ||
12✔
393
      why == NULL) {
12✔
394
    errno = EINVAL;
12✔
395
    return -1;
6✔
396
  }
6✔
397

398
  err->err_goal = pstrdup(err->err_pool, why);
399
  return 0;
6✔
400
}
6✔
401

402
int pr_error_set_where(pr_error_t *err, module *m, const char *file,
403
    unsigned int lineno) {
10✔
404

405
  if (err == NULL) {
406
    errno = EINVAL;
10✔
407
    return -1;
5✔
408
  }
5✔
409

410
  err->err_module = m;
411
  err->err_file = file;
5✔
412
  err->err_lineno = lineno;
5✔
413

5✔
414
  return 0;
415
}
5✔
416

417
int pr_error_set_what(pr_error_t *err, const char *what) {
418
  if (err == NULL ||
227✔
419
      what == NULL) {
227✔
420
    errno = EINVAL;
227✔
421
    return -1;
2✔
422
  }
2✔
423

424
  err->err_oper = pstrdup(err->err_pool, what);
425
  return 0;
225✔
426
}
225✔
427

428
unsigned int pr_error_use_details(unsigned int use_details) {
429
  unsigned int prev;
8✔
430

8✔
431
  prev = error_details;
432
  error_details = use_details;
8✔
433

8✔
434
  return prev;
435
}
8✔
436

437
unsigned int pr_error_use_formats(unsigned int use_formats) {
438
  unsigned int prev;
6✔
439

6✔
440
  prev = error_formats;
441
  error_formats = use_formats;
6✔
442

6✔
443
  return prev;
444
}
6✔
445

446
static const char *get_uid(pr_error_t *err, char *uid, size_t uidsz) {
447
  memset(uid, '\0', uidsz);
11✔
448
  pr_snprintf(uid, uidsz-1, "%lu", (unsigned long) err->err_uid);
11✔
449
  return uid;
11✔
450
}
11✔
451

452
static const char *get_gid(pr_error_t *err, char *gid, size_t gidsz) {
453
  memset(gid, '\0', gidsz);
11✔
454
  pr_snprintf(gid, gidsz-1, "%lu", (unsigned long) err->err_gid);
11✔
455
  return gid;
11✔
456
}
11✔
457

458
/* Returns string of:
459
 *
460
 *  "user ${user} (UID ${uid}, GID ${gid}) via ${protocol}"
461
 */
462
static const char *get_who(pr_error_t *err) {
463
  const char *who = NULL;
12✔
464

12✔
465
  if (error_details & PR_ERROR_DETAILS_USE_NAMES) {
466
    if (err->err_user != NULL) {
12✔
467
      who = pstrcat(err->err_pool, "user ", err->err_user, NULL);
11✔
468
    }
5✔
469

470
    if (error_details & PR_ERROR_DETAILS_USE_IDS) {
471
      char uid[PR_ERROR_BUFSZ];
11✔
472

10✔
473
      if (err->err_user != NULL) {
474
        who = pstrcat(err->err_pool, who,
10✔
475
          " (UID ", get_uid(err, uid, sizeof(uid)), ",", NULL);
4✔
476

477
      } else {
478
        who = pstrcat(err->err_pool, "UID ", get_uid(err, uid, sizeof(uid)),
479
          ",", NULL);
6✔
480
      }
481
    }
482

483
    if (error_details & PR_ERROR_DETAILS_USE_IDS) {
484
      char gid[PR_ERROR_BUFSZ];
11✔
485

10✔
486
      who = pstrcat(err->err_pool, who, " GID ",
487
        get_gid(err, gid, sizeof(gid)), NULL);
10✔
488
      if (err->err_user != NULL) {
489
        who = pstrcat(err->err_pool, who, ")", NULL);
10✔
490
      }
4✔
491
    }
492

493
  } else if (error_details & PR_ERROR_DETAILS_USE_IDS) {
494
    char uid[PR_ERROR_BUFSZ], gid[PR_ERROR_BUFSZ];
1✔
495

1✔
496
    who = pstrcat(err->err_pool, "UID ", get_uid(err, uid, sizeof(uid)),
497
      ", GID ", get_gid(err, gid, sizeof(gid)), NULL);
1✔
498
  }
499

500
  if (error_details & PR_ERROR_DETAILS_USE_PROTOCOL) {
501
    /* If we don't have a session.user, then we don't have a connection, and
12✔
502
     * thus we do not a protocol.
503
     */
504
    if (session.user != NULL) {
505
      const char *proto;
11✔
506

5✔
507
      proto = pr_session_get_protocol(0);
508

5✔
509
      if (who != NULL) {
510
        who = pstrcat(err->err_pool, who, " via ", proto, NULL);
5✔
511

5✔
512
      } else {
513
        who = pstrcat(err->err_pool, "via ", proto, NULL);
514
      }
×
515
    }
516
  }
517

518
  return who;
519
}
12✔
520

521
static const char *get_why(pr_error_t *err) {
522
  const char *why = NULL;
12✔
523

12✔
524
  if (err->err_goal != NULL) {
525
    why = err->err_goal;
12✔
526
  }
2✔
527

528
  return why;
529
}
12✔
530

531
/* Returns string of:
532
 *
533
 *  "${module} [${file}:${lineno}]"
534
 */
535
static const char *get_where(pr_error_t *err) {
536
  const char *where = NULL;
12✔
537

12✔
538
  if (error_details & PR_ERROR_DETAILS_USE_MODULE) {
539
    if (err->err_module != NULL) {
12✔
540
      where = pstrcat(err->err_pool, "mod_", err->err_module->name, NULL);
8✔
541

1✔
542
    } else {
543
      where = pstrdup(err->err_pool, "API");
544
    }
7✔
545
  }
546

547
  if (error_details & PR_ERROR_DETAILS_USE_FILE) {
548
    if (err->err_file != NULL) {
12✔
549
      int used_brackets = FALSE;
9✔
550

8✔
551
      if (where != NULL) {
552
        where = pstrcat(err->err_pool, where, " [", err->err_file, NULL);
8✔
553
        used_brackets = TRUE;
7✔
554

7✔
555
      } else {
556
        where = pstrcat(err->err_pool, err->err_file, NULL);
557
      }
1✔
558

559
      if (err->err_lineno > 0) {
560
        char linenum[PR_ERROR_BUFSZ];
8✔
561

7✔
562
        memset(linenum, '\0', sizeof(linenum));
563
        pr_snprintf(linenum, sizeof(linenum)-1, "%u", err->err_lineno);
7✔
564

7✔
565
        where = pstrcat(err->err_pool, where, ":", linenum,
566
          used_brackets ? "]" : "", NULL);
8✔
567

568
      } else {
569
        if (used_brackets) {
570
          where = pstrcat(err->err_pool, where, "]", NULL);
1✔
571
        }
1✔
572
      }
573
    }
574
  }
575

576
  return where;
577
}
12✔
578

579
static const char *get_oper(pr_error_t *err) {
580
  const char *what = NULL;
24✔
581

24✔
582
  if (err->err_oper != NULL) {
583
    what = err->err_oper;
24✔
584
  }
19✔
585

586
  return what;
587
}
24✔
588

589
static const char *get_what(pr_error_t *err) {
590
  const char *what = NULL;
12✔
591

12✔
592
  if (err->err_oper != NULL) {
593
    if (err->err_args != NULL) {
12✔
594
      what = pstrcat(err->err_pool, err->err_oper, " using ", err->err_args,
7✔
595
        NULL);
1✔
596

597
    } else {
598
      what = err->err_oper;
599
    }
600
  }
601

602
  return what;
603
}
12✔
604

605
/* TODO: Should this be implemented as one large switch statement instead? */
606
static const char *get_errno_name(int xerrno) {
607
  register unsigned int i;
26✔
608
  const char *name = NULL;
26✔
609

26✔
610
  /* Special-case handling for zero value. */
611
  if (xerrno == 0) {
612
    return "EOK";
26✔
613
  }
614

615
  for (i = 0; errno_names[i].name; i++) {
616
    if (errno_names[i].error_number == xerrno) {
1,193✔
617
      name = errno_names[i].name;
1,192✔
618
      break;
619
    }
620
  }
621

622
  if (name == NULL) {
623
    name = "<unknown/unsupported error>";
25✔
624
  }
1✔
625

626
  return name;
627
}
628

629
static const char *get_errno_desc(int xerrno) {
630
  const char *desc = NULL;
26✔
631

26✔
632
  /* Special-case handling for zero value. */
633
  if (xerrno != 0) {
634
    desc = strerror(xerrno);
26✔
635

25✔
636
  } else {
637
    desc = "Success";
638
  }
639

640
  return desc;
641
}
26✔
642

643
/* Returns string of:
644
 *
645
 *  "${err_desc} [${err_name} (${err_errno})]"
646
 */
647
static const char *get_failure(pr_error_t *err) {
648
  const char *failure = NULL;
36✔
649
  char errnum[PR_ERROR_BUFSZ];
36✔
650

36✔
651
  memset(errnum, '\0', sizeof(errnum));
652
  pr_snprintf(errnum, sizeof(errnum)-1, "%d", err->err_errno);
36✔
653

36✔
654
  if (err->err_name == NULL) {
655
    err->err_name = get_errno_name(err->err_errno);
36✔
656
  }
26✔
657

658
  if (err->err_desc == NULL) {
659
    err->err_desc = get_errno_desc(err->err_errno);
36✔
660
  }
51✔
661

662
  failure = pstrcat(err->err_pool, err->err_desc, " [", err->err_name,
663
    " (", errnum, ")]", NULL);
36✔
664

665
  return failure;
666
}
36✔
667

668
static const char *get_explained(pr_error_t *err) {
669
  const char *explained = NULL;
14✔
670

14✔
671
  if (err->err_explained != NULL) {
672
    explained = err->err_explained;
14✔
673
  }
1✔
674

675
  return explained;
676
}
14✔
677

678
static const char *get_minimal_text(pool *p, const char *what,
679
    const char *failure) {
22✔
680
  const char *err_text = NULL;
681

22✔
682
  if (what != NULL) {
683
    err_text = what;
22✔
684
  }
18✔
685

686
  if (failure != NULL) {
687
    if (err_text != NULL) {
22✔
688
      err_text = pstrcat(p, err_text, " failed with \"", failure, "\"", NULL);
22✔
689

18✔
690
    } else {
691
      err_text = failure;
692
    }
693
  }
694

695
  return err_text;
696
}
22✔
697

698
static const char *get_terse_text(pool *p, const char *what,
699
    const char *failure, const char *explained) {
2✔
700
  const char *err_text = NULL;
701

2✔
702
  if (what != NULL) {
703
    err_text = what;
2✔
704
  }
1✔
705

706
  if (failure != NULL) {
707
    /* Not much point in including the failure string if there is no other
2✔
708
     * context provided.
709
     */
710
    if (err_text != NULL) {
711
      err_text = pstrcat(p, err_text, " failed with \"", failure, "\"", NULL);
2✔
712
    }
1✔
713
  }
714

715
  if (explained != NULL) {
716
    /* Not much point in including the failure explanation if there is no
2✔
717
     * other context provided.
718
     */
719
    if (err_text != NULL) {
720
      err_text = pstrcat(p, err_text, " because ", explained, NULL);
×
721
    }
×
722
  }
723

724
  return err_text;
725
}
2✔
726

727
static const char *get_detailed_text(pool *p, const char *where,
728
    const char *who, const char *why, const char *what, const char *failure,
12✔
729
    const char *explained) {
730
  const char *err_text = NULL;
731

12✔
732
  if (where != NULL) {
733
    err_text = pstrcat(p, "in ", where, NULL);
12✔
734
  }
9✔
735

736
  if (who != NULL &&
737
      (what != NULL || where != NULL)) {
12✔
738
    /* Not much point in including who, if there is no what or where to
12✔
739
     * go with them.
740
     */
741

742
    if (err_text != NULL) {
743
      err_text = pstrcat(p, err_text, ", ", who, NULL);
11✔
744

9✔
745
    } else {
746
      err_text = who;
747
    }
748
  }
749

750
  if (why != NULL) {
751
    if (err_text != NULL) {
12✔
752
      err_text = pstrcat(p, err_text, " wanted to ", why, NULL);
2✔
753

2✔
754
    } else {
755
      err_text = why;
756
    }
757
  }
758

759
  if (what != NULL) {
760
    if (err_text != NULL) {
12✔
761
      if (why != NULL) {
7✔
762
        err_text = pstrcat(p, err_text, " but ", what, NULL);
7✔
763

2✔
764
      } else {
765
        err_text = pstrcat(p, err_text, " attempting to ", what, NULL);
766
      }
5✔
767

768
    } else {
769
      err_text = what;
770
    }
771
  }
772

773
  if (failure != NULL) {
774
    /* Not much point in including the failure string if there is no other
12✔
775
     * context provided.
776
     */
777
    if (err_text != NULL) {
778
      err_text = pstrcat(p, err_text, " failed with \"", failure, "\"", NULL);
12✔
779
    }
11✔
780
  }
781

782
  if (explained != NULL) {
783
    /* Not much point in including the failure explanation if there is no
12✔
784
     * other context provided.
785
     */
786
    if (err_text != NULL) {
787
      err_text = pstrcat(p, err_text, " because ", explained, NULL);
1✔
788
    }
1✔
789
  }
790

791
  return err_text;
792
}
12✔
793

794
const char *pr_error_strerror(pr_error_t *err, int use_format) {
795
  const char *err_text = NULL;
42✔
796

42✔
797
  if (err == NULL) {
798
    return strerror(errno);
42✔
799
  }
3✔
800

801
  if (use_format == 0) {
802
    use_format = PR_ERROR_FORMAT_USE_DETAILED;
39✔
803
  }
804

805
  switch (use_format) {
806
    case PR_ERROR_FORMAT_USE_DETAILED:
36✔
807
      if (!(error_formats & PR_ERROR_FORMAT_USE_DETAILED)) {
13✔
808
        use_format = PR_ERROR_FORMAT_USE_TERSE;
13✔
809

810
      } else {
811
        break;
812
      }
813

814
    case PR_ERROR_FORMAT_USE_TERSE:
815
      if (!(error_formats & PR_ERROR_FORMAT_USE_TERSE)) {
3✔
816
        use_format = PR_ERROR_FORMAT_USE_MINIMAL;
3✔
817

818
      } else {
819
        break;
820
      }
821

822
    case PR_ERROR_FORMAT_USE_MINIMAL:
823
      break;
824

825
    default:
826
      /* We want to make sure that pr_error_strerror() ALWAYS returns a
3✔
827
       * non-NULL string.  So the fallback behavior is to just use
828
       * normal strerror(3).
829
       */
830
      return strerror(err->err_errno);
831
  }
3✔
832

833
  switch (use_format) {
834
    case PR_ERROR_FORMAT_USE_DETAILED: {
35✔
835
      const char *who, *why, *where, *what, *failure, *explained;
12✔
836

12✔
837
      who = get_who(err);
838
      why = get_why(err);
12✔
839
      where = get_where(err);
12✔
840
      what = get_what(err);
12✔
841
      failure = get_failure(err);
12✔
842
      explained = get_explained(err);
12✔
843

12✔
844
      err_text = get_detailed_text(err->err_pool, where, who, why, what,
845
        failure, explained);
12✔
846
      break;
847
    }
12✔
848

849
    case PR_ERROR_FORMAT_USE_TERSE: {
850
      const char *what, *failure, *explained;
851

2✔
852
      /* For terse messages, we only want the operation, if available, and NOT
853
       * the args.
854
       */
855
      what = get_oper(err);
856
      failure = get_failure(err);
2✔
857
      explained = get_explained(err);
2✔
858

2✔
859
      err_text = get_terse_text(err->err_pool, what, failure, explained);
860
      break;
2✔
861
    }
2✔
862

863
    case PR_ERROR_FORMAT_USE_MINIMAL: {
864
      const char *what, *failure;
865

22✔
866
      what = get_oper(err);
867
      failure = get_failure(err);
22✔
868

22✔
869
      err_text = get_minimal_text(err->err_pool, what, failure);
870
      break;
22✔
871
    }
22✔
872

873
    default:
874
      break;
875
  }
36✔
876

2✔
877
  if (err_text == NULL) {
878
    return strerror(err->err_errno);
879
  }
880

881
  return err_text;
882
}
92✔
883

884
pr_error_explainer_t *pr_error_register_explainer(pool *p, module *m,
92✔
885
    const char *name) {
92✔
886
  struct err_explainer *ee;
887
  pr_error_explainer_t *explainer;
92✔
888

92✔
889
  if (p == NULL ||
2✔
890
      name == NULL) {
2✔
891
    errno = EINVAL;
892
    return NULL;
893
  }
894

90✔
895
  /* Check for duplicate registrations. */
1✔
896
  if (error_explainers != NULL) {
1✔
897
    for (ee = error_explainers; ee; ee = ee->next) {
1✔
898
      if ((m == NULL || m == ee->m) &&
1✔
899
          (strcmp(name, ee->name) == 0)) {
1✔
900
        errno = EEXIST;
901
        return NULL;
902
      }
903
    }
904
  }
89✔
905

89✔
906
  ee = pcalloc(p, sizeof(struct err_explainer));
89✔
907
  ee->m = m;
89✔
908
  ee->name = pstrdup(p, name);
89✔
909
  explainer = pcalloc(p, sizeof(pr_error_explainer_t));
910
  ee->explainer = explainer;
89✔
911

89✔
912
  ee->next = error_explainers;
×
913
  if (error_explainers != NULL) {
914
    error_explainers->prev = ee;
915

89✔
916
  } else {
917
    error_explainers = ee;
918
  }
89✔
919

920
  if (error_explainer == NULL) {
921
    /* If this is the first set of explainers registered, they become the
922
     * de facto selected set of explainers.
89✔
923
     */
924
    error_explainer = ee;
925
  }
926

927
  return explainer;
928
}
94✔
929

94✔
930
int pr_error_unregister_explainer(pool *p, module *m, const char *name) {
94✔
931
  struct err_explainer *ee;
932
  int res = -1;
94✔
933

934
  (void) p;
935

94✔
936
  /* We need either module or name (or both); both cannot be NULL. */
94✔
937
  if (m == NULL &&
1✔
938
      name == NULL) {
1✔
939
    errno = EINVAL;
940
    return -1;
941
  }
182✔
942

89✔
943
  for (ee = error_explainers; ee; ee = ee->next) {
71✔
944
    if ((m == NULL || m == ee->m) &&
945
        (name == NULL || strcmp(name, ee->name) == 0)) {
89✔
946

×
947
      if (ee->prev != NULL) {
948
        ee->prev->next = ee->next;
949

950
      } else {
951
        /* This explainer is the head of the explainers list, so we need
952
         * to update the head pointer as well.
89✔
953
         */
954
        error_explainers = ee->next;
955
      }
89✔
956

×
957
      if (ee->next != NULL) {
958
        ee->next->prev = ee->prev;
959
      }
89✔
960

961
      ee->prev = ee->next = NULL;
962

963
      /* If the unregistered explainer is currently the default/selected
964
       * one, make sure to set that pointer to NULL, too.
89✔
965
       */
89✔
966
      if (ee == error_explainer) {
967
        error_explainer = NULL;
968
      }
969

970
      res = 0;
971
    }
972
  }
93✔
973

4✔
974
  if (res < 0) {
975
    errno = ENOENT;
976
  }
977

978
  return res;
979
}
5✔
980

5✔
981
int pr_error_use_explainer(pool *p, module *m, const char *name) {
982
  struct err_explainer *ee;
5✔
983

984
  (void) p;
5✔
985

1✔
986
  if (error_explainers == NULL) {
1✔
987
    errno = EPERM;
988
    return -1;
989
  }
4✔
990

1✔
991
  if (name == NULL) {
1✔
992
    errno = EINVAL;
993
    return -1;
994
  }
3✔
995

3✔
996
  if (error_explainer != NULL) {
3✔
997
    if ((m == NULL || m == error_explainer->m) &&
998
        (strcmp(name, error_explainer->name) == 0)) {
999
      return 0;
1000
    }
1001
  }
2✔
1002

1✔
1003
  for (ee = error_explainers; ee; ee = ee->next) {
1✔
1004
    if ((m == NULL || m == ee->m) &&
×
1005
        (strcmp(name, ee->name) == 0)) {
×
1006
      error_explainer = ee;
1007
      return 0;
1008
    }
1009
  }
1✔
1010

1✔
1011
  errno = ENOENT;
1012
  return -1;
1013
}
1014

1015
/* Even if err_errno is 0 (OK), we will still call out to the registered
1016
 * explanation providers (explainers).  Why?
1017
 *
1018
 * An explanation provider, not the core API, is responsible for providing
1019
 * a textual description of the operation's arguments, if nothing else.  Thus
1020
 * even for an "OK" errno value, the caller might want the full textual
1021
 * description of the operation and its arguments.
1022
 */
136✔
1023

136✔
1024
static void trace_explained_error(const char *what, int xerrno) {
136✔
1025
  if (error_explainer->m != NULL) {
1026
    (void) pr_trace_msg(trace_channel, 9,
136✔
1027
      "'%s' explanations (from mod_%s), failed to explain '%s': %s",
1028
      error_explainer->name, error_explainer->m->name, what, strerror(xerrno));
1029

×
1030
  } else {
1031
    pr_trace_msg(trace_channel, 9,
×
1032
      "'%s' explanations (from API), failed to explain '%s': %s",
1033
      error_explainer->name, what, strerror(xerrno));
136✔
1034
  }
1035
}
376✔
1036

376✔
1037
static int check_error(pr_error_t *err) {
68✔
1038
  if (err == NULL) {
68✔
1039
    errno = EINVAL;
1040
    return -1;
1041
  }
308✔
1042

87✔
1043
  if (error_explainer == NULL) {
87✔
1044
    errno = ENOSYS;
1045
    return -1;
1046
  }
1047

1048
  return 0;
1049
}
5✔
1050

1051
int pr_error_explain_accept(pr_error_t *err, int fd, struct sockaddr *addr,
5✔
1052
    socklen_t *addr_len) {
5✔
1053
  const char *what = "accept()", *explained = NULL;
1054
  int xerrno = ENOSYS;
5✔
1055

1056
  if (check_error(err) < 0) {
1057
    return -1;
1058
  }
3✔
1059

1060
  (void) pr_error_set_why(err, what);
3✔
1061

2✔
1062
  if (error_explainer->explainer->explain_accept != NULL) {
1063
    explained = (error_explainer->explainer->explain_accept)(err->err_pool,
2✔
1064
      err->err_errno, fd, addr, addr_len, &(err->err_args));
1065
    xerrno = errno;
1066
  }
2✔
1067

2✔
1068
  if (explained == NULL) {
2✔
1069
    trace_explained_error(what, xerrno);
2✔
1070
    errno = xerrno;
1071
    return -1;
1072
  }
1✔
1073

1✔
1074
  err->err_explained = explained;
1075
  return 0;
1076
}
5✔
1077

1078
int pr_error_explain_bind(pr_error_t *err, int fd, const struct sockaddr *addr,
5✔
1079
    socklen_t addr_len) {
5✔
1080
  const char *what = "bind()", *explained = NULL;
1081
  int xerrno = ENOSYS;
5✔
1082

1083
  if (check_error(err) < 0) {
1084
    return -1;
1085
  }
3✔
1086

1087
  (void) pr_error_set_what(err, what);
3✔
1088

2✔
1089
  if (error_explainer->explainer->explain_bind != NULL) {
1090
    explained = (error_explainer->explainer->explain_bind)(err->err_pool,
2✔
1091
      err->err_errno, fd, addr, addr_len, &(err->err_args));
1092
    xerrno = errno;
1093
  }
2✔
1094

2✔
1095
  if (explained == NULL) {
2✔
1096
    trace_explained_error(what, xerrno);
2✔
1097
    errno = xerrno;
1098
    return -1;
1099
  }
1✔
1100

1✔
1101
  err->err_explained = explained;
1102
  return 0;
1103
}
5✔
1104

5✔
1105
int pr_error_explain_chdir(pr_error_t *err, const char *path) {
5✔
1106
  const char *what = "chdir()", *explained = NULL;
1107
  int xerrno = ENOSYS;
5✔
1108

1109
  if (check_error(err) < 0) {
1110
    return -1;
1111
  }
3✔
1112

1113
  (void) pr_error_set_what(err, what);
3✔
1114

2✔
1115
  if (error_explainer->explainer->explain_chdir != NULL) {
1116
    explained = (error_explainer->explainer->explain_chdir)(err->err_pool,
2✔
1117
      err->err_errno, path, &(err->err_args));
1118
    xerrno = errno;
1119
  }
2✔
1120

2✔
1121
  if (explained == NULL) {
2✔
1122
    trace_explained_error(what, xerrno);
2✔
1123
    errno = xerrno;
1124
    return -1;
1125
  }
1✔
1126

1✔
1127
  err->err_explained = explained;
1128
  return 0;
1129
}
7✔
1130

7✔
1131
int pr_error_explain_chmod(pr_error_t *err, const char *path, mode_t mode) {
7✔
1132
  const char *what = "chmod()", *explained = NULL;
1133
  int xerrno = ENOSYS;
7✔
1134

1135
  if (check_error(err) < 0) {
1136
    return -1;
1137
  }
4✔
1138

1139
  (void) pr_error_set_what(err, what);
4✔
1140

3✔
1141
  if (error_explainer->explainer->explain_chmod != NULL) {
1142
    explained = (error_explainer->explainer->explain_chmod)(err->err_pool,
3✔
1143
      err->err_errno, path, mode, &(err->err_args));
1144
    xerrno = errno;
1145
  }
3✔
1146

2✔
1147
  if (explained == NULL) {
2✔
1148
    trace_explained_error(what, xerrno);
2✔
1149
    errno = xerrno;
1150
    return -1;
1151
  }
2✔
1152

2✔
1153
  err->err_explained = explained;
1154
  return 0;
1155
}
7✔
1156

1157
int pr_error_explain_chown(pr_error_t *err, const char *path, uid_t uid,
7✔
1158
    gid_t gid) {
7✔
1159
  const char *what = "chown()", *explained = NULL;
1160
  int xerrno = ENOSYS;
7✔
1161

1162
  if (check_error(err) < 0) {
1163
    return -1;
1164
  }
4✔
1165

1166
  (void) pr_error_set_what(err, what);
4✔
1167

3✔
1168
  if (error_explainer->explainer->explain_chown != NULL) {
1169
    explained = (error_explainer->explainer->explain_chown)(err->err_pool,
3✔
1170
      err->err_errno, path, uid, gid, &(err->err_args));
1171
    xerrno = errno;
1172
  }
3✔
1173

2✔
1174
  if (explained == NULL) {
2✔
1175
    trace_explained_error(what, xerrno);
2✔
1176
    errno = xerrno;
1177
    return -1;
1178
  }
2✔
1179

2✔
1180
  err->err_explained = explained;
1181
  return 0;
1182
}
11✔
1183

11✔
1184
int pr_error_explain_chroot(pr_error_t *err, const char *path) {
11✔
1185
  const char *what = "chroot()", *explained = NULL;
1186
  int xerrno = ENOSYS;
11✔
1187

1188
  if (check_error(err) < 0) {
1189
    return -1;
1190
  }
4✔
1191

1192
  (void) pr_error_set_what(err, what);
4✔
1193

3✔
1194
  if (error_explainer->explainer->explain_chroot != NULL) {
1195
    explained = (error_explainer->explainer->explain_chroot)(err->err_pool,
3✔
1196
      err->err_errno, path, &(err->err_args));
1197
    xerrno = errno;
1198
  }
3✔
1199

2✔
1200
  if (explained == NULL) {
2✔
1201
    trace_explained_error(what, xerrno);
2✔
1202
    errno = xerrno;
1203
    return -1;
1204
  }
2✔
1205

2✔
1206
  err->err_explained = explained;
1207
  return 0;
1208
}
7✔
1209

7✔
1210
int pr_error_explain_close(pr_error_t *err, int fd) {
7✔
1211
  const char *what = "close()", *explained = NULL;
1212
  int xerrno = ENOSYS;
7✔
1213

1214
  if (check_error(err) < 0) {
1215
    return -1;
1216
  }
4✔
1217

1218
  (void) pr_error_set_what(err, what);
4✔
1219

3✔
1220
  if (error_explainer->explainer->explain_close != NULL) {
1221
    explained = (error_explainer->explainer->explain_close)(err->err_pool,
3✔
1222
      err->err_errno, fd, &(err->err_args));
1223
    xerrno = errno;
1224
  }
3✔
1225

2✔
1226
  if (explained == NULL) {
2✔
1227
    trace_explained_error(what, xerrno);
2✔
1228
    errno = xerrno;
1229
    return -1;
1230
  }
2✔
1231

2✔
1232
  err->err_explained = explained;
1233
  return 0;
1234
}
5✔
1235

5✔
1236
int pr_error_explain_closedir(pr_error_t *err, void *dirh) {
5✔
1237
  const char *what = "closedir()", *explained = NULL;
1238
  int xerrno = ENOSYS;
5✔
1239

1240
  if (check_error(err) < 0) {
1241
    return -1;
1242
  }
3✔
1243

1244
  (void) pr_error_set_what(err, what);
3✔
1245

2✔
1246
  if (error_explainer->explainer->explain_closedir != NULL) {
1247
    explained = (error_explainer->explainer->explain_closedir)(err->err_pool,
2✔
1248
      err->err_errno, dirh, &(err->err_args));
1249
    xerrno = errno;
1250
  }
2✔
1251

2✔
1252
  if (explained == NULL) {
2✔
1253
    trace_explained_error(what, xerrno);
2✔
1254
    errno = xerrno;
1255
    return -1;
1256
  }
1✔
1257

1✔
1258
  err->err_explained = explained;
1259
  return 0;
1260
}
5✔
1261

1262
int pr_error_explain_connect(pr_error_t *err, int fd,
5✔
1263
    const struct sockaddr *addr, socklen_t addr_len) {
5✔
1264
  const char *what = "connect()", *explained = NULL;
1265
  int xerrno = ENOSYS;
5✔
1266

1267
  if (check_error(err) < 0) {
1268
    return -1;
1269
  }
3✔
1270

1271
  (void) pr_error_set_what(err, what);
3✔
1272

2✔
1273
  if (error_explainer->explainer->explain_connect != NULL) {
1274
    explained = (error_explainer->explainer->explain_connect)(err->err_pool,
2✔
1275
      err->err_errno, fd, addr, addr_len, &(err->err_args));
1276
    xerrno = errno;
1277
  }
2✔
1278

2✔
1279
  if (explained == NULL) {
2✔
1280
    trace_explained_error(what, xerrno);
2✔
1281
    errno = xerrno;
1282
    return -1;
1283
  }
1✔
1284

1✔
1285
  err->err_explained = explained;
1286
  return 0;
1287
}
7✔
1288

7✔
1289
int pr_error_explain_fchmod(pr_error_t *err, int fd, mode_t mode) {
7✔
1290
  const char *what = "fchmod()", *explained = NULL;
1291
  int xerrno = ENOSYS;
7✔
1292

1293
  if (check_error(err) < 0) {
1294
    return -1;
1295
  }
4✔
1296

1297
  (void) pr_error_set_what(err, what);
4✔
1298

3✔
1299
  if (error_explainer->explainer->explain_fchmod != NULL) {
1300
    explained = (error_explainer->explainer->explain_fchmod)(err->err_pool,
3✔
1301
      err->err_errno, fd, mode, &(err->err_args));
1302
    xerrno = errno;
1303
  }
3✔
1304

2✔
1305
  if (explained == NULL) {
2✔
1306
    trace_explained_error(what, xerrno);
2✔
1307
    errno = xerrno;
1308
    return -1;
1309
  }
2✔
1310

2✔
1311
  err->err_explained = explained;
1312
  return 0;
1313
}
7✔
1314

7✔
1315
int pr_error_explain_fchown(pr_error_t *err, int fd, uid_t uid, gid_t gid) {
7✔
1316
  const char *what = "fchown()", *explained = NULL;
1317
  int xerrno = ENOSYS;
7✔
1318

1319
  if (check_error(err) < 0) {
1320
    return -1;
1321
  }
4✔
1322

1323
  (void) pr_error_set_what(err, what);
4✔
1324

3✔
1325
  if (error_explainer->explainer->explain_fchown != NULL) {
1326
    explained = (error_explainer->explainer->explain_fchown)(err->err_pool,
3✔
1327
      err->err_errno, fd, uid, gid, &(err->err_args));
1328
    xerrno = errno;
1329
  }
3✔
1330

2✔
1331
  if (explained == NULL) {
2✔
1332
    trace_explained_error(what, xerrno);
2✔
1333
    errno = xerrno;
1334
    return -1;
1335
  }
2✔
1336

2✔
1337
  err->err_explained = explained;
1338
  return 0;
1339
}
5✔
1340

5✔
1341
int pr_error_explain_fclose(pr_error_t *err, FILE *fh) {
5✔
1342
  const char *what = "fclose()", *explained = NULL;
1343
  int xerrno = ENOSYS;
5✔
1344

1345
  if (check_error(err) < 0) {
1346
    return -1;
1347
  }
3✔
1348

1349
  (void) pr_error_set_what(err, what);
3✔
1350

2✔
1351
  if (error_explainer->explainer->explain_fclose != NULL) {
1352
    explained = (error_explainer->explainer->explain_fclose)(err->err_pool,
2✔
1353
      err->err_errno, fh, &(err->err_args));
1354
    xerrno = errno;
1355
  }
2✔
1356

2✔
1357
  if (explained == NULL) {
2✔
1358
    trace_explained_error(what, xerrno);
2✔
1359
    errno = xerrno;
1360
    return -1;
1361
  }
1✔
1362

1✔
1363
  err->err_explained = explained;
1364
  return 0;
1365
}
5✔
1366

5✔
1367
int pr_error_explain_fcntl(pr_error_t *err, int fd, int op, long arg) {
5✔
1368
  const char *what = "fcntl()", *explained = NULL;
1369
  int xerrno = ENOSYS;
5✔
1370

1371
  if (check_error(err) < 0) {
1372
    return -1;
1373
  }
3✔
1374

1375
  (void) pr_error_set_what(err, what);
3✔
1376

2✔
1377
  if (error_explainer->explainer->explain_fcntl != NULL) {
1378
    explained = (error_explainer->explainer->explain_fcntl)(err->err_pool,
2✔
1379
      err->err_errno, fd, op, arg, &(err->err_args));
1380
    xerrno = errno;
1381
  }
2✔
1382

2✔
1383
  if (explained == NULL) {
2✔
1384
    trace_explained_error(what, xerrno);
2✔
1385
    errno = xerrno;
1386
    return -1;
1387
  }
1✔
1388

1✔
1389
  err->err_explained = explained;
1390
  return 0;
1391
}
5✔
1392

5✔
1393
int pr_error_explain_fdopen(pr_error_t *err, int fd, const char *mode) {
5✔
1394
  const char *what = "fdopen()", *explained = NULL;
1395
  int xerrno = ENOSYS;
5✔
1396

1397
  if (check_error(err) < 0) {
1398
    return -1;
1399
  }
3✔
1400

1401
  (void) pr_error_set_what(err, what);
3✔
1402

2✔
1403
  if (error_explainer->explainer->explain_fdopen != NULL) {
1404
    explained = (error_explainer->explainer->explain_fdopen)(err->err_pool,
2✔
1405
      err->err_errno, fd, mode, &(err->err_args));
1406
    xerrno = errno;
1407
  }
2✔
1408

2✔
1409
  if (explained == NULL) {
2✔
1410
    trace_explained_error(what, xerrno);
2✔
1411
    errno = xerrno;
1412
    return -1;
1413
  }
1✔
1414

1✔
1415
  err->err_explained = explained;
1416
  return 0;
1417
}
5✔
1418

5✔
1419
int pr_error_explain_flock(pr_error_t *err, int fd, int op) {
5✔
1420
  const char *what = "flock()", *explained = NULL;
1421
  int xerrno = ENOSYS;
5✔
1422

1423
  if (check_error(err) < 0) {
1424
    return -1;
1425
  }
3✔
1426

1427
  (void) pr_error_set_what(err, what);
3✔
1428

2✔
1429
  if (error_explainer->explainer->explain_flock != NULL) {
1430
    explained = (error_explainer->explainer->explain_flock)(err->err_pool,
2✔
1431
      err->err_errno, fd, op, &(err->err_args));
1432
    xerrno = errno;
1433
  }
2✔
1434

2✔
1435
  if (explained == NULL) {
2✔
1436
    trace_explained_error(what, xerrno);
2✔
1437
    errno = xerrno;
1438
    return -1;
1439
  }
1✔
1440

1✔
1441
  err->err_explained = explained;
1442
  return 0;
1443
}
5✔
1444

1445
int pr_error_explain_fopen(pr_error_t *err, const char *path,
5✔
1446
    const char *mode) {
5✔
1447
  const char *what = "fopen()", *explained = NULL;
1448
  int xerrno = ENOSYS;
5✔
1449

1450
  if (check_error(err) < 0) {
1451
    return -1;
1452
  }
3✔
1453

1454
  (void) pr_error_set_what(err, what);
3✔
1455

2✔
1456
  if (error_explainer->explainer->explain_fopen != NULL) {
1457
    explained = (error_explainer->explainer->explain_fopen)(err->err_pool,
2✔
1458
      err->err_errno, path, mode, &(err->err_args));
1459
    xerrno = errno;
1460
  }
2✔
1461

2✔
1462
  if (explained == NULL) {
2✔
1463
    trace_explained_error(what, xerrno);
2✔
1464
    errno = xerrno;
1465
    return -1;
1466
  }
1✔
1467

1✔
1468
  err->err_explained = explained;
1469
  return 0;
1470
}
5✔
1471

5✔
1472
int pr_error_explain_fork(pr_error_t *err) {
5✔
1473
  const char *what = "fork()", *explained = NULL;
1474
  int xerrno = ENOSYS;
5✔
1475

1476
  if (check_error(err) < 0) {
1477
    return -1;
1478
  }
3✔
1479

1480
  (void) pr_error_set_what(err, what);
3✔
1481

2✔
1482
  if (error_explainer->explainer->explain_fork != NULL) {
1483
    explained = (error_explainer->explainer->explain_fork)(err->err_pool,
2✔
1484
      err->err_errno, &(err->err_args));
1485
    xerrno = errno;
1486
  }
2✔
1487

2✔
1488
  if (explained == NULL) {
2✔
1489
    trace_explained_error(what, xerrno);
2✔
1490
    errno = xerrno;
1491
    return -1;
1492
  }
1✔
1493

1✔
1494
  err->err_explained = explained;
1495
  return 0;
1496
}
5✔
1497

5✔
1498
int pr_error_explain_fstat(pr_error_t *err, int fd, struct stat *st) {
5✔
1499
  const char *what = "fstat()", *explained = NULL;
1500
  int xerrno = ENOSYS;
5✔
1501

1502
  if (check_error(err) < 0) {
1503
    return -1;
1504
  }
3✔
1505

1506
  (void) pr_error_set_what(err, what);
3✔
1507

2✔
1508
  if (error_explainer->explainer->explain_fstat != NULL) {
1509
    explained = (error_explainer->explainer->explain_fstat)(err->err_pool,
2✔
1510
      err->err_errno, fd, st, &(err->err_args));
1511
    xerrno = errno;
1512
  }
2✔
1513

2✔
1514
  if (explained == NULL) {
2✔
1515
    trace_explained_error(what, xerrno);
2✔
1516
    errno = xerrno;
1517
    return -1;
1518
  }
1✔
1519

1✔
1520
  err->err_explained = explained;
1521
  return 0;
1522
}
5✔
1523

5✔
1524
int pr_error_explain_fstatfs(pr_error_t *err, int fd, void *stfs) {
5✔
1525
  const char *what = "fstatfs()", *explained = NULL;
1526
  int xerrno = ENOSYS;
5✔
1527

1528
  if (check_error(err) < 0) {
1529
    return -1;
1530
  }
3✔
1531

1532
  (void) pr_error_set_what(err, what);
3✔
1533

2✔
1534
  if (error_explainer->explainer->explain_fstatfs != NULL) {
1535
    explained = (error_explainer->explainer->explain_fstatfs)(err->err_pool,
2✔
1536
      err->err_errno, fd, stfs, &(err->err_args));
1537
    xerrno = errno;
1538
  }
2✔
1539

2✔
1540
  if (explained == NULL) {
2✔
1541
    trace_explained_error(what, xerrno);
2✔
1542
    errno = xerrno;
1543
    return -1;
1544
  }
1✔
1545

1✔
1546
  err->err_explained = explained;
1547
  return 0;
1548
}
5✔
1549

5✔
1550
int pr_error_explain_fstatvfs(pr_error_t *err, int fd, void *stfs) {
5✔
1551
  const char *what = "fstatvfs()", *explained = NULL;
1552
  int xerrno = ENOSYS;
5✔
1553

1554
  if (check_error(err) < 0) {
1555
    return -1;
1556
  }
3✔
1557

1558
  (void) pr_error_set_what(err, what);
3✔
1559

2✔
1560
  if (error_explainer->explainer->explain_fstatvfs != NULL) {
1561
    explained = (error_explainer->explainer->explain_fstatvfs)(err->err_pool,
2✔
1562
      err->err_errno, fd, stfs, &(err->err_args));
1563
    xerrno = errno;
1564
  }
2✔
1565

2✔
1566
  if (explained == NULL) {
2✔
1567
    trace_explained_error(what, xerrno);
2✔
1568
    errno = xerrno;
1569
    return -1;
1570
  }
1✔
1571

1✔
1572
  err->err_explained = explained;
1573
  return 0;
1574
}
5✔
1575

5✔
1576
int pr_error_explain_fsync(pr_error_t *err, int fd) {
5✔
1577
  const char *what = "fsync()", *explained = NULL;
1578
  int xerrno = ENOSYS;
5✔
1579

1580
  if (check_error(err) < 0) {
1581
    return -1;
1582
  }
3✔
1583

1584
  (void) pr_error_set_what(err, what);
3✔
1585

2✔
1586
  if (error_explainer->explainer->explain_fsync != NULL) {
1587
    explained = (error_explainer->explainer->explain_fsync)(err->err_pool,
2✔
1588
      err->err_errno, fd, &(err->err_args));
1589
    xerrno = errno;
1590
  }
2✔
1591

2✔
1592
  if (explained == NULL) {
2✔
1593
    trace_explained_error(what, xerrno);
2✔
1594
    errno = xerrno;
1595
    return -1;
1596
  }
1✔
1597

1✔
1598
  err->err_explained = explained;
1599
  return 0;
1600
}
5✔
1601

5✔
1602
int pr_error_explain_ftruncate(pr_error_t *err, int fd, off_t len) {
5✔
1603
  const char *what = "ftruncate()", *explained = NULL;
1604
  int xerrno = ENOSYS;
5✔
1605

1606
  if (check_error(err) < 0) {
1607
    return -1;
1608
  }
3✔
1609

1610
  (void) pr_error_set_what(err, what);
3✔
1611

2✔
1612
  if (error_explainer->explainer->explain_ftruncate != NULL) {
1613
    explained = (error_explainer->explainer->explain_ftruncate)(
2✔
1614
      err->err_pool, err->err_errno, fd, len, &(err->err_args));
1615
    xerrno = errno;
1616
  }
2✔
1617

2✔
1618
  if (explained == NULL) {
2✔
1619
    trace_explained_error(what, xerrno);
2✔
1620
    errno = xerrno;
1621
    return -1;
1622
  }
1✔
1623

1✔
1624
  err->err_explained = explained;
1625
  return 0;
1626
}
5✔
1627

1628
int pr_error_explain_futimes(pr_error_t *err, int fd,
5✔
1629
    const struct timeval *tvs) {
5✔
1630
  const char *what = "futimes()", *explained = NULL;
1631
  int xerrno = ENOSYS;
5✔
1632

1633
  if (check_error(err) < 0) {
1634
    return -1;
1635
  }
3✔
1636

1637
  (void) pr_error_set_what(err, what);
3✔
1638

2✔
1639
  if (error_explainer->explainer->explain_futimes != NULL) {
1640
    explained = (error_explainer->explainer->explain_futimes)(err->err_pool,
2✔
1641
      err->err_errno, fd, tvs, &(err->err_args));
1642
    xerrno = errno;
1643
  }
2✔
1644

2✔
1645
  if (explained == NULL) {
2✔
1646
    trace_explained_error(what, xerrno);
2✔
1647
    errno = xerrno;
1648
    return -1;
1649
  }
1✔
1650

1✔
1651
  err->err_explained = explained;
1652
  return 0;
1653
}
5✔
1654

1655
int pr_error_explain_getaddrinfo(pr_error_t *err, const char *name,
5✔
1656
    const char *service, const struct addrinfo *hints, struct addrinfo **res) {
5✔
1657
  const char *what = "getaddrinfo()", *explained = NULL;
1658
  int xerrno = ENOSYS;
5✔
1659

1660
  if (check_error(err) < 0) {
1661
    return -1;
1662
  }
3✔
1663

1664
  (void) pr_error_set_what(err, what);
3✔
1665

2✔
1666
  if (error_explainer->explainer->explain_getaddrinfo != NULL) {
1667
    explained = (error_explainer->explainer->explain_getaddrinfo)(
1668
      err->err_pool, err->err_errno, name, service, hints, res,
2✔
1669
      &(err->err_args));
1670
    xerrno = errno;
1671
  }
2✔
1672

2✔
1673
  if (explained == NULL) {
2✔
1674
    trace_explained_error(what, xerrno);
2✔
1675
    errno = xerrno;
1676
    return -1;
1677
  }
1✔
1678

1✔
1679
  err->err_explained = explained;
1680
  return 0;
1681
}
5✔
1682

5✔
1683
int pr_error_explain_gethostbyname(pr_error_t *err, const char *name) {
5✔
1684
  const char *what = "gethostbyname()", *explained = NULL;
1685
  int xerrno = ENOSYS;
5✔
1686

1687
  if (check_error(err) < 0) {
1688
    return -1;
1689
  }
3✔
1690

1691
  (void) pr_error_set_what(err, what);
3✔
1692

2✔
1693
  if (error_explainer->explainer->explain_gethostbyname != NULL) {
1694
    explained = (error_explainer->explainer->explain_gethostbyname)(
2✔
1695
      err->err_pool, err->err_errno, name, &(err->err_args));
1696
    xerrno = errno;
1697
  }
2✔
1698

2✔
1699
  if (explained == NULL) {
2✔
1700
    trace_explained_error(what, xerrno);
2✔
1701
    errno = xerrno;
1702
    return -1;
1703
  }
1✔
1704

1✔
1705
  err->err_explained = explained;
1706
  return 0;
1707
}
5✔
1708

1709
int pr_error_explain_gethostbyname2(pr_error_t *err, const char *name,
5✔
1710
    int family) {
5✔
1711
  const char *what = "gethostbyname2()", *explained = NULL;
1712
  int xerrno = ENOSYS;
5✔
1713

1714
  if (check_error(err) < 0) {
1715
    return -1;
1716
  }
3✔
1717

1718
  (void) pr_error_set_what(err, what);
3✔
1719

2✔
1720
  if (error_explainer->explainer->explain_gethostbyname2 != NULL) {
1721
    explained = (error_explainer->explainer->explain_gethostbyname2)(
2✔
1722
      err->err_pool, err->err_errno, name, family, &(err->err_args));
1723
    xerrno = errno;
1724
  }
2✔
1725

2✔
1726
  if (explained == NULL) {
2✔
1727
    trace_explained_error(what, xerrno);
2✔
1728
    errno = xerrno;
1729
    return -1;
1730
  }
1✔
1731

1✔
1732
  err->err_explained = explained;
1733
  return 0;
1734
}
5✔
1735

5✔
1736
int pr_error_explain_gethostname(pr_error_t *err, char *buf, size_t sz) {
5✔
1737
  const char *what = "gethostname()", *explained = NULL;
1738
  int xerrno = ENOSYS;
5✔
1739

1740
  if (check_error(err) < 0) {
1741
    return -1;
1742
  }
3✔
1743

1744
  (void) pr_error_set_what(err, what);
3✔
1745

2✔
1746
  if (error_explainer->explainer->explain_gethostname != NULL) {
1747
    explained = (error_explainer->explainer->explain_gethostname)(
2✔
1748
      err->err_pool, err->err_errno, buf, sz, &(err->err_args));
1749
    xerrno = errno;
1750
  }
2✔
1751

2✔
1752
  if (explained == NULL) {
2✔
1753
    trace_explained_error(what, xerrno);
2✔
1754
    errno = xerrno;
1755
    return -1;
1756
  }
1✔
1757

1✔
1758
  err->err_explained = explained;
1759
  return 0;
1760
}
5✔
1761

1762
int pr_error_explain_getnameinfo(pr_error_t *err, const struct sockaddr *addr,
1763
    socklen_t addr_len, char *host, size_t host_len, char *service,
5✔
1764
    size_t service_len, int flags) {
5✔
1765
  const char *what = "getnameinfo()", *explained = NULL;
1766
  int xerrno = ENOSYS;
5✔
1767

1768
  if (check_error(err) < 0) {
1769
    return -1;
1770
  }
3✔
1771

1772
  (void) pr_error_set_what(err, what);
3✔
1773

2✔
1774
  if (error_explainer->explainer->explain_getnameinfo != NULL) {
1775
    explained = (error_explainer->explainer->explain_getnameinfo)(
1776
      err->err_pool, err->err_errno, addr, addr_len, host, host_len, service,
2✔
1777
      service_len, flags, &(err->err_args));
1778
    xerrno = errno;
1779
  }
2✔
1780

2✔
1781
  if (explained == NULL) {
2✔
1782
    trace_explained_error(what, xerrno);
2✔
1783
    errno = xerrno;
1784
    return -1;
1785
  }
1✔
1786

1✔
1787
  err->err_explained = explained;
1788
  return 0;
1789
}
5✔
1790

1791
int pr_error_explain_getpeername(pr_error_t *err, int fd, struct sockaddr *addr,
5✔
1792
    socklen_t *addr_len) {
5✔
1793
  const char *what = "getpeername()", *explained = NULL;
1794
  int xerrno = ENOSYS;
5✔
1795

1796
  if (check_error(err) < 0) {
1797
    return -1;
1798
  }
3✔
1799

1800
  (void) pr_error_set_what(err, what);
3✔
1801

2✔
1802
  if (error_explainer->explainer->explain_getpeername != NULL) {
1803
    explained = (error_explainer->explainer->explain_getpeername)(
2✔
1804
      err->err_pool, err->err_errno, fd, addr, addr_len, &(err->err_args));
1805
    xerrno = errno;
1806
  }
2✔
1807

2✔
1808
  if (explained == NULL) {
2✔
1809
    trace_explained_error(what, xerrno);
2✔
1810
    errno = xerrno;
1811
    return -1;
1812
  }
1✔
1813

1✔
1814
  err->err_explained = explained;
1815
  return 0;
1816
}
5✔
1817

1818
int pr_error_explain_getrlimit(pr_error_t *err, int resource,
5✔
1819
    struct rlimit *rlim) {
5✔
1820
  const char *what = "getrlimit()", *explained = NULL;
1821
  int xerrno = ENOSYS;
5✔
1822

1823
  if (check_error(err) < 0) {
1824
    return -1;
1825
  }
3✔
1826

1827
  (void) pr_error_set_what(err, what);
3✔
1828

2✔
1829
  if (error_explainer->explainer->explain_getrlimit != NULL) {
1830
    explained = (error_explainer->explainer->explain_getrlimit)(
2✔
1831
      err->err_pool, err->err_errno, resource, rlim, &(err->err_args));
1832
    xerrno = errno;
1833
  }
2✔
1834

2✔
1835
  if (explained == NULL) {
2✔
1836
    trace_explained_error(what, xerrno);
2✔
1837
    errno = xerrno;
1838
    return -1;
1839
  }
1✔
1840

1✔
1841
  err->err_explained = explained;
1842
  return 0;
1843
}
5✔
1844

1845
int pr_error_explain_getsockname(pr_error_t *err, int fd, struct sockaddr *addr,
5✔
1846
    socklen_t *addr_len) {
5✔
1847
  const char *what = "getsockname()", *explained = NULL;
1848
  int xerrno = ENOSYS;
5✔
1849

1850
  if (check_error(err) < 0) {
1851
    return -1;
1852
  }
3✔
1853

1854
  (void) pr_error_set_what(err, what);
3✔
1855

2✔
1856
  if (error_explainer->explainer->explain_getsockname != NULL) {
1857
    explained = (error_explainer->explainer->explain_getsockname)(
2✔
1858
      err->err_pool, err->err_errno, fd, addr, addr_len, &(err->err_args));
1859
    xerrno = errno;
1860
  }
2✔
1861

2✔
1862
  if (explained == NULL) {
2✔
1863
    trace_explained_error(what, xerrno);
2✔
1864
    errno = xerrno;
1865
    return -1;
1866
  }
1✔
1867

1✔
1868
  err->err_explained = explained;
1869
  return 0;
1870
}
5✔
1871

1872
int pr_error_explain_getsockopt(pr_error_t *err, int fd, int level, int option,
5✔
1873
    void *val, socklen_t *valsz) {
5✔
1874
  const char *what = "getsockopt()", *explained = NULL;
1875
  int xerrno = ENOSYS;
5✔
1876

1877
  if (check_error(err) < 0) {
1878
    return -1;
1879
  }
3✔
1880

1881
  (void) pr_error_set_what(err, what);
3✔
1882

2✔
1883
  if (error_explainer->explainer->explain_getsockopt != NULL) {
1884
    explained = (error_explainer->explainer->explain_getsockopt)(
1885
      err->err_pool, err->err_errno, fd, level, option, val, valsz,
2✔
1886
      &(err->err_args));
1887
    xerrno = errno;
1888
  }
2✔
1889

2✔
1890
  if (explained == NULL) {
2✔
1891
    trace_explained_error(what, xerrno);
2✔
1892
    errno = xerrno;
1893
    return -1;
1894
  }
1✔
1895

1✔
1896
  err->err_explained = explained;
1897
  return 0;
1898
}
7✔
1899

1900
int pr_error_explain_lchown(pr_error_t *err, const char *path, uid_t uid,
7✔
1901
    gid_t gid) {
7✔
1902
  const char *what = "lchown()", *explained = NULL;
1903
  int xerrno = ENOSYS;
7✔
1904

1905
  if (check_error(err) < 0) {
1906
    return -1;
1907
  }
4✔
1908

1909
  (void) pr_error_set_what(err, what);
4✔
1910

3✔
1911
  if (error_explainer->explainer->explain_lchown != NULL) {
1912
    explained = (error_explainer->explainer->explain_lchown)(err->err_pool,
3✔
1913
      err->err_errno, path, uid, gid, &(err->err_args));
1914
    xerrno = errno;
1915
  }
3✔
1916

2✔
1917
  if (explained == NULL) {
2✔
1918
    trace_explained_error(what, xerrno);
2✔
1919
    errno = xerrno;
1920
    return -1;
1921
  }
2✔
1922

2✔
1923
  err->err_explained = explained;
1924
  return 0;
1925
}
5✔
1926

1927
int pr_error_explain_link(pr_error_t *err, const char *target_path,
5✔
1928
    const char *link_path) {
5✔
1929
  const char *what = "link()", *explained = NULL;
1930
  int xerrno = ENOSYS;
5✔
1931

1932
  if (check_error(err) < 0) {
1933
    return -1;
1934
  }
3✔
1935

1936
  (void) pr_error_set_what(err, what);
3✔
1937

2✔
1938
  if (error_explainer->explainer->explain_link != NULL) {
1939
    explained = (error_explainer->explainer->explain_link)(err->err_pool,
2✔
1940
      err->err_errno, target_path, link_path, &(err->err_args));
1941
    xerrno = errno;
1942
  }
2✔
1943

2✔
1944
  if (explained == NULL) {
2✔
1945
    trace_explained_error(what, xerrno);
2✔
1946
    errno = xerrno;
1947
    return -1;
1948
  }
1✔
1949

1✔
1950
  err->err_explained = explained;
1951
  return 0;
1952
}
5✔
1953

5✔
1954
int pr_error_explain_listen(pr_error_t *err, int fd, int backlog) {
5✔
1955
  const char *what = "listen()", *explained = NULL;
1956
  int xerrno = ENOSYS;
5✔
1957

1958
  if (check_error(err) < 0) {
1959
    return -1;
1960
  }
3✔
1961

1962
  (void) pr_error_set_what(err, what);
3✔
1963

2✔
1964
  if (error_explainer->explainer->explain_listen != NULL) {
1965
    explained = (error_explainer->explainer->explain_listen)(err->err_pool,
2✔
1966
      err->err_errno, fd, backlog, &(err->err_args));
1967
    xerrno = errno;
1968
  }
2✔
1969

2✔
1970
  if (explained == NULL) {
2✔
1971
    trace_explained_error(what, xerrno);
2✔
1972
    errno = xerrno;
1973
    return -1;
1974
  }
1✔
1975

1✔
1976
  err->err_explained = explained;
1977
  return 0;
1978
}
5✔
1979

5✔
1980
int pr_error_explain_lseek(pr_error_t *err, int fd, off_t offset, int whence) {
5✔
1981
  const char *what = "lseek()", *explained = NULL;
1982
  int xerrno = ENOSYS;
5✔
1983

1984
  if (check_error(err) < 0) {
1985
    return -1;
1986
  }
3✔
1987

1988
  (void) pr_error_set_what(err, what);
3✔
1989

2✔
1990
  if (error_explainer->explainer->explain_lseek != NULL) {
1991
    explained = (error_explainer->explainer->explain_lseek)(err->err_pool,
2✔
1992
      err->err_errno, fd, offset, whence, &(err->err_args));
1993
    xerrno = errno;
1994
  }
2✔
1995

2✔
1996
  if (explained == NULL) {
2✔
1997
    trace_explained_error(what, xerrno);
2✔
1998
    errno = xerrno;
1999
    return -1;
2000
  }
1✔
2001

1✔
2002
  err->err_explained = explained;
2003
  return 0;
2004
}
7✔
2005

2006
int pr_error_explain_lstat(pr_error_t *err, const char *path,
7✔
2007
    struct stat *st) {
7✔
2008
  const char *what = "lstat()", *explained = NULL;
2009
  int xerrno = ENOSYS;
7✔
2010

2011
  if (check_error(err) < 0) {
2012
    return -1;
2013
  }
4✔
2014

2015
  (void) pr_error_set_what(err, what);
4✔
2016

3✔
2017
  if (error_explainer->explainer->explain_lstat != NULL) {
2018
    explained = (error_explainer->explainer->explain_lstat)(err->err_pool,
3✔
2019
      err->err_errno, path, st, &(err->err_args));
2020
    xerrno = errno;
2021
  }
3✔
2022

2✔
2023
  if (explained == NULL) {
2✔
2024
    trace_explained_error(what, xerrno);
2✔
2025
    errno = xerrno;
2026
    return -1;
2027
  }
2✔
2028

2✔
2029
  err->err_explained = explained;
2030
  return 0;
2031
}
7✔
2032

7✔
2033
int pr_error_explain_mkdir(pr_error_t *err, const char *path, mode_t mode) {
7✔
2034
  const char *what = "mkdir()", *explained = NULL;
2035
  int xerrno = ENOSYS;
7✔
2036

2037
  if (check_error(err) < 0) {
2038
    return -1;
2039
  }
4✔
2040

2041
  (void) pr_error_set_what(err, what);
4✔
2042

3✔
2043
  if (error_explainer->explainer->explain_mkdir != NULL) {
2044
    explained = (error_explainer->explainer->explain_mkdir)(err->err_pool,
3✔
2045
      err->err_errno, path, mode, &(err->err_args));
2046
    xerrno = errno;
2047
  }
3✔
2048

2✔
2049
  if (explained == NULL) {
2✔
2050
    trace_explained_error(what, xerrno);
2✔
2051
    errno = xerrno;
2052
    return -1;
2053
  }
2✔
2054

2✔
2055
  err->err_explained = explained;
2056
  return 0;
2057
}
5✔
2058

5✔
2059
int pr_error_explain_mkdtemp(pr_error_t *err, char *tmpl) {
5✔
2060
  const char *what = "mkdtemp()", *explained = NULL;
2061
  int xerrno = ENOSYS;
5✔
2062

2063
  if (check_error(err) < 0) {
2064
    return -1;
2065
  }
3✔
2066

2067
  (void) pr_error_set_what(err, what);
3✔
2068

2✔
2069
  if (error_explainer->explainer->explain_mkdtemp != NULL) {
2070
    explained = (error_explainer->explainer->explain_mkdtemp)(err->err_pool,
2✔
2071
      err->err_errno, tmpl, &(err->err_args));
2072
    xerrno = errno;
2073
  }
2✔
2074

2✔
2075
  if (explained == NULL) {
2✔
2076
    trace_explained_error(what, xerrno);
2✔
2077
    errno = xerrno;
2078
    return -1;
2079
  }
1✔
2080

1✔
2081
  err->err_explained = explained;
2082
  return 0;
2083
}
5✔
2084

5✔
2085
int pr_error_explain_mkstemp(pr_error_t *err, char *tmpl) {
5✔
2086
  const char *what = "mkstemp()", *explained = NULL;
2087
  int xerrno = ENOSYS;
5✔
2088

2089
  if (check_error(err) < 0) {
2090
    return -1;
2091
  }
3✔
2092

2093
  (void) pr_error_set_what(err, what);
3✔
2094

2✔
2095
  if (error_explainer->explainer->explain_mkstemp != NULL) {
2096
    explained = (error_explainer->explainer->explain_mkstemp)(err->err_pool,
2✔
2097
      err->err_errno, tmpl, &(err->err_args));
2098
    xerrno = errno;
2099
  }
2✔
2100

2✔
2101
  if (explained == NULL) {
2✔
2102
    trace_explained_error(what, xerrno);
2✔
2103
    errno = xerrno;
2104
    return -1;
2105
  }
1✔
2106

1✔
2107
  err->err_explained = explained;
2108
  return 0;
2109
}
8✔
2110

2111
int pr_error_explain_open(pr_error_t *err, const char *path, int flags,
8✔
2112
    mode_t mode) {
8✔
2113
  const char *what = "open()", *explained = NULL;
2114
  int xerrno = ENOSYS;
8✔
2115

2116
  if (check_error(err) < 0) {
2117
    return -1;
2118
  }
5✔
2119

2120
  (void) pr_error_set_what(err, what);
5✔
2121

4✔
2122
  if (error_explainer->explainer->explain_open != NULL) {
2123
    explained = (error_explainer->explainer->explain_open)(err->err_pool,
4✔
2124
      err->err_errno, path, flags, mode, &(err->err_args));
2125
    xerrno = errno;
2126
  }
4✔
2127

2✔
2128
  if (explained == NULL) {
2✔
2129
    trace_explained_error(what, xerrno);
2✔
2130
    errno = xerrno;
2131
    return -1;
2132
  }
3✔
2133

3✔
2134
  err->err_explained = explained;
2135
  return 0;
2136
}
5✔
2137

5✔
2138
int pr_error_explain_opendir(pr_error_t *err, const char *path) {
5✔
2139
  const char *what = "opendir()", *explained = NULL;
2140
  int xerrno = ENOSYS;
5✔
2141

2142
  if (check_error(err) < 0) {
2143
    return -1;
2144
  }
3✔
2145

2146
  (void) pr_error_set_what(err, what);
3✔
2147

2✔
2148
  if (error_explainer->explainer->explain_opendir != NULL) {
2149
    explained = (error_explainer->explainer->explain_opendir)(err->err_pool,
2✔
2150
      err->err_errno, path, &(err->err_args));
2151
    xerrno = errno;
2152
  }
2✔
2153

2✔
2154
  if (explained == NULL) {
2✔
2155
    trace_explained_error(what, xerrno);
2✔
2156
    errno = xerrno;
2157
    return -1;
2158
  }
1✔
2159

1✔
2160
  err->err_explained = explained;
2161
  return 0;
2162
}
7✔
2163

7✔
2164
int pr_error_explain_read(pr_error_t *err, int fd, void *buf, size_t sz) {
7✔
2165
  const char *what = "read()", *explained = NULL;
2166
  int xerrno = ENOSYS;
7✔
2167

2168
  if (check_error(err) < 0) {
2169
    return -1;
2170
  }
4✔
2171

2172
  (void) pr_error_set_what(err, what);
4✔
2173

3✔
2174
  if (error_explainer->explainer->explain_read != NULL) {
2175
    explained = (error_explainer->explainer->explain_read)(err->err_pool,
3✔
2176
      err->err_errno, fd, buf, sz, &(err->err_args));
2177
    xerrno = errno;
2178
  }
3✔
2179

2✔
2180
  if (explained == NULL) {
2✔
2181
    trace_explained_error(what, xerrno);
2✔
2182
    errno = xerrno;
2183
    return -1;
2184
  }
2✔
2185

2✔
2186
  err->err_explained = explained;
2187
  return 0;
2188
}
5✔
2189

5✔
2190
int pr_error_explain_readdir(pr_error_t *err, void *dirh) {
5✔
2191
  const char *what = "readdir()", *explained = NULL;
2192
  int xerrno = ENOSYS;
5✔
2193

2194
  if (check_error(err) < 0) {
2195
    return -1;
2196
  }
3✔
2197

2198
  (void) pr_error_set_what(err, what);
3✔
2199

2✔
2200
  if (error_explainer->explainer->explain_readdir != NULL) {
2201
    explained = (error_explainer->explainer->explain_readdir)(err->err_pool,
2✔
2202
      err->err_errno, dirh, &(err->err_args));
2203
    xerrno = errno;
2204
  }
2✔
2205

2✔
2206
  if (explained == NULL) {
2✔
2207
    trace_explained_error(what, xerrno);
2✔
2208
    errno = xerrno;
2209
    return -1;
2210
  }
1✔
2211

1✔
2212
  err->err_explained = explained;
2213
  return 0;
2214
}
5✔
2215

2216
int pr_error_explain_readlink(pr_error_t *err, const char *path, char *buf,
5✔
2217
    size_t sz) {
5✔
2218
  const char *what = "readlink()", *explained = NULL;
2219
  int xerrno = ENOSYS;
5✔
2220

2221
  if (check_error(err) < 0) {
2222
    return -1;
2223
  }
3✔
2224

2225
  (void) pr_error_set_what(err, what);
3✔
2226

2✔
2227
  if (error_explainer->explainer->explain_readlink != NULL) {
2228
    explained = (error_explainer->explainer->explain_readlink)(err->err_pool,
2✔
2229
      err->err_errno, path, buf, sz, &(err->err_args));
2230
    xerrno = errno;
2231
  }
2✔
2232

2✔
2233
  if (explained == NULL) {
2✔
2234
    trace_explained_error(what, xerrno);
2✔
2235
    errno = xerrno;
2236
    return -1;
2237
  }
1✔
2238

1✔
2239
  err->err_explained = explained;
2240
  return 0;
2241
}
5✔
2242

2243
int pr_error_explain_readv(pr_error_t *err, int fd, const struct iovec *iov,
5✔
2244
    int iov_len) {
5✔
2245
  const char *what = "readv()", *explained = NULL;
2246
  int xerrno = ENOSYS;
5✔
2247

2248
  if (check_error(err) < 0) {
2249
    return -1;
2250
  }
3✔
2251

2252
  (void) pr_error_set_what(err, what);
3✔
2253

2✔
2254
  if (error_explainer->explainer->explain_readv != NULL) {
2255
    explained = (error_explainer->explainer->explain_readv)(err->err_pool,
2✔
2256
      err->err_errno, fd, iov, iov_len, &(err->err_args));
2257
    xerrno = errno;
2258
  }
2✔
2259

2✔
2260
  if (explained == NULL) {
2✔
2261
    trace_explained_error(what, xerrno);
2✔
2262
    errno = xerrno;
2263
    return -1;
2264
  }
1✔
2265

1✔
2266
  err->err_explained = explained;
2267
  return 0;
2268
}
7✔
2269

2270
int pr_error_explain_rename(pr_error_t *err, const char *old_path,
7✔
2271
    const char *new_path) {
7✔
2272
  const char *what = "rename()", *explained = NULL;
2273
  int xerrno = ENOSYS;
7✔
2274

2275
  if (check_error(err) < 0) {
2276
    return -1;
2277
  }
4✔
2278

2279
  (void) pr_error_set_what(err, what);
4✔
2280

3✔
2281
  if (error_explainer->explainer->explain_rename != NULL) {
2282
    explained = (error_explainer->explainer->explain_rename)(err->err_pool,
3✔
2283
      err->err_errno, old_path, new_path, &(err->err_args));
2284
    xerrno = errno;
2285
  }
3✔
2286

2✔
2287
  if (explained == NULL) {
2✔
2288
    trace_explained_error(what, xerrno);
2✔
2289
    errno = xerrno;
2290
    return -1;
2291
  }
2✔
2292

2✔
2293
  err->err_explained = explained;
2294
  return 0;
2295
}
6✔
2296

6✔
2297
int pr_error_explain_rmdir(pr_error_t *err, const char *path) {
6✔
2298
  const char *what = "rmdir()", *explained = NULL;
2299
  int xerrno = ENOSYS;
6✔
2300

2301
  if (check_error(err) < 0) {
2302
    return -1;
2303
  }
4✔
2304

2305
  (void) pr_error_set_what(err, what);
4✔
2306

3✔
2307
  if (error_explainer->explainer->explain_rmdir != NULL) {
2308
    explained = (error_explainer->explainer->explain_rmdir)(err->err_pool,
3✔
2309
      err->err_errno, path, &(err->err_args));
2310
    xerrno = errno;
2311
  }
3✔
2312

2✔
2313
  if (explained == NULL) {
2✔
2314
    trace_explained_error(what, xerrno);
2✔
2315
    errno = xerrno;
2316
    return -1;
2317
  }
2✔
2318

2✔
2319
  err->err_explained = explained;
2320
  return 0;
2321
}
5✔
2322

5✔
2323
int pr_error_explain_setegid(pr_error_t *err, gid_t gid) {
5✔
2324
  const char *what = "setegid()", *explained = NULL;
2325
  int xerrno = ENOSYS;
5✔
2326

2327
  if (check_error(err) < 0) {
2328
    return -1;
2329
  }
3✔
2330

2331
  (void) pr_error_set_what(err, what);
3✔
2332

2✔
2333
  if (error_explainer->explainer->explain_setegid != NULL) {
2334
    explained = (error_explainer->explainer->explain_setegid)(err->err_pool,
2✔
2335
      err->err_errno, gid, &(err->err_args));
2336
    xerrno = errno;
2337
  }
2✔
2338

2✔
2339
  if (explained == NULL) {
2✔
2340
    trace_explained_error(what, xerrno);
2✔
2341
    errno = xerrno;
2342
    return -1;
2343
  }
1✔
2344

1✔
2345
  err->err_explained = explained;
2346
  return 0;
2347
}
5✔
2348

5✔
2349
int pr_error_explain_seteuid(pr_error_t *err, uid_t uid) {
5✔
2350
  const char *what = "seteuid()", *explained = NULL;
2351
  int xerrno = ENOSYS;
5✔
2352

2353
  if (check_error(err) < 0) {
2354
    return -1;
2355
  }
3✔
2356

2357
  (void) pr_error_set_what(err, what);
3✔
2358

2✔
2359
  if (error_explainer->explainer->explain_seteuid != NULL) {
2360
    explained = (error_explainer->explainer->explain_seteuid)(err->err_pool,
2✔
2361
      err->err_errno, uid, &(err->err_args));
2362
    xerrno = errno;
2363
  }
2✔
2364

2✔
2365
  if (explained == NULL) {
2✔
2366
    trace_explained_error(what, xerrno);
2✔
2367
    errno = xerrno;
2368
    return -1;
2369
  }
1✔
2370

1✔
2371
  err->err_explained = explained;
2372
  return 0;
2373
}
5✔
2374

5✔
2375
int pr_error_explain_setgid(pr_error_t *err, gid_t gid) {
5✔
2376
  const char *what = "setgid()", *explained = NULL;
2377
  int xerrno = ENOSYS;
5✔
2378

2379
  if (check_error(err) < 0) {
2380
    return -1;
2381
  }
3✔
2382

2383
  (void) pr_error_set_what(err, what);
3✔
2384

2✔
2385
  if (error_explainer->explainer->explain_setgid != NULL) {
2386
    explained = (error_explainer->explainer->explain_setgid)(err->err_pool,
2✔
2387
      err->err_errno, gid, &(err->err_args));
2388
    xerrno = errno;
2389
  }
2✔
2390

2✔
2391
  if (explained == NULL) {
2✔
2392
    trace_explained_error(what, xerrno);
2✔
2393
    errno = xerrno;
2394
    return -1;
2395
  }
1✔
2396

1✔
2397
  err->err_explained = explained;
2398
  return 0;
2399
}
5✔
2400

5✔
2401
int pr_error_explain_setregid(pr_error_t *err, gid_t rgid, gid_t egid) {
5✔
2402
  const char *what = "setregid()", *explained = NULL;
2403
  int xerrno = ENOSYS;
5✔
2404

2405
  if (check_error(err) < 0) {
2406
    return -1;
2407
  }
3✔
2408

2409
  (void) pr_error_set_what(err, what);
3✔
2410

2✔
2411
  if (error_explainer->explainer->explain_setregid != NULL) {
2412
    explained = (error_explainer->explainer->explain_setregid)(err->err_pool,
2✔
2413
      err->err_errno, rgid, egid, &(err->err_args));
2414
    xerrno = errno;
2415
  }
2✔
2416

2✔
2417
  if (explained == NULL) {
2✔
2418
    trace_explained_error(what, xerrno);
2✔
2419
    errno = xerrno;
2420
    return -1;
2421
  }
1✔
2422

1✔
2423
  err->err_explained = explained;
2424
  return 0;
2425
}
5✔
2426

2427
int pr_error_explain_setresgid(pr_error_t *err, gid_t rgid, gid_t egid,
5✔
2428
    gid_t sgid) {
5✔
2429
  const char *what = "setresgid()", *explained = NULL;
2430
  int xerrno = ENOSYS;
5✔
2431

2432
  if (check_error(err) < 0) {
2433
    return -1;
2434
  }
3✔
2435

2436
  (void) pr_error_set_what(err, what);
3✔
2437

2✔
2438
  if (error_explainer->explainer->explain_setresgid != NULL) {
2439
    explained = (error_explainer->explainer->explain_setresgid)(
2✔
2440
      err->err_pool, err->err_errno, rgid, egid, sgid, &(err->err_args));
2441
    xerrno = errno;
2442
  }
2✔
2443

2✔
2444
  if (explained == NULL) {
2✔
2445
    trace_explained_error(what, xerrno);
2✔
2446
    errno = xerrno;
2447
    return -1;
2448
  }
1✔
2449

1✔
2450
  err->err_explained = explained;
2451
  return 0;
2452
}
5✔
2453

2454
int pr_error_explain_setresuid(pr_error_t *err, uid_t ruid, uid_t euid,
5✔
2455
    uid_t suid) {
5✔
2456
  const char *what = "setresuid()", *explained = NULL;
2457
  int xerrno = ENOSYS;
5✔
2458

2459
  if (check_error(err) < 0) {
2460
    return -1;
2461
  }
3✔
2462

2463
  (void) pr_error_set_what(err, what);
3✔
2464

2✔
2465
  if (error_explainer->explainer->explain_setresuid != NULL) {
2466
    explained = (error_explainer->explainer->explain_setresuid)(
2✔
2467
      err->err_pool, err->err_errno, ruid, euid, suid, &(err->err_args));
2468
    xerrno = errno;
2469
  }
2✔
2470

2✔
2471
  if (explained == NULL) {
2✔
2472
    trace_explained_error(what, xerrno);
2✔
2473
    errno = xerrno;
2474
    return -1;
2475
  }
1✔
2476

1✔
2477
  err->err_explained = explained;
2478
  return 0;
2479
}
5✔
2480

5✔
2481
int pr_error_explain_setreuid(pr_error_t *err, uid_t ruid, uid_t euid) {
5✔
2482
  const char *what = "setreuid()", *explained = NULL;
2483
  int xerrno = ENOSYS;
5✔
2484

2485
  if (check_error(err) < 0) {
2486
    return -1;
2487
  }
3✔
2488

2489
  (void) pr_error_set_what(err, what);
3✔
2490

2✔
2491
  if (error_explainer->explainer->explain_setreuid != NULL) {
2492
    explained = (error_explainer->explainer->explain_setreuid)(err->err_pool,
2✔
2493
      err->err_errno, ruid, euid, &(err->err_args));
2494
    xerrno = errno;
2495
  }
2✔
2496

2✔
2497
  if (explained == NULL) {
2✔
2498
    trace_explained_error(what, xerrno);
2✔
2499
    errno = xerrno;
2500
    return -1;
2501
  }
1✔
2502

1✔
2503
  err->err_explained = explained;
2504
  return 0;
2505
}
5✔
2506

2507
int pr_error_explain_setrlimit(pr_error_t *err, int resource,
5✔
2508
    const struct rlimit *rlim) {
5✔
2509
  const char *what = "setrlimit()", *explained = NULL;
2510
  int xerrno = ENOSYS;
5✔
2511

2512
  if (check_error(err) < 0) {
2513
    return -1;
2514
  }
3✔
2515

2516
  (void) pr_error_set_what(err, what);
3✔
2517

2✔
2518
  if (error_explainer->explainer->explain_setrlimit != NULL) {
2519
    explained = (error_explainer->explainer->explain_setrlimit)(
2✔
2520
      err->err_pool, err->err_errno, resource, rlim, &(err->err_args));
2521
    xerrno = errno;
2522
  }
2✔
2523

2✔
2524
  if (explained == NULL) {
2✔
2525
    trace_explained_error(what, xerrno);
2✔
2526
    errno = xerrno;
2527
    return -1;
2528
  }
1✔
2529

1✔
2530
  err->err_explained = explained;
2531
  return 0;
2532
}
5✔
2533

2534
int pr_error_explain_setsockopt(pr_error_t *err, int fd, int level, int option,
5✔
2535
    const void *val, socklen_t valsz) {
5✔
2536
  const char *what = "setsockopt()", *explained = NULL;
2537
  int xerrno = ENOSYS;
5✔
2538

2539
  if (check_error(err) < 0) {
2540
    return -1;
2541
  }
3✔
2542

2543
  (void) pr_error_set_what(err, what);
3✔
2544

2✔
2545
  if (error_explainer->explainer->explain_setsockopt != NULL) {
2546
    explained = (error_explainer->explainer->explain_setsockopt)(
2547
      err->err_pool, err->err_errno, fd, level, option, val, valsz,
2✔
2548
      &(err->err_args));
2549
    xerrno = errno;
2550
  }
2✔
2551

2✔
2552
  if (explained == NULL) {
2✔
2553
    trace_explained_error(what, xerrno);
2✔
2554
    errno = xerrno;
2555
    return -1;
2556
  }
1✔
2557

1✔
2558
  err->err_explained = explained;
2559
  return 0;
2560
}
5✔
2561

5✔
2562
int pr_error_explain_setuid(pr_error_t *err, uid_t uid) {
5✔
2563
  const char *what = "setuid()", *explained = NULL;
2564
  int xerrno = ENOSYS;
5✔
2565

2566
  if (check_error(err) < 0) {
2567
    return -1;
2568
  }
3✔
2569

2570
  (void) pr_error_set_what(err, what);
3✔
2571

2✔
2572
  if (error_explainer->explainer->explain_setuid != NULL) {
2573
    explained = (error_explainer->explainer->explain_setuid)(err->err_pool,
2✔
2574
      err->err_errno, uid, &(err->err_args));
2575
    xerrno = errno;
2576
  }
2✔
2577

2✔
2578
  if (explained == NULL) {
2✔
2579
    trace_explained_error(what, xerrno);
2✔
2580
    errno = xerrno;
2581
    return -1;
2582
  }
1✔
2583

1✔
2584
  err->err_explained = explained;
2585
  return 0;
2586
}
5✔
2587

5✔
2588
int pr_error_explain_socket(pr_error_t *err, int domain, int type, int proto) {
5✔
2589
  const char *what = "socket()", *explained = NULL;
2590
  int xerrno = ENOSYS;
5✔
2591

2592
  if (check_error(err) < 0) {
2593
    return -1;
2594
  }
3✔
2595

2596
  (void) pr_error_set_what(err, what);
3✔
2597

2✔
2598
  if (error_explainer->explainer->explain_socket != NULL) {
2599
    explained = (error_explainer->explainer->explain_socket)(err->err_pool,
2✔
2600
      err->err_errno, domain, type, proto, &(err->err_args));
2601
    xerrno = errno;
2602
  }
2✔
2603

2✔
2604
  if (explained == NULL) {
2✔
2605
    trace_explained_error(what, xerrno);
2✔
2606
    errno = xerrno;
2607
    return -1;
2608
  }
1✔
2609

1✔
2610
  err->err_explained = explained;
2611
  return 0;
2612
}
7✔
2613

7✔
2614
int pr_error_explain_stat(pr_error_t *err, const char *path, struct stat *st) {
7✔
2615
  const char *what = "stat()", *explained = NULL;
2616
  int xerrno = ENOSYS;
7✔
2617

2618
  if (check_error(err) < 0) {
2619
    return -1;
2620
  }
4✔
2621

2622
  (void) pr_error_set_what(err, what);
4✔
2623

3✔
2624
  if (error_explainer->explainer->explain_stat != NULL) {
2625
    explained = (error_explainer->explainer->explain_stat)(err->err_pool,
3✔
2626
      err->err_errno, path, st, &(err->err_args));
2627
    xerrno = errno;
2628
  }
3✔
2629

2✔
2630
  if (explained == NULL) {
2✔
2631
    trace_explained_error(what, xerrno);
2✔
2632
    errno = xerrno;
2633
    return -1;
2634
  }
2✔
2635

2✔
2636
  err->err_explained = explained;
2637
  return 0;
2638
}
5✔
2639

5✔
2640
int pr_error_explain_statfs(pr_error_t *err, const char *path, void *stfs) {
5✔
2641
  const char *what = "statfs()", *explained = NULL;
2642
  int xerrno = ENOSYS;
5✔
2643

2644
  if (check_error(err) < 0) {
2645
    return -1;
2646
  }
3✔
2647

2648
  (void) pr_error_set_what(err, what);
3✔
2649

2✔
2650
  if (error_explainer->explainer->explain_statfs != NULL) {
2651
    explained = (error_explainer->explainer->explain_statfs)(err->err_pool,
2✔
2652
      err->err_errno, path, stfs, &(err->err_args));
2653
    xerrno = errno;
2654
  }
2✔
2655

2✔
2656
  if (explained == NULL) {
2✔
2657
    trace_explained_error(what, xerrno);
2✔
2658
    errno = xerrno;
2659
    return -1;
2660
  }
1✔
2661

1✔
2662
  err->err_explained = explained;
2663
  return 0;
2664
}
5✔
2665

5✔
2666
int pr_error_explain_statvfs(pr_error_t *err, const char *path, void *stfs) {
5✔
2667
  const char *what = "statvfs()", *explained = NULL;
2668
  int xerrno = ENOSYS;
5✔
2669

2670
  if (check_error(err) < 0) {
2671
    return -1;
2672
  }
3✔
2673

2674
  (void) pr_error_set_what(err, what);
3✔
2675

2✔
2676
  if (error_explainer->explainer->explain_statvfs != NULL) {
2677
    explained = (error_explainer->explainer->explain_statvfs)(err->err_pool,
2✔
2678
      err->err_errno, path, stfs, &(err->err_args));
2679
    xerrno = errno;
2680
  }
2✔
2681

2✔
2682
  if (explained == NULL) {
2✔
2683
    trace_explained_error(what, xerrno);
2✔
2684
    errno = xerrno;
2685
    return -1;
2686
  }
1✔
2687

1✔
2688
  err->err_explained = explained;
2689
  return 0;
2690
}
5✔
2691

2692
int pr_error_explain_symlink(pr_error_t *err, const char *target_path,
5✔
2693
    const char *link_path) {
5✔
2694
  const char *what = "symlink()", *explained = NULL;
2695
  int xerrno = ENOSYS;
5✔
2696

2697
  if (check_error(err) < 0) {
2698
    return -1;
2699
  }
3✔
2700

2701
  (void) pr_error_set_what(err, what);
3✔
2702

2✔
2703
  if (error_explainer->explainer->explain_symlink != NULL) {
2704
    explained = (error_explainer->explainer->explain_symlink)(err->err_pool,
2✔
2705
      err->err_errno, target_path, link_path, &(err->err_args));
2706
    xerrno = errno;
2707
  }
2✔
2708

2✔
2709
  if (explained == NULL) {
2✔
2710
    trace_explained_error(what, xerrno);
2✔
2711
    errno = xerrno;
2712
    return -1;
2713
  }
1✔
2714

1✔
2715
  err->err_explained = explained;
2716
  return 0;
2717
}
5✔
2718

5✔
2719
int pr_error_explain_truncate(pr_error_t *err, const char *path, off_t len) {
5✔
2720
  const char *what = "truncate()", *explained = NULL;
2721
  int xerrno = ENOSYS;
5✔
2722

2723
  if (check_error(err) < 0) {
2724
    return -1;
2725
  }
3✔
2726

2727
  (void) pr_error_set_what(err, what);
3✔
2728

2✔
2729
  if (error_explainer->explainer->explain_truncate != NULL) {
2730
    explained = (error_explainer->explainer->explain_truncate)(err->err_pool,
2✔
2731
      err->err_errno, path, len, &(err->err_args));
2732
    xerrno = errno;
2733
  }
2✔
2734

2✔
2735
  if (explained == NULL) {
2✔
2736
    trace_explained_error(what, xerrno);
2✔
2737
    errno = xerrno;
2738
    return -1;
2739
  }
1✔
2740

1✔
2741
  err->err_explained = explained;
2742
  return 0;
2743
}
7✔
2744

7✔
2745
int pr_error_explain_unlink(pr_error_t *err, const char *path) {
7✔
2746
  const char *what = "unlink()", *explained = NULL;
2747
  int xerrno = ENOSYS;
7✔
2748

2749
  if (check_error(err) < 0) {
2750
    return -1;
2751
  }
4✔
2752

2753
  (void) pr_error_set_what(err, what);
4✔
2754

3✔
2755
  if (error_explainer->explainer->explain_unlink != NULL) {
2756
    explained = (error_explainer->explainer->explain_unlink)(err->err_pool,
3✔
2757
      err->err_errno, path, &(err->err_args));
2758
    xerrno = errno;
2759
  }
3✔
2760

2✔
2761
  if (explained == NULL) {
2✔
2762
    trace_explained_error(what, xerrno);
2✔
2763
    errno = xerrno;
2764
    return -1;
2765
  }
2✔
2766

2✔
2767
  err->err_explained = explained;
2768
  return 0;
2769
}
5✔
2770

2771
int pr_error_explain_utimes(pr_error_t *err, const char *path,
5✔
2772
    const struct timeval *tvs) {
5✔
2773
  const char *what = "utimes()", *explained = NULL;
2774
  int xerrno = ENOSYS;
5✔
2775

2776
  if (check_error(err) < 0) {
2777
    return -1;
2778
  }
3✔
2779

2780
  (void) pr_error_set_what(err, what);
3✔
2781

2✔
2782
  if (error_explainer->explainer->explain_utimes != NULL) {
2783
    explained = (error_explainer->explainer->explain_utimes)(err->err_pool,
2✔
2784
      err->err_errno, path, tvs, &(err->err_args));
2785
    xerrno = errno;
2786
  }
2✔
2787

2✔
2788
  if (explained == NULL) {
2✔
2789
    trace_explained_error(what, xerrno);
2✔
2790
    errno = xerrno;
2791
    return -1;
2792
  }
1✔
2793

1✔
2794
  err->err_explained = explained;
2795
  return 0;
2796
}
7✔
2797

2798
int pr_error_explain_write(pr_error_t *err, int fd, const void *buf,
7✔
2799
    size_t sz) {
7✔
2800
  const char *what = "write()", *explained = NULL;
2801
  int xerrno = ENOSYS;
7✔
2802

2803
  if (check_error(err) < 0) {
2804
    return -1;
2805
  }
4✔
2806

2807
  (void) pr_error_set_what(err, what);
4✔
2808

3✔
2809
  if (error_explainer->explainer->explain_write != NULL) {
2810
    explained = (error_explainer->explainer->explain_write)(err->err_pool,
3✔
2811
      err->err_errno, fd, buf, sz, &(err->err_args));
2812
    xerrno = errno;
2813
  }
3✔
2814

2✔
2815
  if (explained == NULL) {
2✔
2816
    trace_explained_error(what, xerrno);
2✔
2817
    errno = xerrno;
2818
    return -1;
2819
  }
2✔
2820

2✔
2821
  err->err_explained = explained;
2822
  return 0;
2823
}
5✔
2824

2825
int pr_error_explain_writev(pr_error_t *err, int fd,
5✔
2826
    const struct iovec *iov, int iov_len) {
5✔
2827
  const char *what = "writev()", *explained = NULL;
2828
  int xerrno = ENOSYS;
5✔
2829

2830
  if (check_error(err) < 0) {
2831
    return -1;
2832
  }
3✔
2833

2834
  (void) pr_error_set_what(err, what);
3✔
2835

2✔
2836
  if (error_explainer->explainer->explain_writev != NULL) {
2837
    explained = (error_explainer->explainer->explain_writev)(err->err_pool,
2✔
2838
      err->err_errno, fd, iov, iov_len, &(err->err_args));
2839
    xerrno = errno;
2840
  }
2✔
2841

2✔
2842
  if (explained == NULL) {
2✔
2843
    trace_explained_error(what, xerrno);
2✔
2844
    errno = xerrno;
2845
    return -1;
2846
  }
1✔
2847

1✔
2848
  err->err_explained = explained;
2849
  return 0;
2850
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc