netatalk  4.6.0
Free and Open Source Apple Filing Protocol (AFP) Server
Loading...
Searching...
No Matches
sl_cnid.c File Reference
#include <ctype.h>
#include <inttypes.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <talloc.h>
#include <atalk/cnid.h>
#include <atalk/directory.h>
#include <atalk/errchk.h>
#include <atalk/globals.h>
#include <atalk/logger.h>
#include <atalk/spotlight.h>
#include <atalk/util.h>
#include <atalk/volume.h>
#include "etc/afpd/volume.h"
#include "etc/spotlight/spotlight_private.h"

Data Structures

struct  sl_did_cache_ent
struct  sl_cnid_query

Macros

#define SL_CNID_START_RESULTS   10000
#define SL_CNID_MAX_CAP   SPOTLIGHT_RESULTS_LIMIT_MAX
#define SL_CNID_GROWTH   8
#define SL_CNID_DBD_HARD_CAP   10000
#define SL_CNID_MIN_TERMLEN   3
#define SL_CNID_MAX_TERMS   8
#define SL_CNID_PAGE_SIZE   20
#define SL_CNID_MAX_DEPTH   64
#define SL_CNID_DCACHE_MAX   4096

Functions

static int cnid_comp_fn (const void *p1, const void *p2)
static int cnid32_comp_fn (const void *p1, const void *p2)
static char * sl_cnid_quoted_value (TALLOC_CTX *mem_ctx, const char *p, const char **endp)
 Extract the quoted value starting at or after p.
static bool sl_cnid_add_term (char **terms, int *count, char *term)
static int sl_cnid_extract_terms (TALLOC_CTX *mem_ctx, const char *qstring, char **terms, int max_terms)
 Extract all filename search terms from a Spotlight query.
static const char * sl_dcache_get (struct sl_cnid_query *csq, cnid_t did)
static void sl_dcache_put (struct sl_cnid_query *csq, cnid_t did, const char *path)
static char * sl_cnid_to_path (TALLOC_CTX *mem_ctx, const struct vol *vol, struct sl_cnid_query *csq, cnid_t cnid)
 Reconstruct the full filesystem path for a CNID.
static int sl_cnid_init (AFPObj *obj)
static void sl_cnid_close (AFPObj *obj)
static int sl_cnid_fill_results (slq_t *slq)
 Emit up to SL_CNID_PAGE_SIZE results from the private CNID buffer.
static int sl_cnid_cap_for (uint64_t want, int nterms)
static int sl_cnid_collect (slq_t *slq, struct sl_cnid_query *csq, char **terms, int nterms, cnid_t scope_did)
 Search every term into the candidate buffer and deduplicate.
static bool sl_cnid_scope_is_vol_root (const char *scope, const char *vol_path)
static int sl_cnid_open_query (slq_t *slq)
static int sl_cnid_fetch_results (slq_t *slq)
static void sl_cnid_close_query (slq_t *slq)

Variables

const sl_backend_ops sl_cnid_ops

Macro Definition Documentation

◆ SL_CNID_DBD_HARD_CAP

#define SL_CNID_DBD_HARD_CAP   10000

◆ SL_CNID_DCACHE_MAX

#define SL_CNID_DCACHE_MAX   4096

◆ SL_CNID_GROWTH

#define SL_CNID_GROWTH   8

◆ SL_CNID_MAX_CAP

#define SL_CNID_MAX_CAP   SPOTLIGHT_RESULTS_LIMIT_MAX

◆ SL_CNID_MAX_DEPTH

#define SL_CNID_MAX_DEPTH   64

◆ SL_CNID_MAX_TERMS

#define SL_CNID_MAX_TERMS   8

◆ SL_CNID_MIN_TERMLEN

#define SL_CNID_MIN_TERMLEN   3

◆ SL_CNID_PAGE_SIZE

#define SL_CNID_PAGE_SIZE   20

◆ SL_CNID_START_RESULTS

#define SL_CNID_START_RESULTS   10000

Function Documentation

◆ cnid32_comp_fn()

int cnid32_comp_fn ( const void * p1,
const void * p2 )
static

◆ cnid_comp_fn()

int cnid_comp_fn ( const void * p1,
const void * p2 )
static

◆ sl_cnid_add_term()

bool sl_cnid_add_term ( char ** terms,
int * count,
char * term )
static

Append term to terms unless already present.

Returns
true when the term was appended

◆ sl_cnid_cap_for()

int sl_cnid_cap_for ( uint64_t want,
int nterms )
static

Candidate capacity for want results across nterms search terms.

Every term needs a full CNID_FIND_MIN_RESULTS batch of room or cnid_find() refuses the call, so a small limit still allocates enough for all the terms; the surplus is trimmed from the results afterwards.

◆ sl_cnid_close()

void sl_cnid_close ( AFPObj * obj)
static

◆ sl_cnid_close_query()

void sl_cnid_close_query ( slq_t * slq)
static

◆ sl_cnid_collect()

int sl_cnid_collect ( slq_t * slq,
struct sl_cnid_query * csq,
char ** terms,
int nterms,
cnid_t scope_did )
static

Search every term into the candidate buffer and deduplicate.

Finder joins one predicate per typed word with ||, so the terms are alternatives: one cnid_find() per term into the shared buffer, then a sort and unique pass because a name can match more than one term. Each call's slice is kept a multiple of CNID_FIND_MIN_RESULTS so the DBD pagination loop fills complete batches.

Restartable: count and the truncation flag are reset on entry so the caller can re-run against a grown buffer.

Returns
0 on success, -1 when a backend search failed

◆ sl_cnid_extract_terms()

int sl_cnid_extract_terms ( TALLOC_CTX * mem_ctx,
const char * qstring,
char ** terms,
int max_terms )
static

Extract all filename search terms from a Spotlight query.

Handles the common macOS patterns: kMDItemFSName = "foo*"cd → "foo" kMDItemDisplayName = "*foo*"cd → "foo" _kMDItemFileName = "foo*"cd → "foo" *=="foo*"cdw → "foo"

Finder splits a multi-word search into one predicate per word joined with ||, so every extracted term contributes to the result set. Named filename attributes take precedence; the *== "any attribute" form is scanned only when no named attribute matched. Duplicate terms are collapsed.

Returns
the number of talloc'd terms stored in terms

◆ sl_cnid_fetch_results()

int sl_cnid_fetch_results ( slq_t * slq)
static

◆ sl_cnid_fill_results()

int sl_cnid_fill_results ( slq_t * slq)
static

Emit up to SL_CNID_PAGE_SIZE results from the private CNID buffer.

Iterates over the remaining entries in csq->cnids[csq->pos..csq->count-1], resolving each CNID to a filesystem path and adding it to query_results. Stops after SL_CNID_PAGE_SIZE accepted results or when the buffer is exhausted, whichever comes first.

Sets slq_state to: SLQ_STATE_FULL — page is full, more results remain; client must poll SLQ_STATE_DONE — all results have been delivered SLQ_STATE_ERROR — add_filemeta() failed

Returns
0 on success, -1 on error

◆ sl_cnid_init()

int sl_cnid_init ( AFPObj * obj)
static

◆ sl_cnid_open_query()

int sl_cnid_open_query ( slq_t * slq)
static

◆ sl_cnid_quoted_value()

char * sl_cnid_quoted_value ( TALLOC_CTX * mem_ctx,
const char * p,
const char ** endp )
static

Extract the quoted value starting at or after p.

Scans to the first unescaped closing quote, strips unescaped leading/trailing '*' wildcards, drops one wrapping escaped-quote pair (Finder's exact-phrase delimiters; the substring search preserves adjacency by construction) and removes the remaining backslash escapes.

Parameters
mem_ctxtalloc context for the returned term
pquery-string position the scan starts from
endpset to just past the closing quote when a quoted span was found (even if the term is rejected), NULL when no quoted span follows — the caller must stop scanning then
Returns
talloc'd term, or NULL when no quoted value follows or the result is shorter than SL_CNID_MIN_TERMLEN

◆ sl_cnid_scope_is_vol_root()

bool sl_cnid_scope_is_vol_root ( const char * scope,
const char * vol_path )
static

True when scope names the volume root (ignoring trailing slashes).

◆ sl_cnid_to_path()

char * sl_cnid_to_path ( TALLOC_CTX * mem_ctx,
const struct vol * vol,
struct sl_cnid_query * csq,
cnid_t cnid )
static

Reconstruct the full filesystem path for a CNID.

Walks the DID chain upward via repeated cnid_resolve() calls, prepending path components, until reaching DIRDID_ROOT or a directory whose path is already memoized in the query's cache. Ancestor directory paths discovered along the way are memoized, so results sharing a directory resolve it once per query.

Parameters
mem_ctxtalloc context for the returned string
volvolume whose CNID database to query
csqper-query state carrying the directory memo
cnidnetwork-byte-order CNID (as returned by cnid_find)
Returns
talloc-allocated full path, or NULL on error

◆ sl_dcache_get()

const char * sl_dcache_get ( struct sl_cnid_query * csq,
cnid_t did )
static

◆ sl_dcache_put()

void sl_dcache_put ( struct sl_cnid_query * csq,
cnid_t did,
const char * path )
static

Variable Documentation

◆ sl_cnid_ops

const sl_backend_ops sl_cnid_ops
Initial value:
= {
.sbo_name = "cnid",
.sbo_init = sl_cnid_init,
.sbo_close = sl_cnid_close,
.sbo_open_query = sl_cnid_open_query,
.sbo_fetch_results = sl_cnid_fetch_results,
.sbo_close_query = sl_cnid_close_query,
}
static void sl_cnid_close(AFPObj *obj)
Definition sl_cnid.c:519
static int sl_cnid_fetch_results(slq_t *slq)
Definition sl_cnid.c:931
static int sl_cnid_open_query(slq_t *slq)
Definition sl_cnid.c:777
static int sl_cnid_init(AFPObj *obj)
Definition sl_cnid.c:513
static void sl_cnid_close_query(slq_t *slq)
Definition sl_cnid.c:950