diff options
Diffstat (limited to 'Src/utils.c')
-rw-r--r-- | Src/utils.c | 119 |
1 files changed, 101 insertions, 18 deletions
diff --git a/Src/utils.c b/Src/utils.c index c6d178ce2..998e46a36 100644 --- a/Src/utils.c +++ b/Src/utils.c @@ -725,32 +725,36 @@ xsymlinks(char *s) char **pp, **opp; char xbuf2[PATH_MAX*2], xbuf3[PATH_MAX*2]; int t0, ret = 0; + zulong xbuflen = strlen(xbuf); opp = pp = slashsplit(s); - for (; *pp; pp++) { - if (!strcmp(*pp, ".")) { - zsfree(*pp); + for (; xbuflen < sizeof(xbuf) && *pp; pp++) { + if (!strcmp(*pp, ".")) continue; - } if (!strcmp(*pp, "..")) { char *p; - zsfree(*pp); if (!strcmp(xbuf, "/")) continue; if (!*xbuf) continue; - p = xbuf + strlen(xbuf); - while (*--p != '/'); + p = xbuf + xbuflen; + while (*--p != '/') + xbuflen--; *p = '\0'; continue; } sprintf(xbuf2, "%s/%s", xbuf, *pp); t0 = readlink(unmeta(xbuf2), xbuf3, PATH_MAX); if (t0 == -1) { - strcat(xbuf, "/"); - strcat(xbuf, *pp); - zsfree(*pp); + zulong pplen = strlen(*pp) + 1; + if ((xbuflen += pplen) < sizeof(xbuf)) { + strcat(xbuf, "/"); + strcat(xbuf, *pp); + } else { + *xbuf = 0; + break; + } } else { ret = 1; metafy(xbuf3, t0, META_NOALLOC); @@ -759,10 +763,9 @@ xsymlinks(char *s) xsymlinks(xbuf3 + 1); } else xsymlinks(xbuf3); - zsfree(*pp); } } - free(opp); + freearray(opp); return ret; } @@ -779,8 +782,10 @@ xsymlink(char *s) return NULL; *xbuf = '\0'; xsymlinks(s + 1); - if (!*xbuf) + if (!*xbuf) { + zwarn("path expansion failed, using root directory"); return ztrdup("/"); + } return ztrdup(xbuf); } @@ -2486,7 +2491,7 @@ getquery(char *valid_chars, int purge) static int d; static char *guess, *best; -static Patprog spckpat; +static Patprog spckpat, spnamepat; /**/ static void @@ -2557,6 +2562,13 @@ spckword(char **s, int hist, int cmd, int ask) } else spckpat = NULL; + if ((correct_ignore = getsparam("CORRECT_IGNORE_FILE")) != NULL) { + tokenize(correct_ignore = dupstring(correct_ignore)); + remnulargs(correct_ignore); + spnamepat = patcompile(correct_ignore, 0, NULL); + } else + spnamepat = NULL; + if (**s == String && !*t) { guess = *s + 1; if (itype_end(guess, IIDENT, 1) == guess) @@ -2698,10 +2710,13 @@ ztrftimebuf(int *bufsizeptr, int decr) /**/ mod_export int -ztrftime(char *buf, int bufsize, char *fmt, struct tm *tm) +ztrftime(char *buf, int bufsize, char *fmt, struct tm *tm, long usec) { - int hr12, decr; -#ifndef HAVE_STRFTIME + int hr12; +#ifdef HAVE_STRFTIME + int decr; + char tmp[4]; +#else static char *astr[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; static char *estr[] = @@ -2709,12 +2724,12 @@ ztrftime(char *buf, int bufsize, char *fmt, struct tm *tm) "Aug", "Sep", "Oct", "Nov", "Dec"}; #endif char *origbuf = buf; - char tmp[4]; while (*fmt) if (*fmt == '%') { int strip; + int digs = 3; fmt++; if (*fmt == '-') { @@ -2722,6 +2737,17 @@ ztrftime(char *buf, int bufsize, char *fmt, struct tm *tm) fmt++; } else strip = 0; + if (idigit(*fmt)) { + /* Digit --- only useful with . */ + char *dstart = fmt; + char *dend = fmt+1; + while (idigit(*dend)) + dend++; + if (*dend == '.') { + fmt = dend; + digs = atoi(dstart); + } + } /* * Assume this format will take up at least two * characters. Not always true, but if that matters @@ -2731,6 +2757,20 @@ ztrftime(char *buf, int bufsize, char *fmt, struct tm *tm) if (ztrftimebuf(&bufsize, 2)) return -1; switch (*fmt++) { + case '.': + if (ztrftimebuf(&bufsize, digs)) + return -1; + if (digs > 6) + digs = 6; + if (digs < 6) { + int trunc; + for (trunc = 5 - digs; trunc; trunc--) + usec /= 10; + usec = (usec + 5) / 10; + } + sprintf(buf, "%0*ld", digs, usec); + buf += digs; + break; case 'd': if (tm->tm_mday > 9 || !strip) *buf++ = '0' + tm->tm_mday / 10; @@ -3332,6 +3372,17 @@ mkarray(char *s) } /**/ +mod_export char ** +hmkarray(char *s) +{ + char **t = (char **) zhalloc((s) ? (2 * sizeof s) : (sizeof s)); + + if ((*t = s)) + t[1] = NULL; + return t; +} + +/**/ mod_export void zbeep(void) { @@ -3778,6 +3829,8 @@ mindist(char *dir, char *mindistguess, char *mindistbest) if (!(dd = opendir(unmeta(dir)))) return mindistd; while ((fn = zreaddir(dd, 0))) { + if (spnamepat && pattry(spnamepat, fn)) + continue; nd = spdist(fn, mindistguess, (int)strlen(mindistguess) / 4 + 1); if (nd <= mindistd) { @@ -4256,6 +4309,12 @@ mod_export char * zreaddir(DIR *dir, int ignoredots) { struct dirent *de; +#if defined(HAVE_ICONV) && defined(__APPLE__) + static iconv_t conv_ds = (iconv_t)0; + static char *conv_name = 0; + char *conv_name_ptr, *orig_name_ptr; + size_t conv_name_len, orig_name_len; +#endif do { de = readdir(dir); @@ -4264,6 +4323,30 @@ zreaddir(DIR *dir, int ignoredots) } while(ignoredots && de->d_name[0] == '.' && (!de->d_name[1] || (de->d_name[1] == '.' && !de->d_name[2]))); +#if defined(HAVE_ICONV) && defined(__APPLE__) + if (!conv_ds) + conv_ds = iconv_open("UTF-8", "UTF-8-MAC"); + if (conv_ds != (iconv_t)(-1)) { + /* Force initial state in case re-using conv_ds */ + (void) iconv(conv_ds, 0, &orig_name_len, 0, &conv_name_len); + + orig_name_ptr = de->d_name; + orig_name_len = strlen(de->d_name); + conv_name = zrealloc(conv_name, orig_name_len+1); + conv_name_ptr = conv_name; + conv_name_len = orig_name_len; + if (iconv(conv_ds, + &orig_name_ptr, &orig_name_len, + &conv_name_ptr, &conv_name_len) != (size_t)(-1) && + orig_name_len == 0) { + /* Completely converted, metafy and return */ + *conv_name_ptr = '\0'; + return metafy(conv_name, -1, META_STATIC); + } + /* Error, or conversion incomplete, keep the original name */ + } +#endif + return metafy(de->d_name, -1, META_STATIC); } |