static int domove(char *nam, MoveFunc movefn, char *p, char *q, int flags) { struct stat st; char *pbuf, *qbuf; pbuf = ztrdup(unmeta(p)); qbuf = unmeta(q); if(flags & MV_NODIRS) { errno = EISDIR; if(lstat(pbuf, &st) || S_ISDIR(st.st_mode)) { zwarnnam(nam, "%s: %e", p, errno); zsfree(pbuf); return 1; } } if(!lstat(qbuf, &st)) { int doit = flags & MV_FORCE; if(S_ISDIR(st.st_mode)) { zwarnnam(nam, "%s: cannot overwrite directory", q); zsfree(pbuf); return 1; } else if(flags & MV_INTERACTIVE) { nicezputs(nam, stderr); fputs(": replace `", stderr); nicezputs(q, stderr); fputs("'? ", stderr); fflush(stderr); if(!ask()) { zsfree(pbuf); return 0; } doit = 1; } else if((flags & MV_ASKNW) && !S_ISLNK(st.st_mode) && access(qbuf, W_OK)) { nicezputs(nam, stderr); fputs(": replace `", stderr); nicezputs(q, stderr); fprintf(stderr, "', overriding mode %04o? ", mode_to_octal(st.st_mode)); fflush(stderr); if(!ask()) { zsfree(pbuf); return 0; } doit = 1; } if(doit && !(flags & MV_ATOMIC)) unlink(qbuf); } if(movefn(pbuf, qbuf)) { zwarnnam(nam, "%s: %e", p, errno); zsfree(pbuf); return 1; } zsfree(pbuf); return 0; }
char * zgetcwd(void) { char *ret = zgetdir(NULL); #ifdef HAVE_GETCWD if (!ret) { #ifdef GETCWD_CALLS_MALLOC char *cwd = getcwd(NULL, 0); if (cwd) { ret = dupstring(cwd); free(cwd); } #else char *cwdbuf = zalloc(PATH_MAX); ret = getcwd(cwdbuf, PATH_MAX); if (ret) ret = dupstring(ret); zfree(cwdbuf, PATH_MAX); #endif /* GETCWD_CALLS_MALLOC */ } #endif /* HAVE_GETCWD */ if (!ret) ret = unmeta(pwd); if (!ret) ret = dupstring("."); return ret; }
int stuff(char *fn) { FILE *in; char *buf; off_t len; if (!(in = fopen(unmeta(fn), "r"))) { zerr("can't open %s", fn); return 1; } fseek(in, 0, 2); len = ftell(in); fseek(in, 0, 0); buf = (char *)zalloc(len + 1); if (!(fread(buf, len, 1, in))) { zerr("read error on %s", fn); fclose(in); zfree(buf, len + 1); return 1; } fclose(in); buf[len] = '\0'; fwrite(buf, len, 1, stderr); fflush(stderr); inputsetline(metafy(buf, len, META_REALLOC), INP_FREE); return 0; }
static mode_t dolstat(char *s) { if (lstat(unmeta(s), &st) < 0) return 0; return st.st_mode; }
mod_export void trashzle(void) { if (zleactive && !trashedzle) { /* This zrefresh() is just to get the main editor display right and * * get the cursor in the right place. For that reason, we disable * * list display (which would otherwise result in infinite * * recursion [at least, it would if zrefresh() didn't have its * * extra `inlist' check]). */ int sl = showinglist; showinglist = 0; trashedzle = 1; zrefresh(); showinglist = sl; moveto(nlnct, 0); if (clearflag && tccan(TCCLEAREOD)) { tcout(TCCLEAREOD); clearflag = listshown = 0; } if (postedit) fprintf(shout, "%s", unmeta(postedit)); fflush(shout); resetneeded = 1; if (!(zlereadflags & ZLRF_NOSETTY)) settyinfo(&shttyinfo); } if (errflag) kungetct = 0; }
static int doaccess(char *s, int c) { #ifdef HAVE_FACCESSX if (!strncmp(s, "/dev/fd/", 8)) return !faccessx(atoi(s + 8), c, ACC_SELF); #endif return !access(unmeta(s), c); }
void hashdir(char **dirp) { Cmdnam cn; DIR *dir; char *fn; if (isrelative(*dirp) || !(dir = opendir(unmeta(*dirp)))) return; while ((fn = zreaddir(dir))) { /* Ignore `.' and `..'. */ if (fn[0] == '.' && (fn[1] == '\0' || (fn[1] == '.' && fn[2] == '\0'))) continue; #ifndef WINNT if (!cmdnamtab->getnode(cmdnamtab, fn)) { cn = (Cmdnam) zcalloc(sizeof *cn); cn->flags = 0; cn->u.name = dirp; cmdnamtab->addnode(cmdnamtab, ztrdup(fn), cn); } #else if (!cmdnamtab->getnode(cmdnamtab, fn)) { char *fext; fext = fn; while(*fext++) ; while((fext >fn )&& (*fext != '.')) fext--; if ( (fext == fn) /*no extension */ || is_pathext(fext+1) ) { cn = (Cmdnam) zcalloc(sizeof *cn); cn->flags = 0; cn->u.name = dirp; cmdnamtab->addnode(cmdnamtab, ztrdup(fn), cn); /*if (fext != fn && !strnicmp(fext+1,"exe",3)) */ *fext = 0; cn = (Cmdnam) zcalloc(sizeof *cn); cn->flags = 0; cn->u.name = dirp; cmdnamtab->addnode(cmdnamtab, ztrdup(fn), cn); } #ifdef ZSH_HASH_DEBUG printhashtabinfo(cmdnamtab); #endif /* ZSH_HASH_DEBUG */ } #endif /* WINNT */ } closedir(dir); }
int source(char *s) { int tempfd, fd, cj, oldlineno; int oldshst, osubsh, oloops; FILE *obshin; char *old_scriptname = scriptname; if (!s || (tempfd = movefd(open(unmeta(s), O_RDONLY))) == -1) { return 1; } /* save the current shell state */ fd = SHIN; /* store the shell input fd */ obshin = bshin; /* store file handle for buffered shell input */ osubsh = subsh; /* store whether we are in a subshell */ cj = thisjob; /* store our current job number */ oldlineno = lineno; /* store our current lineno */ oloops = loops; /* stored the # of nested loops we are in */ oldshst = opts[SHINSTDIN]; /* store current value of this option */ SHIN = tempfd; bshin = fdopen(SHIN, "r"); subsh = 0; lineno = 0; loops = 0; dosetopt(SHINSTDIN, 0, 1); scriptname = s; sourcelevel++; loop(0); /* loop through the file to be sourced */ sourcelevel--; fclose(bshin); fdtable[SHIN] = 0; /* restore the current shell state */ SHIN = fd; /* the shell input fd */ bshin = obshin; /* file handle for buffered shell input */ subsh = osubsh; /* whether we are in a subshell */ thisjob = cj; /* current job number */ lineno = oldlineno; /* our current lineno */ loops = oloops; /* the # of nested loops we are in */ dosetopt(SHINSTDIN, oldshst, 1); /* SHINSTDIN option */ errflag = 0; retflag = 0; scriptname = old_scriptname; return 0; }
static int bin_rmdir(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) { int err = 0; for(; *args; args++) { char *rpath = unmeta(*args); if(!rpath) { zwarnnam(nam, "%s: %e", *args, ENAMETOOLONG); err = 1; } else if(rmdir(rpath)) { zwarnnam(nam, "cannot remove directory `%s': %e", *args, errno); err = 1; } } return err; }
static struct stat * getstat(char *s) { char *us; /* /dev/fd/n refers to the open file descriptor n. We always use fstat * * in this case since on Solaris /dev/fd/n is a device special file */ if (!strncmp(s, "/dev/fd/", 8)) { if (fstat(atoi(s + 8), &st)) return NULL; return &st; } if (!(us = unmeta(s))) return NULL; if (stat(us, &st)) return NULL; return &st; }
static int domkdir(char *nam, char *path, mode_t mode, int p) { int err; mode_t oumask; char const *rpath = unmeta(path); if(p) { struct stat st; if(!stat(rpath, &st) && S_ISDIR(st.st_mode)) return 0; } oumask = umask(0); err = mkdir(rpath, mode) ? errno : 0; umask(oumask); if(!err) return 0; zwarnnam(nam, "cannot make directory `%s': %e", path, err); return 1; }
void hashdir(char **dirp) { Cmdnam cn; DIR *dir; char *fn; #if defined(_WIN32) || defined(__CYGWIN__) char *exe; #endif /* _WIN32 || _CYGWIN__ */ if (isrelative(*dirp) || !(dir = opendir(unmeta(*dirp)))) return; while ((fn = zreaddir(dir, 1))) { if (!cmdnamtab->getnode(cmdnamtab, fn)) { cn = (Cmdnam) zshcalloc(sizeof *cn); cn->flags = 0; cn->u.name = dirp; cmdnamtab->addnode(cmdnamtab, ztrdup(fn), cn); } #if defined(_WIN32) || defined(__CYGWIN__) /* Hash foo.exe as foo, since when no real foo exists, foo.exe will get executed by DOS automatically. This quiets spurious corrections when CORRECT or CORRECT_ALL is set. */ if ((exe = strrchr(fn, '.')) && (exe[1] == 'E' || exe[1] == 'e') && (exe[2] == 'X' || exe[2] == 'x') && (exe[3] == 'E' || exe[3] == 'e') && exe[4] == 0) { *exe = 0; if (!cmdnamtab->getnode(cmdnamtab, fn)) { cn = (Cmdnam) zshcalloc(sizeof *cn); cn->flags = 0; cn->u.name = dirp; cmdnamtab->addnode(cmdnamtab, ztrdup(fn), cn); } } #endif /* _WIN32 || __CYGWIN__ */ } closedir(dir); }
void parseargs(char **argv) { char **x; int action, optno; LinkList paramlist; int bourne = (emulation == EMULATE_KSH || emulation == EMULATE_SH); hackzero = argzero = *argv++; SHIN = 0; /* There's a bit of trickery with opts[INTERACTIVE] here. It starts * * at a value of 2 (instead of 1) or 0. If it is explicitly set on * * the command line, it goes to 1 or 0. If input is coming from * * somewhere that normally makes the shell non-interactive, we do * * "opts[INTERACTIVE] &= 1", so that only a *default* on state will * * be changed. At the end of the function, a value of 2 gets * * changed to 1. */ opts[INTERACTIVE] = isatty(0) ? 2 : 0; opts[SHINSTDIN] = 0; opts[SINGLECOMMAND] = 0; /* loop through command line options (begins with "-" or "+") */ while (*argv && (**argv == '-' || **argv == '+')) { action = (**argv == '-'); if(!argv[0][1]) *argv = "--"; while (*++*argv) { /* The pseudo-option `--' signifies the end of options. * * `-b' does too, csh-style, unless we're emulating a * * Bourne style shell. */ if (**argv == '-' || (!bourne && **argv == 'b')) { argv++; goto doneoptions; } if (**argv == 'c') { /* -c command */ if (!*++argv) { zerr("string expected after -c", NULL, 0); exit(1); } cmd = *argv++; opts[INTERACTIVE] &= 1; opts[SHINSTDIN] = 0; goto doneoptions; } else if (**argv == 'o') { if (!*++*argv) argv++; if (!*argv) { zerr("string expected after -o", NULL, 0); exit(1); } if(!(optno = optlookup(*argv))) zerr("no such option: %s", *argv, 0); else dosetopt(optno, action, 1); break; } else { if (!(optno = optlookupc(**argv))) { zerr("bad option: -%c", NULL, **argv); exit(1); } else dosetopt(optno, action, 1); } } argv++; } doneoptions: paramlist = newlinklist(); if (*argv) { if (unset(SHINSTDIN)) { argzero = *argv; if (!cmd) SHIN = movefd(open(unmeta(argzero), O_RDONLY)); if (SHIN == -1) { zerr("can't open input file: %s", argzero, 0); exit(1); } opts[INTERACTIVE] &= 1; argv++; } while (*argv) addlinknode(paramlist, ztrdup(*argv++)); } else opts[SHINSTDIN] = 1; if(isset(SINGLECOMMAND)) opts[INTERACTIVE] &= 1; opts[INTERACTIVE] = !!opts[INTERACTIVE]; pparams = x = (char **) zcalloc((countlinknodes(paramlist) + 1) * sizeof(char *)); while ((*x++ = (char *)getlinknode(paramlist))); free(paramlist); argzero = ztrdup(argzero); }
static int bin_zsystem_flock(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) { int cloexec = 1, unlock = 0, readlock = 0; time_t timeout = 0; char *fdvar = NULL; #ifdef HAVE_FCNTL_H struct flock lck; int flock_fd, flags; #endif while (*args && **args == '-') { int opt; char *optptr = *args + 1, *optarg; args++; if (!*optptr || !strcmp(optptr, "-")) break; while ((opt = *optptr)) { switch (opt) { case 'e': /* keep lock on "exec" */ cloexec = 0; break; case 'f': /* variable for fd */ if (optptr[1]) { fdvar = optptr + 1; optptr += strlen(fdvar) - 1; } else if (*args) { fdvar = *args++; } if (fdvar == NULL || !isident(fdvar)) { zwarnnam(nam, "flock: option %c requires a variable name", opt); return 1; } break; case 'r': /* read lock rather than read-write lock */ readlock = 1; break; case 't': /* timeout in seconds */ if (optptr[1]) { optarg = optptr + 1; optptr += strlen(optarg) - 1; } else if (!*args) { zwarnnam(nam, "flock: option %c requires a numeric timeout", opt); return 1; } else { optarg = *args++; } timeout = (time_t)mathevali(optarg); break; case 'u': /* unlock: argument is fd */ unlock = 1; break; default: zwarnnam(nam, "flock: unknown option: %c", *optptr); return 1; } optptr++; } } if (!args[0]) { zwarnnam(nam, "flock: not enough arguments"); return 1; } if (args[1]) { zwarnnam(nam, "flock: too many arguments"); return 1; } #ifdef HAVE_FCNTL_H if (unlock) { flock_fd = (int)mathevali(args[0]); if (zcloselockfd(flock_fd) < 0) { zwarnnam(nam, "flock: file descriptor %d not in use for locking", flock_fd); return 1; } return 0; } if (readlock) flags = O_RDONLY | O_NOCTTY; else flags = O_RDWR | O_NOCTTY; if ((flock_fd = open(unmeta(args[0]), flags)) < 0) { zwarnnam(nam, "failed to open %s for writing: %e", args[0], errno); return 1; } flock_fd = movefd(flock_fd); if (flock_fd == -1) return 1; #ifdef FD_CLOEXEC if (cloexec) { long fdflags = fcntl(flock_fd, F_GETFD, 0); if (fdflags != (long)-1) fcntl(flock_fd, F_SETFD, fdflags | FD_CLOEXEC); } #endif addlockfd(flock_fd, cloexec); lck.l_type = readlock ? F_RDLCK : F_WRLCK; lck.l_whence = SEEK_SET; lck.l_start = 0; lck.l_len = 0; /* lock the whole file */ if (timeout > 0) { time_t end = time(NULL) + (time_t)timeout; while (fcntl(flock_fd, F_SETLK, &lck) < 0) { if (errflag) return 1; if (errno != EINTR && errno != EACCES && errno != EAGAIN) { zwarnnam(nam, "failed to lock file %s: %e", args[0], errno); return 1; } if (time(NULL) >= end) return 2; sleep(1); } } else { while (fcntl(flock_fd, F_SETLKW, &lck) < 0) { if (errflag) return 1; if (errno == EINTR) continue; zwarnnam(nam, "failed to lock file %s: %e", args[0], errno); return 1; } } if (fdvar) setiparam(fdvar, flock_fd); return 0; #else /* HAVE_FCNTL_H */ zwarnnam(nam, "flock: not implemented on this system"); return 255; #endif /* HAVE_FCNTL_H */ }
void hashdir(char **dirp) { Cmdnam cn; DIR *dir; char *fn, *unmetadir, *pathbuf, *pathptr; int dirlen; #if defined(_WIN32) || defined(__CYGWIN__) char *exe; #endif /* _WIN32 || _CYGWIN__ */ if (isrelative(*dirp)) return; unmetadir = unmeta(*dirp); if (!(dir = opendir(unmetadir))) return; dirlen = strlen(unmetadir); pathbuf = (char *)zalloc(dirlen + PATH_MAX + 2); sprintf(pathbuf, "%s/", unmetadir); pathptr = pathbuf + dirlen + 1; while ((fn = zreaddir(dir, 1))) { if (!cmdnamtab->getnode(cmdnamtab, fn)) { char *fname = ztrdup(fn); struct stat statbuf; int add = 0, dummylen; unmetafy(fn, &dummylen); if (strlen(fn) > PATH_MAX) { /* Too heavy to do all the allocation */ add = 1; } else { strcpy(pathptr, fn); /* * This is the same test as for the glob qualifier for * executable plain files. */ if (unset(HASHEXECUTABLESONLY) || (access(pathbuf, X_OK) == 0 && stat(pathbuf, &statbuf) == 0 && S_ISREG(statbuf.st_mode) && (statbuf.st_mode & S_IXUGO))) add = 1; } if (add) { cn = (Cmdnam) zshcalloc(sizeof *cn); cn->node.flags = 0; cn->u.name = dirp; cmdnamtab->addnode(cmdnamtab, fname, cn); } else zsfree(fname); } #if defined(_WIN32) || defined(__CYGWIN__) /* Hash foo.exe as foo, since when no real foo exists, foo.exe will get executed by DOS automatically. This quiets spurious corrections when CORRECT or CORRECT_ALL is set. */ if ((exe = strrchr(fn, '.')) && (exe[1] == 'E' || exe[1] == 'e') && (exe[2] == 'X' || exe[2] == 'x') && (exe[3] == 'E' || exe[3] == 'e') && exe[4] == 0) { *exe = 0; if (!cmdnamtab->getnode(cmdnamtab, fn)) { cn = (Cmdnam) zshcalloc(sizeof *cn); cn->node.flags = 0; cn->u.name = dirp; cmdnamtab->addnode(cmdnamtab, ztrdup(fn), cn); } } #endif /* _WIN32 || __CYGWIN__ */ } closedir(dir); zfree(pathbuf, dirlen + PATH_MAX + 2); }
static int bin_stat(char *name, char **args, Options ops, UNUSED(int func)) { char **aptr, *arrnam = NULL, **array = NULL, **arrptr = NULL; char *hashnam = NULL, **hash = NULL, **hashptr = NULL; int len, iwhich = -1, ret = 0, flags = 0, arrsize = 0, fd = 0; struct stat statbuf; int found = 0, nargs; timefmt = "%a %b %e %k:%M:%S %Z %Y"; for (; *args && (**args == '+' || **args == '-'); args++) { char *arg = *args+1; if (!*arg || *arg == '-' || *arg == '+') { args++; break; } if (**args == '+') { if (found) break; len = strlen(arg); for (aptr = statelts; *aptr; aptr++) if (!strncmp(*aptr, arg, len)) { found++; iwhich = aptr - statelts; } if (found > 1) { zwarnnam(name, "%s: ambiguous stat element", arg); return 1; } else if (found == 0) { zwarnnam(name, "%s: no such stat element", arg); return 1; } /* if name of link requested, turn on lstat */ if (iwhich == ST_READLINK) ops->ind['L'] = 1; flags |= STF_PICK; } else { for (; *arg; arg++) { if (strchr("glLnNorstT", *arg)) ops->ind[STOUC(*arg)] = 1; else if (*arg == 'A') { if (arg[1]) { arrnam = arg+1; } else if (!(arrnam = *++args)) { zwarnnam(name, "missing parameter name"); return 1; } flags |= STF_ARRAY; break; } else if (*arg == 'H') { if (arg[1]) { hashnam = arg+1; } else if (!(hashnam = *++args)) { zwarnnam(name, "missing parameter name"); return 1; } flags |= STF_HASH; break; } else if (*arg == 'f') { char *sfd; ops->ind['f'] = 1; if (arg[1]) { sfd = arg+1; } else if (!(sfd = *++args)) { zwarnnam(name, "missing file descriptor"); return 1; } fd = zstrtol(sfd, &sfd, 10); if (*sfd) { zwarnnam(name, "bad file descriptor"); return 1; } break; } else if (*arg == 'F') { if (arg[1]) { timefmt = arg+1; } else if (!(timefmt = *++args)) { zwarnnam(name, "missing time format"); return 1; } /* force string format in order to use time format */ ops->ind['s'] = 1; break; } else { zwarnnam(name, "bad option: -%c", *arg); return 1; } } } } if ((flags & STF_ARRAY) && (flags & STF_HASH)) { /* We don't implement setting multiple variables at once */ zwarnnam(name, "both array and hash requested"); return 1; /* Alternate method would be to make -H blank arrnam etc etc * * and so get 'silent loss' of earlier choice, which would * * be similar to stat -A foo -A bar filename */ } if (OPT_ISSET(ops,'l')) { /* list types and return: can also list to array */ if (arrnam) { arrptr = array = (char **)zalloc((ST_COUNT+1)*sizeof(char *)); array[ST_COUNT] = NULL; } for (aptr = statelts; *aptr; aptr++) { if (arrnam) { *arrptr++ = ztrdup(*aptr); } else { printf("%s", *aptr); if (aptr[1]) putchar(' '); } } if (arrnam) { setaparam(arrnam, array); if (errflag) return 1; } else putchar('\n'); return 0; } if (!*args && !OPT_ISSET(ops,'f')) { zwarnnam(name, "no files given"); return 1; } else if (*args && OPT_ISSET(ops,'f')) { zwarnnam(name, "no files allowed with -f"); return 1; } nargs = 0; if (OPT_ISSET(ops,'f')) nargs = 1; else for (aptr = args; *aptr; aptr++) nargs++; if (OPT_ISSET(ops,'g')) { flags |= STF_GMT; ops->ind['s'] = 1; } if (OPT_ISSET(ops,'s') || OPT_ISSET(ops,'r')) flags |= STF_STRING; if (OPT_ISSET(ops,'r') || !OPT_ISSET(ops,'s')) flags |= STF_RAW; if (OPT_ISSET(ops,'n')) flags |= STF_FILE; if (OPT_ISSET(ops,'o')) flags |= STF_OCTAL; if (OPT_ISSET(ops,'t')) flags |= STF_NAME; if (!(arrnam || hashnam)) { if (nargs > 1) flags |= STF_FILE; if (!(flags & STF_PICK)) flags |= STF_NAME; } if (OPT_ISSET(ops,'N') || OPT_ISSET(ops,'f')) flags &= ~STF_FILE; if (OPT_ISSET(ops,'T') || OPT_ISSET(ops,'H')) flags &= ~STF_NAME; if (hashnam) { if (nargs > 1) { zwarnnam(name, "only one file allowed with -H"); return 1; } arrsize = (flags & STF_PICK) ? 1 : ST_COUNT; if (flags & STF_FILE) arrsize++; hashptr = hash = (char **)zshcalloc((arrsize+1)*2*sizeof(char *)); } if (arrnam) { arrsize = (flags & STF_PICK) ? 1 : ST_COUNT; if (flags & STF_FILE) arrsize++; arrsize *= nargs; arrptr = array = (char **)zshcalloc((arrsize+1)*sizeof(char *)); } for (; OPT_ISSET(ops,'f') || *args; args++) { char outbuf[PATH_MAX + 9]; /* "link " + link name + NULL */ int rval = OPT_ISSET(ops,'f') ? fstat(fd, &statbuf) : OPT_ISSET(ops,'L') ? lstat(unmeta(*args), &statbuf) : stat(unmeta(*args), &statbuf); if (rval) { if (OPT_ISSET(ops,'f')) sprintf(outbuf, "%d", fd); zwarnnam(name, "%s: %e", OPT_ISSET(ops,'f') ? outbuf : *args, errno); ret = 1; if (OPT_ISSET(ops,'f') || arrnam) break; else continue; } if (flags & STF_FILE) { if (arrnam) *arrptr++ = ztrdup(*args); else if (hashnam) { *hashptr++ = ztrdup(HNAMEKEY); *hashptr++ = ztrdup(*args); } else printf("%s%s", *args, (flags & STF_PICK) ? " " : ":\n"); } if (iwhich > -1) { statprint(&statbuf, outbuf, *args, iwhich, flags); if (arrnam) *arrptr++ = metafy(outbuf, -1, META_DUP); else if (hashnam) { /* STF_NAME explicitly turned off for ops.ind['H'] above */ *hashptr++ = ztrdup(statelts[iwhich]); *hashptr++ = metafy(outbuf, -1, META_DUP); } else printf("%s\n", outbuf); } else { int i; for (i = 0; i < ST_COUNT; i++) { statprint(&statbuf, outbuf, *args, i, flags); if (arrnam) *arrptr++= metafy(outbuf, -1, META_DUP); else if (hashnam) { /* STF_NAME explicitly turned off for ops.ind['H'] above */ *hashptr++ = ztrdup(statelts[i]); *hashptr++ = metafy(outbuf, -1, META_DUP); } else printf("%s\n", outbuf); } } if (OPT_ISSET(ops,'f')) break; if (!arrnam && !hashnam && args[1] && !(flags & STF_PICK)) putchar('\n'); } if (arrnam) { if (ret) freearray(array); else { setaparam(arrnam, array); if (errflag) return 1; } } if (hashnam) { if (ret) freearray(hash); else { sethparam(hashnam, hash); if (errflag) return 1; } } return ret; }
static int bin_ln(char *nam, char **args, Options ops, int func) { MoveFunc movefn; int flags, have_dir, err = 0; char **a, *ptr, *rp, *buf; struct stat st; size_t blen; if(func == BIN_MV) { movefn = (MoveFunc) rename; flags = OPT_ISSET(ops,'f') ? 0 : MV_ASKNW; flags |= MV_ATOMIC; } else { flags = OPT_ISSET(ops,'f') ? MV_FORCE : 0; #ifdef HAVE_LSTAT if(OPT_ISSET(ops,'h') || OPT_ISSET(ops,'n')) flags |= MV_NOCHASETARGET; if(OPT_ISSET(ops,'s')) movefn = (MoveFunc) symlink; else #endif { movefn = (MoveFunc) link; if(!OPT_ISSET(ops,'d')) flags |= MV_NODIRS; } } if(OPT_ISSET(ops,'i') && !OPT_ISSET(ops,'f')) flags |= MV_INTERACTIVE; for(a = args; a[1]; a++) ; if(a != args) { rp = unmeta(*a); if(rp && !stat(rp, &st) && S_ISDIR(st.st_mode)) { have_dir = 1; if((flags & MV_NOCHASETARGET) && !lstat(rp, &st) && S_ISLNK(st.st_mode)) { /* * So we have "ln -h" with the target being a symlink pointing * to a directory; if there are multiple sources but the target * is a symlink, then it's an error as we're not following * symlinks; if OTOH there's just one source, then we need to * either fail EEXIST or if "-f" given then remove the target. */ if(a > args+1) { errno = ENOTDIR; zwarnnam(nam, "%s: %e", *a, errno); return 1; } if(flags & MV_FORCE) { unlink(rp); have_dir = 0; } else { errno = EEXIST; zwarnnam(nam, "%s: %e", *a, errno); return 1; } } /* Normal case, target is a directory, chase into it */ if (have_dir) goto havedir; } } if(a > args+1) { zwarnnam(nam, "last of many arguments must be a directory"); return 1; } if(!args[1]) { ptr = strrchr(args[0], '/'); if(ptr) args[1] = ptr+1; else args[1] = args[0]; } return domove(nam, movefn, args[0], args[1], flags); havedir: buf = ztrdup(*a); *a = NULL; buf = appstr(buf, "/"); blen = strlen(buf); for(; *args; args++) { ptr = strrchr(*args, '/'); if(ptr) ptr++; else ptr = *args; buf[blen] = 0; buf = appstr(buf, ptr); err |= domove(nam, movefn, *args, buf, flags); } zsfree(buf); return err; }