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

proftpd / proftpd / 30135626854

25 Jul 2026 12:15AM UTC coverage: 93.034% (+0.6%) from 92.428%
30135626854

push

github

51363 of 55209 relevant lines covered (93.03%)

219.82 hits per line

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

97.61
/tests/api/scoreboard.c
1
/*
2
 * ProFTPD - FTP server testsuite
3
 * Copyright (c) 2008-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
/* Scoreboard API tests */
25

26
#include "tests.h"
27

28
static pool *p = NULL;
29

30
static const char *test_dir = "/tmp/prt-scoreboard/";
31
static const char *test_file = "/tmp/prt-scoreboard/test.dat";
32
static const char *test_mutex = "/tmp/prt-scoreboard/test.dat.lck";
33
static const char *test_file2 = "/tmp/prt-scoreboard-mutex.dat";
34

35
static void set_up(void) {
36
  (void) unlink(test_file);
20✔
37
  (void) unlink(test_file2);
20✔
38
  (void) unlink(test_mutex);
20✔
39
  (void) rmdir(test_dir);
20✔
40

20✔
41
  if (p == NULL) {
42
    p = permanent_pool = make_sub_pool(NULL);
20✔
43
  }
20✔
44

45
  ServerType = SERVER_STANDALONE;
46
  init_netaddr();
20✔
47

20✔
48
  if (getenv("TEST_VERBOSE") != NULL) {
49
    pr_trace_set_levels("lock", 1, 20);
20✔
50
    pr_trace_set_levels("scoreboard", 1, 20);
20✔
51
  }
20✔
52
}
53

20✔
54
static void tear_down(void) {
55
  (void) unlink(test_file);
20✔
56
  (void) unlink(test_file2);
20✔
57
  (void) unlink(test_mutex);
20✔
58
  (void) rmdir(test_dir);
20✔
59

20✔
60
  if (getenv("TEST_VERBOSE") != NULL) {
61
    pr_trace_set_levels("lock", 0, 0);
20✔
62
    pr_trace_set_levels("scoreboard", 0, 0);
20✔
63
  }
20✔
64

65
  if (p) {
66
    destroy_pool(p);
20✔
67
    p = permanent_pool = NULL;
20✔
68
  }
20✔
69
}
70

20✔
71
START_TEST (scoreboard_get_test) {
72
  const char *ok, *res;
1✔
73

1✔
74
  ok = PR_RUN_DIR "/proftpd.scoreboard";
75

1✔
76
  res = pr_get_scoreboard();
77
  ck_assert_msg(res != NULL, "Failed to get scoreboard path: %s",
1✔
78
    strerror(errno));
1✔
79
  ck_assert_msg(strcmp(res, ok) == 0,
80
    "Expected scoreboard path '%s', got '%s'", ok, res);
1✔
81

82
  ok = PR_RUN_DIR "/proftpd.scoreboard.lck";
83

1✔
84
  res = pr_get_scoreboard_mutex();
85
  ck_assert_msg(res != NULL, "Failed to get scoreboard mutex path: %s",
1✔
86
    strerror(errno));
1✔
87
  ck_assert_msg(strcmp(res, ok) == 0,
88
    "Expected scoreboard mutex path '%s', got '%s'", ok, res);
1✔
89
}
90
END_TEST
1✔
91

92
START_TEST (scoreboard_set_test) {
93
  int fd, res;
1✔
94
  const char *path;
1✔
95

1✔
96
  mark_point();
97
  res = pr_set_scoreboard(NULL);
1✔
98
  ck_assert_msg(res < 0, "Failed to handle null argument");
1✔
99
  ck_assert_msg(errno == EINVAL, "Failed to set errno to EINVAL");
1✔
100

1✔
101
  mark_point();
102
  res = pr_set_scoreboard("foo");
1✔
103
  ck_assert_msg(res < 0, "Failed to handle non-path argument");
1✔
104
  ck_assert_msg(errno == EINVAL, "Failed to set errno to EINVAL (got %d)",
1✔
105
    errno);
1✔
106

107
  mark_point();
108
  res = pr_set_scoreboard("foo/");
1✔
109
  ck_assert_msg(res < 0, "Failed to handle relative path argument");
1✔
110
  ck_assert_msg(errno == EINVAL, "Failed to set errno to EINVAL (got %d)",
1✔
111
    errno);
1✔
112

113
  mark_point();
114
  res = pr_set_scoreboard("/foo");
1✔
115
  ck_assert_msg(res < 0, "Failed to handle nonexistent path argument");
1✔
116
  ck_assert_msg(errno == EINVAL, "Failed to set errno to EINVAL (got %d)",
1✔
117
    errno);
1✔
118

119
  mark_point();
120
  res = pr_set_scoreboard("/tmp");
1✔
121
  ck_assert_msg(res < 0, "Failed to handle nonexistent path argument");
1✔
122
  ck_assert_msg(errno == EINVAL, "Failed to set errno to EINVAL (got %d)",
1✔
123
    errno);
1✔
124

125
  mark_point();
126
  res = pr_set_scoreboard("/tmp/");
1✔
127
  ck_assert_msg(res < 0, "Failed to handle nonexistent path argument");
1✔
128
  ck_assert_msg(errno == EINVAL, "Failed to set errno to EINVAL (got %d)",
1✔
129
    errno);
1✔
130

131
  mark_point();
132
  res = pr_set_scoreboard("/tmp/foo/bar");
1✔
133
  ck_assert_msg(res < 0, "Failed to handle nonexistent path argument");
1✔
134
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
1✔
135
    strerror(errno), errno);
1✔
136

137
  res = mkdir(test_dir, 0777);
138
  ck_assert_msg(res == 0,
1✔
139
    "Failed to create tmp directory '%s': %s", test_dir, strerror(errno));
1✔
140
  res = chmod(test_dir, 0777);
141
  ck_assert_msg(res == 0,
1✔
142
    "Failed to create set 0777 perms on '%s': %s", test_dir, strerror(errno));
1✔
143

144
  mark_point();
145
  fd = open("/tmp/foo", O_CREAT|O_RDONLY, 0400);
1✔
146
  if (fd < 0) {
1✔
147
    return;
1✔
148
  }
149
  (void) close(fd);
150

1✔
151
  res = pr_set_scoreboard("/tmp/foo/bar");
152
  ck_assert_msg(res < 0, "Failed to handle non-directory path argument");
1✔
153
  ck_assert_msg(errno == ENOTDIR, "Expected ENOTDIR (%d), got %s (%d)", ENOTDIR,
1✔
154
    strerror(errno), errno);
1✔
155
  (void) unlink("/tmp/foo");
156

1✔
157
  mark_point();
158
  res = pr_set_scoreboard(test_dir);
1✔
159
  ck_assert_msg(res < 0, "Failed to handle nonexistent file argument");
1✔
160
  ck_assert_msg(errno == EINVAL, "Failed to set errno to EINVAL");
1✔
161

1✔
162
  mark_point();
163
  res = pr_set_scoreboard("/tmp/prt-scoreboard/bar");
1✔
164
  ck_assert_msg(res < 0, "Failed to handle world-writable path argument");
1✔
165
  ck_assert_msg(errno == EPERM, "Failed to set errno to EPERM");
1✔
166

1✔
167
  res = chmod(test_dir, 0775);
168
  ck_assert_msg(res == 0, "Failed to set 0775 perms on '%s': %s", test_dir,
1✔
169
    strerror(errno));
1✔
170

171
  mark_point();
172
  res = pr_set_scoreboard("/tmp/prt-scoreboard/bar");
1✔
173
  ck_assert_msg(res == 0, "Failed to set scoreboard: %s", strerror(errno));
1✔
174
  (void) rmdir(test_dir);
1✔
175

1✔
176
  path = pr_get_scoreboard();
177
  ck_assert_msg(path != NULL, "Failed to get scoreboard path: %s",
1✔
178
    strerror(errno));
1✔
179
  ck_assert_msg(strcmp("/tmp/prt-scoreboard/bar", path) == 0,
180
    "Expected '%s', got '%s'", "/tmp/prt-scoreboard/bar", path);
1✔
181

182
  (void) rmdir(test_dir);
183
}
1✔
184
END_TEST
185

186
START_TEST (scoreboard_set_mutex_test) {
187
  int res;
1✔
188
  const char *path;
1✔
189

1✔
190
  res = pr_set_scoreboard_mutex(NULL);
191
  ck_assert_msg(res == -1, "Failed to handle null argument");
1✔
192
  ck_assert_msg(errno == EINVAL, "Failed to set errno to EINVAL");
1✔
193

1✔
194
  res = pr_set_scoreboard_mutex("/tmp");
195
  ck_assert_msg(res == 0, "Failed to set scoreboard mutex: %s",
1✔
196
    strerror(errno));
1✔
197

198
  path = pr_get_scoreboard_mutex();
199
  ck_assert_msg(path != NULL, "Failed to get scoreboard mutex path: %s",
1✔
200
    strerror(errno));
1✔
201
  ck_assert_msg(strcmp("/tmp", path) == 0,
202
    "Expected '%s', got '%s'", "/tmp", path);
1✔
203
}
204
END_TEST
1✔
205

206
START_TEST (scoreboard_open_close_test) {
207
  int res;
1✔
208
  const char *symlink_path = "/tmp/prt-scoreboard/symlink";
1✔
209

1✔
210
  res = mkdir(test_dir, 0775);
211
  ck_assert_msg(res == 0, "Failed to create directory '%s': %s", test_dir,
1✔
212
    strerror(errno));
1✔
213

214
  res = chmod(test_dir, 0775);
215
  ck_assert_msg(res == 0, "Failed to set perms on '%s': %s", test_dir,
1✔
216
    strerror(errno));
1✔
217

218
  res = pr_set_scoreboard(test_file);
219
  ck_assert_msg(res == 0, "Failed to set scoreboard to '%s': %s", test_file,
1✔
220
    strerror(errno));
1✔
221

222
  if (symlink(symlink_path, test_file) == 0) {
223

1✔
224
    res = pr_open_scoreboard(O_RDWR);
225
    if (res == 0) {
1✔
226
      (void) unlink(symlink_path);
1✔
227

×
228
      ck_abort_msg("Unexpectedly opened symlink scoreboard");
229
    }
×
230

231
    if (errno != EPERM) {
232
      int xerrno = errno;
1✔
233

×
234
      (void) unlink(symlink_path);
235

×
236
      ck_abort_msg("Failed to set errno to EPERM (got %d)", xerrno);
237
    }
×
238

239
    (void) unlink(symlink_path);
240

1✔
241
    res = pr_set_scoreboard(test_file);
242
    ck_assert_msg(res == 0, "Failed to set scoreboard to '%s': %s", test_file,
1✔
243
      strerror(errno));
1✔
244
  }
245

246
  res = pr_open_scoreboard(O_RDONLY);
247
  ck_assert_msg(res < 0, "Unexpectedly opened scoreboard using O_RDONLY");
1✔
248

1✔
249
  if (errno != EINVAL) {
250
    int xerrno = errno;
1✔
251

×
252
    (void) unlink(symlink_path);
253

×
254
    ck_abort_msg("Failed to set errno to EINVAL (got %d)", xerrno);
255
  }
×
256

257
  (void) unlink(test_mutex);
258
  (void) unlink(test_file);
1✔
259
  res = pr_open_scoreboard(O_RDWR);
1✔
260
  ck_assert_msg(res == 0, "Failed to open scoreboard: %s", strerror(errno));
1✔
261

1✔
262
  /* Try opening the scoreboard again; it should be OK, since we are the
263
   * opener.
264
   */
265
  res = pr_open_scoreboard(O_RDWR);
266
  ck_assert_msg(res == 0, "Failed to open scoreboard again: %s", strerror(errno));
1✔
267

1✔
268
  /* Now that we have a scoreboard, try opening it again using O_RDONLY. */
269
  mark_point();
270
  pr_close_scoreboard(FALSE);
1✔
271

1✔
272
  res = pr_open_scoreboard(O_RDONLY);
273
  ck_assert_msg(res < 0, "Unexpectedly opened scoreboard using O_RDONLY");
1✔
274
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
275
    strerror(errno), errno);
1✔
276

277
  mark_point();
278
  res = pr_open_scoreboard(O_RDWR);
1✔
279
  ck_assert_msg(res == 0, "Failed to open scoreboard: %s", strerror(errno));
1✔
280

1✔
281
  res = pr_close_scoreboard(FALSE);
282
  ck_assert_msg(res == 0, "Failed to close scoreboard: %s", strerror(errno));
1✔
283

1✔
284
  /* Close the already-closed scoreboard, to assert that it is a no-op. */
285
  mark_point();
286
  res = pr_close_scoreboard(FALSE);
1✔
287
  ck_assert_msg(res == 0, "Failed to close scoreboard: %s", strerror(errno));
1✔
288

1✔
289
  (void) unlink(test_mutex);
290
  (void) unlink(test_file);
1✔
291
  (void) rmdir(test_dir);
1✔
292
}
1✔
293
END_TEST
1✔
294

295
START_TEST (scoreboard_open_invalid_header_test) {
296
  int fd, res;
1✔
297
  pr_scoreboard_header_t sch;
1✔
298

1✔
299
  res = mkdir(test_dir, 0775);
300
  ck_assert_msg(res == 0, "Failed to create directory '%s': %s", test_dir,
1✔
301
    strerror(errno));
1✔
302

303
  res = chmod(test_dir, 0775);
304
  ck_assert_msg(res == 0, "Failed to set perms on '%s': %s", test_dir,
1✔
305
    strerror(errno));
1✔
306

307
  (void) unlink(test_file);
308
  res = pr_set_scoreboard(test_file);
1✔
309
  ck_assert_msg(res == 0, "Failed to set scoreboard to '%s': %s", test_file,
1✔
310
    strerror(errno));
1✔
311

312
  /* Bad magic */
313
  mark_point();
314
  fd = open(test_file, O_CREAT|O_RDWR, PR_SCOREBOARD_MODE);
1✔
315
  if (fd < 0) {
1✔
316
    return;
1✔
317
  }
×
318

319
  memset(&sch, 0, sizeof(sch));
320
  (void) write(fd, &sch, sizeof(sch));
1✔
321
  (void) close(fd);
1✔
322
  res = pr_open_scoreboard(O_RDWR);
1✔
323
  ck_assert_msg(res == PR_SCORE_ERR_BAD_MAGIC,
1✔
324
    "Failed to handle invalid header magic; expected %d, got %d",
1✔
325
    PR_SCORE_ERR_BAD_MAGIC, res);
326
  (void) unlink(test_file);
327

1✔
328
  /* Version too old */
329
  mark_point();
330
  fd = open(test_file, O_CREAT|O_RDWR, PR_SCOREBOARD_MODE);
1✔
331
  if (fd < 0) {
1✔
332
    return;
1✔
333
  }
334

335
  memset(&sch, 0, sizeof(sch));
336
  sch.sch_magic = PR_SCOREBOARD_MAGIC;
1✔
337
  sch.sch_version = 1;
1✔
338
  (void) write(fd, &sch, sizeof(sch));
1✔
339
  (void) close(fd);
1✔
340
  res = pr_open_scoreboard(O_RDWR);
1✔
341
  ck_assert_msg(res == PR_SCORE_ERR_OLDER_VERSION,
1✔
342
    "Failed to handle too-old header version; expected %d, got %d",
1✔
343
    PR_SCORE_ERR_OLDER_VERSION, res);
344
  (void) unlink(test_file);
345

1✔
346
  /* Version too new */
347
  mark_point();
348
  fd = open(test_file, O_CREAT|O_RDWR, PR_SCOREBOARD_MODE);
1✔
349
  if (fd < 0) {
1✔
350
    return;
1✔
351
  }
352

353
  memset(&sch, 0, sizeof(sch));
354
  sch.sch_magic = PR_SCOREBOARD_MAGIC;
1✔
355
  sch.sch_version = PR_SCOREBOARD_VERSION + 1;
1✔
356
  (void) write(fd, &sch, sizeof(sch));
1✔
357
  (void) close(fd);
1✔
358
  res = pr_open_scoreboard(O_RDWR);
1✔
359
  ck_assert_msg(res == PR_SCORE_ERR_NEWER_VERSION,
1✔
360
    "Failed to handle too-new header version; expected %d, got %d",
1✔
361
    PR_SCORE_ERR_NEWER_VERSION, res);
362
  (void) unlink(test_file);
363

1✔
364
  (void) unlink(test_mutex);
365
  (void) rmdir(test_dir);
1✔
366
}
1✔
367
END_TEST
368

369
START_TEST (scoreboard_lock_test) {
370
  int fd = -1, lock_type = -1, res;
1✔
371

1✔
372
  res = pr_lock_scoreboard(fd, lock_type);
373
  ck_assert_msg(res < 0, "Failed to handle bad lock type");
1✔
374
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
375
    strerror(errno), errno);
1✔
376

377
  lock_type = F_RDLCK;
378
  res = pr_lock_scoreboard(fd, lock_type);
1✔
379
  ck_assert_msg(res < 0, "Failed to handle bad file descriptor");
1✔
380
  ck_assert_msg(errno == EBADF, "Expected EBADF (%d), got %s (%d)", EBADF,
1✔
381
    strerror(errno), errno);
1✔
382

383
  fd = open(test_file2, O_CREAT|O_EXCL|O_RDWR, S_IRUSR|S_IWUSR);
384
  ck_assert_msg(fd >= 0, "Failed to open '%s': %s", test_file2, strerror(errno));
1✔
385

1✔
386
  res = pr_lock_scoreboard(fd, lock_type);
387
  ck_assert_msg(res == 0, "Failed to lock fd %d: %s", fd, strerror(errno));
1✔
388

1✔
389
  lock_type = F_WRLCK;
390
  res = pr_lock_scoreboard(fd, lock_type);
1✔
391
  ck_assert_msg(res == 0, "Failed to lock fd %d: %s", fd, strerror(errno));
1✔
392

1✔
393
  lock_type = F_UNLCK;
394
  res = pr_lock_scoreboard(fd, lock_type);
1✔
395
  ck_assert_msg(res == 0, "Failed to lock fd %d: %s", fd, strerror(errno));
1✔
396

1✔
397
  lock_type = F_WRLCK;
398
  res = pr_lock_scoreboard(fd, lock_type);
1✔
399
  ck_assert_msg(res == 0, "Failed to lock fd %d: %s", fd, strerror(errno));
1✔
400

1✔
401
  /* Note: apparently attempt to lock (again) a file on which a lock
402
   * (of the same type) is already held will succeed.  Huh.
403
   */
404
  res = pr_lock_scoreboard(fd, lock_type);
405
  ck_assert_msg(res == 0, "Failed to lock fd %d: %s", fd, strerror(errno));
1✔
406

1✔
407
  lock_type = F_RDLCK;
408
  res = pr_lock_scoreboard(fd, lock_type);
1✔
409
  ck_assert_msg(res == 0, "Failed to lock fd %d: %s", fd, strerror(errno));
1✔
410

1✔
411
  lock_type = F_UNLCK;
412
  res = pr_lock_scoreboard(fd, lock_type);
1✔
413
  ck_assert_msg(res == 0, "Failed to lock fd %d: %s", fd, strerror(errno));
1✔
414

1✔
415
  (void) unlink(test_file2);
416
}
1✔
417
END_TEST
1✔
418

419
START_TEST (scoreboard_delete_test) {
420
  int res;
1✔
421
  struct stat st;
1✔
422

1✔
423
  res = mkdir(test_dir, 0775);
424
  ck_assert_msg(res == 0, "Failed to create directory '%s': %s", test_dir,
1✔
425
    strerror(errno));
1✔
426

427
  res = chmod(test_dir, 0775);
428
  ck_assert_msg(res == 0, "Failed to set perms on '%s' to 0775': %s", test_dir,
1✔
429
    strerror(errno));
1✔
430

431
  res = pr_set_scoreboard(test_file);
432
  ck_assert_msg(res == 0, "Failed to set scoreboard to '%s': %s", test_file,
1✔
433
    strerror(errno));
1✔
434

435
  res = pr_open_scoreboard(O_RDWR);
436
  ck_assert_msg(res == 0, "Failed to open scoreboard: %s", strerror(errno));
1✔
437

1✔
438
  res = stat(pr_get_scoreboard(), &st);
439
  ck_assert_msg(res == 0, "Failed to stat scoreboard: %s", strerror(errno));
1✔
440

1✔
441
  pr_delete_scoreboard();
442

1✔
443
  res = stat(pr_get_scoreboard(), &st);
444
  ck_assert_msg(res < 0, "Unexpectedly found deleted scoreboard");
1✔
445

1✔
446
  res = stat(pr_get_scoreboard_mutex(), &st);
447
  ck_assert_msg(res < 0, "Unexpectedly found deleted scoreboard mutex");
1✔
448

1✔
449
  (void) unlink(test_mutex);
450
  (void) unlink(test_file);
1✔
451
  (void) rmdir(test_dir);
1✔
452
}
1✔
453
END_TEST
1✔
454

455
START_TEST (scoreboard_restore_test) {
456
  int res;
1✔
457
  const char *path;
1✔
458

1✔
459
  res = mkdir(test_dir, 0775);
460
  ck_assert_msg(res == 0, "Failed to create directory '%s': %s", test_dir,
1✔
461
    strerror(errno));
1✔
462

463
  res = chmod(test_dir, 0775);
464
  ck_assert_msg(res == 0, "Failed to set perms on '%s' to 0775': %s", test_dir,
1✔
465
    strerror(errno));
1✔
466

467
  res = pr_set_scoreboard(test_file);
468
  ck_assert_msg(res == 0, "Failed to set scoreboard to '%s': %s", test_file,
1✔
469
    strerror(errno));
1✔
470

471
  mark_point();
472
  res = pr_restore_scoreboard();
1✔
473
  ck_assert_msg(res < 0, "Unexpectedly restored scoreboard");
1✔
474
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
475
    strerror(errno), errno);
1✔
476

477
  res = pr_open_scoreboard(O_RDWR);
478
  ck_assert_msg(res == 0, "Failed to open scoreboard: %s", strerror(errno));
1✔
479

1✔
480
  mark_point();
481
  res = pr_restore_scoreboard();
1✔
482
  ck_assert_msg(res < 0,
1✔
483
    "Restoring scoreboard before rewind succeeded unexpectedly");
1✔
484

485
  mark_point();
486
  res = pr_rewind_scoreboard();
1✔
487
  ck_assert_msg(res == 0, "Failed to rewind scoreboard: %s", strerror(errno));
1✔
488
  res = pr_restore_scoreboard();
1✔
489
  ck_assert_msg(res == 0, "Failed to restore scoreboard: %s", strerror(errno));
1✔
490

1✔
491
  mark_point();
492
  path = pr_get_scoreboard();
1✔
493
  res = pr_set_scoreboard("none");
1✔
494
  ck_assert_msg(res == 0, "Failed to disable scoreboarding: %s", strerror(errno));
1✔
495
  res = pr_restore_scoreboard();
1✔
496
  ck_assert_msg(res == 0, "Failed to restore scoreboard: %s", strerror(errno));
1✔
497
  res = pr_set_scoreboard(path);
1✔
498
  ck_assert_msg(res == 0, "Failed to enable scoreboarding: %s", strerror(errno));
1✔
499

1✔
500
  (void) unlink(test_mutex);
501
  (void) unlink(test_file);
1✔
502
  (void) rmdir(test_dir);
1✔
503
}
1✔
504
END_TEST
1✔
505

506
START_TEST (scoreboard_rewind_test) {
507
  int res;
1✔
508
  const char *path;
1✔
509

1✔
510
  res = mkdir(test_dir, 0775);
511
  ck_assert_msg(res == 0, "Failed to create directory '%s': %s", test_dir,
1✔
512
    strerror(errno));
1✔
513

514
  res = chmod(test_dir, 0775);
515
  ck_assert_msg(res == 0, "Failed to set perms on '%s' to 0775': %s", test_dir,
1✔
516
    strerror(errno));
1✔
517

518
  mark_point();
519
  res = pr_set_scoreboard(test_file);
1✔
520
  ck_assert_msg(res == 0, "Failed to set scoreboard to '%s': %s", test_file,
1✔
521
    strerror(errno));
1✔
522

523
  res = pr_rewind_scoreboard();
524
  ck_assert_msg(res < 0, "Unexpectedly rewound scoreboard");
1✔
525
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
526
    strerror(errno), errno);
1✔
527

528
  mark_point();
529
  res = pr_open_scoreboard(O_RDWR);
1✔
530
  ck_assert_msg(res == 0, "Failed to open scoreboard: %s", strerror(errno));
1✔
531
  res = pr_rewind_scoreboard();
1✔
532
  ck_assert_msg(res == 0, "Failed to rewind scoreboard: %s", strerror(errno));
1✔
533

1✔
534
  mark_point();
535
  path = pr_get_scoreboard();
1✔
536
  res = pr_set_scoreboard("none");
1✔
537
  ck_assert_msg(res == 0, "Failed to disable scoreboarding: %s", strerror(errno));
1✔
538
  res = pr_rewind_scoreboard();
1✔
539
  ck_assert_msg(res == 0, "Failed to rewind scoreboard: %s", strerror(errno));
1✔
540
  res = pr_set_scoreboard(path);
1✔
541
  ck_assert_msg(res == 0, "Failed to enable scoreboarding: %s", strerror(errno));
1✔
542

1✔
543
  (void) unlink(test_mutex);
544
  (void) unlink(test_file);
1✔
545
  (void) rmdir(test_dir);
1✔
546
}
1✔
547
END_TEST
1✔
548

549
START_TEST (scoreboard_scrub_test) {
550
  uid_t euid;
1✔
551
  pid_t pid;
1✔
552
  int res;
1✔
553

554
  res = mkdir(test_dir, 0775);
1✔
555
  ck_assert_msg(res == 0, "Failed to create directory '%s': %s", test_dir,
1✔
556
    strerror(errno));
557

558
  res = chmod(test_dir, 0775);
1✔
559
  ck_assert_msg(res == 0, "Failed to set perms on '%s' to 0775': %s", test_dir,
1✔
560
    strerror(errno));
561

562
  res = pr_set_scoreboard(test_file);
1✔
563
  ck_assert_msg(res == 0, "Failed to set scoreboard to '%s': %s", test_file,
1✔
564
    strerror(errno));
565

566
  res = pr_scoreboard_scrub();
1✔
567
  ck_assert_msg(res < 0, "Unexpectedly scrubbed scoreboard");
1✔
568

569
  euid = geteuid();
1✔
570
  if (euid != 0) {
1✔
571
    if (errno != EPERM &&
×
572
        errno != ENOENT) {
573
      ck_abort_msg("Failed to set errno to EPERM/ENOENT, got %d [%s] (euid = %lu)",
×
574
        errno, strerror(errno), (unsigned long) euid);
575
    }
576

577
  } else {
578
    if (errno != ENOENT) {
1✔
579
      ck_abort_msg("Failed to set errno to ENOENT, got %d [%s] (euid = %lu)", errno,
×
580
        strerror(errno), (unsigned long) euid);
581
    }
582
  }
583

584
  res = pr_open_scoreboard(O_RDWR);
1✔
585
  ck_assert_msg(res == 0, "Failed to open scoreboard: %s", strerror(errno));
1✔
586

587
  mark_point();
1✔
588
  res = pr_scoreboard_scrub();
1✔
589
  ck_assert_msg(res == 0, "Failed to scrub scoreboard: %s", strerror(errno));
590

1✔
591
  mark_point();
1✔
592
  res = pr_scoreboard_entry_add();
1✔
593
  ck_assert_msg(res == 0, "Failed to add entry to scoreboard: %s",
1✔
594
    strerror(errno));
595

596
  mark_point();
1✔
597
  pid = getpid();
1✔
598
  res = pr_scoreboard_entry_update(pid, PR_SCORE_CLIENT_NAME, NULL, NULL);
1✔
599
  ck_assert_msg(res == 0, "Failed to update PR_SCORE_CLIENT_NAME: %s",
600
    strerror(errno));
1✔
601

1✔
602
  mark_point();
603
  res = pr_scoreboard_scrub();
604
  ck_assert_msg(res == 0, "Failed to scrub scoreboard: %s", strerror(errno));
1✔
605

1✔
606
  mark_point();
607
  res = pr_scoreboard_entry_del(FALSE);
608
  ck_assert_msg(res == 0, "Failed to delete entry from scoreboard: %s",
1✔
609
    strerror(errno));
1✔
610

611
  mark_point();
612
  res = pr_scoreboard_scrub();
1✔
613
  ck_assert_msg(res == 0, "Failed to scrub scoreboard: %s", strerror(errno));
1✔
614

615
  (void) unlink(test_mutex);
1✔
616
  (void) unlink(test_file);
1✔
617
  (void) rmdir(test_dir);
×
618
}
619
END_TEST
620

621
START_TEST (scoreboard_get_daemon_pid_test) {
1✔
622
  int res;
623
  pid_t daemon_pid;
1✔
624

625
  res = mkdir(test_dir, 0775);
1✔
626
  ck_assert_msg(res == 0, "Failed to create directory '%s': %s", test_dir,
1✔
627
    strerror(errno));
628

1✔
629
  res = chmod(test_dir, 0775);
1✔
630
  ck_assert_msg(res == 0, "Failed to set perms on '%s' to 0775': %s", test_dir,
×
631
    strerror(errno));
632

633
  res = pr_set_scoreboard(test_file);
634
  ck_assert_msg(res == 0, "Failed to set scoreboard to '%s': %s", test_file,
1✔
635
    strerror(errno));
1✔
636

1✔
637
  res = pr_open_scoreboard(O_RDWR);
1✔
638
  ck_assert_msg(res == 0, "Failed to open scoreboard: %s", strerror(errno));
639

640
  daemon_pid = pr_scoreboard_get_daemon_pid();
1✔
641
  if (daemon_pid != getpid()) {
1✔
642
    ck_abort_msg("Expected %lu, got %lu", (unsigned long) getpid(),
1✔
643
      (unsigned long) daemon_pid);
644
  }
1✔
645

1✔
646
  pr_delete_scoreboard();
647

648
  ServerType = SERVER_INETD;
1✔
649

1✔
650
  res = pr_open_scoreboard(O_RDWR);
651
  ck_assert_msg(res == 0, "Failed to open scoreboard: %s", strerror(errno));
652

1✔
653
  daemon_pid = pr_scoreboard_get_daemon_pid();
1✔
654
  if (daemon_pid != 0) {
655
    ck_abort_msg("Expected %lu, got %lu", (unsigned long) 0,
656
      (unsigned long) daemon_pid);
1✔
657
  }
1✔
658

659
  (void) unlink(test_mutex);
1✔
660
  (void) unlink(test_file);
1✔
661
  (void) rmdir(test_dir);
662
}
1✔
663
END_TEST
×
664

665
START_TEST (scoreboard_get_daemon_uptime_test) {
666
  int res;
667
  time_t daemon_uptime, now;
1✔
668

669
  res = mkdir(test_dir, 0775);
1✔
670
  ck_assert_msg(res == 0, "Failed to create directory '%s': %s", test_dir,
671
    strerror(errno));
1✔
672

1✔
673
  res = chmod(test_dir, 0775);
674
  ck_assert_msg(res == 0, "Failed to set perms on '%s' to 0775': %s", test_dir,
1✔
675
    strerror(errno));
1✔
676

×
677
  res = pr_set_scoreboard(test_file);
678
  ck_assert_msg(res == 0, "Failed to set scoreboard to '%s': %s", test_file,
679
    strerror(errno));
680

1✔
681
  res = pr_open_scoreboard(O_RDWR);
1✔
682
  ck_assert_msg(res == 0, "Failed to open scoreboard: %s", strerror(errno));
1✔
683

1✔
684
  daemon_uptime = pr_scoreboard_get_daemon_uptime();
685
  now = time(NULL);
686

1✔
687
  if (daemon_uptime > now) {
1✔
688
    ck_abort_msg("Expected %lu, got %lu", (unsigned long) now,
689
      (unsigned long) daemon_uptime);
1✔
690
  }
1✔
691

692
  pr_delete_scoreboard();
693

1✔
694
  ServerType = SERVER_INETD;
1✔
695

696
  res = pr_open_scoreboard(O_RDWR);
697
  ck_assert_msg(res == 0, "Failed to open scoreboard: %s", strerror(errno));
1✔
698

1✔
699
  daemon_uptime = pr_scoreboard_get_daemon_uptime();
700
  if (daemon_uptime != 0) {
701
    ck_abort_msg("Expected %lu, got %lu", (unsigned long) 0,
1✔
702
      (unsigned long) daemon_uptime);
1✔
703
  }
1✔
704

705
  (void) unlink(test_mutex);
706
  (void) unlink(test_file);
1✔
707
  (void) rmdir(test_dir);
1✔
708
}
709
END_TEST
1✔
710

1✔
711
START_TEST (scoreboard_entry_add_test) {
712
  int res;
713

1✔
714
  res = mkdir(test_dir, 0775);
1✔
715
  ck_assert_msg(res == 0, "Failed to create directory '%s': %s", test_dir,
1✔
716
    strerror(errno));
717

718
  res = chmod(test_dir, 0775);
1✔
719
  ck_assert_msg(res == 0, "Failed to set perms on '%s' to 0775': %s", test_dir,
1✔
720
    strerror(errno));
1✔
721

1✔
722
  res = pr_set_scoreboard(test_file);
723
  ck_assert_msg(res == 0, "Failed to set scoreboard to '%s': %s", test_file,
724
    strerror(errno));
1✔
725

1✔
726
  res = pr_scoreboard_entry_add();
727
  ck_assert_msg(res < 0, "Unexpectedly added entry to scoreboard");
1✔
728
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
729
    strerror(errno), errno);
730

731
  res = pr_open_scoreboard(O_RDWR);
1✔
732
  ck_assert_msg(res == 0, "Failed to open scoreboard: %s", strerror(errno));
1✔
733

734
  res = pr_scoreboard_entry_add();
735
  ck_assert_msg(res == 0, "Failed to add entry to scoreboard: %s",
1✔
736
    strerror(errno));
1✔
737

738
  res = pr_scoreboard_entry_add();
739
  ck_assert_msg(res < 0, "Unexpectedly added entry to scoreboard");
1✔
740
  ck_assert_msg(errno == EPERM, "Expected EPERM (%d), got %s (%d)", EPERM,
1✔
741
    strerror(errno), errno);
1✔
742

743
  (void) unlink(test_mutex);
744
  (void) unlink(test_file);
1✔
745
  (void) rmdir(test_dir);
1✔
746
}
747
END_TEST
1✔
748

1✔
749
START_TEST (scoreboard_entry_del_test) {
1✔
750
  int res;
751

752
  res = mkdir(test_dir, 0775);
1✔
753
  ck_assert_msg(res == 0, "Failed to create directory '%s': %s", test_dir,
1✔
754
    strerror(errno));
755

756
  res = chmod(test_dir, 0775);
1✔
757
  ck_assert_msg(res == 0, "Failed to set perms on '%s' to 0775': %s", test_dir,
1✔
758
    strerror(errno));
759

760
  res = pr_set_scoreboard(test_file);
1✔
761
  ck_assert_msg(res == 0, "Failed to set scoreboard to '%s': %s", test_file,
1✔
762
    strerror(errno));
1✔
763

764
  res = pr_scoreboard_entry_del(FALSE);
765
  ck_assert_msg(res < 0, "Unexpectedly deleted entry from scoreboard");
1✔
766
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
767
    strerror(errno), errno);
1✔
768

1✔
769
  res = pr_open_scoreboard(O_RDWR);
770
  ck_assert_msg(res == 0, "Failed to open scoreboard: %s", strerror(errno));
771

1✔
772
  res = pr_scoreboard_entry_del(FALSE);
1✔
773
  ck_assert_msg(res < 0, "Unexpectedly deleted entry from scoreboard");
1✔
774
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
775
    strerror(errno), errno);
1✔
776

1✔
777
  res = pr_scoreboard_entry_add();
778
  ck_assert_msg(res == 0, "Failed to add entry to scoreboard: %s",
779
    strerror(errno));
1✔
780

1✔
781
  res = pr_scoreboard_entry_del(FALSE);
782
  ck_assert_msg(res == 0, "Failed to delete entry from scoreboard: %s",
783
    strerror(errno));
1✔
784

1✔
785
  res = pr_scoreboard_entry_del(FALSE);
786
  ck_assert_msg(res < 0, "Unexpectedly deleted entry from scoreboard");
787
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
1✔
788
    strerror(errno), errno);
1✔
789

1✔
790
  /* Add another entry; we should reuse the previously written (and zeroed out)
791
   * record/entry.
792
   */
1✔
793
  mark_point();
1✔
794
  res = pr_scoreboard_entry_add();
795
  ck_assert_msg(res == 0, "Failed to add entry to scoreboard: %s",
796
    strerror(errno));
1✔
797

1✔
798
  res = pr_scoreboard_entry_del(FALSE);
799
  ck_assert_msg(res == 0, "Failed to delete entry from scoreboard: %s",
1✔
800
    strerror(errno));
1✔
801

802
  (void) unlink(test_mutex);
803
  (void) unlink(test_file);
1✔
804
  (void) rmdir(test_dir);
1✔
805
}
806
END_TEST
807

1✔
808
START_TEST (scoreboard_entry_read_test) {
×
809
  int res;
810
  pr_scoreboard_entry_t *score;
811

812
  res = mkdir(test_dir, 0775);
1✔
813
  ck_assert_msg(res == 0, "Failed to create directory '%s': %s", test_dir,
1✔
814
    strerror(errno));
815

1✔
816
  res = chmod(test_dir, 0775);
1✔
817
  ck_assert_msg(res == 0, "Failed to set perms on '%s' to 0775': %s", test_dir,
1✔
818
    strerror(errno));
1✔
819

820
  res = pr_set_scoreboard(test_file);
821
  ck_assert_msg(res == 0, "Failed to set scoreboard to '%s': %s", test_file,
1✔
822
    strerror(errno));
1✔
823

1✔
824
  score = pr_scoreboard_entry_read();
1✔
825
  ck_assert_msg(score == NULL, "Unexpectedly read scoreboard entry");
1✔
826
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
827
    strerror(errno), errno);
828

829
  res = pr_open_scoreboard(O_RDWR);
830
  ck_assert_msg(res == 0, "Failed to open scoreboard: %s", strerror(errno));
831

832
  /* We expect NULL here because the scoreboard file should be empty. */
833
  score = pr_scoreboard_entry_read();
834
  ck_assert_msg(score == NULL, "Unexpectedly read scoreboard entry");
835

836
  res = pr_scoreboard_entry_add();
837
  ck_assert_msg(res == 0, "Failed to add entry to scoreboard: %s",
1✔
838
    strerror(errno));
1✔
839

840
  score = pr_scoreboard_entry_read();
841
  ck_assert_msg(score != NULL, "Failed to read scoreboard entry: %s",
1✔
842
    strerror(errno));
1✔
843

844
  if (score->sce_pid != getpid()) {
845
    ck_abort_msg("Failed to read expected scoreboard entry (expected PID %lu, got %lu)",
1✔
846
      (unsigned long) getpid(), (unsigned long) score->sce_pid);
1✔
847
  }
848

849
  score = pr_scoreboard_entry_read();
1✔
850
  ck_assert_msg(score == NULL, "Unexpectedly read scoreboard entry");
1✔
851

1✔
852
  (void) unlink(test_mutex);
853
  (void) unlink(test_file);
854
  (void) rmdir(test_dir);
1✔
855
}
1✔
856
END_TEST
857

1✔
858
START_TEST (scoreboard_entry_get_test) {
1✔
859
  register unsigned int i;
1✔
860
  int res;
861
  const char *val;
862
  int scoreboard_fields[] = {
1✔
863
    PR_SCORE_USER,
1✔
864
    PR_SCORE_CLIENT_ADDR,
865
    PR_SCORE_CLIENT_NAME,
866
    PR_SCORE_CLASS,
1✔
867
    PR_SCORE_CWD,
1✔
868
    PR_SCORE_CMD,
1✔
869
    PR_SCORE_CMD_ARG,
870
    PR_SCORE_PROTOCOL,
871
    -1
10✔
872
  };
8✔
873

8✔
874
  res = mkdir(test_dir, 0775);
875
  ck_assert_msg(res == 0, "Failed to create directory '%s': %s", test_dir,
876
    strerror(errno));
877

1✔
878
  res = chmod(test_dir, 0775);
1✔
879
  ck_assert_msg(res == 0, "Failed to set perms on '%s' to 0775': %s", test_dir,
1✔
880
    strerror(errno));
1✔
881

882
  res = pr_set_scoreboard(test_file);
883
  ck_assert_msg(res == 0, "Failed to set scoreboard to '%s': %s", test_file,
1✔
884
    strerror(errno));
1✔
885

1✔
886
  val = pr_scoreboard_entry_get(-1);
1✔
887
  ck_assert_msg(val == NULL, "Unexpectedly read value from scoreboard entry");
1✔
888
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
889
    strerror(errno), errno);
1✔
890

1✔
891
  res = pr_open_scoreboard(O_RDWR);
892
  ck_assert_msg(res == 0, "Failed to open scoreboard: %s", strerror(errno));
1✔
893

1✔
894
  val = pr_scoreboard_entry_get(-1);
895
  ck_assert_msg(val == NULL, "Unexpectedly read value from scoreboard entry");
896
  ck_assert_msg(errno == EPERM, "Expected EPERM (%d), got %s (%d)", EPERM,
1✔
897
    strerror(errno), errno);
1✔
898

899
  res = pr_scoreboard_entry_add();
900
  ck_assert_msg(res == 0, "Failed to add entry to scoreboard: %s",
1✔
901
    strerror(errno));
1✔
902

903
  val = pr_scoreboard_entry_get(-1);
904
  ck_assert_msg(val == NULL, "Unexpectedly read value from scoreboard entry");
1✔
905
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
1✔
906
    strerror(errno), errno);
1✔
907

908
  for (i = 0; scoreboard_fields[i] != -1; i++) {
909
    val = pr_scoreboard_entry_get(scoreboard_fields[i]);
1✔
910
    ck_assert_msg(val != NULL, "Failed to read scoreboard field %d: %s",
1✔
911
      scoreboard_fields[i], strerror(errno));
912
  }
1✔
913

1✔
914
  (void) unlink(test_mutex);
1✔
915
  (void) unlink(test_file);
916
  (void) rmdir(test_dir);
917
}
1✔
918
END_TEST
1✔
919

920
START_TEST (scoreboard_entry_update_test) {
921
  int num, res;
1✔
922
  const char *val;
1✔
923
  pid_t pid = getpid();
1✔
924
  const pr_netaddr_t *addr;
925
  time_t now;
926
  off_t len;
1✔
927
  unsigned long elapsed;
1✔
928

1✔
929
  res = mkdir(test_dir, 0775);
930
  ck_assert_msg(res == 0, "Failed to create directory '%s': %s", test_dir,
1✔
931
    strerror(errno));
1✔
932

933
  res = chmod(test_dir, 0775);
1✔
934
  ck_assert_msg(res == 0, "Failed to set perms on '%s' to 0775': %s", test_dir,
935
    strerror(errno));
1✔
936

1✔
937
  res = pr_set_scoreboard(test_file);
1✔
938
  ck_assert_msg(res == 0, "Failed to set scoreboard to '%s': %s", test_file,
939
    strerror(errno));
1✔
940

1✔
941
  res = pr_scoreboard_entry_update(pid, 0);
942
  ck_assert_msg(res < 0, "Unexpectedly updated scoreboard entry");
943
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
944
    strerror(errno), errno);
1✔
945

946
  res = pr_open_scoreboard(O_RDWR);
947
  ck_assert_msg(res == 0, "Failed to open scoreboard: %s", strerror(errno));
1✔
948

1✔
949
  res = pr_scoreboard_entry_update(pid, 0);
1✔
950
  ck_assert_msg(res < 0, "Unexpectedly updated scoreboard entry");
951
  ck_assert_msg(errno == EPERM, "Expected EPERM (%d), got %s (%d)", EPERM,
952
    strerror(errno), errno);
1✔
953

1✔
954
  res = pr_scoreboard_entry_add();
1✔
955
  ck_assert_msg(res == 0, "Failed to add entry to scoreboard: %s",
956
    strerror(errno));
1✔
957

1✔
958
  res = pr_scoreboard_entry_update(pid, -1);
1✔
959
  ck_assert_msg(res < 0, "Unexpectedly updated scoreboard entry");
960
  ck_assert_msg(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT,
1✔
961
    strerror(errno), errno);
1✔
962

963
  val = "cwd";
1✔
964
  res = pr_scoreboard_entry_update(pid, PR_SCORE_CWD, val, NULL);
965
  ck_assert_msg(res == 0, "Failed to update PR_SCORE_CWD: %s", strerror(errno));
966

1✔
967
  val = pr_scoreboard_entry_get(PR_SCORE_CWD);
1✔
968
  ck_assert_msg(val != NULL, "Failed to get entry PR_SCORE_CWD: %s",
1✔
969
    strerror(errno));
970
  ck_assert_msg(strcmp(val, "cwd") == 0, "Expected 'cwd', got '%s'", val);
971

1✔
972
  val = "user";
1✔
973
  res = pr_scoreboard_entry_update(pid, PR_SCORE_USER, val, NULL);
974
  ck_assert_msg(res == 0, "Failed to update PR_SCORE_USER: %s", strerror(errno));
975

1✔
976
  addr = pr_netaddr_get_addr(p, "127.0.0.1", NULL);
1✔
977
  ck_assert_msg(addr != NULL, "Failed to resolve '127.0.0.1': %s",
1✔
978
    strerror(errno));
979

980
  res = pr_scoreboard_entry_update(pid, PR_SCORE_CLIENT_ADDR, addr, NULL);
1✔
981
  ck_assert_msg(res == 0, "Failed to update PR_SCORE_CLIENT_ADDR: %s",
1✔
982
    strerror(errno));
1✔
983

984
  val = "remote_name";
985
  res = pr_scoreboard_entry_update(pid, PR_SCORE_CLIENT_NAME, val, NULL);
1✔
986
  ck_assert_msg(res == 0, "Failed to update PR_SCORE_CLIENT_NAME: %s",
1✔
987
    strerror(errno));
1✔
988

989
  val = "session_class";
990
  res = pr_scoreboard_entry_update(pid, PR_SCORE_CLASS, val, NULL);
1✔
991
  ck_assert_msg(res == 0, "Failed to update PR_SCORE_CLASS: %s", strerror(errno));
1✔
992

1✔
993
  val = "USER";
994
  res = pr_scoreboard_entry_update(pid, PR_SCORE_CMD, "%s", val, NULL, NULL);
995
  ck_assert_msg(res == 0, "Failed to update PR_SCORE_CMD: %s", strerror(errno));
1✔
996

1✔
997
  val = "foo bar";
1✔
998
  res = pr_scoreboard_entry_update(pid, PR_SCORE_CMD_ARG, "%s", val, NULL,
999
    NULL);
1000
  ck_assert_msg(res == 0, "Failed to update PR_SCORE_CMD_ARG: %s",
1✔
1001
    strerror(errno));
1✔
1002

1✔
1003
  num = 77;
1004
  res = pr_scoreboard_entry_update(pid, PR_SCORE_SERVER_PORT, num, NULL);
1005
  ck_assert_msg(res == 0, "Failed to update PR_SCORE_SERVER_PORT: %s",
1✔
1006
    strerror(errno));
1✔
1007

1✔
1008
  res = pr_scoreboard_entry_update(pid, PR_SCORE_SERVER_ADDR, addr, num, NULL);
1009
  ck_assert_msg(res == 0, "Failed to update PR_SCORE_SERVER_ADDR: %s",
1010
    strerror(errno));
1✔
1011

1✔
1012
  val = "label";
1✔
1013
  res = pr_scoreboard_entry_update(pid, PR_SCORE_SERVER_LABEL, val, NULL);
1014
  ck_assert_msg(res == 0, "Failed to update PR_SCORE_SERVER_LABEL: %s",
1015
    strerror(errno));
1✔
1016

1✔
1017
  now = 1;
1✔
1018
  res = pr_scoreboard_entry_update(pid, PR_SCORE_BEGIN_IDLE, now, NULL);
1✔
1019
  ck_assert_msg(res == 0, "Failed to update PR_SCORE_BEGIN_IDLE: %s",
1020
    strerror(errno));
1021

1✔
1022
  now = 2;
1✔
1023
  res = pr_scoreboard_entry_update(pid, PR_SCORE_BEGIN_SESSION, now, NULL);
1✔
1024
  ck_assert_msg(res == 0, "Failed to update PR_SCORE_BEGIN_SESSION: %s",
1025
    strerror(errno));
1✔
1026

1✔
1027
  len = 7;
1✔
1028
  res = pr_scoreboard_entry_update(pid, PR_SCORE_XFER_DONE, len, NULL);
1✔
1029
  ck_assert_msg(res == 0, "Failed to update PR_SCORE_XFER_DONE: %s",
1030
    strerror(errno));
1031

1✔
1032
  len = 8;
1✔
1033
  res = pr_scoreboard_entry_update(pid, PR_SCORE_XFER_SIZE, len, NULL);
1✔
1034
  ck_assert_msg(res == 0, "Failed to update PR_SCORE_XFER_SIZE: %s",
1✔
1035
    strerror(errno));
1✔
1036

1037
  len = 9;
1038
  res = pr_scoreboard_entry_update(pid, PR_SCORE_XFER_LEN, len, NULL);
1✔
1039
  ck_assert_msg(res == 0, "Failed to update PR_SCORE_XFER_LEN: %s",
1✔
1040
    strerror(errno));
1✔
1041

1✔
1042
  elapsed = 1;
1043
  res = pr_scoreboard_entry_update(pid, PR_SCORE_XFER_ELAPSED, elapsed, NULL);
1044
  ck_assert_msg(res == 0, "Failed to update PR_SCORE_XFER_ELAPSED: %s",
1✔
1045
    strerror(errno));
1✔
1046

1✔
1047
  val = "protocol";
1✔
1048
  res = pr_scoreboard_entry_update(pid, PR_SCORE_PROTOCOL, val, NULL);
1✔
1049
  ck_assert_msg(res == 0, "Failed to update PR_SCORE_PROTOCOL: %s",
1✔
1050
    strerror(errno));
1✔
1051

1052
  (void) unlink(test_mutex);
1053
  (void) unlink(test_file);
1✔
1054
  (void) rmdir(test_dir);
1✔
1055
}
1056
END_TEST
1✔
1057

1✔
1058
START_TEST (scoreboard_entry_kill_test) {
1✔
1059
  int res;
1060
  pr_scoreboard_entry_t sce;
1061

1✔
1062
  mark_point();
1✔
1063
  res = pr_scoreboard_entry_kill(NULL, 0);
1✔
1064
  ck_assert_msg(res < 0, "Failed to handle null arguments");
1✔
1065
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1066
    strerror(errno), errno);
1067

1✔
1068
  mark_point();
1✔
1069
  sce.sce_pid = 1;
1070
  res = pr_scoreboard_entry_kill(&sce, 0);
1✔
1071
  ck_assert_msg(res < 0, "Failed to handle bad PID");
1✔
1072
  ck_assert_msg(errno == EPERM, "Expected EPERM (%d), got %s (%d)", EPERM,
1073
    strerror(errno), errno);
1✔
1074

1✔
1075
  mark_point();
1✔
1076
  sce.sce_pid = getpid();
1077
  res = pr_scoreboard_entry_kill(&sce, 0);
1✔
1078
  ck_assert_msg(res == 0, "Failed to send signal 0 to PID %lu: %s",
1✔
1079
    (unsigned long) sce.sce_pid, strerror(errno));
1✔
1080

1081
  mark_point();
1✔
1082
  res = pr_set_scoreboard("none");
1✔
1083
  ck_assert_msg(res == 0, "Failed to disable scoreboarding: %s", strerror(errno));
1✔
1084
  sce.sce_pid = getpid();
1085
  res = pr_scoreboard_entry_kill(&sce, 0);
1086
  ck_assert_msg(res == 0, "Failed to send signal: %s", strerror(errno));
1087
}
1088
END_TEST
1✔
1089

1✔
1090
START_TEST (scoreboard_entry_lock_test) {
1091
  int fd = -1, lock_type = -1, res;
1✔
1092

1✔
1093
  res = pr_scoreboard_entry_lock(fd, lock_type);
1✔
1094
  ck_assert_msg(res < 0, "Failed to handle bad lock type");
1095
  ck_assert_msg(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
1✔
1096
    strerror(errno), errno);
1✔
1097

1✔
1098
  lock_type = F_RDLCK;
1099
  res = pr_scoreboard_entry_lock(fd, lock_type);
1✔
1100
  ck_assert_msg(res < 0, "Failed to handle bad file descriptor");
1✔
1101
  ck_assert_msg(errno == EBADF, "Expected EBADF (%d), got %s (%d)", EBADF,
1102
    strerror(errno), errno);
1103

1✔
1104
  fd = open(test_file2, O_CREAT|O_EXCL|O_RDWR, S_IRUSR|S_IWUSR);
1✔
1105
  ck_assert_msg(fd >= 0, "Failed to open '%s': %s", test_file2, strerror(errno));
1✔
1106

1107
  res = pr_scoreboard_entry_lock(fd, lock_type);
1108
  ck_assert_msg(res == 0, "Failed to lock fd %d: %s", fd, strerror(errno));
1109

1110
  lock_type = F_WRLCK;
1111
  res = pr_scoreboard_entry_lock(fd, lock_type);
1✔
1112
  ck_assert_msg(res == 0, "Failed to lock fd %d: %s", fd, strerror(errno));
1113

5✔
1114
  lock_type = F_UNLCK;
4✔
1115
  res = pr_scoreboard_entry_lock(fd, lock_type);
4✔
1116
  ck_assert_msg(res == 0, "Failed to lock fd %d: %s", fd, strerror(errno));
4✔
1117

4✔
1118
  lock_type = F_WRLCK;
4✔
1119
  res = pr_scoreboard_entry_lock(fd, lock_type);
1120
  ck_assert_msg(res == 0, "Failed to lock fd %d: %s", fd, strerror(errno));
4✔
1121

4✔
1122
  /* Note: apparently attempt to lock (again) a file on which a lock
1123
   * (of the same type) is already held will succeed.  Huh.
1124
   */
4✔
1125
  res = pr_scoreboard_entry_lock(fd, lock_type);
1126
  ck_assert_msg(res == 0, "Failed to lock fd %d: %s", fd, strerror(errno));
4✔
1127

4✔
1128
  lock_type = F_RDLCK;
1129
  res = pr_scoreboard_entry_lock(fd, lock_type);
4✔
1130
  ck_assert_msg(res == 0, "Failed to lock fd %d: %s", fd, strerror(errno));
1131

1132
  lock_type = F_UNLCK;
4✔
1133
  res = pr_scoreboard_entry_lock(fd, lock_type);
4✔
1134
  ck_assert_msg(res == 0, "Failed to lock fd %d: %s", fd, strerror(errno));
1135

1136
  (void) unlink(test_file2);
4✔
1137
}
4✔
1138
END_TEST
1139

1140
START_TEST (scoreboard_disabled_test) {
4✔
1141
  register unsigned int i = 0;
4✔
1142
  const char *paths[4] = {
1143
    "/dev/null",
1144
    "none",
1145
    "off",
4✔
1146
    NULL
4✔
1147
  };
1148
  const char *path;
1149

1150
  for (path = paths[i]; path != NULL; path = paths[i++]) {
4✔
1151
    int res;
4✔
1152
    const char *field, *ok;
1153
    pid_t scoreboard_pid;
1154
    time_t scoreboard_uptime;
4✔
1155
    pr_scoreboard_entry_t *score;
4✔
1156

1157
    res = pr_set_scoreboard(path);
4✔
1158
    ck_assert_msg(res == 0, "Failed set to scoreboard to '%s': %s", path,
4✔
1159
      strerror(errno));
1160

4✔
1161
    ok = PR_RUN_DIR "/proftpd.scoreboard";
4✔
1162

1163
    path = pr_get_scoreboard();
4✔
1164
    ck_assert_msg(path != NULL, "Failed to get scoreboard path: %s",
4✔
1165
      strerror(errno));
1166
    ck_assert_msg(strcmp(path, ok) == 0,
1167
      "Expected path '%s', got '%s'", ok, path);
4✔
1168

4✔
1169
    res = pr_open_scoreboard(O_RDONLY);
1170
    ck_assert_msg(res == 0, "Failed to open '%s' scoreboard: %s", path,
1171
      strerror(errno));
1172

1173
    res = pr_scoreboard_scrub();
1174
    ck_assert_msg(res == 0, "Failed to scrub '%s' scoreboard: %s", path,
4✔
1175
      strerror(errno));
1176

1✔
1177
    scoreboard_pid = pr_scoreboard_get_daemon_pid();
1178
    ck_assert_msg(scoreboard_pid == 0,
1179
      "Expected to get scoreboard PID 0, got %lu",
890✔
1180
      (unsigned long) scoreboard_pid);
890✔
1181

890✔
1182
    scoreboard_uptime = pr_scoreboard_get_daemon_uptime();
1183
    ck_assert_msg(scoreboard_uptime == 0,
890✔
1184
      "Expected to get scoreboard uptime 0, got %lu",
1185
      (unsigned long) scoreboard_uptime);
890✔
1186

890✔
1187
    res = pr_scoreboard_entry_add();
1188
    ck_assert_msg(res == 0, "Failed to add entry to '%s' scoreboard: %s", path,
890✔
1189
      strerror(errno));
890✔
1190

890✔
1191
    score = pr_scoreboard_entry_read();
890✔
1192
    ck_assert_msg(score == NULL, "Expected null entry");
890✔
1193

890✔
1194
    field = pr_scoreboard_entry_get(PR_SCORE_CMD_ARG);
890✔
1195
    ck_assert_msg(field == NULL, "Expected null CMD_ARG field");
890✔
1196

890✔
1197
    res = pr_scoreboard_entry_update(getpid(), PR_SCORE_CWD, "foo", NULL);
890✔
1198
    ck_assert_msg(res == 0, "Failed to update CWD field: %s", strerror(errno));
890✔
1199

890✔
1200
    res = pr_scoreboard_entry_del(FALSE);
890✔
1201
    ck_assert_msg(res == 0, "Failed to delete entry from '%s' scoreboard: %s",
890✔
1202
      path, strerror(errno));
890✔
1203

890✔
1204
    res = pr_close_scoreboard(FALSE);
890✔
1205
    ck_assert_msg(res == 0, "Failed to close '%s' scoreboard: %s", path,
890✔
1206
      strerror(errno));
890✔
1207

890✔
1208
    /* Internal hack: even calling pr_set_scoreboard() with a NULL
1209
     * argument will set the Scoreboard API internal flag back to true.
890✔
1210
     */
890✔
1211
    pr_set_scoreboard(NULL);
1212
  }
1213
}
1214
END_TEST
1215

1216
Suite *tests_get_scoreboard_suite(void) {
1217
  Suite *suite;
1218
  TCase *testcase;
1219

1220
  suite = suite_create("scoreboard");
1221

1222
  testcase = tcase_create("base");
1223
  tcase_add_checked_fixture(testcase, set_up, tear_down);
1224

1225
  tcase_add_test(testcase, scoreboard_get_test);
1226
  tcase_add_test(testcase, scoreboard_set_test);
1227
  tcase_add_test(testcase, scoreboard_set_mutex_test);
1228
  tcase_add_test(testcase, scoreboard_open_close_test);
1229
  tcase_add_test(testcase, scoreboard_open_invalid_header_test);
1230
  tcase_add_test(testcase, scoreboard_lock_test);
1231
  tcase_add_test(testcase, scoreboard_delete_test);
1232
  tcase_add_test(testcase, scoreboard_restore_test);
1233
  tcase_add_test(testcase, scoreboard_rewind_test);
1234
  tcase_add_test(testcase, scoreboard_scrub_test);
1235
  tcase_add_test(testcase, scoreboard_get_daemon_pid_test);
1236
  tcase_add_test(testcase, scoreboard_get_daemon_uptime_test);
1237
  tcase_add_test(testcase, scoreboard_entry_add_test);
1238
  tcase_add_test(testcase, scoreboard_entry_del_test);
1239
  tcase_add_test(testcase, scoreboard_entry_read_test);
1240
  tcase_add_test(testcase, scoreboard_entry_get_test);
1241
  tcase_add_test(testcase, scoreboard_entry_update_test);
1242
  tcase_add_test(testcase, scoreboard_entry_kill_test);
1243
  tcase_add_test(testcase, scoreboard_entry_lock_test);
1244
  tcase_add_test(testcase, scoreboard_disabled_test);
1245

1246
  suite_add_tcase(suite, testcase);
1247
  return suite;
1248
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc