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

proftpd / proftpd / 15076294441

16 May 2025 07:54PM UTC coverage: 92.989% (+0.001%) from 92.988%
15076294441

push

github

51409 of 55285 relevant lines covered (92.99%)

204.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-2025 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, write to the Free Software
17
 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
18
 *
19
 * As a special exemption, The ProFTPD Project team and other respective
20
 * copyright holders give permission to link this program with OpenSSL, and
21
 * distribute the resulting executable, without including the source code for
22
 * OpenSSL in the source distribution.
23
 */
24

25
/* Error API */
26

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

34
#define PR_ERROR_BUFSZ                32
35

36
struct err_rec {
37
  pool *err_pool;
38

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

322
  { -1, NULL }
323
};
324

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

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

331
  /* Known errno values are not negative.  Right? */
332

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

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

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

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

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

354
  return err;
119✔
355
}
356

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

360
  xerrno = errno;
120✔
361

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

366
  errno = xerrno;
120✔
367
}
120✔
368

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

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

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

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

389
  return 0;
390
}
391

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

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

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

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

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

415
  return 0;
5✔
416
}
417

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

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

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

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

435
  return prev;
8✔
436
}
437

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

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

444
  return prev;
6✔
445
}
446

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

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

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

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

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

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

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

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

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

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

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

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

508
      proto = pr_session_get_protocol(0);
5✔
509

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

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

519
  return who;
12✔
520
}
521

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

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

529
  return why;
12✔
530
}
531

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

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

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

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

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

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

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

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

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

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

577
  return where;
12✔
578
}
579

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

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

587
  return what;
24✔
588
}
589

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

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

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

603
  return what;
12✔
604
}
605

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

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

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

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

627
  return name;
628
}
629

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

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

637
  } else {
638
    desc = "Success";
639
  }
640

641
  return desc;
26✔
642
}
643

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

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

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

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

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

666
  return failure;
36✔
667
}
668

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

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

676
  return explained;
14✔
677
}
678

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

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

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

691
    } else {
692
      err_text = failure;
693
    }
694
  }
695

696
  return err_text;
22✔
697
}
698

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

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

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

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

725
  return err_text;
2✔
726
}
727

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

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

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

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

746
    } else {
747
      err_text = who;
748
    }
749
  }
750

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

755
    } else {
756
      err_text = why;
757
    }
758
  }
759

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

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

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

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

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

792
  return err_text;
12✔
793
}
794

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

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

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

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

811
      } else {
812
        break;
813
      }
814

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

819
      } else {
820
        break;
821
      }
822

823
    case PR_ERROR_FORMAT_USE_MINIMAL:
824
      break;
825

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

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

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

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

850
    case PR_ERROR_FORMAT_USE_TERSE: {
851
      const char *what, *failure, *explained;
2✔
852

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

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

864
    case PR_ERROR_FORMAT_USE_MINIMAL: {
865
      const char *what, *failure;
22✔
866

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

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

874
    default:
875
      break;
876
  }
877

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

882
  return err_text;
883
}
884

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

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

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

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

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

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

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

928
  return explainer;
929
}
930

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

935
  (void) p;
94✔
936

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

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

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

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

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

962
      ee->prev = ee->next = NULL;
89✔
963

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

971
      res = 0;
972
    }
973
  }
974

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

979
  return res;
980
}
981

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

985
  (void) p;
5✔
986

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

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

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

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

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

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

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

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

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

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

1049
  return 0;
1050
}
1051

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2849
  err->err_explained = explained;
1✔
2850
  return 0;
1✔
2851
}
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