111
111
if (nrow>0 && row != NULL) {
112
CTX->totals.spam_learned = strtol (row[ncolumn], NULL, 0);
113
CTX->totals.innocent_learned = strtol (row[ncolumn+1], NULL, 0);
114
CTX->totals.spam_misclassified = strtol (row[ncolumn+2], NULL, 0);
115
CTX->totals.innocent_misclassified = strtol (row[ncolumn+3], NULL, 0);
116
CTX->totals.spam_corpusfed = strtol (row[ncolumn+4], NULL, 0);
117
CTX->totals.innocent_corpusfed = strtol (row[ncolumn+5], NULL, 0);
118
CTX->totals.spam_classified = strtol (row[ncolumn+6], NULL, 0);
119
CTX->totals.innocent_classified = strtol (row[ncolumn+7], NULL, 0);
112
CTX->totals.spam_learned = strtoul (row[ncolumn], NULL, 0);
113
if (CTX->totals.spam_learned == ULONG_MAX && errno == ERANGE) {
114
LOGDEBUG("_sqlite_drv_get_spamtotals: failed converting %s to CTX->totals.spam_learned", row[ncolumn]);
118
CTX->totals.innocent_learned = strtoul (row[ncolumn+1], NULL, 0);
119
if (CTX->totals.innocent_learned == ULONG_MAX && errno == ERANGE) {
120
LOGDEBUG("_sqlite_drv_get_spamtotals: failed converting %s to CTX->totals.innocent_learned", row[ncolumn+1]);
124
CTX->totals.spam_misclassified = strtoul (row[ncolumn+2], NULL, 0);
125
if (CTX->totals.spam_misclassified == ULONG_MAX && errno == ERANGE) {
126
LOGDEBUG("_sqlite_drv_get_spamtotals: failed converting %s to CTX->totals.spam_misclassified", row[ncolumn+2]);
130
CTX->totals.innocent_misclassified = strtoul (row[ncolumn+3], NULL, 0);
131
if (CTX->totals.innocent_misclassified == ULONG_MAX && errno == ERANGE) {
132
LOGDEBUG("_sqlite_drv_get_spamtotals: failed converting %s to CTX->totals.innocent_misclassified", row[ncolumn+3]);
136
CTX->totals.spam_corpusfed = strtoul (row[ncolumn+4], NULL, 0);
137
if (CTX->totals.spam_corpusfed == ULONG_MAX && errno == ERANGE) {
138
LOGDEBUG("_sqlite_drv_get_spamtotals: failed converting %s to CTX->totals.spam_corpusfed", row[ncolumn+4]);
142
CTX->totals.innocent_corpusfed = strtoul (row[ncolumn+5], NULL, 0);
143
if (CTX->totals.innocent_corpusfed == ULONG_MAX && errno == ERANGE) {
144
LOGDEBUG("_sqlite_drv_get_spamtotals: failed converting %s to CTX->totals.innocent_corpusfed", row[ncolumn+5]);
148
if (row[ncolumn+6] != NULL && row[ncolumn+7] != NULL) {
149
CTX->totals.spam_classified = strtoul (row[ncolumn+6], NULL, 0);
150
if (CTX->totals.spam_classified == ULONG_MAX && errno == ERANGE) {
151
LOGDEBUG("_sqlite_drv_get_spamtotals: failed converting %s to CTX->totals.spam_classified", row[ncolumn+6]);
155
CTX->totals.innocent_classified = strtoul (row[ncolumn+7], NULL, 0);
156
if (CTX->totals.innocent_classified == ULONG_MAX && errno == ERANGE) {
157
LOGDEBUG("_sqlite_drv_get_spamtotals: failed converting %s to CTX->totals.innocent_classified", row[ncolumn+7]);
162
CTX->totals.spam_classified = 0;
163
CTX->totals.innocent_classified = 0;
125
171
sqlite3_free_table(row);
127
173
memcpy(&s->control_totals, &CTX->totals, sizeof(struct _ds_spam_totals));
154
200
if (s->control_totals.innocent_learned == 0)
156
202
snprintf (query, sizeof (query),
157
"insert into dspam_stats(dspam_stat_id, spam_learned, "
158
"innocent_learned, spam_misclassified, innocent_misclassified, "
159
"spam_corpusfed, innocent_corpusfed, "
160
"spam_classified, innocent_classified) "
161
"values(%d, %ld, %ld, %ld, %ld, %ld, %ld, %ld, %ld)",
203
"INSERT INTO dspam_stats (dspam_stat_id,spam_learned,"
204
"innocent_learned,spam_misclassified,innocent_misclassified,"
205
"spam_corpusfed,innocent_corpusfed,"
206
"spam_classified,innocent_classified)"
207
" VALUES (%d,%lu,%lu,%lu,%lu,%lu,%lu,%lu,%lu)",
163
209
CTX->totals.spam_learned,
164
CTX->totals.innocent_learned,
165
CTX->totals.spam_misclassified,
166
CTX->totals.innocent_misclassified,
167
CTX->totals.spam_corpusfed,
168
CTX->totals.innocent_corpusfed,
169
CTX->totals.spam_classified,
210
CTX->totals.innocent_learned, CTX->totals.spam_misclassified,
211
CTX->totals.innocent_misclassified, CTX->totals.spam_corpusfed,
212
CTX->totals.innocent_corpusfed, CTX->totals.spam_classified,
170
213
CTX->totals.innocent_classified);
171
result = sqlite3_exec(s->dbh, query, NULL, NULL, &err);
214
result = sqlite3_exec(s->dbh, query, NULL, NULL, NULL);
174
217
if (s->control_totals.innocent_learned != 0 || result != SQLITE_OK)
176
219
snprintf (query, sizeof (query),
177
"update dspam_stats set spam_learned = spam_learned %s %d, "
178
"innocent_learned = innocent_learned %s %d, "
179
"spam_misclassified = spam_misclassified %s %d, "
180
"innocent_misclassified = innocent_misclassified %s %d, "
181
"spam_corpusfed = spam_corpusfed %s %d, "
182
"innocent_corpusfed = innocent_corpusfed %s %d, "
183
"spam_classified = spam_classified %s %d, "
184
"innocent_classified = innocent_classified %s %d ",
220
"UPDATE dspam_stats SET spam_learned=spam_learned%s%d,"
221
"innocent_learned=innocent_learned%s%d,"
222
"spam_misclassified=spam_misclassified%s%d,"
223
"innocent_misclassified=innocent_misclassified%s%d,"
224
"spam_corpusfed=spam_corpusfed%s%d,"
225
"innocent_corpusfed=innocent_corpusfed%s%d,"
226
"spam_classified=spam_classified%s%d,"
227
"innocent_classified=innocent_classified%s%d",
185
228
(CTX->totals.spam_learned >
186
229
s->control_totals.spam_learned) ? "+" : "-",
187
230
abs (CTX->totals.spam_learned -
257
snprintf (scratch, sizeof (scratch),
258
"select token, spam_hits, innocent_hits "
259
"from dspam_token_data where token in(");
305
snprintf (queryhead, sizeof (queryhead),
306
"SELECT token,spam_hits,innocent_hits"
307
" FROM dspam_token_data WHERE token IN (");
261
buffer_cat (query, scratch);
262
309
ds_c = ds_diction_cursor(diction);
263
310
ds_term = ds_diction_next(ds_c);
266
snprintf (scratch, sizeof (scratch), "'%" LLU_FMT_SPEC "'", ds_term->key);
267
buffer_cat (query, scratch);
268
ds_term->s.innocent_hits = 0;
269
ds_term->s.spam_hits = 0;
270
ds_term->s.probability = 0;
271
ds_term->s.status &= ~TST_DISK;
272
ds_term = ds_diction_next(ds_c);
274
buffer_cat (query, ",");
277
ds_diction_close(ds_c);
278
buffer_cat (query, ")");
313
buffer_copy(query, queryhead);
315
snprintf (scratch, sizeof (scratch), "'%" LLU_FMT_SPEC "'", ds_term->key);
316
buffer_cat (query, scratch);
317
ds_term->s.innocent_hits = 0;
318
ds_term->s.spam_hits = 0;
319
ds_term->s.probability = 0.00000;
320
ds_term->s.status = 0;
321
if((query->used + 1024) > 1000000) {
322
LOGDEBUG("_ds_getall_spamrecords: Splitting query at %ld characters", query->used);
325
ds_term = ds_diction_next(ds_c);
327
buffer_cat (query, ",");
329
buffer_cat (query, ")");
281
LOGDEBUG ("sqlite query length: %ld\n", query->used);
282
_sqlite_drv_query_error (strdup("VERBOSE DEBUG (INFO ONLY - NOT AN ERROR)"), query->data);
332
LOGDEBUG ("SQLite query length: %ld\n", query->used);
333
_sqlite_drv_query_error (strdup("VERBOSE DEBUG (INFO ONLY - NOT AN ERROR)"), query->data);
288
if ((sqlite3_get_table(s->dbh, query->data, &row, &nrow, &ncolumn, &err))
291
_sqlite_drv_query_error (err, query->data);
292
buffer_destroy(query);
297
sqlite3_free_table(row);
298
buffer_destroy(query);
305
stat.probability = 0;
306
stat.status |= TST_DISK;
307
for(i=1;i<=nrow;i++) {
308
token = strtoull (row[(i*ncolumn)], NULL, 0);
309
stat.spam_hits = strtol (row[1+(i*ncolumn)], NULL, 0);
310
stat.innocent_hits = strtol (row[2+(i*ncolumn)], NULL, 0);
312
if (stat.spam_hits < 0)
314
if (stat.innocent_hits < 0)
315
stat.innocent_hits = 0;
317
ds_diction_addstat(diction, token, &stat);
320
sqlite3_free_table(row);
322
ds_c = ds_diction_cursor(diction);
323
ds_term = ds_diction_next(ds_c);
324
while(ds_term && !s->control_token) {
325
if (ds_term->s.spam_hits && ds_term->s.innocent_hits) {
326
s->control_token = ds_term->key;
327
s->control_sh = ds_term->s.spam_hits;
328
s->control_ih = ds_term->s.innocent_hits;
336
if ((sqlite3_get_table(s->dbh, query->data, &row, &nrow, &ncolumn, &err))
339
_sqlite_drv_query_error (err, query->data);
340
LOGDEBUG ("_ds_getall_spamrecords: unable to run query: %s", query->data);
341
buffer_destroy(query);
342
ds_diction_close(ds_c);
347
sqlite3_free_table(row);
348
buffer_destroy(query);
349
ds_diction_close(ds_c);
354
buffer_destroy(query);
355
ds_diction_close(ds_c);
359
for(i=1;i<=nrow;i++) {
360
token = strtoull (row[(i*ncolumn)], NULL, 0);
361
stat.spam_hits = strtoul (row[1+(i*ncolumn)], NULL, 0);
362
if (stat.spam_hits == ULONG_MAX && errno == ERANGE) {
363
LOGDEBUG("_ds_getall_spamrecords: failed converting %s to stat.spam_hits", row[1+(i*ncolumn)]);
364
sqlite3_free_table(row);
367
stat.innocent_hits = strtoul (row[2+(i*ncolumn)], NULL, 0);
368
if (stat.innocent_hits == ULONG_MAX && errno == ERANGE) {
369
LOGDEBUG("_ds_getall_spamrecords: failed converting %s to stat.innocent_hits", row[2+(i*ncolumn)]);
370
sqlite3_free_table(row);
374
stat.status |= TST_DISK;
375
if (stat.spam_hits < 0)
377
if (stat.innocent_hits < 0)
378
stat.innocent_hits = 0;
379
ds_diction_addstat(diction, token, &stat);
382
sqlite3_free_table(row);
330
384
ds_term = ds_diction_next(ds_c);
332
386
ds_diction_close(ds_c);
334
if (!s->control_token)
336
ds_c = ds_diction_cursor(diction);
337
ds_term = ds_diction_next(ds_c);
338
s->control_token = ds_term->key;
339
s->control_sh = ds_term->s.spam_hits;
340
s->control_ih = ds_term->s.innocent_hits;
341
ds_diction_close(ds_c);
344
387
buffer_destroy (query);
389
sqlite3_free_table(row);
394
stat.innocent_hits = 10;
396
ds_diction_touch(diction, CONTROL_TOKEN, "$$CONTROL$$", 0);
397
ds_diction_addstat(diction, CONTROL_TOKEN, &stat);
398
s->control_token = CONTROL_TOKEN;
378
if (s->control_token == 0)
380
ds_c = ds_diction_cursor(diction);
381
ds_term = ds_diction_next(ds_c);
385
stat.innocent_hits = 0;
389
stat.spam_hits = ds_term->s.spam_hits;
390
stat.innocent_hits = ds_term->s.innocent_hits;
392
ds_diction_close(ds_c);
396
ds_diction_getstat(diction, s->control_token, &stat);
399
snprintf (scratch, sizeof (scratch),
400
"update dspam_token_data set last_hit = date('now'), "
401
"spam_hits = max(0, spam_hits %s %d), "
402
"innocent_hits = max(0, innocent_hits %s %d) "
404
(stat.spam_hits > s->control_sh) ? "+" : "-",
405
abs (stat.spam_hits - s->control_sh),
406
(stat.innocent_hits > s->control_ih) ? "+" : "-",
407
abs (stat.innocent_hits - s->control_ih));
409
buffer_cat (query, scratch);
439
ds_diction_getstat(diction, s->control_token, &control);
441
snprintf (queryhead, sizeof (queryhead),
442
"UPDATE dspam_token_data SET last_hit=date('now'),"
443
"spam_hits=max(0,spam_hits%s%d),"
444
"innocent_hits=max(0,innocent_hits%s%d)"
446
(control.spam_hits > s->control_sh) ? "+" : "-",
447
abs (control.spam_hits - s->control_sh),
448
(control.innocent_hits > s->control_ih) ? "+" : "-",
449
abs (control.innocent_hits - s->control_ih));
451
buffer_copy (query, queryhead);
455
* Add each token in the diction to either an update or an insert queue
411
458
ds_c = ds_diction_cursor(diction);
412
459
ds_term = ds_diction_next(ds_c);
416
if (CTX->training_mode == DST_TOE &&
417
CTX->classification == DSR_NONE &&
418
CTX->operating_mode == DSM_CLASSIFY &&
419
diction->whitelist_token != ds_term->key &&
420
(!ds_term->name || strncmp(ds_term->name, "bnr.", 4)))
422
ds_term = ds_diction_next(ds_c);
426
if (!(ds_term->s.status & TST_DIRTY)) {
427
ds_term = ds_diction_next(ds_c);
431
ds_diction_getstat(diction, ds_term->key, &stat2);
433
if (!(stat2.status & TST_DISK))
437
snprintf(insert, sizeof (insert),
438
"insert into dspam_token_data(token, spam_hits, "
439
"innocent_hits, last_hit) values('%" LLU_FMT_SPEC "', %ld, %ld, "
442
stat2.spam_hits > 0 ? (long) 1 : (long) 0,
443
stat2.innocent_hits > 0 ? (long) 1 : (long) 0);
445
if ((sqlite3_exec(s->dbh, insert, NULL, NULL, &err)) != SQLITE_OK)
447
stat2.status |= TST_DISK;
452
if ((stat2.status & TST_DISK))
463
if (ds_term->key == s->control_token) {
464
ds_term = ds_diction_next(ds_c);
468
/* Don't write lexical tokens if we're in TOE mode classifying */
470
if (CTX->training_mode == DST_TOE &&
471
CTX->operating_mode == DSM_CLASSIFY &&
472
ds_term->key != diction->whitelist_token &&
473
(!ds_term->name || strncmp(ds_term->name, "bnr.", 4)))
475
ds_term = ds_diction_next(ds_c);
479
ds_diction_getstat(diction, ds_term->key, &stat);
481
/* Changed tokens are marked as "dirty" by libdspam */
483
if (!(stat.status & TST_DIRTY)) {
484
ds_term = ds_diction_next(ds_c);
487
stat.status &= ~TST_DIRTY;
490
/* This token wasn't originally loaded from disk, so try an insert */
492
if (!(stat.status & TST_DISK))
495
snprintf(ins, sizeof (ins),
496
"INSERT INTO dspam_token_data (token,spam_hits,"
497
"innocent_hits,last_hit) VALUES ('%" LLU_FMT_SPEC "',%d,%d,"
500
stat.spam_hits > 0 ? 1 : 0,
501
stat.innocent_hits > 0 ? 1 : 0);
502
if ((sqlite3_exec(s->dbh, ins, NULL, NULL, NULL)) != SQLITE_OK)
503
stat.status |= TST_DISK;
506
if (stat.status & TST_DISK) {
454
507
snprintf (scratch, sizeof (scratch), "'%" LLU_FMT_SPEC "'", ds_term->key);
455
508
buffer_cat (query, scratch);
458
ds_term->s.status |= TST_DISK;
513
ds_term->s.status |= TST_DISK;
460
515
ds_term = ds_diction_next(ds_c);
461
if (ds_term && wrote_this)
516
if((query->used + 1024) > 1000000) {
517
LOGDEBUG("_ds_setall_spamrecords: Splitting update query at %ld characters", query->used);
518
buffer_cat (query, ")");
520
if ((sqlite3_exec(s->dbh, query->data, NULL, NULL, &err)) != SQLITE_OK) {
521
_sqlite_drv_query_error (err, query->data);
522
LOGDEBUG ("_ds_setall_spamrecords: unable to run query: %s", query->data);
523
ds_diction_close(ds_c);
524
buffer_destroy(query);
528
buffer_copy (query, queryhead);
529
} else if (ds_term && use_comma)
462
530
buffer_cat (query, ",");
464
532
ds_diction_close(ds_c);
466
536
if (query->used && query->data[strlen (query->data) - 1] == ',')
469
539
query->data[strlen (query->data) - 1] = 0;
473
542
buffer_cat (query, ")");
475
LOGDEBUG("Control: [%ld %ld] [%ld %ld]", s->control_sh, s->control_ih, stat.spam_hits, stat.innocent_hits);
544
LOGDEBUG("Control: [%ld %ld] [%lu %lu] Delta: [%lu %lu]",
545
s->control_sh, s->control_ih,
546
control.spam_hits, control.innocent_hits,
547
control.spam_hits - s->control_sh, control.innocent_hits - s->control_ih);
479
551
if ((sqlite3_exec(s->dbh, query->data, NULL, NULL, &err))!=SQLITE_OK)
481
553
_sqlite_drv_query_error (err, query->data);
554
LOGDEBUG ("_ds_setall_spamrecords: unable to run query: %s", query->data);
482
555
buffer_destroy(query);
554
638
if (!(stat->status & TST_DISK))
556
640
snprintf (query, sizeof (query),
557
"insert into dspam_token_data(token, spam_hits, "
558
"innocent_hits, last_hit)"
559
" values('%" LLU_FMT_SPEC "', %ld, %ld, date('now'))",
641
"INSERT INTO dspam_token_data (token,spam_hits,innocent_hits,last_hit)"
642
" VALUES ('%" LLU_FMT_SPEC "',%lu,%lu,date('now'))",
561
644
stat->spam_hits > 0 ? stat->spam_hits : 0,
562
645
stat->innocent_hits > 0 ? stat->innocent_hits : 0);
563
result = sqlite3_exec(s->dbh, query, NULL, NULL, &err);
646
result = sqlite3_exec(s->dbh, query, NULL, NULL, NULL);
566
649
if ((stat->status & TST_DISK) || result)
568
651
/* insert failed; try updating instead */
569
snprintf (query, sizeof (query), "update dspam_token_data "
570
"set spam_hits = %ld, "
571
"innocent_hits = %ld "
572
"where token = %" LLD_FMT_SPEC,
652
snprintf (query, sizeof (query), "UPDATE dspam_token_data"
653
" SET spam_hits=%lu,"
655
" WHERE token='%" LLU_FMT_SPEC "'",
573
656
stat->spam_hits > 0 ? stat->spam_hits : 0,
574
657
stat->innocent_hits > 0 ? stat->innocent_hits : 0,
577
if ((sqlite3_exec(s->dbh, query, NULL, NULL, &err))!=SQLITE_OK)
660
if ((sqlite3_exec(s->dbh, query, NULL, NULL, &err))!=SQLITE_OK) {
579
661
_sqlite_drv_query_error (err, query);
662
LOGDEBUG ("_ds_set_spamrecord: unable to run query: %s", query);
660
"create table dspam_token_data (token char(20) primary key, "
661
"spam_hits int, innocent_hits int, last_hit date)",
667
"create index id_token_data_02 on dspam_token_data"
674
"create table dspam_signature_data ("
675
"signature char(128) primary key, data blob, created_on date)",
681
"create table dspam_stats (dspam_stat_id int primary key, "
682
"spam_learned int, innocent_learned int, "
683
"spam_misclassified int, innocent_misclassified int, "
684
"spam_corpusfed int, innocent_corpusfed int, "
685
"spam_classified int, innocent_classified int)",
743
LOGDEBUG ("_ds_init_storage: Creating object structure in database: %s", filename);
746
snprintf (buff, sizeof (buff),
747
"CREATE TABLE dspam_token_data (token CHAR(20) PRIMARY KEY,"
748
"spam_hits INT,innocent_hits INT,last_hit DATE)");
749
if ((sqlite3_exec(s->dbh, buff, NULL, NULL, &err))!=SQLITE_OK) {
750
_sqlite_drv_query_error (err, buff);
756
snprintf (buff, sizeof (buff),
757
"CREATE INDEX id_token_data_02 ON dspam_token_data"
759
if ((sqlite3_exec(s->dbh, buff, NULL, NULL, &err))!=SQLITE_OK) {
760
_sqlite_drv_query_error (err, buff);
766
snprintf (buff, sizeof (buff),
767
"CREATE TABLE dspam_signature_data ("
768
"signature CHAR(128) PRIMARY KEY,data BLOB,created_on DATE)");
769
if ((sqlite3_exec(s->dbh, buff, NULL, NULL, &err))!=SQLITE_OK) {
770
_sqlite_drv_query_error (err, buff);
776
snprintf (buff, sizeof (buff),
777
"CREATE TABLE dspam_stats (dspam_stat_id INT PRIMARY KEY,"
778
"spam_learned INT,innocent_learned INT,"
779
"spam_misclassified INT,innocent_misclassified INT,"
780
"spam_corpusfed INT,innocent_corpusfed INT,"
781
"spam_classified INT,innocent_classified INT)");
782
if ((sqlite3_exec(s->dbh, buff, NULL, NULL, &err))!=SQLITE_OK) {
783
_sqlite_drv_query_error (err, buff);
691
791
if (_ds_read_attribute(CTX->config->attributes, "SQLitePragma")) {
855
955
const char *signature)
857
957
struct _sqlite_drv_storage *s = (struct _sqlite_drv_storage *) CTX->storage;
859
958
char scratch[1024];
861
960
const char *query_tail=NULL;
862
961
sqlite3_stmt *stmt;
865
963
if (s->dbh == NULL)
867
LOGDEBUG ("_ds_set_signature; invalid database handle (NULL)");
965
LOGDEBUG ("_ds_set_signature: invalid database handle (NULL)");
871
mem = calloc (1, 2 + (257*SIG->length)/254);
874
LOG (LOG_CRIT, ERR_MEM_ALLOC);
878
969
snprintf (scratch, sizeof (scratch),
879
"insert into dspam_signature_data(signature, created_on, data) "
880
"values(\"%s\", date('now'), ?)", signature);
970
"INSERT INTO dspam_signature_data (signature,created_on,data)"
971
" VALUES (\"%s\",date('now'),?)", signature);
882
if ((r = sqlite3_prepare(s->dbh, scratch, -1, &stmt, &query_tail))
973
if ((sqlite3_prepare(s->dbh, scratch, -1, &stmt, &query_tail))!=SQLITE_OK)
885
_sqlite_drv_query_error ("sqlite3_prepare() failed", scratch);
975
_sqlite_drv_query_error ("_ds_set_signature: sqlite3_prepare() failed", scratch);
1000
while ((entry = readdir (dir)) != NULL)
1003
char filename[MAX_FILENAME_LENGTH];
1004
snprintf (filename, sizeof (filename), "%s/%s", path, entry->d_name);
1006
if (!strcmp (entry->d_name, ".") || !strcmp (entry->d_name, ".."))
1009
if (stat (filename, &st)) {
1013
/* push a new directory */
1014
if (st.st_mode & S_IFDIR)
1018
ndir = opendir (filename);
1021
strlcat (path, "/", sizeof (path));
1022
strlcat (path, entry->d_name, sizeof (path));
1023
nt_add (s->dir_handles, (void *) ndir);
1024
return _ds_get_nextuser (CTX);
1027
(entry->d_name + strlen (entry->d_name) - 4, ".sdb", 4))
1029
strlcpy (user, entry->d_name, sizeof (user));
1030
user[strlen (user) - 4] = 0;
1090
while ((entry = readdir (dir)) != NULL)
1093
char filename[MAX_FILENAME_LENGTH];
1094
snprintf (filename, sizeof (filename), "%s/%s", path, entry->d_name);
1096
if (!strcmp (entry->d_name, ".") || !strcmp (entry->d_name, ".."))
1099
if (stat (filename, &st)) {
1103
/* push a new directory */
1104
if (st.st_mode & S_IFDIR)
1108
ndir = opendir (filename);
1111
strlcat (path, "/", sizeof (path));
1112
strlcat (path, entry->d_name, sizeof (path));
1113
nt_add (s->dir_handles, (void *) ndir);
1114
return _ds_get_nextuser (CTX);
1117
(entry->d_name + strlen (entry->d_name) - 4, ".sdb", 4))
1119
strlcpy (user, entry->d_name, sizeof (user));
1120
user[strlen (user) - 4] = 0;