Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,17 @@ tests_LTszoff_CFLAGS = @LSOF_TEST_CFLAGS@ -I$(top_srcdir)/include
tests_LTunix_SOURCES = tests/LTunix.c tests/LTlib.c
tests_LTunix_CFLAGS = @LSOF_TEST_CFLAGS@ -I$(top_srcdir)/include

# Internal cleanup tests also run when the shared library is disabled.
check_LIBRARIES = tests/liblsof_test.a
tests_liblsof_test_a_SOURCES = $(LIBLSOF_SOURCES)
tests_liblsof_test_a_CPPFLAGS = $(lsof_CPPFLAGS)
TESTS += tests/LTfsnames
check_PROGRAMS += tests/LTfsnames
tests_LTfsnames_SOURCES = tests/LTfsnames.c
tests_LTfsnames_CPPFLAGS = $(lsof_CPPFLAGS)
tests_LTfsnames_LDADD = tests/liblsof_test.a
tests/LTfsnames-LTfsnames.$(OBJEXT): $(top_srcdir)/lib/proc.c $(top_srcdir)/lib/lsof.c

# Library tests, only build when liblsof is enabled
if INSTALL_LIBLSOF
TESTS += tests/LTbasic2 tests/LTnull
Expand Down
2 changes: 2 additions & 0 deletions lib/lsof.c
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,8 @@ enum lsof_error lsof_gather(struct lsof_context *ctx,
CLEAN(ctx->cur_file->dev_ch);
CLEAN(ctx->cur_file->nm);
CLEAN(ctx->cur_file->nma);
CLEAN(ctx->cur_file->fsdir);
CLEAN(ctx->cur_file->fsdev);
CLEAN(ctx->cur_file);
}

Expand Down
4 changes: 4 additions & 0 deletions lib/proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ void alloc_lfile(struct lsof_context *ctx,
(void)free((FREE_P *)Lf->nm);
if (Lf->nma)
(void)free((FREE_P *)Lf->nma);
CLEAN(Lf->fsdir);
CLEAN(Lf->fsdev);

#if defined(HASLFILEADD) && defined(CLRLFILEADD)
CLRLFILEADD(Lf)
Expand Down Expand Up @@ -480,6 +482,8 @@ void free_lproc(struct lproc *lp) {
(void)free((FREE_P *)lf->nma);
lf->nma = (char *)NULL;
}
CLEAN(lf->fsdir);
CLEAN(lf->fsdev);

#if defined(HASLFILEADD) && defined(CLRLFILEADD)
CLRLFILEADD(lf)
Expand Down
90 changes: 90 additions & 0 deletions tests/LTfsnames.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/* LTfsnames.c -- filesystem-name ownership in file record cleanup. */

#include "common.h"

static char *names[2];

static void tracked_free(void *ptr) {
int i;
for (i = 0; i < 2; i++) {
if (ptr && ptr == names[i])
names[i] = NULL;
}
free(ptr);
}

/* No kernel access: leave the test's orphaned file for lsof_gather to free. */
static void test_gather_proc_info(struct lsof_context *ctx) { (void)ctx; }

/* Intercept only these implementations' frees, without production test hooks
* or platform-specific allocator/linker support. Link other sources normally. */
#define free tracked_free
#define gather_proc_info test_gather_proc_info
#include "../lib/proc.c"
#include "../lib/lsof.c"
#undef gather_proc_info
#undef free

static void set_names(struct lfile *lf) {
names[0] = lf->fsdir = mkstrcpy("/mountpoint", NULL);
names[1] = lf->fsdev = mkstrcpy("/dev/filesystem", NULL);
if (!names[0] || !names[1]) {
fprintf(stderr, "cannot allocate filesystem names\n");
exit(1);
}
}

static int expect_freed(const char *test) {
int i, failed = 0;
for (i = 0; i < 2; i++) {
if (names[i]) {
fprintf(stderr, "FAIL: %s did not free %s\n", test,
i ? "fsdev" : "fsdir");
failed = 1;
/* Reclaim missed allocations so all cases can run on broken code. */
CLEAN(names[i]);
}
}
if (!failed)
printf("PASS: %s frees both filesystem names\n", test);
return failed;
}

int main(int argc, char *argv[]) {
struct lsof_context *ctx = lsof_new();
struct lproc lp = {0};
struct lsof_result *result = NULL;
int failed = 0;
(void)argc;
(void)argv;
if (!ctx) {
fprintf(stderr, "lsof_new failed\n");
return 1;
}
ctx->cur_proc = &lp;

alloc_lfile(ctx, LSOF_FD_NUMERIC, 0);
set_names(ctx->cur_file);
alloc_lfile(ctx, LSOF_FD_NUMERIC, 1);
failed |= expect_freed("reusing an unselected file record");

set_names(ctx->cur_file);
lp.file = ctx->cur_file;
ctx->cur_file = NULL;
free_lproc(&lp);
failed |= expect_freed("freeing a process's file records");

alloc_lfile(ctx, LSOF_FD_NUMERIC, 2);
set_names(ctx->cur_file);
ctx->frozen = 1; /* Skip kernel initialization as well as enumeration. */
if (lsof_gather(ctx, &result) != LSOF_SUCCESS) {
fprintf(stderr, "lsof_gather failed\n");
failed = 1;
}
failed |= expect_freed("discarding an orphaned file after gathering");

lsof_free_result(result);
ctx->cur_proc = NULL;
lsof_destroy(ctx);
return failed;
}
Loading