18 #if defined(__has_include)
19 #if __has_include(<sys/mman.h>)
21 #define ZPMOD_HAVE_MMAP 1
27 #if defined(ZSH_VERSION) && defined(HAVE_GETAPARAM)
28 #define get_zpmod_config(K) getaparam("ZPMOD", (K))
30 #define GET_ZPMOD_CONFIG(K) getsparam("ZPMOD_" #K)
43 zwarnnam(nam,
"%s: input must be an indexed array", inname);
46 const int want_type = (!fields || strstr(fields,
"type"));
47 const int want_size = (!fields || strstr(fields,
"size"));
48 const int want_mode = (!fields || strstr(fields,
"mode"));
49 const int want_mtime = (!fields || strstr(fields,
"mtime"));
50 const int want_uid = (!fields || strstr(fields,
"uid"));
51 const int want_gid = (!fields || strstr(fields,
"gid"));
52 const int want_ino = (!fields || strstr(fields,
"ino"));
53 const int want_nlink = (!fields || strstr(fields,
"nlink"));
57 for (
int i = 0; inarr[i]; ++i) {
60 char **out = (
char **)
zalloc((in_count + 1) *
sizeof(
char *));
66 for (
int i = 0; inarr[i]; ++i) {
74 int rc = follow ? stat(p_in, &st) : lstat(p_in, &st);
78 off += snprintf(buf + off, (
int)
sizeof(buf) - off,
"path=%s", p_in);
81 if (S_ISREG(st.st_mode)) {
83 }
else if (S_ISDIR(st.st_mode)) {
85 }
else if (S_ISLNK(st.st_mode)) {
88 off += snprintf(buf + off, (
int)
sizeof(buf) - off,
",type=%c", t);
91 off += snprintf(buf + off, (
int)
sizeof(buf) - off,
",size=%ld",
95 off += snprintf(buf + off, (
int)
sizeof(buf) - off,
",mode=%o",
96 (
unsigned)(st.st_mode & 07777));
99 off += snprintf(buf + off, (
int)
sizeof(buf) - off,
",mtime=%ld",
103 off += snprintf(buf + off, (
int)
sizeof(buf) - off,
",uid=%ld",
107 off += snprintf(buf + off, (
int)
sizeof(buf) - off,
",gid=%ld",
111 off += snprintf(buf + off, (
int)
sizeof(buf) - off,
",ino=%ld",
115 off += snprintf(buf + off, (
int)
sizeof(buf) - off,
",nlink=%ld",
119 off += snprintf(buf + off, (
int)
sizeof(buf) - off,
"path=%s", p_in);
121 off += snprintf(buf + off, (
int)
sizeof(buf) - off,
",type=%c",
'?');
123 off += snprintf(buf + off, (
int)
sizeof(buf) - off,
",errno=%d", errno);
125 buf[
sizeof(buf) - 1] =
'\0';
127 volatile int zpmod_sink_off = off;
128 (void)zpmod_sink_off;
129 int used = (int)strlen(buf);
130 char *outstr =
metafy(buf, used, META_DUP);
132 snprintf(indexed,
sizeof(indexed),
"%s[%d]", outname, idx++);
134 zfree(p_in, p_len + 1);
146 return e && *e && (*e !=
'0');
158 #define ZP_FS_CACHE_MAX 64
169 if (e->
dev == st->st_dev && e->
ino == st->st_ino &&
170 e->
mtime == st->st_mtime && e->
size == st->st_size) {
185 e->
mtime = st->st_mtime;
186 e->
size = st->st_size;
202 e->
mtime = st->st_mtime;
203 e->
size = st->st_size;
263 long plen = (long)
arrlen(p);
266 fprintf(stderr,
"zpmod: path-warmup scanning %ld directories...\n", plen);
271 for (
int i = 0; p[i]; ++i) {
276 DIR *dp = opendir(dir);
283 while ((de = readdir(dp)) != NULL) {
284 const char *name = de->d_name;
285 if (!name || name[0] ==
'.') {
288 int n = snprintf(full,
sizeof(full),
"%s/%s", dir, name);
289 if (n <= 0 || (
size_t)n >=
sizeof(full)) {
292 if (stat(full, &st) == 0 && S_ISREG(st.st_mode) && (st.st_mode & 0111)) {
318 for (
int i = 0; p[i]; ++i) {
323 struct stat check_st;
324 if (stat(dir, &check_st) == 0 && S_ISDIR(check_st.st_mode)) {
328 fprintf(stderr,
"zpmod: path-warmup %s missing directory: %s\n",
329 dry_run ?
"would prune" :
"pruning", dir);
335 if (!dry_run && valid_count < (
int)plen) {
340 char **new_path = (
char **)
zalloc((valid_count + 1) *
sizeof(
char *));
344 for (
int i = 0; p[i]; ++i) {
349 struct stat check_st;
350 if (stat(dir, &check_st) == 0 && S_ISDIR(check_st.st_mode)) {
356 new_path[new_idx++] =
ztrdup(dir);
359 new_path[new_idx] = NULL;
371 fprintf(stderr,
"zpmod: path-warmup touched %ld executables.\n",
374 return (
int)total_exec;
394 DIR *dp = opendir(udir);
397 zfree(udir, dlen + 1);
402 char **out = (
char **)
zalloc(
sizeof(
char *));
409 while ((de = readdir(dp)) != NULL) {
410 const char *name = de->d_name;
411 if (!inc_all && name[0] ==
'.') {
416 int n = snprintf(full,
sizeof(full),
"%s/%s", udir, name);
417 if (n <= 0 || (
size_t)n >=
sizeof(full)) {
420 if (lstat(full, &st) != 0) {
423 if (only_dirs && !S_ISDIR(st.st_mode)) {
426 if (only_files && !S_ISREG(st.st_mode)) {
431 snprintf(indexed,
sizeof(indexed),
"%s[%d]", outname, idx++);
435 zfree(udir, dlen + 1);
456 int fd = open(upath, O_RDONLY);
462 if (fstat(fd, &st) != 0) {
468 size_t sz = (size_t)st.st_size;
471 #ifdef ZPMOD_HAVE_MMAP
472 if (use_mmap && sz > 0) {
473 void *m = mmap(NULL, sz, PROT_READ, MAP_PRIVATE, fd, 0);
474 if (m != MAP_FAILED) {
481 cap = sz ? sz + 1 : 4096;
482 buf = (
char *)
zalloc(cap);
491 while ((rd = read(fd, buf + off, cap - off)) > 0) {
494 size_t ncap = cap * 2;
495 char *nb = (
char *)
zrealloc(buf, ncap);
517 zfree(upath, plen + 1);
522 #ifdef ZPMOD_HAVE_MMAP
523 if (use_mmap && cap == sz) {
535 char **out = (
char **)
zalloc(
sizeof(
char *));
540 for (
size_t i = 0; i < sz; ++i) {
541 if ((
unsigned char)buf[i] == (
unsigned char)delim) {
542 int len = (int)(i - start);
543 char *rec =
metafy(buf + start, len, META_DUP);
545 snprintf(indexed,
sizeof(indexed),
"%s[%d]", outname, idx++);
547 if ((
unsigned char)delim == (
unsigned char)
'\r' && (i + 1) < sz &&
548 (
unsigned char)buf[i + 1] == (
unsigned char)
'\n') {
557 int len = (int)(sz - start);
558 char *rec =
metafy(buf + start, len, META_DUP);
560 snprintf(indexed,
sizeof(indexed),
"%s[%d]", outname, idx++);
563 #ifdef ZPMOD_HAVE_MMAP
564 if (use_mmap && cap == sz) {
static int zp_fs_cache_count
static int zp_fs_cache_enabled(void)
static int zp_fs_cache_insert_dir(const char *dir, const struct stat *st, char *serialized)
int zp_path_warmup_core(const char *nam, int quiet, int prune_missing, int dry_run)
Implements path-warmup functionality for executable discovery and path pruning.
int zp_readfile_core(char *nam, char *outname, char *path, int use_mmap, int split, int delim)
See zpmod_fs.h for contract.
#define GET_ZPMOD_CONFIG(K)
int zp_dirlist_core(char *nam, char *outname, char *dir, int inc_all, int only_dirs, int only_files)
See zpmod_fs.h for contract.
int zp_pathstat_core(char *nam, char *outname, char *inname, int follow, char *fields)
See zpmod_fs.h for contract.
static zp_fs_cache_entry zp_fs_cache[ZP_FS_CACHE_MAX]
static int zp_fs_cache_lookup(const char *dir, struct stat *st, int *out_idx)
char * zp_unmetafy_zalloc(const char *to_copy, int *new_len)
Duplicate and unmetafy a zsh string with zalloc; see header for details.
Module declaration header (mdh) for zpmod.
Prototype stub for zpmod when building out-of-tree.
Filesystem helpers used by builtins and zpmod subcommands.
void * zalloc(size_t size)
void unsetparam(const char *name)
char * metafy(char *s, int len, int how)
void setaparam(const char *name, char **value)
void zfree(void *ptr, size_t size)
char ** getaparam(const char *name)
void setsparam(const char *name, char *value)
void * zrealloc(void *ptr, size_t size)
void zwarnnam(const char *, const char *,...)
char * ztrdup(const char *)
Local, non-invasive shims to suppress benign vendor header warnings.