]> Sergey Matveev's repositories - nnn.git/commitdiff
Opinionated xstrlcpy changes (#513)
authorSaagar Jha <saagar@saagarjha.com>
Sun, 12 Apr 2020 00:35:14 +0000 (17:35 -0700)
committerGitHub <noreply@github.com>
Sun, 12 Apr 2020 00:35:14 +0000 (06:05 +0530)
* Unvectorize xstrlcpy

On all libcs I could find, memcpy does a better job than we can.

* Rename xstrlcpy to xstrsncpy to avoid confusion

The semantics of our xstrlcpy differed slightly from strlcpy; we return
the number of copied characters; strlcpy returns the strlen(src).
strscpy from Linux is similar except it returns the number of copied
characters sans the NUL byte, so this is named strsncpy to be different.

src/nnn.c

index 05c865a810d0a479b241e377fd55a59dfdc3a5da..6e0db039f555569e13d8cb01ebd19f5d67b790f7 100644 (file)
--- a/src/nnn.c
+++ b/src/nnn.c
@@ -359,7 +359,6 @@ static kv *bookmark;
 static kv *plug;
 static uchar tmpfplen;
 static uchar blk_shift = BLK_SHIFT_512;
-static const uint _WSHIFT = (LONG_SIZE == 8) ? 3 : 2;
 #ifndef NOMOUSE
 static int middle_click_key;
 #endif
@@ -670,7 +669,7 @@ static haiku_nm_h haiku_hnd;
 #define exitcurses() endwin()
 #define printwarn(presel) printwait(strerror(errno), presel)
 #define istopdir(path) ((path)[1] == '\0' && (path)[0] == '/')
-#define copycurname() xstrlcpy(lastname, dents[cur].name, NAME_MAX + 1)
+#define copycurname() xstrsncpy(lastname, dents[cur].name, NAME_MAX + 1)
 #define settimeout() timeout(1000)
 #define cleartimeout() timeout(-1)
 #define errexit() printerr(__LINE__)
@@ -689,7 +688,7 @@ static haiku_nm_h haiku_hnd;
 #endif /* __GNUC__ */
 
 /* Forward declarations */
-static size_t xstrlcpy(char *dest, const char *src, size_t n);
+static size_t xstrsncpy(char *dest, const char *src, size_t n);
 static void redraw(char *path);
 static int spawn(char *file, char *arg1, char *arg2, const char *dir, uchar flag);
 static int (*nftw_fn)(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf);
@@ -805,7 +804,7 @@ static void printwait(const char *msg, int *presel)
        if (presel) {
                *presel = MSGWAIT;
                if (ndents)
-                       xstrlcpy(g_ctx[cfg.curctx].c_name, dents[cur].name, NAME_MAX + 1);
+                       xstrsncpy(g_ctx[cfg.curctx].c_name, dents[cur].name, NAME_MAX + 1);
        }
 }
 
@@ -937,54 +936,21 @@ static void *xrealloc(void *pcur, size_t len)
  * Always null ('\0') terminates if both src and dest are valid pointers.
  * Returns the number of bytes copied including terminating null byte.
  */
-static size_t xstrlcpy(char *dest, const char *src, size_t n)
+static size_t xstrsncpy(char *restrict dest, const char *restrict src, size_t n)
 {
        if (!src || !dest || !n)
                return 0;
 
-       ulong *s, *d;
-       size_t len = strlen(src) + 1, blocks;
-
-       if (n > len)
+       size_t len = strlen(src) + 1;
+       if (len <= n) {
+               memcpy(dest, src, len);
                n = len;
-       else if (len > n)
-               /* Save total number of bytes to copy in len */
-               len = n;
-
-       /*
-        * To enable -O3 ensure src and dest are 16-byte aligned
-        * More info: https://www.felixcloutier.com/x86/MOVDQA:VMOVDQA32:VMOVDQA64
-        */
-       if ((n >= LONG_SIZE) && (((ulong)src & _ALIGNMENT_MASK) == 0 &&
-           ((ulong)dest & _ALIGNMENT_MASK) == 0)) {
-               s = (ulong *)src;
-               d = (ulong *)dest;
-               blocks = n >> _WSHIFT;
-               n &= LONG_SIZE - 1;
-
-               while (blocks) {
-                       *d = *s; // NOLINT
-                       ++d, ++s;
-                       --blocks;
-               }
-
-               if (!n) {
-                       dest = (char *)d;
-                       *--dest = '\0';
-                       return len;
-               }
-
-               src = (char *)s;
-               dest = (char *)d;
+       } else {
+               memcpy(dest, src, n - 1);
+               dest[n - 1] = '\0';
        }
 
-       while (--n && (*dest = *src)) // NOLINT
-               ++dest, ++src;
-
-       if (!n)
-               *dest = '\0';
-
-       return len;
+       return n;
 }
 
 static bool is_suffix(const char *str, const char *suffix)
@@ -1032,7 +998,7 @@ static char *common_prefix(const char *path, char *prefix)
                return NULL;
 
        if (!*prefix) {
-               xstrlcpy(prefix, path, PATH_MAX);
+               xstrsncpy(prefix, path, PATH_MAX);
                return prefix;
        }
 
@@ -1045,7 +1011,7 @@ static char *common_prefix(const char *path, char *prefix)
 
        /* Path is shorter */
        if (!*x && *y == '/') {
-               xstrlcpy(prefix, path, y - path);
+               xstrsncpy(prefix, path, y - path);
                return prefix;
        }
 
@@ -1083,7 +1049,7 @@ static char *abspath(const char *path, const char *cwd)
 
        /* Turn relative paths into absolute */
        if (path[0] != '/')
-               dst_size = xstrlcpy(resolved_path, cwd, cwd_size + 1) - 1;
+               dst_size = xstrsncpy(resolved_path, cwd, cwd_size + 1) - 1;
        else
                resolved_path[0] = '\0';
 
@@ -1103,7 +1069,7 @@ static char *abspath(const char *path, const char *cwd)
                        /* NOP */
                } else if (next - src) {
                        *(dst++) = '/';
-                       xstrlcpy(dst, src, next - src + 1);
+                       xstrsncpy(dst, src, next - src + 1);
                        dst += next - src;
                }
 
@@ -1127,7 +1093,7 @@ static char *xbasename(char *path)
 
 static int create_tmp_file(void)
 {
-       xstrlcpy(g_tmpfpath + tmpfplen - 1, messages[STR_TMPFILE], TMP_LEN_MAX - tmpfplen);
+       xstrsncpy(g_tmpfpath + tmpfplen - 1, messages[STR_TMPFILE], TMP_LEN_MAX - tmpfplen);
 
        int fd = mkstemp(g_tmpfpath);
 
@@ -1163,7 +1129,7 @@ static void appendfpath(const char *path, const size_t len)
                        errexit();
        }
 
-       selbufpos += xstrlcpy(pselbuf + selbufpos, path, len);
+       selbufpos += xstrsncpy(pselbuf + selbufpos, path, len);
 }
 
 /* Write selected file paths to fd, linefeed separated */
@@ -1671,7 +1637,7 @@ static int spawn(char *file, char *arg1, char *arg2, const char *dir, uchar flag
                        return retstatus;
                }
 
-               xstrlcpy(cmd, file, len);
+               xstrsncpy(cmd, file, len);
                status = parseargs(cmd, argv);
                if (status == -1 || status > (EXEC_ARGS_MAX - 3)) { /* arg1, arg2 and last NULL */
                        free(cmd);
@@ -1921,7 +1887,7 @@ static bool batch_rename(const char *path)
        if (fd1 == -1)
                return ret;
 
-       xstrlcpy(foriginal, g_tmpfpath, strlen(g_tmpfpath)+1);
+       xstrsncpy(foriginal, g_tmpfpath, strlen(g_tmpfpath)+1);
 
        fd2 = create_tmp_file();
        if (fd2 == -1) {
@@ -1986,7 +1952,7 @@ static void get_archive_cmd(char *cmd, const char *archive)
                i = 2;
        // else tar
 
-       xstrlcpy(cmd, arcmd[i], ARCHIVE_CMD_LEN);
+       xstrsncpy(cmd, arcmd[i], ARCHIVE_CMD_LEN);
 }
 
 static void archive_selection(const char *cmd, const char *archive, const char *curpath)
@@ -2016,7 +1982,7 @@ static bool write_lastdir(const char *curpath)
        bool ret = TRUE;
        size_t len = strlen(cfgdir);
 
-       xstrlcpy(cfgdir + len, "/.lastd", 8);
+       xstrsncpy(cfgdir + len, "/.lastd", 8);
        DPRINTF_S(cfgdir);
 
        FILE *fp = fopen(cfgdir, "w");
@@ -2873,7 +2839,7 @@ static char *getreadline(const char *prompt, char *path, char *curpath, int *pre
                printwarn(presel);
        else if (input && input[0]) {
                add_history(input);
-               xstrlcpy(g_buf, input, CMD_LEN_MAX);
+               xstrsncpy(g_buf, input, CMD_LEN_MAX);
                free(input);
                return g_buf;
        }
@@ -2893,16 +2859,16 @@ static size_t mkpath(const char *dir, const char *name, char *out)
 
        /* Handle absolute path */
        if (name[0] == '/')
-               return xstrlcpy(out, name, PATH_MAX);
+               return xstrsncpy(out, name, PATH_MAX);
 
        /* Handle root case */
        if (istopdir(dir))
                len = 1;
        else
-               len = xstrlcpy(out, dir, PATH_MAX);
+               len = xstrsncpy(out, dir, PATH_MAX);
 
        out[len - 1] = '/'; // NOLINT
-       return (xstrlcpy(out + len, name, PATH_MAX - len) + len);
+       return (xstrsncpy(out + len, name, PATH_MAX - len) + len);
 }
 
 /*
@@ -2927,8 +2893,8 @@ static int xlink(char *prefix, char *path, char *curfname, char *buf, int *prese
                link_fn = &link;
 
        if (choice == 'c') {
-               r = xstrlcpy(buf, prefix, NAME_MAX + 1); /* Copy prefix */
-               xstrlcpy(buf + r - 1, curfname, NAME_MAX - r); /* Suffix target file name */
+               r = xstrsncpy(buf, prefix, NAME_MAX + 1); /* Copy prefix */
+               xstrsncpy(buf + r - 1, curfname, NAME_MAX - r); /* Suffix target file name */
                mkpath(path, buf, lnpath); /* Generate link path */
                mkpath(path, curfname, buf); /* Generate target file path */
 
@@ -2943,8 +2909,8 @@ static int xlink(char *prefix, char *path, char *curfname, char *buf, int *prese
                len = strlen(psel);
                fname = xbasename(psel);
 
-               r = xstrlcpy(buf, prefix, NAME_MAX + 1); /* Copy prefix */
-               xstrlcpy(buf + r - 1, fname, NAME_MAX - r); /* Suffix target file name */
+               r = xstrsncpy(buf, prefix, NAME_MAX + 1); /* Copy prefix */
+               xstrsncpy(buf + r - 1, fname, NAME_MAX - r); /* Suffix target file name */
                mkpath(path, buf, lnpath); /* Generate link path */
 
                if (!link_fn(psel, lnpath))
@@ -3057,8 +3023,8 @@ static char *get_kv_val(kv *kvarr, char *buf, int key, uchar max, bool bookmark)
                                ssize_t len = strlen(home);
                                ssize_t loclen = strlen(kvarr[r].val);
 
-                               xstrlcpy(g_buf, home, len + 1);
-                               xstrlcpy(g_buf + len, kvarr[r].val + 1, loclen);
+                               xstrsncpy(g_buf, home, len + 1);
+                               xstrsncpy(g_buf + len, kvarr[r].val + 1, loclen);
                        }
 
                        return realpath(((kvarr[r].val[0] == '~') ? g_buf : kvarr[r].val), buf);
@@ -3176,7 +3142,7 @@ static char *coolsize(off_t size)
        }
 
        if (i > 0 && i < 6 && rem) {
-               ret = xstrlcpy(size_buf, xitoa(size), 12);
+               ret = xstrsncpy(size_buf, xitoa(size), 12);
                size_buf[ret - 1] = '.';
 
                char *frac = xitoa(rem);
@@ -3185,13 +3151,13 @@ static char *coolsize(off_t size)
 
                if (len < toprint) {
                        size_buf[ret] = size_buf[ret + 1] = size_buf[ret + 2] = '0';
-                       xstrlcpy(size_buf + ret + (toprint - len), frac, len + 1);
+                       xstrsncpy(size_buf + ret + (toprint - len), frac, len + 1);
                } else
-                       xstrlcpy(size_buf + ret, frac, toprint + 1);
+                       xstrsncpy(size_buf + ret, frac, toprint + 1);
 
                ret += toprint;
        } else {
-               ret = xstrlcpy(size_buf, size ? xitoa(size) : "0", 12);
+               ret = xstrsncpy(size_buf, size ? xitoa(size) : "0", 12);
                --ret;
        }
 
@@ -3235,9 +3201,9 @@ static char *get_lsperms(mode_t mode)
 
        bits[0] = get_ind(mode, TRUE);
 
-       xstrlcpy(&bits[1], rwx[(mode >> 6) & 7], 4);
-       xstrlcpy(&bits[4], rwx[(mode >> 3) & 7], 4);
-       xstrlcpy(&bits[7], rwx[(mode & 7)], 4);
+       xstrsncpy(&bits[1], rwx[(mode >> 6) & 7], 4);
+       xstrsncpy(&bits[4], rwx[(mode >> 3) & 7], 4);
+       xstrsncpy(&bits[7], rwx[(mode & 7)], 4);
 
        if (mode & S_ISUID)
                bits[3] = (mode & 0100) ? 's' : 'S';  /* user executable */
@@ -3374,7 +3340,7 @@ static void savecurctx(settings *curcfg, char *path, char *curname, int r /* nex
        bool selmode = cfg.selmode ? TRUE : FALSE;
 
        /* Save current context */
-       xstrlcpy(g_ctx[cfg.curctx].c_name, curname, NAME_MAX + 1);
+       xstrsncpy(g_ctx[cfg.curctx].c_name, curname, NAME_MAX + 1);
        g_ctx[cfg.curctx].c_cfg = cfg;
 
        if (g_ctx[r].c_cfg.ctxactive) { /* Switch to saved context */
@@ -3386,7 +3352,7 @@ static void savecurctx(settings *curcfg, char *path, char *curname, int r /* nex
                cfg = g_ctx[r].c_cfg;
        } else { /* Setup a new context from current context */
                g_ctx[r].c_cfg.ctxactive = 1;
-               xstrlcpy(g_ctx[r].c_path, path, PATH_MAX);
+               xstrsncpy(g_ctx[r].c_path, path, PATH_MAX);
                g_ctx[r].c_last[0] = '\0';
                g_ctx[r].c_name[0] = '\0';
                g_ctx[r].c_fltr[0] = g_ctx[r].c_fltr[1] = '\0';
@@ -3418,7 +3384,7 @@ static void save_session(bool last_session, int *presel)
                if (g_ctx[i].c_cfg.ctxactive) {
                        if (cfg.curctx == i && ndents)
                                /* Update current file name, arrows don't update it */
-                               xstrlcpy(g_ctx[i].c_name, dents[cur].name, NAME_MAX + 1);
+                               xstrsncpy(g_ctx[i].c_name, dents[cur].name, NAME_MAX + 1);
                        header.pathln[i] = strnlen(g_ctx[i].c_path, PATH_MAX) + 1;
                        header.lastln[i] = strnlen(g_ctx[i].c_last, PATH_MAX) + 1;
                        header.nameln[i] = strnlen(g_ctx[i].c_name, NAME_MAX) + 1;
@@ -3631,8 +3597,8 @@ static bool show_stats(const char *fpath, const struct stat *sb)
        if (fd == -1)
                return FALSE;
 
-       r = xstrlcpy(g_buf, "stat \"", PATH_MAX);
-       r += xstrlcpy(g_buf + r - 1, fpath, PATH_MAX);
+       r = xstrsncpy(g_buf, "stat \"", PATH_MAX);
+       r += xstrsncpy(g_buf + r - 1, fpath, PATH_MAX);
        g_buf[r - 2] = '\"';
        g_buf[r - 1] = '\0';
        DPRINTF_S(g_buf);
@@ -3740,7 +3706,7 @@ static char *visit_parent(char *path, char *newpath, int *presel)
        }
 
        /* Use a copy as dirname() may change the string passed */
-       xstrlcpy(newpath, path, PATH_MAX);
+       xstrsncpy(newpath, path, PATH_MAX);
 
        dir = dirname(newpath);
        if (access(dir, R_OK) == -1) {
@@ -3756,9 +3722,9 @@ static void find_accessible_parent(char *path, char *newpath, char *lastname, in
        char *dir;
 
        /* Save history */
-       xstrlcpy(lastname, xbasename(path), NAME_MAX + 1);
+       xstrsncpy(lastname, xbasename(path), NAME_MAX + 1);
 
-       xstrlcpy(newpath, path, PATH_MAX);
+       xstrsncpy(newpath, path, PATH_MAX);
        while (true) {
                dir = visit_parent(path, newpath, presel);
                if (istopdir(path) || istopdir(newpath)) {
@@ -3767,13 +3733,13 @@ static void find_accessible_parent(char *path, char *newpath, char *lastname, in
                        break;
                }
                if (!dir) {
-                       xstrlcpy(path, newpath, PATH_MAX);
+                       xstrsncpy(path, newpath, PATH_MAX);
                        continue;
                }
                break;
        }
 
-       xstrlcpy(path, dir, PATH_MAX);
+       xstrsncpy(path, dir, PATH_MAX);
        printwarn(NULL);
        xdelay(XDELAY_INTERVAL_MS);
 }
@@ -3930,7 +3896,7 @@ static bool remote_mount(char *newpath, char *currentpath)
 
        if (tmp[0] == '-' && !tmp[1]) {
                if (!strcmp(cfgdir, currentpath) && ndents && (dents[cur].flags & DIR_OR_LINK_TO_DIR))
-                       xstrlcpy(tmp, dents[cur].name, NAME_MAX + 1);
+                       xstrsncpy(tmp, dents[cur].name, NAME_MAX + 1);
                else {
                        printmsg(messages[MSG_FAILED]);
                        return FALSE;
@@ -4069,7 +4035,7 @@ static void printkeys(kv *kvarr, char *buf, uchar max)
 static size_t handle_bookmark(const char *mark, char *newpath)
 {
        int fd;
-       size_t r = xstrlcpy(g_buf, messages[MSG_BOOKMARK_KEYS], CMD_LEN_MAX);
+       size_t r = xstrsncpy(g_buf, messages[MSG_BOOKMARK_KEYS], CMD_LEN_MAX);
 
        if (mark) { /* There is a pinned directory */
                g_buf[--r] = ' ';
@@ -4083,7 +4049,7 @@ static size_t handle_bookmark(const char *mark, char *newpath)
        r = FALSE;
        fd = get_input(NULL);
        if (fd == ',') /* Visit pinned directory */
-               mark ? xstrlcpy(newpath, mark, PATH_MAX) : (r = MSG_NOT_SET);
+               mark ? xstrsncpy(newpath, mark, PATH_MAX) : (r = MSG_NOT_SET);
        else if (!get_kv_val(bookmark, newpath, fd, maxbm, TRUE))
                r = MSG_INVALID_KEY;
 
@@ -4217,7 +4183,7 @@ static bool run_cmd_as_plugin(const char *path, const char *file, char *runfile)
                        return FALSE;
        }
 
-       xstrlcpy(g_buf, file, PATH_MAX);
+       xstrsncpy(g_buf, file, PATH_MAX);
 
        len = strlen(g_buf);
        if (len > 1 && g_buf[len - 1] == '*') {
@@ -4271,7 +4237,7 @@ static bool run_selected_plugin(char **path, const char *file, char *runfile, ch
        mkpath(plugindir, file, g_buf);
 
        if (runfile && runfile[0]) {
-               xstrlcpy(*lastname, runfile, NAME_MAX);
+               xstrsncpy(*lastname, runfile, NAME_MAX);
                spawn(g_buf, *lastname, *path, *path, F_NORMAL);
        } else
                spawn(g_buf, NULL, *path, *path, F_NORMAL);
@@ -4285,8 +4251,8 @@ static bool run_selected_plugin(char **path, const char *file, char *runfile, ch
                int ctx = g_buf[0] - '0';
 
                if (ctx == 0 || ctx == cfg.curctx + 1) {
-                       xstrlcpy(*lastdir, *path, PATH_MAX);
-                       xstrlcpy(*path, g_buf + 1, PATH_MAX);
+                       xstrsncpy(*lastdir, *path, PATH_MAX);
+                       xstrsncpy(*path, g_buf + 1, PATH_MAX);
                } else if (ctx >= 1 && ctx <= CTX_MAX) {
                        int r = ctx - 1;
 
@@ -4524,7 +4490,7 @@ static int dentfill(char *path, struct entry **dents)
 
                /* Selection file name */
                dentp->name = (char *)((size_t)pnamebuf + off);
-               dentp->nlen = xstrlcpy(dentp->name, namep, NAME_MAX + 1);
+               dentp->nlen = xstrsncpy(dentp->name, namep, NAME_MAX + 1);
                off += dentp->nlen;
 
                /* Copy other fields */
@@ -4850,7 +4816,7 @@ static bool set_time_type(int *presel)
 
        for (; r < (int)ELEMENTS(time_type); ++r)
                if (r != cfg.timetype) {
-                       chars += xstrlcpy(buf + chars, time_type[r], sizeof(buf) - chars) - 1;
+                       chars += xstrsncpy(buf + chars, time_type[r], sizeof(buf) - chars) - 1;
                        if (first) {
                                buf[chars++] = ' ';
                                buf[chars++] = '/';
@@ -4910,7 +4876,7 @@ static void statusbar(char *path)
        if (cfg.blkorder) { /* du mode */
                char buf[24];
 
-               xstrlcpy(buf, coolsize(dir_blocks << blk_shift), 12);
+               xstrsncpy(buf, coolsize(dir_blocks << blk_shift), 12);
 
                printw("%d/%d [%s:%s] %cu:%s free:%s files:%lu %lldB %s\n",
                       cur + 1, ndents, (cfg.selmode ? "s" : ""),
@@ -5103,10 +5069,10 @@ static bool cdprep(char *lastdir, char *lastname, char *path, char *newpath)
                lastname[0] =  '\0';
 
        /* Save last working directory */
-       xstrlcpy(lastdir, path, PATH_MAX);
+       xstrsncpy(lastdir, path, PATH_MAX);
 
        /* Save the newly opted dir in path */
-       xstrlcpy(path, newpath, PATH_MAX);
+       xstrsncpy(path, newpath, PATH_MAX);
        DPRINTF_S(path);
 
        clearfilter();
@@ -5143,7 +5109,7 @@ static bool browse(char *ipath, const char *session)
 
        /* setup first context */
        if (!session || !load_session(session, &path, &lastdir, &lastname, FALSE)) {
-               xstrlcpy(g_ctx[0].c_path, ipath, PATH_MAX); /* current directory */
+               xstrsncpy(g_ctx[0].c_path, ipath, PATH_MAX); /* current directory */
                path = g_ctx[0].c_path;
                g_ctx[0].c_last[0] = g_ctx[0].c_name[0] = '\0';
                lastdir = g_ctx[0].c_last; /* last visited directory */
@@ -5295,7 +5261,7 @@ nochange:
                                        goto nochange;
 
                                /* Save history */
-                               xstrlcpy(lastname, xbasename(path), NAME_MAX + 1);
+                               xstrsncpy(lastname, xbasename(path), NAME_MAX + 1);
 
                                cdprep(lastdir, NULL, path, dir) ? (presel = FILTER) : (watch = TRUE);
                                goto begin;
@@ -5427,7 +5393,7 @@ nochange:
                                        if ((cfg.runctx == cfg.curctx) && !strcmp(path, plugindir)) {
                                                endselection();
                                                /* Copy path so we can return back to earlier dir */
-                                               xstrlcpy(path, rundir, PATH_MAX);
+                                               xstrsncpy(path, rundir, PATH_MAX);
                                                rundir[0] = '\0';
 
                                                if (!run_selected_plugin(&path, dents[cur].name,
@@ -5557,7 +5523,7 @@ nochange:
                        }
 
                        /* SEL_CDLAST: dir pointing to lastdir */
-                       xstrlcpy(newpath, dir, PATH_MAX); // fallthrough
+                       xstrsncpy(newpath, dir, PATH_MAX); // fallthrough
                case SEL_BOOKMARK:
                        if (sel == SEL_BOOKMARK) {
                                r = (int)handle_bookmark(mark, newpath);
@@ -5928,7 +5894,7 @@ nochange:
                                plugscript(utils[UTIL_NTFY], NULL, F_NOWAIT | F_NOTRACE);
 
                        if (newpath[0] && !access(newpath, F_OK))
-                               xstrlcpy(lastname, xbasename(newpath), NAME_MAX+1);
+                               xstrsncpy(lastname, xbasename(newpath), NAME_MAX+1);
                        else if (ndents)
                                copycurname();
                        goto begin;
@@ -6019,7 +5985,7 @@ nochange:
 
                                mkpath(path, tmp, newpath);
                                if (access(newpath, F_OK) == 0) { /* File created */
-                                       xstrlcpy(lastname, tmp, NAME_MAX + 1);
+                                       xstrsncpy(lastname, tmp, NAME_MAX + 1);
                                        clearfilter(); /* Archive name may not match */
                                        goto begin;
                                }
@@ -6090,7 +6056,7 @@ nochange:
                                        goto nochange;
                                }
                                close(fd);
-                               xstrlcpy(lastname, tmp, NAME_MAX + 1);
+                               xstrsncpy(lastname, tmp, NAME_MAX + 1);
                        } else { /* SEL_NEW */
                                close(fd);
                                presel = 0;
@@ -6116,7 +6082,7 @@ nochange:
                                        goto nochange;
 
                                if (r == 'f' || r == 'd')
-                                       xstrlcpy(lastname, tmp, NAME_MAX + 1);
+                                       xstrsncpy(lastname, tmp, NAME_MAX + 1);
                                else if (ndents) {
                                        if (cfg.filtermode)
                                                presel = FILTER;
@@ -6134,7 +6100,7 @@ nochange:
                                goto nochange;
                        }
 
-                       r = xstrlcpy(g_buf, messages[MSG_PLUGIN_KEYS], CMD_LEN_MAX);
+                       r = xstrsncpy(g_buf, messages[MSG_PLUGIN_KEYS], CMD_LEN_MAX);
                        printkeys(plug, g_buf + r - 1, maxplug);
                        printmsg(g_buf);
                        r = get_input(NULL);
@@ -6173,8 +6139,8 @@ nochange:
                                         * switch to original directory
                                         */
                                        if (strcmp(path, plugindir) == 0) {
-                                               xstrlcpy(path, rundir, PATH_MAX);
-                                               xstrlcpy(lastname, runfile, NAME_MAX);
+                                               xstrsncpy(path, rundir, PATH_MAX);
+                                               xstrsncpy(lastname, runfile, NAME_MAX);
                                                rundir[0] = runfile[0] = '\0';
                                                setdirwatch();
                                                goto begin;
@@ -6184,10 +6150,10 @@ nochange:
                                        cfg.runplugin = 1;
                                }
 
-                               xstrlcpy(rundir, path, PATH_MAX);
-                               xstrlcpy(path, plugindir, PATH_MAX);
+                               xstrsncpy(rundir, path, PATH_MAX);
+                               xstrsncpy(path, plugindir, PATH_MAX);
                                if (ndents)
-                                       xstrlcpy(runfile, dents[cur].name, NAME_MAX);
+                                       xstrsncpy(runfile, dents[cur].name, NAME_MAX);
                                cfg.runctx = cfg.curctx;
                                lastname[0] = '\0';
                        }
@@ -6362,8 +6328,8 @@ static char *make_tmp_tree(char **paths, ssize_t entries, const char *prefix)
        }
 
        tmp = tmpdir + tmpfplen - 1;
-       xstrlcpy(tmpdir, g_tmpfpath, tmpfplen);
-       xstrlcpy(tmp, "/nnnXXXXXX", 11);
+       xstrsncpy(tmpdir, g_tmpfpath, tmpfplen);
+       xstrsncpy(tmp, "/nnnXXXXXX", 11);
 
        /* Points right after the base tmp dir */
        tmp += 10;
@@ -6388,7 +6354,7 @@ static char *make_tmp_tree(char **paths, ssize_t entries, const char *prefix)
                }
 
                /* Don't copy the common prefix */
-               xstrlcpy(tmp, paths[i] + len, strlen(paths[i]) - len + 1);
+               xstrsncpy(tmp, paths[i] + len, strlen(paths[i]) - len + 1);
 
                /* Get the dir containing the path */
                slash = xmemrchr((uchar *)tmp, '/', strlen(paths[i]) - len);
@@ -6530,7 +6496,7 @@ static char *load_input()
 
                DPRINTF_S(paths[i]);
 
-               xstrlcpy(g_buf, paths[i], PATH_MAX);
+               xstrsncpy(g_buf, paths[i], PATH_MAX);
                if (!common_prefix(dirname(g_buf), prefixpath)) {
                        entries = i + 1; // free from the current entry
                        goto malloc_2;
@@ -6625,8 +6591,8 @@ static bool setup_config(void)
        if (xdgcfg && xdgcfg[0]) {
                DPRINTF_S(xdgcfg);
                if (xdgcfg[0] == '~') {
-                       r = xstrlcpy(g_buf, home, PATH_MAX);
-                       xstrlcpy(g_buf + r - 1, xdgcfg + 1, PATH_MAX);
+                       r = xstrsncpy(g_buf, home, PATH_MAX);
+                       xstrsncpy(g_buf + r - 1, xdgcfg + 1, PATH_MAX);
                        xdgcfg = g_buf;
                        DPRINTF_S(xdgcfg);
                }
@@ -6652,24 +6618,24 @@ static bool setup_config(void)
        }
 
        if (xdg) {
-               xstrlcpy(cfgdir, xdgcfg, len);
+               xstrsncpy(cfgdir, xdgcfg, len);
                r = len - 13; /* subtract length of "/nnn/sessions" */
        } else {
-               r = xstrlcpy(cfgdir, home, len);
+               r = xstrsncpy(cfgdir, home, len);
 
                /* Create ~/.config */
-               xstrlcpy(cfgdir + r - 1, "/.config", len - r);
+               xstrsncpy(cfgdir + r - 1, "/.config", len - r);
                DPRINTF_S(cfgdir);
                r += 8; /* length of "/.config" */
        }
 
        /* Create ~/.config/nnn */
-       xstrlcpy(cfgdir + r - 1, "/nnn", len - r);
+       xstrsncpy(cfgdir + r - 1, "/nnn", len - r);
        DPRINTF_S(cfgdir);
 
        /* Create ~/.config/nnn/plugins */
-       xstrlcpy(plugindir, cfgdir, PATH_MAX);
-       xstrlcpy(plugindir + r + 4 - 1, "/plugins", 9); /* subtract length of "/nnn" (4) */
+       xstrsncpy(plugindir, cfgdir, PATH_MAX);
+       xstrsncpy(plugindir + r + 4 - 1, "/plugins", 9); /* subtract length of "/nnn" (4) */
        DPRINTF_S(plugindir);
 
        if (access(plugindir, F_OK) && !xmktree(plugindir, TRUE)) {
@@ -6678,8 +6644,8 @@ static bool setup_config(void)
        }
 
        /* Create ~/.config/nnn/sessions */
-       xstrlcpy(sessiondir, cfgdir, PATH_MAX);
-       xstrlcpy(sessiondir + r + 4 - 1, "/sessions", 10); /* subtract length of "/nnn" (4) */
+       xstrsncpy(sessiondir, cfgdir, PATH_MAX);
+       xstrsncpy(sessiondir + r + 4 - 1, "/sessions", 10); /* subtract length of "/nnn" (4) */
        DPRINTF_S(sessiondir);
 
        if (access(sessiondir, F_OK) && !xmktree(sessiondir, TRUE)) {
@@ -6696,8 +6662,8 @@ static bool setup_config(void)
                        return FALSE;
                }
 
-               r = xstrlcpy(selpath, cfgdir, len + 3);
-               xstrlcpy(selpath + r - 1, "/.selection", 12);
+               r = xstrsncpy(selpath, cfgdir, len + 3);
+               xstrsncpy(selpath + r - 1, "/.selection", 12);
                DPRINTF_S(selpath);
        }
 
@@ -6714,7 +6680,7 @@ static bool set_tmp_path(void)
                 return FALSE;
         }
 
-        tmpfplen = (uchar)xstrlcpy(g_tmpfpath, path, TMP_LEN_MAX);
+        tmpfplen = (uchar)xstrsncpy(g_tmpfpath, path, TMP_LEN_MAX);
         return TRUE;
 }