• 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.68
/tests/api/misc.c
1
/*
2
 * ProFTPD - FTP server testsuite
3
 * Copyright (c) 2015-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
/* Miscellaneous tests
25
 */
26

27
#include "tests.h"
28

29
static pool *p = NULL;
30

31
static unsigned int schedule_called = 0;
32
static const char *misc_test_shutmsg = "/tmp/prt-shutmsg.dat";
33
static const char *misc_test_readlink = "/tmp/prt-readlink.lnk";
34
static const char *misc_test_readlink2_dir = "/tmp/prt-readlink/";
35
static const char *misc_test_readlink2 = "/tmp/prt-readlink/test.lnk";
36

37
/* Fixtures */
38

39
static void set_up(void) {
40
  (void) unlink(misc_test_readlink);
33✔
41
  (void) unlink(misc_test_readlink2);
33✔
42
  (void) unlink(misc_test_shutmsg);
33✔
43
  (void) rmdir(misc_test_readlink2_dir);
33✔
44

33✔
45
  if (p == NULL) {
46
    p = permanent_pool = make_sub_pool(NULL);
33✔
47
  }
33✔
48

49
  init_fs();
50
  pr_fs_statcache_set_policy(PR_TUNABLE_FS_STATCACHE_SIZE,
33✔
51
    PR_TUNABLE_FS_STATCACHE_MAX_AGE, 0);
33✔
52

53
  if (getenv("TEST_VERBOSE") != NULL) {
54
    pr_trace_set_levels("auth", 1, 20);
33✔
55
    pr_trace_set_levels("fsio", 1, 20);
33✔
56
    pr_trace_set_levels("fs.statcache", 1, 20);
33✔
57
  }
33✔
58

59
  schedule_called = 0;
60
  session.user = NULL;
33✔
61
}
33✔
62

33✔
63
static void tear_down(void) {
64
  (void) unlink(misc_test_readlink);
33✔
65
  (void) unlink(misc_test_readlink2);
33✔
66
  (void) unlink(misc_test_shutmsg);
33✔
67
  (void) rmdir(misc_test_readlink2_dir);
33✔
68

33✔
69
  pr_fs_statcache_set_policy(PR_TUNABLE_FS_STATCACHE_SIZE,
70
    PR_TUNABLE_FS_STATCACHE_MAX_AGE, 0);
33✔
71

72
  if (getenv("TEST_VERBOSE") != NULL) {
73
    pr_trace_set_levels("auth", 0, 0);
33✔
74
    pr_trace_set_levels("fsio", 0, 0);
33✔
75
    pr_trace_set_levels("fs.statcache", 0, 0);
33✔
76
  }
33✔
77

78
  session.user = NULL;
79

33✔
80
  if (p) {
81
    destroy_pool(p);
33✔
82
    p = session.pool = permanent_pool = NULL;
33✔
83
  }
33✔
84
}
85

33✔
86
static void schedule_cb(void *arg1, void *arg2, void *arg3, void *arg4) {
87
  schedule_called++;
4✔
88
}
4✔
89

4✔
90
/* Tests */
91

92
START_TEST (schedule_test) {
93
  mark_point();
1✔
94
  schedule(NULL, 0, NULL, NULL, NULL, NULL);
1✔
95

1✔
96
  mark_point();
97
  schedule(schedule_cb, -1, NULL, NULL, NULL, NULL);
1✔
98

1✔
99
  mark_point();
100
  run_schedule();
1✔
101

1✔
102
  mark_point();
103
  schedule(schedule_cb, 0, NULL, NULL, NULL, NULL);
1✔
104

1✔
105
  run_schedule();
106
  ck_assert_msg(schedule_called == 1, "Expected 1, got %u", schedule_called);
1✔
107

1✔
108
  run_schedule();
109
  ck_assert_msg(schedule_called == 1, "Expected 1, got %u", schedule_called);
1✔
110

1✔
111
  mark_point();
112
  schedule(schedule_cb, 0, NULL, NULL, NULL, NULL);
1✔
113
  schedule(schedule_cb, 0, NULL, NULL, NULL, NULL);
1✔
114

1✔
115
  run_schedule();
116
  ck_assert_msg(schedule_called == 3, "Expected 3, got %u", schedule_called);
1✔
117

1✔
118
  run_schedule();
119
  ck_assert_msg(schedule_called == 3, "Expected 3, got %u", schedule_called);
1✔
120

1✔
121
  mark_point();
122

1✔
123
  /* Schedule this callback to run after 2 "loops", i.e. calls to
124
   * run_schedule().
125
   */
126
  schedule(schedule_cb, 2, NULL, NULL, NULL, NULL);
127

1✔
128
  run_schedule();
129
  ck_assert_msg(schedule_called == 3, "Expected 3, got %u", schedule_called);
1✔
130

1✔
131
  run_schedule();
132
  ck_assert_msg(schedule_called == 3, "Expected 3, got %u", schedule_called);
1✔
133

1✔
134
  run_schedule();
135
  ck_assert_msg(schedule_called == 4, "Expected 4, got %u", schedule_called);
1✔
136
}
1✔
137
END_TEST
1✔
138

139
START_TEST (get_name_max_test) {
140
  long res;
1✔
141
  char *path;
1✔
142
  int fd;
1✔
143

1✔
144
  res = get_name_max(NULL, -1);
145
  ck_assert_msg(res < 0, "Failed to handle invalid arguments");
1✔
146
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
147
    strerror(errno), errno);
1✔
148

149
  path = "/";
150
  res = get_name_max(path, -1);
1✔
151
  ck_assert_msg(res >= 0, "Failed to handle path '%s': %s", path, strerror(errno));
1✔
152

1✔
153
  fd = 1;
154
  res = get_name_max(NULL, fd);
1✔
155

1✔
156
  /* It seems that fpathconf(2) on some platforms will handle stdin as a
157
   * valid file descriptor, and some will not.
158
   */
159
  if (res < 0) {
160
    ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
161
      strerror(errno), errno);
×
162
  }
163
}
164
END_TEST
1✔
165

166
START_TEST (dir_interpolate_test) {
167
  char *res;
1✔
168
  const char *path;
1✔
169

1✔
170
  mark_point();
171
  res = dir_interpolate(NULL, NULL);
1✔
172
  ck_assert_msg(res == NULL, "Failed to handle null arguments");
1✔
173
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
174
    strerror(errno), errno);
1✔
175

176
  mark_point();
177
  res = dir_interpolate(p, NULL);
1✔
178
  ck_assert_msg(res == NULL, "Failed to handle null path");
1✔
179
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
180
    strerror(errno), errno);
1✔
181

182
  mark_point();
183
  path = "/foo";
1✔
184
  res = dir_interpolate(p, path);
1✔
185
  ck_assert_msg(path != NULL, "Failed to interpolate '%s': %s", path,
1✔
186
    strerror(errno));
1✔
187
  ck_assert_msg(strcmp(res, path) == 0, "Expected '%s', got '%s'", path, res);
188

1✔
189
  mark_point();
190
  path = "~foo.bar.baz.quxx.quzz/foo";
1✔
191
  res = dir_interpolate(p, path);
1✔
192
  ck_assert_msg(path != NULL, "Failed to interpolate '%s': %s", path,
1✔
193
    strerror(errno));
1✔
194
  ck_assert_msg(*path == '~',
195
    "Interpolated path with unknown user unexpectedly");
1✔
196
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
197
    strerror(errno), errno);
1✔
198

199
  mark_point();
200
  session.user = "foo.bar.baz.quxx.quzz";
1✔
201
  session.user_homedir = "/alef.d";
1✔
202
  res = dir_interpolate(p, path);
1✔
203
  ck_assert_msg(res != NULL, "Failed to interpolate '%s': %s", path,
1✔
204
    strerror(errno));
1✔
205
  ck_assert_msg(strcmp(res, "/alef.d/foo") == 0,
206
    "Expected '/alef.d/foo', got '%s'", res);
1✔
207

208
  session.user = NULL;
209
  session.user_homedir = NULL;
1✔
210
}
1✔
211
END_TEST
1✔
212

213
START_TEST (dir_best_path_test) {
214
  char *res;
1✔
215
  const char *path;
1✔
216

1✔
217
  res = dir_best_path(NULL, NULL);
218
  ck_assert_msg(res == NULL, "Failed to handle null arguments");
1✔
219
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
220
    strerror(errno), errno);
1✔
221

222
  res = dir_best_path(p, NULL);
223
  ck_assert_msg(res == NULL, "Failed to handle null path");
1✔
224
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
225
    strerror(errno), errno);
1✔
226

227
  mark_point();
228
  path = "/foo";
1✔
229
  res = dir_best_path(p, path);
1✔
230
  ck_assert_msg(path != NULL, "Failed to get best path for '%s': %s", path,
1✔
231
    strerror(errno));
1✔
232
  ck_assert_msg(strcmp(res, path) == 0, "Expected '%s', got '%s'", path, res);
233
}
1✔
234
END_TEST
1✔
235

236
START_TEST (dir_canonical_path_test) {
237
  char *res;
1✔
238
  const char *path;
1✔
239

1✔
240
  res = dir_canonical_path(NULL, NULL);
241
  ck_assert_msg(res == NULL, "Failed to handle null arguments");
1✔
242
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
243
    strerror(errno), errno);
1✔
244

245
  res = dir_canonical_path(p, NULL);
246
  ck_assert_msg(res == NULL, "Failed to handle null path");
1✔
247
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
248
    strerror(errno), errno);
1✔
249

250
  mark_point();
251
  path = "/foo";
1✔
252
  res = dir_canonical_path(p, path);
1✔
253
  ck_assert_msg(path != NULL, "Failed to get canonical path for '%s': %s", path,
1✔
254
    strerror(errno));
1✔
255
  ck_assert_msg(strcmp(res, path) == 0, "Expected '%s', got '%s'", path, res);
256
}
1✔
257
END_TEST
1✔
258

259
START_TEST (dir_canonical_vpath_test) {
260
  char *res;
1✔
261
  const char *path;
1✔
262

1✔
263
  res = dir_canonical_vpath(NULL, NULL);
264
  ck_assert_msg(res == NULL, "Failed to handle null arguments");
1✔
265
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
266
    strerror(errno), errno);
1✔
267

268
  res = dir_canonical_vpath(p, NULL);
269
  ck_assert_msg(res == NULL, "Failed to handle null path");
1✔
270
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
271
    strerror(errno), errno);
1✔
272

273
  mark_point();
274
  path = "/foo";
1✔
275
  res = dir_canonical_vpath(p, path);
1✔
276
  ck_assert_msg(path != NULL, "Failed to get canonical vpath for '%s': %s", path,
1✔
277
    strerror(errno));
1✔
278
  ck_assert_msg(strcmp(res, path) == 0, "Expected '%s', got '%s'", path, res);
279
}
1✔
280
END_TEST
1✔
281

282
START_TEST (dir_readlink_test) {
283
  int res, flags = 0;
1✔
284
  const char *path;
1✔
285
  char *buf, *dst_path, *expected_path;
1✔
286
  size_t bufsz, dst_pathlen, expected_pathlen;
1✔
287

1✔
288
  (void) unlink(misc_test_readlink);
289

1✔
290
  /* Parameter validation */
291
  res = dir_readlink(NULL, NULL, NULL, 0, flags);
292
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
293
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
294
    strerror(errno), errno);
1✔
295

296
  res = dir_readlink(p, NULL, NULL, 0, flags);
297
  ck_assert_msg(res < 0, "Failed to handle null path");
1✔
298
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
299
    strerror(errno), errno);
1✔
300

301
  path = misc_test_readlink;
302
  res = dir_readlink(p, path, NULL, 0, flags);
1✔
303
  ck_assert_msg(res < 0, "Failed to handle null buffer");
1✔
304
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
305
    strerror(errno), errno);
1✔
306

307
  bufsz = 1024;
308
  buf = palloc(p, bufsz);
1✔
309
  res = dir_readlink(p, path, buf, 0, flags);
1✔
310
  ck_assert_msg(res == 0, "Failed to handle zero buffer length");
1✔
311

1✔
312
  res = dir_readlink(p, path, buf, bufsz, flags);
313
  ck_assert_msg(res < 0, "Failed to handle nonexistent file");
1✔
314
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
1✔
315
    strerror(errno), errno);
1✔
316

317
  dst_path = "";
318
  res = symlink(dst_path, path);
1✔
319
  if (res == 0) {
1✔
320
    /* Some platforms will not allow creation of empty symlinks.  Nice of
1✔
321
     * them.
322
     */
323
    res = dir_readlink(p, path, buf, bufsz, flags);
324
    ck_assert_msg(res == 0, "Failed to handle empty symlink");
×
325
  }
×
326
  (void) unlink(path);
327

1✔
328
  /* Not chrooted, absolute dst path */
329
  memset(buf, '\0', bufsz);
330
  dst_path = "/home/user/file.dat";
1✔
331
  dst_pathlen = strlen(dst_path);
1✔
332
  res = symlink(dst_path, path);
1✔
333
  ck_assert_msg(res == 0, "Failed to symlink '%s' to '%s': %s", path, dst_path,
1✔
334
    strerror(errno));
1✔
335

336
  res = dir_readlink(p, path, buf, bufsz, flags);
337
  ck_assert_msg(res >= 0, "Failed to read '%s' symlink: %s", path, strerror(errno));
1✔
338
  ck_assert_msg((size_t) res == dst_pathlen, "Expected length %lu, got %d",
1✔
339
    (unsigned long) dst_pathlen, res);
1✔
340
  ck_assert_msg(strcmp(buf, dst_path) == 0, "Expected '%s', got '%s'",
341
    dst_path, buf);
1✔
342

343
  /* Not chrooted, relative dst path, flags to ignore rel path */
344
  memset(buf, '\0', bufsz);
345
  dst_path = "./file.dat";
1✔
346
  dst_pathlen = strlen(dst_path);
1✔
347

1✔
348
  (void) unlink(path);
349
  res = symlink(dst_path, path);
1✔
350
  ck_assert_msg(res == 0, "Failed to symlink '%s' to '%s': %s", path, dst_path,
1✔
351
    strerror(errno));
1✔
352

353
  res = dir_readlink(p, path, buf, bufsz, flags);
354
  ck_assert_msg(res >= 0, "Failed to read '%s' symlink: %s", path, strerror(errno));
1✔
355
  ck_assert_msg((size_t) res == dst_pathlen, "Expected length %lu, got %d",
1✔
356
    (unsigned long) dst_pathlen, res);
1✔
357
  ck_assert_msg(strcmp(buf, dst_path) == 0, "Expected '%s', got '%s'",
358
    dst_path, buf);
1✔
359

360
  /* Not chrooted, relative dst path without leading '.', flags to ignore rel
361
   * path.
362
   */
363
  memset(buf, '\0', bufsz);
364
  dst_path = "file.dat";
1✔
365
  dst_pathlen = strlen(dst_path);
1✔
366

1✔
367
  (void) unlink(path);
368
  res = symlink(dst_path, path);
1✔
369
  ck_assert_msg(res == 0, "Failed to symlink '%s' to '%s': %s", path, dst_path,
1✔
370
    strerror(errno));
1✔
371

372
  res = dir_readlink(p, path, buf, bufsz, flags);
373
  ck_assert_msg(res >= 0, "Failed to read '%s' symlink: %s", path, strerror(errno));
1✔
374
  ck_assert_msg((size_t) res == dst_pathlen, "Expected length %lu, got %d",
1✔
375
    (unsigned long) dst_pathlen, res);
1✔
376
  ck_assert_msg(strcmp(buf, dst_path) == 0, "Expected '%s', got '%s'",
377
    dst_path, buf);
1✔
378

379
  /* Not chrooted, relative dst path, flags to HANDLE rel path */
380
  memset(buf, '\0', bufsz);
381
  dst_path = "./file.dat";
1✔
382
  dst_pathlen = strlen(dst_path);
1✔
383
  expected_path = "/tmp/file.dat";
1✔
384
  expected_pathlen = strlen(expected_path);
1✔
385

1✔
386
  (void) unlink(path);
387
  res = symlink(dst_path, path);
1✔
388
  ck_assert_msg(res == 0, "Failed to symlink '%s' to '%s': %s", path, dst_path,
1✔
389
    strerror(errno));
1✔
390

391
  flags = PR_DIR_READLINK_FL_HANDLE_REL_PATH;
392
  res = dir_readlink(p, path, buf, bufsz, flags);
1✔
393
  ck_assert_msg(res >= 0, "Failed to read '%s' symlink: %s", path, strerror(errno));
1✔
394
  ck_assert_msg((size_t) res == expected_pathlen, "Expected length %lu, got %d",
1✔
395
    (unsigned long) expected_pathlen, res);
1✔
396
  ck_assert_msg(strcmp(buf, expected_path) == 0, "Expected '%s', got '%s'",
397
    expected_path, buf);
1✔
398

399
  /* Not chrooted, relative dst path without leading '.', flags to HANDLE rel
400
   * path.
401
   */
402
  memset(buf, '\0', bufsz);
403
  dst_path = "file.dat";
1✔
404
  dst_pathlen = strlen(dst_path);
1✔
405
  expected_path = "/tmp/file.dat";
1✔
406
  expected_pathlen = strlen(expected_path);
1✔
407

1✔
408
  (void) unlink(path);
409
  res = symlink(dst_path, path);
1✔
410
  ck_assert_msg(res == 0, "Failed to symlink '%s' to '%s': %s", path, dst_path,
1✔
411
    strerror(errno));
1✔
412

413
  flags = PR_DIR_READLINK_FL_HANDLE_REL_PATH;
414
  res = dir_readlink(p, path, buf, bufsz, flags);
1✔
415
  ck_assert_msg(res >= 0, "Failed to read '%s' symlink: %s", path, strerror(errno));
1✔
416
  ck_assert_msg((size_t) res == expected_pathlen, "Expected length %lu, got %d",
1✔
417
    (unsigned long) expected_pathlen, res);
1✔
418
  ck_assert_msg(strcmp(buf, expected_path) == 0, "Expected '%s', got '%s'",
419
    expected_path, buf);
1✔
420

421
  /* Not chrooted, dst path longer than given buffer */
422
  flags = 0;
423
  memset(buf, '\0', bufsz);
1✔
424
  res = dir_readlink(p, path, buf, 2, flags);
1✔
425
  ck_assert_msg(res >= 0, "Failed to read '%s' symlink: %s", path, strerror(errno));
1✔
426
  ck_assert_msg(res == 2, "Expected length 2, got %d", res);
1✔
427
  ck_assert_msg(strncmp(buf, dst_path, 2) == 0, "Expected '%.*s', got '%.*s'",
1✔
428
    2, dst_path, 2, buf);
1✔
429

430
  /* Chrooted to "/" */
431
  session.chroot_path = "/";
432
  memset(buf, '\0', bufsz);
1✔
433
  res = dir_readlink(p, path, buf, bufsz, flags);
1✔
434
  ck_assert_msg(res >= 0, "Failed to read '%s' symlink: %s", path, strerror(errno));
1✔
435
  ck_assert_msg((size_t) res == dst_pathlen, "Expected length %lu, got %d",
1✔
436
    (unsigned long) dst_pathlen, res);
1✔
437
  ck_assert_msg(strcmp(buf, dst_path) == 0, "Expected '%s', got '%s'",
438
    dst_path, buf);
1✔
439

440
  /* Chrooted, absolute destination path shorter than chroot path */
441
  session.chroot_path = "/home/user";
442
  memset(buf, '\0', bufsz);
1✔
443
  dst_path = "/foo";
1✔
444
  dst_pathlen = strlen(dst_path);
1✔
445

1✔
446
  (void) unlink(path);
447
  res = symlink(dst_path, path);
1✔
448
  ck_assert_msg(res == 0, "Failed to symlink '%s' to '%s': %s", path, dst_path,
1✔
449
    strerror(errno));
1✔
450

451
  res = dir_readlink(p, path, buf, bufsz, flags);
452
  ck_assert_msg(res >= 0, "Failed to read '%s' symlink: %s", path, strerror(errno));
1✔
453
  ck_assert_msg((size_t) res == dst_pathlen, "Expected length %lu, got %d",
1✔
454
    (unsigned long) dst_pathlen, res);
1✔
455
  ck_assert_msg(strcmp(buf, dst_path) == 0, "Expected '%s', got '%s'",
456
    dst_path, buf);
1✔
457

458
  /* Chrooted, overlapping chroot to non-dir */
459
  memset(buf, '\0', bufsz);
460
  dst_path = "/home/user2";
1✔
461
  dst_pathlen = strlen(dst_path);
1✔
462

1✔
463
  (void) unlink(path);
464
  res = symlink(dst_path, path);
1✔
465
  ck_assert_msg(res == 0, "Failed to symlink '%s' to '%s': %s", path, dst_path,
1✔
466
    strerror(errno));
1✔
467

468
  res = dir_readlink(p, path, buf, bufsz, flags);
469
  ck_assert_msg(res >= 0, "Failed to read '%s' symlink: %s", path, strerror(errno));
1✔
470
  ck_assert_msg((size_t) res == dst_pathlen, "Expected length %lu, got %d",
1✔
471
    (unsigned long) dst_pathlen, res);
1✔
472
  ck_assert_msg(strcmp(buf, dst_path) == 0, "Expected '%s', got '%s'",
473
    dst_path, buf);
1✔
474

475
  /* Chrooted, absolute destination within chroot */
476
  memset(buf, '\0', bufsz);
477
  dst_path = "/home/user/file.txt";
1✔
478
  dst_pathlen = strlen(dst_path);
1✔
479
  expected_path = "/file.txt";
1✔
480
  expected_pathlen = strlen(expected_path);
1✔
481

1✔
482
  (void) unlink(path);
483
  res = symlink(dst_path, path);
1✔
484
  ck_assert_msg(res == 0, "Failed to symlink '%s' to '%s': %s", path, dst_path,
1✔
485
    strerror(errno));
1✔
486

487
  res = dir_readlink(p, path, buf, bufsz, flags);
488
  ck_assert_msg(res >= 0, "Failed to read '%s' symlink: %s", path, strerror(errno));
1✔
489
  ck_assert_msg((size_t) res == expected_pathlen, "Expected length %lu, got %d",
1✔
490
    (unsigned long) expected_pathlen, res);
1✔
491
  ck_assert_msg(strcmp(buf, expected_path) == 0, "Expected '%s', got '%s'",
492
    expected_path, buf);
1✔
493

494
  /* Chrooted, absolute destination outside of chroot */
495
  memset(buf, '\0', bufsz);
496
  dst_path = "/home/user/../file.txt";
1✔
497
  dst_pathlen = strlen(dst_path);
1✔
498
  expected_path = "/home/file.txt";
1✔
499
  expected_pathlen = strlen(expected_path);
1✔
500

1✔
501
  (void) unlink(path);
502
  res = symlink(dst_path, path);
1✔
503
  ck_assert_msg(res == 0, "Failed to symlink '%s' to '%s': %s", path, dst_path,
1✔
504
    strerror(errno));
1✔
505

506
  res = dir_readlink(p, path, buf, bufsz, flags);
507
  ck_assert_msg(res >= 0, "Failed to read '%s' symlink: %s", path, strerror(errno));
1✔
508
  ck_assert_msg((size_t) res == expected_pathlen, "Expected length %lu, got %d",
1✔
509
    (unsigned long) expected_pathlen, res);
1✔
510
  ck_assert_msg(strcmp(buf, expected_path) == 0, "Expected '%s', got '%s'",
511
    expected_path, buf);
1✔
512

513
  /* Chrooted, relative destination within chroot */
514
  memset(buf, '\0', bufsz);
515
  dst_path = "./file.txt";
1✔
516
  dst_pathlen = strlen(dst_path);
1✔
517
  expected_path = "./file.txt";
1✔
518
  expected_pathlen = strlen(expected_path);
1✔
519

1✔
520
  (void) unlink(path);
521
  res = symlink(dst_path, path);
1✔
522
  ck_assert_msg(res == 0, "Failed to symlink '%s' to '%s': %s", path, dst_path,
1✔
523
    strerror(errno));
1✔
524

525
  res = dir_readlink(p, path, buf, bufsz, flags);
526
  ck_assert_msg(res >= 0, "Failed to read '%s' symlink: %s", path, strerror(errno));
1✔
527
  ck_assert_msg((size_t) res == expected_pathlen, "Expected length %lu, got %d",
1✔
528
    (unsigned long) expected_pathlen, res);
1✔
529
  ck_assert_msg(strcmp(buf, expected_path) == 0, "Expected '%s', got '%s'",
530
    expected_path, buf);
1✔
531

532
  /* Chrooted, relative destination (without leading '.') within chroot */
533
  memset(buf, '\0', bufsz);
534
  dst_path = "file.txt";
1✔
535
  dst_pathlen = strlen(dst_path);
1✔
536
  expected_path = "file.txt";
1✔
537
  expected_pathlen = strlen(expected_path);
1✔
538

1✔
539
  (void) unlink(path);
540
  res = symlink(dst_path, path);
1✔
541
  ck_assert_msg(res == 0, "Failed to symlink '%s' to '%s': %s", path, dst_path,
1✔
542
    strerror(errno));
1✔
543

544
  res = dir_readlink(p, path, buf, bufsz, flags);
545
  ck_assert_msg(res >= 0, "Failed to read '%s' symlink: %s", path, strerror(errno));
1✔
546
  ck_assert_msg((size_t) res == expected_pathlen, "Expected length %lu, got %d",
1✔
547
    (unsigned long) expected_pathlen, res);
1✔
548
  ck_assert_msg(strcmp(buf, expected_path) == 0, "Expected '%s', got '%s'",
549
    expected_path, buf);
1✔
550

551
  /* Chrooted, relative destination outside of chroot */
552
  memset(buf, '\0', bufsz);
553
  dst_path = "../file.txt";
1✔
554
  dst_pathlen = strlen(dst_path);
1✔
555
  expected_path = "../file.txt";
1✔
556
  expected_pathlen = strlen(expected_path);
1✔
557

1✔
558
  (void) unlink(path);
559
  res = symlink(dst_path, path);
1✔
560
  ck_assert_msg(res == 0, "Failed to symlink '%s' to '%s': %s", path, dst_path,
1✔
561
    strerror(errno));
1✔
562

563
  /* First, tell dir_readlink() to ignore relative destination paths. */
564
  flags = 0;
565
  res = dir_readlink(p, path, buf, bufsz, flags);
1✔
566
  ck_assert_msg(res >= 0, "Failed to read '%s' symlink: %s", path, strerror(errno));
1✔
567
  ck_assert_msg((size_t) res == expected_pathlen, "Expected length %lu, got %d",
1✔
568
    (unsigned long) expected_pathlen, res);
1✔
569
  ck_assert_msg(strcmp(buf, expected_path) == 0, "Expected '%s', got '%s'",
570
    expected_path, buf);
1✔
571

572
  /* Now do it again, telling dir_readlink() to handle relative destination
573
   * paths.
574
   */
575
  memset(buf, '\0', bufsz);
576
  dst_path = "../file.txt";
1✔
577
  dst_pathlen = strlen(dst_path);
1✔
578
  expected_path = "/file.txt";
1✔
579
  expected_pathlen = strlen(expected_path);
1✔
580

1✔
581
  (void) unlink(path);
582
  res = symlink(dst_path, path);
1✔
583
  ck_assert_msg(res == 0, "Failed to symlink '%s' to '%s': %s", path, dst_path,
1✔
584
    strerror(errno));
1✔
585

586
  flags = PR_DIR_READLINK_FL_HANDLE_REL_PATH;
587
  res = dir_readlink(p, path, buf, bufsz, flags);
1✔
588
  ck_assert_msg(res >= 0, "Failed to read '%s' symlink: %s", path, strerror(errno));
1✔
589
  ck_assert_msg((size_t) res == expected_pathlen, "Expected length %lu, got %d",
1✔
590
    (unsigned long) expected_pathlen, res);
1✔
591
  ck_assert_msg(strcmp(buf, expected_path) == 0, "Expected '%s', got '%s'",
592
    expected_path, buf);
1✔
593

594
  /* One more time, this time changing the chroot path to align with the
595
   * source path.
596
   */
597
  memset(buf, '\0', bufsz);
598
  dst_path = "../file.txt";
1✔
599
  dst_pathlen = strlen(dst_path);
1✔
600
  expected_path = "/file.txt";
1✔
601
  expected_pathlen = strlen(expected_path);
1✔
602

1✔
603
  (void) unlink(path);
604
  res = symlink(dst_path, path);
1✔
605
  ck_assert_msg(res == 0, "Failed to symlink '%s' to '%s': %s", path, dst_path,
1✔
606
    strerror(errno));
1✔
607

608
  session.chroot_path = "/tmp";
609
  flags = PR_DIR_READLINK_FL_HANDLE_REL_PATH;
1✔
610
  res = dir_readlink(p, path, buf, bufsz, flags);
1✔
611
  ck_assert_msg(res >= 0, "Failed to read '%s' symlink: %s", path, strerror(errno));
1✔
612
  ck_assert_msg((size_t) res == expected_pathlen, "Expected length %lu, got %d",
1✔
613
    (unsigned long) expected_pathlen, res);
1✔
614
  ck_assert_msg(strcmp(buf, expected_path) == 0, "Expected '%s', got '%s'",
615
    expected_path, buf);
1✔
616

617
  /* Now use a relative path that does not start with '.' */
618
  memset(buf, '\0', bufsz);
619
  dst_path = "file.txt";
1✔
620
  dst_pathlen = strlen(dst_path);
1✔
621
  expected_path = "./file.txt";
1✔
622
  expected_pathlen = strlen(expected_path);
1✔
623

1✔
624
  (void) unlink(path);
625
  res = symlink(dst_path, path);
1✔
626
  ck_assert_msg(res == 0, "Failed to symlink '%s' to '%s': %s", path, dst_path,
1✔
627
    strerror(errno));
1✔
628

629
  session.chroot_path = "/tmp";
630
  flags = PR_DIR_READLINK_FL_HANDLE_REL_PATH;
1✔
631
  res = dir_readlink(p, path, buf, bufsz, flags);
1✔
632
  ck_assert_msg(res >= 0, "Failed to read '%s' symlink: %s", path, strerror(errno));
1✔
633
  ck_assert_msg((size_t) res == expected_pathlen,
1✔
634
    "Expected length %lu, got %d (%s)", (unsigned long) expected_pathlen, res,
1✔
635
    buf);
636
  ck_assert_msg(strcmp(buf, expected_path) == 0, "Expected '%s', got '%s'",
637
    expected_path, buf);
1✔
638

639
  /* Now use a relative path that does not start with '.', and a chroot
640
   * deeper down than one directory.
641
   */
642
  memset(buf, '\0', bufsz);
643
  dst_path = "file.txt";
1✔
644
  dst_pathlen = strlen(dst_path);
1✔
645
  expected_path = "/tmp/file.txt";
1✔
646
  expected_pathlen = strlen(expected_path);
1✔
647

1✔
648
  (void) unlink(path);
649
  res = symlink(dst_path, path);
1✔
650
  ck_assert_msg(res == 0, "Failed to symlink '%s' to '%s': %s", path, dst_path,
1✔
651
    strerror(errno));
1✔
652

653
  session.chroot_path = "/tmp/foo/bar";
654
  flags = PR_DIR_READLINK_FL_HANDLE_REL_PATH;
1✔
655
  res = dir_readlink(p, path, buf, bufsz, flags);
1✔
656
  ck_assert_msg(res >= 0, "Failed to read '%s' symlink: %s", path, strerror(errno));
1✔
657
  ck_assert_msg((size_t) res == expected_pathlen,
1✔
658
    "Expected length %lu, got %d (%s)", (unsigned long) expected_pathlen, res,
1✔
659
    buf);
660
  ck_assert_msg(strcmp(buf, expected_path) == 0, "Expected '%s', got '%s'",
661
    expected_path, buf);
1✔
662

663
  /* Now use a relative path, and a chroot deeper down than one directory, and
664
   * a deeper/longer source path.
665
   */
666
  memset(buf, '\0', bufsz);
667
  dst_path = "./file.txt";
1✔
668
  dst_pathlen = strlen(dst_path);
1✔
669
  expected_path = "/tmp/prt-readlink/file.txt";
1✔
670
  expected_pathlen = strlen(expected_path);
1✔
671

1✔
672
  (void) unlink(path);
673
  (void) rmdir(misc_test_readlink2_dir);
1✔
674
  (void) mkdir(misc_test_readlink2_dir, 0777);
1✔
675
  path = misc_test_readlink2;
1✔
676
  res = symlink(dst_path, path);
1✔
677
  ck_assert_msg(res == 0, "Failed to symlink '%s' to '%s': %s", path, dst_path,
1✔
678
    strerror(errno));
1✔
679

680
  session.chroot_path = "/tmp/foo/bar";
681
  flags = PR_DIR_READLINK_FL_HANDLE_REL_PATH;
1✔
682
  res = dir_readlink(p, path, buf, bufsz, flags);
1✔
683
  ck_assert_msg(res >= 0, "Failed to read '%s' symlink: %s", path, strerror(errno));
1✔
684
  ck_assert_msg((size_t) res == expected_pathlen,
1✔
685
    "Expected length %lu, got %d (%s)", (unsigned long) expected_pathlen, res,
1✔
686
    buf);
687
  ck_assert_msg(strcmp(buf, expected_path) == 0, "Expected '%s', got '%s'",
688
    expected_path, buf);
1✔
689

690
  /* Now use a relative path that does not start with '.', and a chroot
691
   * deeper down than one directory, and a deeper/longer source path.
692
   */
693
  memset(buf, '\0', bufsz);
694
  dst_path = "file.txt";
1✔
695
  dst_pathlen = strlen(dst_path);
1✔
696
  expected_path = "/tmp/prt-readlink/file.txt";
1✔
697
  expected_pathlen = strlen(expected_path);
1✔
698

1✔
699
  (void) unlink(path);
700
  (void) rmdir(misc_test_readlink2_dir);
1✔
701
  (void) mkdir(misc_test_readlink2_dir, 0777);
1✔
702
  path = misc_test_readlink2;
1✔
703
  res = symlink(dst_path, path);
1✔
704
  ck_assert_msg(res == 0, "Failed to symlink '%s' to '%s': %s", path, dst_path,
1✔
705
    strerror(errno));
1✔
706

707
  session.chroot_path = "/tmp/foo/bar";
708
  flags = PR_DIR_READLINK_FL_HANDLE_REL_PATH;
1✔
709
  res = dir_readlink(p, path, buf, bufsz, flags);
1✔
710
  ck_assert_msg(res >= 0, "Failed to read '%s' symlink: %s", path, strerror(errno));
1✔
711
  ck_assert_msg((size_t) res == expected_pathlen,
1✔
712
    "Expected length %lu, got %d (%s)", (unsigned long) expected_pathlen, res,
1✔
713
    buf);
714
  ck_assert_msg(strcmp(buf, expected_path) == 0, "Expected '%s', got '%s'",
715
    expected_path, buf);
1✔
716

717
  (void) unlink(misc_test_readlink);
718
  (void) unlink(misc_test_readlink2);
1✔
719
  (void) rmdir(misc_test_readlink2_dir);
1✔
720
}
1✔
721
END_TEST
1✔
722

723
START_TEST (dir_realpath_test) {
724
  char *res;
1✔
725
  const char *path;
1✔
726

1✔
727
  res = dir_realpath(NULL, NULL);
728
  ck_assert_msg(res == NULL, "Failed to handle null arguments");
1✔
729
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
730
    strerror(errno), errno);
1✔
731

732
  res = dir_realpath(p, NULL);
733
  ck_assert_msg(res == NULL, "Failed to handle null path");
1✔
734
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
735
    strerror(errno), errno);
1✔
736

737
  mark_point();
738
  path = "/foo";
1✔
739
  res = dir_realpath(p, path);
1✔
740
  ck_assert_msg(res == NULL, "Got real path for '%s' unexpectedly", path);
1✔
741
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
1✔
742
    strerror(errno), errno);
1✔
743

744
  mark_point();
745
  path = "/";
1✔
746
  res = dir_realpath(p, path);
1✔
747
  ck_assert_msg(res != NULL, "Failed to get real path for '%s': %s", path,
1✔
748
    strerror(errno));
1✔
749
  ck_assert_msg(strcmp(res, path) == 0, "Expected '%s', got '%s'", path, res);
750
}
1✔
751
END_TEST
1✔
752

753
START_TEST (dir_abs_path_test) {
754
  char *res;
1✔
755
  const char *path;
1✔
756

1✔
757
  res = dir_abs_path(NULL, NULL, TRUE);
758
  ck_assert_msg(res == NULL, "Failed to handle null arguments");
1✔
759
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
760
    strerror(errno), errno);
1✔
761

762
  res = dir_abs_path(p, NULL, TRUE);
763
  ck_assert_msg(res == NULL, "Failed to handle null path");
1✔
764
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
765
    strerror(errno), errno);
1✔
766

767
  mark_point();
768
  path = "/foo";
1✔
769
  res = dir_abs_path(p, path, TRUE);
1✔
770
  ck_assert_msg(path != NULL, "Failed to get absolute path for '%s': %s", path,
1✔
771
    strerror(errno));
1✔
772
  ck_assert_msg(strcmp(res, path) == 0, "Expected '%s', got '%s'", path, res);
773
}
1✔
774
END_TEST
1✔
775

776
START_TEST (safe_token_test) {
777
  char *res, *text, *expected;
1✔
778

1✔
779
  mark_point();
780
  expected = "";
1✔
781
  res = safe_token(NULL);
1✔
782
  ck_assert_msg(res != NULL, "Failed to handle null arguments");
1✔
783
  ck_assert_msg(strcmp(res, expected) == 0, "Expected '%s', got '%s'", expected,
1✔
784
    res);
1✔
785

786
  mark_point();
787
  text = "";
1✔
788
  expected = "";
1✔
789
  res = safe_token(&text);
1✔
790
  ck_assert_msg(res != NULL, "Failed to handle null arguments");
1✔
791
  ck_assert_msg(strcmp(res, expected) == 0, "Expected '%s', got '%s'", expected,
1✔
792
    res);
1✔
793

794
  mark_point();
795
  text = "foo";
1✔
796
  expected = text;
1✔
797
  res = safe_token(&text);
1✔
798
  ck_assert_msg(res != NULL, "Failed to handle null arguments");
1✔
799
  ck_assert_msg(res == expected, "Expected '%s', got '%s'", expected, res);
1✔
800
  ck_assert_msg(strcmp(text, "") == 0, "Expected '', got '%s'", text);
1✔
801

1✔
802
  mark_point();
803
  text = "  foo";
1✔
804
  expected = text + 2;
1✔
805
  res = safe_token(&text);
1✔
806
  ck_assert_msg(res != NULL, "Failed to handle null arguments");
1✔
807
  ck_assert_msg(res == expected, "Expected '%s', got '%s'", expected, res);
1✔
808
  ck_assert_msg(strcmp(text, "") == 0, "Expected '', got '%s'", text);
1✔
809

1✔
810
  mark_point();
811
  text = "  \t";
1✔
812
  expected = "";
1✔
813
  res = safe_token(&text);
1✔
814
  ck_assert_msg(res != NULL, "Failed to handle null arguments");
1✔
815
  ck_assert_msg(strcmp(res, expected) == 0, "Expected '%s', got '%s'", expected,
1✔
816
    res);
1✔
817
}
818
END_TEST
1✔
819

820
static int write_shutmsg(const char *path, const char *line) {
821
  FILE *fh;
3✔
822
  int res;
3✔
823
  size_t line_len;
3✔
824

3✔
825
  fh = fopen(path, "w+");
826
  if (fh == NULL) {
3✔
827
    return -1;
3✔
828
  }
829

830

831
  line_len = strlen(line);
832
  fwrite(line, line_len, 1, fh);
3✔
833

3✔
834
  res = fclose(fh);
835
  return res;
3✔
836
}
3✔
837

838
START_TEST (check_shutmsg_test) {
839
  int res;
1✔
840
  const char *path;
1✔
841
  time_t when_shutdown = 0, when_deny = 0, when_disconnect = 0;
1✔
842
  char shutdown_msg[PR_TUNABLE_BUFFER_SIZE];
1✔
843

1✔
844
  res = check_shutmsg(NULL, NULL, NULL, NULL, NULL, NULL, 0);
845
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
846
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
847
    strerror(errno), errno);
1✔
848

849
  path = "/foo/bar/baz/quxx/quzz";
850
  res = check_shutmsg(p, path, NULL, NULL, NULL, NULL, 0);
1✔
851
  ck_assert_msg(res < 0, "Failed to handle nonexistent path");
1✔
852
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
1✔
853
    strerror(errno), errno);
1✔
854

855
  path = "/";
856
  res = check_shutmsg(p, path, NULL, NULL, NULL, NULL, 0);
1✔
857
  ck_assert_msg(res < 0, "Failed to handle directory path");
1✔
858
  ck_assert_msg(errno == EISDIR, "Expected EISDIR (%d), got %s (%d)", EISDIR,
1✔
859
    strerror(errno), errno);
1✔
860

861
  /* XXX More testing needed */
862

863
  path = misc_test_shutmsg;
864

1✔
865
  (void) unlink(path);
866
  res = write_shutmsg(path,
1✔
867
    "1970 1 1 0 0 0 0000 0000\nGoodbye, cruel world!\n");
1✔
868
  ck_assert_msg(res == 0, "Failed to write '%s': %s", path, strerror(errno));
869

1✔
870
  memset(shutdown_msg, '\0', sizeof(shutdown_msg));
871
  pr_env_set(p, "TZ", "GMT");
1✔
872

1✔
873
  mark_point();
874
  res = check_shutmsg(p, path, &when_shutdown, &when_deny, &when_disconnect,
1✔
875
    shutdown_msg, sizeof(shutdown_msg));
1✔
876
  ck_assert_msg(res == 1, "Expected 1, got %d", res);
877
  ck_assert_msg(when_shutdown == (time_t) 0, "Expected 0, got %lu",
1✔
878
    (unsigned long) when_shutdown);
1✔
879
  ck_assert_msg(when_deny == (time_t) 0, "Expected 0, got %lu",
880
    (unsigned long) when_deny);
1✔
881
  ck_assert_msg(when_disconnect == (time_t) 0, "Expected 0, got %lu",
882
    (unsigned long) when_disconnect);
1✔
883
  ck_assert_msg(strcmp(shutdown_msg, "Goodbye, cruel world!") == 0,
884
    "Expected 'Goodbye, cruel world!', got '%s'", shutdown_msg);
1✔
885

886
  (void) unlink(path);
887
  res = write_shutmsg(path,
1✔
888
    "2037 1 1 0 0 0 0000 0000\nGoodbye, cruel world!\n");
1✔
889
  ck_assert_msg(res == 0, "Failed to write '%s': %s", path, strerror(errno));
890

1✔
891
  mark_point();
892
  res = check_shutmsg(p, path, NULL, NULL, NULL, NULL, 0);
1✔
893
  ck_assert_msg(res == 1, "Expected 1, got %d", res);
1✔
894

1✔
895
  (void) unlink(path);
896
  res = write_shutmsg(path,
1✔
897
    "0 0 0 0 0 0 0000 0000\nGoodbye, cruel world!\n");
1✔
898
  ck_assert_msg(res == 0, "Failed to write '%s': %s", path, strerror(errno));
899

1✔
900
  mark_point();
901
  res = check_shutmsg(p, path, NULL, NULL, NULL, NULL, 0);
1✔
902

1✔
903
  (void) unlink(misc_test_shutmsg);
904
}
1✔
905
END_TEST
1✔
906

907
START_TEST (memscrub_test) {
908
  size_t len;
1✔
909
  char *expected, *text;
1✔
910

1✔
911
  mark_point();
912
  pr_memscrub(NULL, 1);
1✔
913

1✔
914
  expected = "Hello, World!";
915
  text = pstrdup(p, expected);
1✔
916

1✔
917
  mark_point();
918
  pr_memscrub(text, 0);
1✔
919

1✔
920
  len = strlen(text);
921

1✔
922
  mark_point();
923
  pr_memscrub(text, len);
1✔
924
  ck_assert_msg(strncmp(text, expected, len + 1) != 0,
1✔
925
    "Expected other than '%s'", expected);
1✔
926
}
927
END_TEST
1✔
928

929
START_TEST (getopt_reset_test) {
930
  mark_point();
1✔
931
  pr_getopt_reset();
1✔
932
}
1✔
933
END_TEST
1✔
934

935
START_TEST (exists_test) {
936
  int res;
1✔
937
  const char *path;
1✔
938

1✔
939
  res = exists(NULL);
940
  ck_assert_msg(res == FALSE, "Failed to handle null path");
1✔
941

1✔
942
  path = "/";
943
  res = exists(path);
1✔
944
  ck_assert_msg(res == TRUE, "Expected TRUE for path '%s', got FALSE", path);
1✔
945
}
1✔
946
END_TEST
1✔
947

948
START_TEST (exists2_test) {
949
  int res;
1✔
950
  const char *path;
1✔
951

1✔
952
  res = exists2(NULL, NULL);
953
  ck_assert_msg(res == FALSE, "Failed to handle null arguments");
1✔
954

1✔
955
  res = exists2(p, NULL);
956
  ck_assert_msg(res == FALSE, "Failed to handle null path");
1✔
957

1✔
958
  path = "/";
959
  res = exists2(p, path);
1✔
960
  ck_assert_msg(res == TRUE, "Expected TRUE for path '%s', got FALSE", path);
1✔
961
}
1✔
962
END_TEST
1✔
963

964
START_TEST (dir_exists_test) {
965
  int res;
1✔
966
  const char *path;
1✔
967

1✔
968
  res = dir_exists(NULL);
969
  ck_assert_msg(res == FALSE, "Failed to handle null path");
1✔
970

1✔
971
  path = "/";
972
  res = dir_exists(path);
1✔
973
  ck_assert_msg(res == TRUE, "Expected TRUE for path '%s', got FALSE", path);
1✔
974

1✔
975
  path = "./api-tests";
976
  res = dir_exists(path);
1✔
977
  ck_assert_msg(res == FALSE, "Expected FALSE for path '%s', got TRUE", path);
1✔
978
}
1✔
979
END_TEST
1✔
980

981
START_TEST (dir_exists2_test) {
982
  int res;
1✔
983
  const char *path;
1✔
984

1✔
985
  res = dir_exists2(NULL, NULL);
986
  ck_assert_msg(res == FALSE, "Failed to handle null arguments");
1✔
987

1✔
988
  res = dir_exists2(p, NULL);
989
  ck_assert_msg(res == FALSE, "Failed to handle null path");
1✔
990

1✔
991
  path = "/";
992
  res = dir_exists2(p, path);
1✔
993
  ck_assert_msg(res == TRUE, "Expected TRUE for path '%s', got FALSE", path);
1✔
994

1✔
995
  path = "./api-tests";
996
  res = dir_exists2(p, path);
1✔
997
  ck_assert_msg(res == FALSE, "Expected FALSE for path '%s', got TRUE", path);
1✔
998
}
1✔
999
END_TEST
1✔
1000

1001
START_TEST (symlink_mode_test) {
1002
  mode_t res;
1✔
1003
  const char *path;
1✔
1004

1✔
1005
  res = symlink_mode(NULL);
1006
  ck_assert_msg(res == 0, "Failed to handle null arguments");
1✔
1007
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1008
    strerror(errno), errno);
1✔
1009

1010
  path = "/";
1011
  res = symlink_mode(path);
1✔
1012
  ck_assert_msg(res == 0, "Found mode for non-symlink '%s'", path);
1✔
1013
}
1✔
1014
END_TEST
1✔
1015

1016
START_TEST (symlink_mode2_test) {
1017
  mode_t res;
1✔
1018
  const char *path;
1✔
1019

1✔
1020
  res = symlink_mode2(NULL, NULL);
1021
  ck_assert_msg(res == 0, "Failed to handle null arguments");
1✔
1022
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1023
    strerror(errno), errno);
1✔
1024

1025
  res = symlink_mode2(p, NULL);
1026
  ck_assert_msg(res == 0, "Failed to handle null path");
1✔
1027
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1028
    strerror(errno), errno);
1✔
1029

1030
  path = "/";
1031
  res = symlink_mode2(p, path);
1✔
1032
  ck_assert_msg(res == 0, "Found mode for non-symlink '%s'", path);
1✔
1033
}
1✔
1034
END_TEST
1✔
1035

1036
START_TEST (file_mode_test) {
1037
  mode_t res;
1✔
1038
  const char *path;
1✔
1039

1✔
1040
  res = file_mode(NULL);
1041
  ck_assert_msg(res == 0, "Failed to handle null path");
1✔
1042
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1043
    strerror(errno), errno);
1✔
1044

1045
  path = "/";
1046
  res = file_mode(path);
1✔
1047
  ck_assert_msg(res != 0, "Failed to find mode for '%s': %s", path,
1✔
1048
    strerror(errno));
1✔
1049
}
1050
END_TEST
1✔
1051

1052
START_TEST (file_mode2_test) {
1053
  mode_t res;
1✔
1054
  const char *path;
1✔
1055

1✔
1056
  res = file_mode2(NULL, NULL);
1057
  ck_assert_msg(res == 0, "Failed to handle null arguments");
1✔
1058
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1059
    strerror(errno), errno);
1✔
1060

1061
  res = file_mode2(p, NULL);
1062
  ck_assert_msg(res == 0, "Failed to handle null path");
1✔
1063
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1064
    strerror(errno), errno);
1✔
1065

1066
  path = "/";
1067
  res = file_mode2(p, path);
1✔
1068
  ck_assert_msg(res != 0, "Failed to find mode for '%s': %s", path,
1✔
1069
    strerror(errno));
1✔
1070
}
1071
END_TEST
1✔
1072

1073
START_TEST (file_exists_test) {
1074
  int res;
1✔
1075
  const char *path;
1✔
1076

1✔
1077
  res = file_exists(NULL);
1078
  ck_assert_msg(res == FALSE, "Failed to handle null path");
1✔
1079

1✔
1080
  path = "/";
1081
  res = file_exists(path);
1✔
1082
  ck_assert_msg(res == FALSE, "Expected FALSE for path '%s', got TRUE", path);
1✔
1083

1✔
1084
  path = "./api-tests";
1085
  res = file_exists(path);
1✔
1086
  ck_assert_msg(res == TRUE, "Expected TRUE for path '%s', got FALSE", path);
1✔
1087
}
1✔
1088
END_TEST
1✔
1089

1090
START_TEST (file_exists2_test) {
1091
  int res;
1✔
1092
  const char *path;
1✔
1093

1✔
1094
  res = file_exists2(NULL, NULL);
1095
  ck_assert_msg(res == FALSE, "Failed to handle null arguments");
1✔
1096

1✔
1097
  res = file_exists2(p, NULL);
1098
  ck_assert_msg(res == FALSE, "Failed to handle null path");
1✔
1099

1✔
1100
  path = "/";
1101
  res = file_exists2(p, path);
1✔
1102
  ck_assert_msg(res == FALSE, "Expected FALSE for path '%s', got TRUE", path);
1✔
1103

1✔
1104
  path = "./api-tests";
1105
  res = file_exists2(p, path);
1✔
1106
  ck_assert_msg(res == TRUE, "Expected TRUE for path '%s', got FALSE", path);
1✔
1107
}
1✔
1108
END_TEST
1✔
1109

1110
START_TEST (gmtime_test) {
1111
  struct tm *res;
1✔
1112
  time_t now;
1✔
1113

1✔
1114
  mark_point();
1115
  res = pr_gmtime(NULL, NULL);
1✔
1116
  ck_assert_msg(res == NULL, "Failed to handle null arguments");
1✔
1117
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1118
    strerror(errno), errno);
1✔
1119

1120
  time(&now);
1121

1✔
1122
  mark_point();
1123
  res = pr_gmtime(NULL, &now);
1✔
1124
#if defined(HAVE_GMTIME_R)
1✔
1125
  ck_assert_msg(res == NULL, "Failed to handle null pool");
1126
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1127
    strerror(errno), errno);
1✔
1128
#else
1129
  ck_assert_msg(res != NULL, "Failed to handle %lu: %s", (unsigned long) now,
1130
    strerror(errno));
1131
#endif /* HAVE_GMTIME_R */
1132

1133
  mark_point();
1134
  res = pr_gmtime(p, &now);
1✔
1135
  ck_assert_msg(res != NULL, "Failed to handle %lu: %s", (unsigned long) now,
1✔
1136
    strerror(errno));
1✔
1137
}
1138
END_TEST
1✔
1139

1140
START_TEST (localtime_test) {
1141
  struct tm *res;
1✔
1142
  time_t now;
1✔
1143

1✔
1144
  mark_point();
1145
  res = pr_localtime(NULL, NULL);
1✔
1146
  ck_assert_msg(res == NULL, "Failed to handle null arguments");
1✔
1147
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1148
    strerror(errno), errno);
1✔
1149

1150
  time(&now);
1151

1✔
1152
  mark_point();
1153
  res = pr_localtime(NULL, &now);
1✔
1154
#if defined(HAVE_LOCALTIME_R)
1✔
1155
  ck_assert_msg(res == NULL, "Failed to handle null pool");
1156
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1157
    strerror(errno), errno);
1✔
1158
#else
1159
  ck_assert_msg(res != NULL, "Failed to handle %lu: %s", (unsigned long) now,
1160
    strerror(errno));
1161
#endif /* HAVE_LOCALTIME_R */
1162

1163
  mark_point();
1164
  res = pr_localtime(p, &now);
1✔
1165
  ck_assert_msg(res != NULL, "Failed to handle %lu: %s", (unsigned long) now,
1✔
1166
    strerror(errno));
1✔
1167
}
1168
END_TEST
1✔
1169

1170
START_TEST (timingsafe_bcmp_test) {
1171
  int res;
1✔
1172

1✔
1173
  mark_point();
1✔
1174
  res = pr_timingsafe_bcmp("foo", "bar", 4);
1175
  ck_assert_msg(res != 0, "Failed to handle mismatched text");
1✔
1176

1✔
1177
  mark_point();
1✔
1178
  res = pr_timingsafe_bcmp("foo", "foo", 4);
1179
  ck_assert_msg(res == 0, "Failed to handle matching text");
1✔
1180
}
1✔
1181
END_TEST
1182

1183
START_TEST (strtime_test) {
1184
  const char *res;
1185
  time_t now;
1186

1✔
1187
  mark_point();
1188
  now = 0;
1189
  res = pr_strtime(now);
1✔
1190
#if defined(HAVE_LOCALTIME_R)
1✔
1191
  ck_assert_msg(res == NULL, "Failed to handle null pool");
1✔
1192
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1193
    strerror(errno), errno);
1194
#else
1✔
1195
  ck_assert_msg(res != NULL, "Failed to convert time %lu: %s",
1✔
1196
    (unsigned long) now, strerror(errno));
1✔
1197
#endif /* HAVE_LOCALTIME_R */
1✔
1198
}
1199
END_TEST
1✔
1200

1✔
1201
START_TEST (strtime2_test) {
1202
  const char *res;
1203
  char *expected;
1204
  time_t now;
1205

1206
  mark_point();
1207
  now = 0;
1208
  res = pr_strtime2(now, TRUE);
1✔
1209
#if defined(HAVE_GMTIME_R)
1210
  (void) expected;
1211

1✔
1212
  ck_assert_msg(res == NULL, "Failed to handle null pool");
1✔
1213
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1214
    strerror(errno), errno);
1✔
1215
#else
1216
  expected = "Thu Jan 01 00:00:00 1970";
1✔
1217

1✔
1218
  ck_assert_msg(res != NULL, "Failed to convert time %lu: %s",
1219
    (unsigned long) now, strerror(errno));
1✔
1220
  ck_assert_msg(strcmp(res, expected) == 0, "Expected '%s', got '%s'", expected,
1✔
1221
    res);
1✔
1222
#endif /* HAVE_GMTIME_R */
1223
}
1224
END_TEST
1225

1✔
1226
START_TEST (strtime3_test) {
1✔
1227
  const char *res;
1✔
1228
  char *expected;
1✔
1229
  time_t now;
1230

1✔
1231
  mark_point();
1232
  now = 0;
1✔
1233
#if defined(HAVE_GMTIME_R)
1234
  res = pr_strtime3(NULL, now, TRUE);
1235
  ck_assert_msg(res == NULL, "Failed to handle null pool argument");
1✔
1236
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%s), got %s (%d)",
1✔
1237
    strerror(EINVAL), strerror(errno), errno);
1✔
1238
#endif /* HAVE_GMTIME_R */
1✔
1239

1240
  mark_point();
1✔
1241
  expected = "Thu Jan 01 00:00:00 1970";
1✔
1242
  res = pr_strtime3(p, now, TRUE);
1✔
1243
  ck_assert_msg(res != NULL, "Failed to convert time %lu: %s",
1244
    (unsigned long) now, strerror(errno));
1245
  ck_assert_msg(strcmp(res, expected) == 0, "Expected '%s', got '%s'", expected,
1✔
1246
    res);
1✔
1247
}
1✔
1248
END_TEST
1249

1250
START_TEST (timeval2millis_test) {
1✔
1251
  int res;
1✔
1252
  struct timeval tv;
1✔
1253
  uint64_t ms;
1254

1✔
1255
  res = pr_timeval2millis(NULL, NULL);
1✔
1256
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1257
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1258
    strerror(errno), errno);
1✔
1259

1✔
1260
  res = pr_timeval2millis(&tv, NULL);
1✔
1261
  ck_assert_msg(res < 0, "Failed to handle null millis argument");
1262
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1263
    strerror(errno), errno);
1✔
1264

1✔
1265
  tv.tv_sec = tv.tv_usec = 0;
1266
  res = pr_timeval2millis(&tv, &ms);
1267
  ck_assert_msg(res == 0, "Failed to convert timeval to millis: %s",
1✔
1268
    strerror(errno));
1✔
1269
  ck_assert_msg(ms == 0, "Expected 0 ms, got %lu", (unsigned long) ms);
1✔
1270
}
1✔
1271
END_TEST
1✔
1272

1273
START_TEST (gettimeofday_millis_test) {
1274
  int res;
1✔
1275
  uint64_t ms;
1✔
1276

1✔
1277
  res = pr_gettimeofday_millis(NULL);
1✔
1278
  ck_assert_msg(res < 0, "Failed to handle null argument");
1279
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1280
    strerror(errno), errno);
1✔
1281

1✔
1282
  ms = 0;
1283
  res = pr_gettimeofday_millis(&ms);
1284
  ck_assert_msg(res == 0, "Failed to get current time ms: %s", strerror(errno));
1✔
1285
  ck_assert_msg(ms > 0, "Expected >0, got %lu", (unsigned long) ms);
1✔
1286
}
1287
END_TEST
1✔
1288

1✔
1289
START_TEST (snprintf_test) {
1✔
1290
  char *buf;
1291
  size_t bufsz;
1292
  int res, expected;
1✔
1293

1✔
1294
  res = pr_snprintf(NULL, 0, NULL);
1295
  ck_assert_msg(res < 0, "Failed to handle null buffer");
1✔
1296
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1297
    strerror(errno), errno);
1✔
1298

1299
  bufsz = 1;
1300
  buf = palloc(p, bufsz);
1✔
1301

1✔
1302
  res = pr_snprintf(buf, 0, NULL);
1✔
1303
  ck_assert_msg(res < 0, "Failed to handle null format");
1304
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1305
    strerror(errno), errno);
1✔
1306

1✔
1307
  res = pr_snprintf(buf, 0, "%d", 0);
1308
  ck_assert_msg(res == 0, "Failed to handle zero-length buffer");
1✔
1309

1✔
1310
  res = pr_snprintf(buf, bufsz, "%d", 0);
1✔
1311
  ck_assert_msg(res < 0, "Failed to handle too-small buffer");
1✔
1312
  ck_assert_msg(errno == ENOSPC, "Expected ENOSPC (%d), got %s (%d)", ENOSPC,
1313
    strerror(errno), errno);
1314

1✔
1315
  res = pr_snprintf(buf, bufsz, "%s", "foobar");
1✔
1316
  ck_assert_msg(res < 0, "Failed to handle too-small buffer");
1✔
1317
  ck_assert_msg(errno == ENOSPC, "Expected ENOSPC (%d), got %s (%d)", ENOSPC,
1✔
1318
    strerror(errno), errno);
1319

1✔
1320
  bufsz = 32;
1✔
1321
  buf = palloc(p, bufsz);
1✔
1322

1323
  expected = 6;
1324
  res = pr_snprintf(buf, bufsz, "%s", "foobar");
1✔
1325
  ck_assert_msg(res == expected, "Expected %d, got %d", expected, res);
1✔
1326
}
1327
END_TEST
1✔
1328

1✔
1329
START_TEST (snprintfl_test) {
1✔
1330
  char *buf;
1331
  size_t bufsz;
1332
  int res, expected;
1✔
1333

1✔
1334
  res = pr_snprintfl(NULL, -1, NULL, 0, NULL);
1335
  ck_assert_msg(res < 0, "Failed to handle null buffer");
1✔
1336
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1337
    strerror(errno), errno);
1✔
1338

1339
  bufsz = 1;
1340
  buf = palloc(p, bufsz);
1✔
1341

1✔
1342
  res = pr_snprintfl(NULL, -1, buf, 0, NULL);
1✔
1343
  ck_assert_msg(res < 0, "Failed to handle null format");
1344
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1345
    strerror(errno), errno);
1✔
1346

1✔
1347
  res = pr_snprintfl(__FILE__, __LINE__, buf, 0, "%d", 0);
1348
  ck_assert_msg(res == 0, "Failed to handle zero-length buffer");
1✔
1349

1✔
1350
  res = pr_snprintfl(__FILE__, __LINE__, buf, bufsz, "%d", 0);
1✔
1351
  ck_assert_msg(res < 0, "Failed to handle too-small buffer");
1✔
1352
  ck_assert_msg(errno == ENOSPC, "Expected ENOSPC (%d), got %s (%d)", ENOSPC,
1353
    strerror(errno), errno);
1354

1✔
1355
  res = pr_snprintfl(__FILE__, __LINE__, buf, bufsz, "%s", "foobar");
1✔
1356
  ck_assert_msg(res < 0, "Failed to handle too-small buffer");
1357
  ck_assert_msg(errno == ENOSPC, "Expected ENOSPC (%d), got %s (%d)", ENOSPC,
1✔
1358
    strerror(errno), errno);
1✔
1359

1✔
1360
  bufsz = 32;
1361
  buf = palloc(p, bufsz);
1362

1✔
1363
  expected = 6;
1✔
1364
  res = pr_snprintfl(__FILE__, __LINE__, buf, bufsz, "%s", "foobar");
1✔
1365
  ck_assert_msg(res == expected, "Expected %d, got %d", expected, res);
1366
}
1367
END_TEST
1✔
1368

1✔
1369
START_TEST (path_subst_uservar_test) {
1✔
1370
  const char *path = NULL, *res, *original, *expected;
1371

1372
  res = path_subst_uservar(NULL, NULL);
1✔
1373
  ck_assert_msg(res == NULL, "Failed to handle null pool");
1✔
1374
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1375
    strerror(errno), errno);
1✔
1376

1✔
1377
  res = path_subst_uservar(p, NULL);
1378
  ck_assert_msg(res == NULL, "Failed to handle null path pointer");
1✔
1379
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1380
    strerror(errno), errno);
1381

1✔
1382
  res = path_subst_uservar(p, &path);
1✔
1383
  ck_assert_msg(res == NULL, "Failed to handle null path");
1✔
1384
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1385
    strerror(errno), errno);
1✔
1386

1✔
1387
  original = expected = "somepathhere";
1✔
1388
  path = pstrdup(p, expected);
1389
  mark_point();
1✔
1390
  res = path_subst_uservar(p, &path);
1391
  ck_assert_msg(res != NULL, "Failed to handle path '%s': %s", path,
1392
    strerror(errno));
1✔
1393
  ck_assert_msg(strcmp(res, expected) == 0, "Expected '%s', got '%s'", expected,
1✔
1394
    res);
1✔
1395

1✔
1396
  session.user = "user";
1✔
1397
  original = "/home/%u";
1✔
1398
  expected = "/home/user";
1✔
1399
  path = pstrdup(p, original);
1400
  mark_point();
1✔
1401
  res = path_subst_uservar(p, &path);
1402
  ck_assert_msg(res != NULL, "Failed to handle path '%s': %s", path,
1403
    strerror(errno));
1✔
1404
  ck_assert_msg(strcmp(res, expected) == 0, "Expected '%s', got '%s'", expected,
1✔
1405
    res);
1✔
1406

1✔
1407
  session.user = "user";
1✔
1408
  original = "/home/%u[";
1✔
1409
  expected = "/home/user[";
1✔
1410
  path = pstrdup(p, original);
1411
  mark_point();
1✔
1412
  res = path_subst_uservar(p, &path);
1413
  ck_assert_msg(res != NULL, "Failed to handle path '%s': %s", path,
1414
    strerror(errno));
1✔
1415
  ck_assert_msg(strcmp(res, expected) == 0, "Expected '%s', got '%s'", expected,
1✔
1416
    res);
1✔
1417

1✔
1418
  session.user = "user";
1✔
1419
  original = "/home/%u[]";
1✔
1420
  expected = "/home/user[]";
1✔
1421
  path = pstrdup(p, original);
1422
  mark_point();
1✔
1423
  res = path_subst_uservar(p, &path);
1424
  ck_assert_msg(res != NULL, "Failed to handle path '%s': %s", path,
1425
    strerror(errno));
1426
  ck_assert_msg(strcmp(res, expected) == 0, "Expected '%s', got '%s'", expected,
1✔
1427
    res);
1✔
1428

1✔
1429
  session.user = "user";
1✔
1430
  original = "/home/users/%u[0]/%u[0]%u[1]/%u";
1✔
1431
  expected = "/home/users/u/us/user";
1✔
1432
  path = pstrdup(p, original);
1✔
1433
  mark_point();
1434
  res = path_subst_uservar(p, &path);
1✔
1435
  ck_assert_msg(res != NULL, "Failed to handle path '%s': %s", path,
1436
    strerror(errno));
1437
  ck_assert_msg(strcmp(res, expected) == 0, "Expected '%s', got '%s'", expected,
1438
    res);
1✔
1439

1✔
1440
  /* Attempt to use an invalid index */
1✔
1441
  session.user = "user";
1✔
1442
  original = "/home/users/%u[a]/%u[b]%u[c]/%u";
1✔
1443
  expected = original;
1✔
1444
  path = pstrdup(p, original);
1✔
1445
  mark_point();
1446
  res = path_subst_uservar(p, &path);
1✔
1447
  ck_assert_msg(res != NULL, "Failed to handle path '%s': %s", path,
1448
    strerror(errno));
1449
  ck_assert_msg(strcmp(res, expected) == 0, "Expected '%s', got '%s'", expected,
1450
    res);
1✔
1451

1✔
1452
  /* Attempt to use an out-of-bounds index */
1✔
1453
  session.user = "user";
1✔
1454
  original = "/home/users/%u[0]/%u[-1]%u[1]/%u";
1✔
1455
  expected = original;
1✔
1456
  path = pstrdup(p, original);
1✔
1457
  mark_point();
1458
  res = path_subst_uservar(p, &path);
1✔
1459
  ck_assert_msg(res != NULL, "Failed to handle path '%s': %s", path,
1460
    strerror(errno));
1✔
1461
  ck_assert_msg(strcmp(res, expected) == 0, "Expected '%s', got '%s'", expected,
1462
    res);
1463

889✔
1464
  /* Attempt to use an out-of-bounds index */
889✔
1465
  session.user = "user";
889✔
1466
  original = "/home/users/%u[0]/%u[0]%u[4]/%u";
1467
  expected = original;
889✔
1468
  path = pstrdup(p, original);
1469
  mark_point();
889✔
1470
  res = path_subst_uservar(p, &path);
889✔
1471
  ck_assert_msg(res != NULL, "Failed to handle path '%s': %s", path,
1472
    strerror(errno));
889✔
1473
  ck_assert_msg(strcmp(res, expected) == 0, "Expected '%s', got '%s'", expected,
889✔
1474
    res);
889✔
1475
}
889✔
1476
END_TEST
889✔
1477

889✔
1478
Suite *tests_get_misc_suite(void) {
889✔
1479
  Suite *suite;
889✔
1480
  TCase *testcase;
889✔
1481

889✔
1482
  suite = suite_create("misc");
889✔
1483

889✔
1484
  testcase = tcase_create("base");
889✔
1485
  tcase_add_checked_fixture(testcase, set_up, tear_down);
889✔
1486

889✔
1487
  tcase_add_test(testcase, schedule_test);
889✔
1488
  tcase_add_test(testcase, get_name_max_test);
889✔
1489
  tcase_add_test(testcase, dir_interpolate_test);
889✔
1490
  tcase_add_test(testcase, dir_best_path_test);
889✔
1491
  tcase_add_test(testcase, dir_canonical_path_test);
889✔
1492
  tcase_add_test(testcase, dir_canonical_vpath_test);
889✔
1493
  tcase_add_test(testcase, dir_readlink_test);
889✔
1494
  tcase_add_test(testcase, dir_realpath_test);
889✔
1495
  tcase_add_test(testcase, dir_abs_path_test);
889✔
1496
  tcase_add_test(testcase, symlink_mode_test);
889✔
1497
  tcase_add_test(testcase, symlink_mode2_test);
889✔
1498
  tcase_add_test(testcase, file_mode_test);
889✔
1499
  tcase_add_test(testcase, file_mode2_test);
889✔
1500
  tcase_add_test(testcase, exists_test);
889✔
1501
  tcase_add_test(testcase, exists2_test);
889✔
1502
  tcase_add_test(testcase, dir_exists_test);
889✔
1503
  tcase_add_test(testcase, dir_exists2_test);
889✔
1504
  tcase_add_test(testcase, file_exists_test);
889✔
1505
  tcase_add_test(testcase, file_exists2_test);
1506
  tcase_add_test(testcase, safe_token_test);
889✔
1507
  tcase_add_test(testcase, check_shutmsg_test);
889✔
1508
  tcase_add_test(testcase, memscrub_test);
1509
  tcase_add_test(testcase, getopt_reset_test);
1510
  tcase_add_test(testcase, gmtime_test);
1511
  tcase_add_test(testcase, localtime_test);
1512
  tcase_add_test(testcase, timingsafe_bcmp_test);
1513
  tcase_add_test(testcase, strtime_test);
1514
  tcase_add_test(testcase, strtime2_test);
1515
  tcase_add_test(testcase, strtime3_test);
1516
  tcase_add_test(testcase, timeval2millis_test);
1517
  tcase_add_test(testcase, gettimeofday_millis_test);
1518
  tcase_add_test(testcase, snprintf_test);
1519
  tcase_add_test(testcase, snprintfl_test);
1520
  tcase_add_test(testcase, path_subst_uservar_test);
1521

1522
  suite_add_tcase(suite, testcase);
1523
  return suite;
1524
}
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