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

tstack / lnav / 17589970077-2502

09 Sep 2025 05:00PM UTC coverage: 65.196% (-5.0%) from 70.225%
17589970077-2502

push

github

tstack
[format] add fields for source file/line

Knowing the source file/line context in a log
message can help find log messages when using
log2src.

56 of 70 new or added lines in 2 files covered. (80.0%)

13954 existing lines in 210 files now uncovered.

45516 of 69814 relevant lines covered (65.2%)

404154.37 hits per line

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

79.07
/src/fstat_vtab.cc
1
/**
2
 * Copyright (c) 2017, Timothy Stack
3
 *
4
 * All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions are met:
8
 *
9
 * * Redistributions of source code must retain the above copyright notice, this
10
 * list of conditions and the following disclaimer.
11
 * * Redistributions in binary form must reproduce the above copyright notice,
12
 * this list of conditions and the following disclaimer in the documentation
13
 * and/or other materials provided with the distribution.
14
 * * Neither the name of Timothy Stack nor the names of its contributors
15
 * may be used to endorse or promote products derived from this software
16
 * without specific prior written permission.
17
 *
18
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ''AS IS'' AND ANY
19
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
22
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
 */
29

30
#include <filesystem>
31

32
#include "fstat_vtab.hh"
33

34
#include <fcntl.h>
35
#include <glob.h>
36
#include <grp.h>
37
#include <pwd.h>
38
#include <string.h>
39
#include <sys/stat.h>
40

41
#include "base/auto_mem.hh"
42
#include "base/fs_util.hh"
43
#include "base/injector.hh"
44
#include "base/lnav_log.hh"
45
#include "bound_tags.hh"
46
#include "config.h"
47
#include "sql_help.hh"
48
#include "sql_util.hh"
49
#include "vtab_module.hh"
50

51
namespace {
52

53
enum {
54
    FSTAT_COL_PARENT,
55
    FSTAT_COL_NAME,
56
    FSTAT_COL_DEV,
57
    FSTAT_COL_INO,
58
    FSTAT_COL_TYPE,
59
    FSTAT_COL_MODE,
60
    FSTAT_COL_NLINK,
61
    FSTAT_COL_UID,
62
    FSTAT_COL_USER,
63
    FSTAT_COL_GID,
64
    FSTAT_COL_GROUP,
65
    FSTAT_COL_RDEV,
66
    FSTAT_COL_SIZE,
67
    FSTAT_COL_BLKSIZE,
68
    FSTAT_COL_BLOCKS,
69
    FSTAT_COL_ATIME,
70
    FSTAT_COL_MTIME,
71
    FSTAT_COL_CTIME,
72
    FSTAT_COL_ERROR,
73
    FSTAT_COL_PATTERN,
74
    FSTAT_COL_DATA,
75
};
76

77
/**
78
 * @feature f0:sql.tables.fstat
79
 */
80
struct fstat_table {
81
    static constexpr const char* NAME = "fstat";
82
    static constexpr const char* CREATE_STMT = R"(
83
-- The fstat() table-valued function allows you to query the file system.
84
CREATE TABLE fstat (
85
    st_parent TEXT,
86
    st_name TEXT,
87
    st_dev INTEGER,
88
    st_ino INTEGER,
89
    st_type TEXT,
90
    st_mode INTEGER,
91
    st_nlink INTEGER,
92
    st_uid TEXT,
93
    st_user TEXT,
94
    st_gid TEXT,
95
    st_group TEXT,
96
    st_rdev INTEGER,
97
    st_size INTEGER,
98
    st_blksize INTEGER,
99
    st_blocks INTEGER,
100
    st_atime DATETIME,
101
    st_mtime DATETIME,
102
    st_ctime DATETIME,
103
    error TEXT,
104
    pattern TEXT HIDDEN,
105
    data BLOB HIDDEN
106
);
107
)";
108

109
    struct cursor {
110
        sqlite3_vtab_cursor base;
111
        std::string c_pattern;
112
        static_root_mem<glob_t, globfree> c_glob;
113
        size_t c_path_index{0};
114
        struct stat c_stat;
115
        std::string c_error;
116

117
        explicit cursor(sqlite3_vtab* vt) : base({vt})
9✔
118
        {
119
            memset(&this->c_stat, 0, sizeof(this->c_stat));
9✔
120
        }
9✔
121

122
        void load_stat()
13✔
123
        {
124
            if (this->c_path_index >= this->c_glob->gl_pathc) {
13✔
125
                return;
4✔
126
            }
127
            auto rc = lstat(this->c_glob->gl_pathv[this->c_path_index],
9✔
128
                            &this->c_stat);
129

130
            if (rc == -1) {
9✔
131
                this->c_error = strerror(errno);
6✔
132
            }
133
        }
134

135
        int next()
4✔
136
        {
137
            log_debug("fstat_vtab::next %d %d",
4✔
138
                      this->c_path_index,
139
                      this->c_glob->gl_pathc);
140
            if (this->c_path_index < this->c_glob->gl_pathc) {
4✔
141
                this->c_path_index += 1;
4✔
142
                this->load_stat();
4✔
143
            }
144

145
            return SQLITE_OK;
4✔
146
        }
147

148
        int reset() { return SQLITE_OK; }
×
149

150
        int eof()
14✔
151
        {
152
            log_debug("eof %d %d", this->c_path_index, this->c_glob->gl_pathc);
14✔
153
            return this->c_path_index >= this->c_glob->gl_pathc;
14✔
154
        }
155

UNCOV
156
        int get_rowid(sqlite3_int64& rowid_out)
×
157
        {
UNCOV
158
            rowid_out = this->c_path_index;
×
159

UNCOV
160
            return SQLITE_OK;
×
161
        }
162
    };
163

164
    int get_column(const cursor& vc, sqlite3_context* ctx, int col)
53✔
165
    {
166
        const char* path = vc.c_glob->gl_pathv[vc.c_path_index];
53✔
167
        char time_buf[32];
168

169
        switch (col) {
53✔
170
            case FSTAT_COL_PARENT: {
1✔
171
                const char* slash = strrchr(path, '/');
1✔
172

173
                if (slash == nullptr) {
1✔
UNCOV
174
                    sqlite3_result_text(ctx, ".", 1, SQLITE_STATIC);
×
175
                } else if (path[1] == '\0') {
1✔
UNCOV
176
                    sqlite3_result_text(ctx, "", 0, SQLITE_STATIC);
×
177
                } else {
178
                    sqlite3_result_text(
1✔
179
                        ctx, path, slash - path + 1, SQLITE_TRANSIENT);
1✔
180
                }
181
                break;
1✔
182
            }
183
            case FSTAT_COL_NAME: {
7✔
184
                const char* slash = strrchr(path, '/');
7✔
185

186
                if (slash == nullptr) {
7✔
187
                    sqlite3_result_text(ctx, path, -1, SQLITE_TRANSIENT);
1✔
188
                } else {
189
                    sqlite3_result_text(ctx, slash + 1, -1, SQLITE_TRANSIENT);
6✔
190
                }
191
                break;
7✔
192
            }
193
            case FSTAT_COL_DEV:
1✔
194
                if (vc.c_error.empty()) {
1✔
UNCOV
195
                    sqlite3_result_int(ctx, vc.c_stat.st_dev);
×
196
                } else {
197
                    sqlite3_result_null(ctx);
1✔
198
                }
199
                break;
1✔
200
            case FSTAT_COL_INO:
1✔
201
                if (vc.c_error.empty()) {
1✔
202
                    sqlite3_result_int64(ctx, vc.c_stat.st_ino);
×
203
                } else {
204
                    sqlite3_result_null(ctx);
1✔
205
                }
206
                break;
1✔
207
            case FSTAT_COL_TYPE:
2✔
208
                if (!vc.c_error.empty()) {
2✔
209
                    sqlite3_result_null(ctx);
1✔
210
                } else if (S_ISREG(vc.c_stat.st_mode)) {
1✔
211
                    sqlite3_result_text(ctx, "reg", 3, SQLITE_STATIC);
1✔
UNCOV
212
                } else if (S_ISBLK(vc.c_stat.st_mode)) {
×
UNCOV
213
                    sqlite3_result_text(ctx, "blk", 3, SQLITE_STATIC);
×
UNCOV
214
                } else if (S_ISCHR(vc.c_stat.st_mode)) {
×
UNCOV
215
                    sqlite3_result_text(ctx, "chr", 3, SQLITE_STATIC);
×
UNCOV
216
                } else if (S_ISDIR(vc.c_stat.st_mode)) {
×
UNCOV
217
                    sqlite3_result_text(ctx, "dir", 3, SQLITE_STATIC);
×
UNCOV
218
                } else if (S_ISFIFO(vc.c_stat.st_mode)) {
×
UNCOV
219
                    sqlite3_result_text(ctx, "fifo", 4, SQLITE_STATIC);
×
UNCOV
220
                } else if (S_ISLNK(vc.c_stat.st_mode)) {
×
UNCOV
221
                    sqlite3_result_text(ctx, "lnk", 3, SQLITE_STATIC);
×
UNCOV
222
                } else if (S_ISSOCK(vc.c_stat.st_mode)) {
×
UNCOV
223
                    sqlite3_result_text(ctx, "sock", 3, SQLITE_STATIC);
×
224
                }
225
                break;
2✔
226
            case FSTAT_COL_MODE:
2✔
227
                if (vc.c_error.empty()) {
2✔
228
                    sqlite3_result_int(ctx, vc.c_stat.st_mode & 0777);
1✔
229
                } else {
230
                    sqlite3_result_null(ctx);
1✔
231
                }
232
                break;
2✔
233
            case FSTAT_COL_NLINK:
2✔
234
                if (vc.c_error.empty()) {
2✔
235
                    sqlite3_result_int(ctx, vc.c_stat.st_nlink);
1✔
236
                } else {
237
                    sqlite3_result_null(ctx);
1✔
238
                }
239
                break;
2✔
240
            case FSTAT_COL_UID:
1✔
241
                if (vc.c_error.empty()) {
1✔
UNCOV
242
                    sqlite3_result_int(ctx, vc.c_stat.st_uid);
×
243
                } else {
244
                    sqlite3_result_null(ctx);
1✔
245
                }
246
                break;
1✔
247
            case FSTAT_COL_USER: {
1✔
248
                if (vc.c_error.empty()) {
1✔
UNCOV
249
                    struct passwd* pw = getpwuid(vc.c_stat.st_uid);
×
250

UNCOV
251
                    if (pw != nullptr) {
×
252
                        sqlite3_result_text(
×
UNCOV
253
                            ctx, pw->pw_name, -1, SQLITE_TRANSIENT);
×
254
                    } else {
UNCOV
255
                        sqlite3_result_int(ctx, vc.c_stat.st_uid);
×
256
                    }
257
                } else {
258
                    sqlite3_result_null(ctx);
1✔
259
                }
260
                break;
1✔
261
            }
262
            case FSTAT_COL_GID:
1✔
263
                if (vc.c_error.empty()) {
1✔
UNCOV
264
                    sqlite3_result_int(ctx, vc.c_stat.st_gid);
×
265
                } else {
266
                    sqlite3_result_null(ctx);
1✔
267
                }
268
                break;
1✔
269
            case FSTAT_COL_GROUP: {
1✔
270
                if (vc.c_error.empty()) {
1✔
UNCOV
271
                    struct group* gr = getgrgid(vc.c_stat.st_gid);
×
272

UNCOV
273
                    if (gr != nullptr) {
×
274
                        sqlite3_result_text(
×
UNCOV
275
                            ctx, gr->gr_name, -1, SQLITE_TRANSIENT);
×
276
                    } else {
UNCOV
277
                        sqlite3_result_int(ctx, vc.c_stat.st_gid);
×
278
                    }
279
                } else {
280
                    sqlite3_result_null(ctx);
1✔
281
                }
282
                break;
1✔
283
            }
284
            case FSTAT_COL_RDEV:
1✔
285
                if (vc.c_error.empty()) {
1✔
UNCOV
286
                    sqlite3_result_int(ctx, vc.c_stat.st_rdev);
×
287
                } else {
288
                    sqlite3_result_null(ctx);
1✔
289
                }
290
                break;
1✔
291
            case FSTAT_COL_SIZE:
4✔
292
                if (vc.c_error.empty()) {
4✔
293
                    sqlite3_result_int64(ctx, vc.c_stat.st_size);
3✔
294
                } else {
295
                    sqlite3_result_null(ctx);
1✔
296
                }
297
                break;
4✔
298
            case FSTAT_COL_BLKSIZE:
1✔
299
                if (vc.c_error.empty()) {
1✔
UNCOV
300
                    sqlite3_result_int(ctx, vc.c_stat.st_blksize);
×
301
                } else {
302
                    sqlite3_result_null(ctx);
1✔
303
                }
304
                break;
1✔
305
            case FSTAT_COL_BLOCKS:
1✔
306
                if (vc.c_error.empty()) {
1✔
UNCOV
307
                    sqlite3_result_int(ctx, vc.c_stat.st_blocks);
×
308
                } else {
309
                    sqlite3_result_null(ctx);
1✔
310
                }
311
                break;
1✔
312
            case FSTAT_COL_ATIME:
1✔
313
                if (vc.c_error.empty()) {
1✔
UNCOV
314
                    sql_strftime(
×
UNCOV
315
                        time_buf, sizeof(time_buf), vc.c_stat.st_atime, 0);
×
UNCOV
316
                    sqlite3_result_text(ctx, time_buf, -1, SQLITE_TRANSIENT);
×
317
                } else {
318
                    sqlite3_result_null(ctx);
1✔
319
                }
320
                break;
1✔
321
            case FSTAT_COL_MTIME:
2✔
322
                if (vc.c_error.empty()) {
2✔
323
                    sql_strftime(
1✔
324
                        time_buf, sizeof(time_buf), vc.c_stat.st_mtime, 0);
1✔
325
                    sqlite3_result_text(ctx, time_buf, -1, SQLITE_TRANSIENT);
1✔
326
                } else {
327
                    sqlite3_result_null(ctx);
1✔
328
                }
329
                break;
2✔
330
            case FSTAT_COL_CTIME:
1✔
331
                if (vc.c_error.empty()) {
1✔
UNCOV
332
                    sql_strftime(
×
UNCOV
333
                        time_buf, sizeof(time_buf), vc.c_stat.st_ctime, 0);
×
UNCOV
334
                    sqlite3_result_text(ctx, time_buf, -1, SQLITE_TRANSIENT);
×
335
                } else {
336
                    sqlite3_result_null(ctx);
1✔
337
                }
338
                break;
1✔
339
            case FSTAT_COL_ERROR:
7✔
340
                if (vc.c_error.empty()) {
7✔
341
                    sqlite3_result_null(ctx);
1✔
342
                } else {
343
                    to_sqlite(ctx, vc.c_error);
6✔
344
                }
345
                break;
7✔
346
            case FSTAT_COL_PATTERN:
9✔
347
                sqlite3_result_text(ctx,
9✔
348
                                    vc.c_pattern.c_str(),
349
                                    vc.c_pattern.length(),
9✔
350
                                    SQLITE_TRANSIENT);
351
                break;
9✔
352
            case FSTAT_COL_DATA: {
6✔
353
                auto fs_path = std::filesystem::path{path};
6✔
354
                if (!vc.c_error.empty()) {
6✔
355
                    sqlite3_result_null(ctx);
5✔
356
                } else if (S_ISREG(vc.c_stat.st_mode)) {
1✔
357
                    auto open_res
358
                        = lnav::filesystem::open_file(fs_path, O_RDONLY);
1✔
359

360
                    if (open_res.isErr()) {
1✔
UNCOV
361
                        log_error("unable to read file: %s -- %s",
×
362
                                  path,
363
                                  open_res.unwrapErr().c_str());
UNCOV
364
                        sqlite3_result_null(ctx);
×
365
                    } else {
366
                        auto buffer = auto_buffer::alloc(vc.c_stat.st_size);
1✔
367
                        auto fd = open_res.unwrap();
1✔
368

369
                        while (true) {
370
                            if (buffer.available() == 0) {
2✔
371
                                buffer.expand_by(4096);
1✔
372
                            }
373
                            auto rc = read(fd,
4✔
374
                                           buffer.next_available(),
2✔
375
                                           buffer.available());
376

377
                            if (rc <= 0) {
2✔
378
                                break;
1✔
379
                            }
380
                            buffer.resize_by(rc);
1✔
381
                        }
1✔
382
                        to_sqlite(ctx, blob_auto_buffer{std::move(buffer)});
1✔
383
                    }
1✔
384
                } else if (S_ISLNK(vc.c_stat.st_mode)) {
1✔
UNCOV
385
                    auto link_path = std::filesystem::read_symlink(fs_path);
×
386

UNCOV
387
                    to_sqlite(ctx, link_path.string());
×
UNCOV
388
                } else {
×
UNCOV
389
                    sqlite3_result_null(ctx);
×
390
                }
391
                break;
6✔
392
            }
6✔
393
        }
394

395
        return SQLITE_OK;
53✔
396
    }
397

398
#if 0
399
    int update_row(sqlite3_vtab *tab,
400
                   sqlite3_int64 &index,
401
                   const char *st_parent,
402
                   const char *st_name,
403
                   int64_t st_dev,
404
                   int64_t st_ino,
405
                   const char *st_type,
406
                   int64_t st_mode,
407
                   int64_t st_nlink,
408
                   int64_t st_uid,
409
                   const char *st_user,
410
                   int64_t st_gid,
411
                   const char *st_group,
412
                   int64_t st_rdev,
413
                   int64_t st_size,
414
                   int64_t st_blksize,
415
                   int64_t st_blocks,
416
                   const char *atime,
417
                   const char *mtime,
418
                   const char *ctime,
419
                   const char *pattern) {
420

421
    };
422
#endif
423
};
424

425
int
426
rcBestIndex(sqlite3_vtab* tab, sqlite3_index_info* pIdxInfo)
10✔
427
{
428
    vtab_index_constraints vic(pIdxInfo);
10✔
429
    vtab_index_usage viu(pIdxInfo);
10✔
430

431
    for (auto iter = vic.begin(); iter != vic.end(); ++iter) {
19✔
432
        if (iter->op != SQLITE_INDEX_CONSTRAINT_EQ) {
9✔
UNCOV
433
            continue;
×
434
        }
435

436
        switch (iter->iColumn) {
9✔
437
            case FSTAT_COL_PATTERN:
9✔
438
                viu.column_used(iter);
9✔
439
                break;
9✔
440
        }
441
    }
442

443
    viu.allocate_args(FSTAT_COL_PATTERN, FSTAT_COL_PATTERN, 1);
10✔
444
    return SQLITE_OK;
10✔
445
}
446

447
int
448
rcFilter(sqlite3_vtab_cursor* pVtabCursor,
10✔
449
         int idxNum,
450
         const char* idxStr,
451
         int argc,
452
         sqlite3_value** argv)
453
{
454
    auto* pCur = (fstat_table::cursor*) pVtabCursor;
10✔
455

456
    if (argc != 1) {
10✔
UNCOV
457
        pCur->c_pattern.clear();
×
UNCOV
458
        return SQLITE_OK;
×
459
    }
460

461
    const char* pattern = (const char*) sqlite3_value_text(argv[0]);
10✔
462
    pCur->c_pattern = pattern;
10✔
463
    pCur->c_path_index = 0;
10✔
464
    pCur->c_error.clear();
10✔
465

466
    auto glob_flags = GLOB_ERR;
10✔
467
    if (!lnav::filesystem::is_glob(pCur->c_pattern)) {
10✔
468
        glob_flags |= GLOB_NOCHECK;
9✔
469
    }
470

471
#ifdef GLOB_TILDE
472
    glob_flags |= GLOB_TILDE;
10✔
473
#endif
474

475
    log_debug("doing glob %s", pattern);
10✔
476
#if defined(__MSYS__)
477
    auto win_path = lnav::filesystem::escape_glob_for_win(pattern);
478
    switch (glob(win_path.c_str(), glob_flags, nullptr, pCur->c_glob.inout())) {
479
#else
480
    switch (glob(pattern, glob_flags, nullptr, pCur->c_glob.inout())) {
10✔
481
#endif
UNCOV
482
        case GLOB_NOSPACE:
×
UNCOV
483
            pVtabCursor->pVtab->zErrMsg
×
UNCOV
484
                = sqlite3_mprintf("No space to perform glob()");
×
UNCOV
485
            return SQLITE_ERROR;
×
486
        case GLOB_NOMATCH:
1✔
487
            return SQLITE_OK;
1✔
488
    }
489

490
    pCur->load_stat();
9✔
491

492
    return SQLITE_OK;
9✔
493
}
494

495
}  // namespace
496

497
int
498
register_fstat_vtab(sqlite3* db)
693✔
499
{
500
    static vtab_module<tvt_no_update<fstat_table>> FSTAT_MODULE;
693✔
501
    static auto fstat_help
502
        = help_text("fstat",
693✔
503
                    "A table-valued function for getting information about "
504
                    "file paths/globs")
505
              .sql_table_valued_function()
693✔
506
              .with_parameter(
1,386✔
507
                  {"pattern", "The file path or glob pattern to query."})
508
              .with_result(
1,386✔
509
                  {"st_parent", "The parent path of the directory entry"})
510
              .with_result({"st_name", "The name of the directory entry"})
1,386✔
511
              .with_result({"st_dev", "The device number"})
1,386✔
512
              .with_result({"st_ino", "The inode number"})
1,386✔
513
              .with_result(help_text{"st_type", "The type of the entry"}
2,079✔
514
                               .with_enum_values({
693✔
515
                                   "reg"_frag,
516
                                   "blk"_frag,
517
                                   "chr"_frag,
518
                                   "dir"_frag,
519
                                   "fifo"_frag,
520
                                   "lnk"_frag,
521
                                   "sock"_frag,
522
                               }))
523
              .with_result({"st_mode", "The protection mode"})
1,386✔
524
              .with_result(
1,386✔
525
                  {"st_nlink", "The number of hard links to the entry"})
526
              .with_result({"st_uid", "The ID of the owning user"})
1,386✔
527
              .with_result({"st_user", "The user name"})
1,386✔
528
              .with_result({"st_gid", "The ID of the owning group"})
1,386✔
529
              .with_result({"st_group", "The group name"})
1,386✔
530
              .with_result({"st_rdev", "The device type"})
1,386✔
531
              .with_result({"st_size", "The size of the entry in bytes"})
1,386✔
532
              .with_result({"st_blksize", "The optimal size for I/O"})
1,386✔
533
              .with_result({"st_blocks", "Blocks allocated for the file"})
1,386✔
534
              .with_result({"st_atime", "The last access time"})
1,386✔
535
              .with_result({"st_mtime", "The last modified time"})
1,386✔
536
              .with_result({"st_ctime", "The creation time"})
1,386✔
537
              .with_result({"error",
1,386✔
538
                            "Error message if there was a problem looking up "
539
                            "the entry"})
540
              .with_result({"data", "The contents of the file"})
1,386✔
541
              .with_example(help_example{
1,386✔
542
                  "To read a file and raise an error if there is a problem",
543
                  "SELECT ifnull(data, raise_error('cannot read: ' || st_name, "
544
                  "error)) FROM fstat('/non-existent')",
545
              });
1,386✔
546

547
    int rc;
548

549
    FSTAT_MODULE.vm_module.xBestIndex = rcBestIndex;
693✔
550
    FSTAT_MODULE.vm_module.xFilter = rcFilter;
693✔
551

552
    static auto& lnav_flags = injector::get<unsigned long&, lnav_flags_tag>();
693✔
553

554
    if (lnav_flags & LNF_SECURE_MODE) {
693✔
555
        return SQLITE_OK;
5✔
556
    }
557

558
    rc = FSTAT_MODULE.create(db, "fstat");
688✔
559
    sqlite_function_help.emplace("fstat", &fstat_help);
688✔
560
    fstat_help.index_tags();
688✔
561

562
    ensure(rc == SQLITE_OK);
688✔
563

564
    return rc;
688✔
565
}
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