Subject: some changes to recent bin/ln/ln.c
To: None <tech-userlevel@netbsd.org>
From: enami tsugutomo <enami@sm.sony.co.jp>
List: tech-userlevel
Date: 09/07/2003 09:03:32
Attached diff includes some changes to bin/ln/ln.c. Especially,
- ln(1) in the tree may pass printescpaed() string to syscall, which
isn't user wanted to.
- It initializes stdout_ok after it may be used. As a result, even
the most usual case doesn't work as expected.
- It assumes that stdout == stderr.
I'm not sure if it is really necessary to output filenames in raw form
in the error message when stderr is not a terminal.
enami.
Index: ln.c
===================================================================
RCS file: /cvsroot/src/bin/ln/ln.c,v
retrieving revision 1.25
diff -c -r1.25 ln.c
*** ln.c 2003/08/21 04:30:25 1.25
--- ln.c 2003/09/06 23:30:39
***************
*** 57,68 ****
int fflag; /* Unlink existing files. */
int hflag; /* Check new name for symlink first. */
int sflag; /* Symbolic, not hard, link. */
! int vflag; /* Verbose output */
! int stdout_ok; /* stdout connected to a terminal */
/* System link call. */
! int (*linkf)(const char *, const char *);
! char linkch;
int linkit(char *, char *, int);
void usage(void);
--- 57,69 ----
int fflag; /* Unlink existing files. */
int hflag; /* Check new name for symlink first. */
int sflag; /* Symbolic, not hard, link. */
! int vflag; /* Verbose output */
! int stdout_isatty; /* stdout connected to a terminal */
! int stderr_isatty; /* stderr connected to a terminal */
/* System link call. */
! int (*linkf)(const char *, const char *);
! char linkch;
int linkit(char *, char *, int);
void usage(void);
***************
*** 89,97 ****
case 's':
sflag = 1;
break;
! case 'v':
! vflag = 1;
! break;
case '?':
default:
usage();
--- 90,98 ----
case 's':
sflag = 1;
break;
! case 'v':
! vflag = 1;
! break;
case '?':
default:
usage();
***************
*** 108,115 ****
linkf = link;
linkch = '=';
}
! switch(argc) {
case 0:
usage();
/* NOTREACHED */
--- 109,119 ----
linkf = link;
linkch = '=';
}
+
+ stdout_isatty = isatty(STDOUT_FILENO);
+ stderr_isatty = isatty(STDERR_FILENO);
! switch (argc) {
case 0:
usage();
/* NOTREACHED */
***************
*** 121,139 ****
/* NOTREACHED */
}
- stdout_ok = isatty(STDOUT_FILENO);
-
/* ln target1 target2 directory */
sourcedir = argv[argc - 1];
if (hflag && lstat(sourcedir, &sb) == 0 && S_ISLNK(sb.st_mode)) {
! /* we were asked not to follow symlinks, but found one at
! the target--simulate "not a directory" error */
errno = ENOTDIR;
! err(EXIT_FAILURE, "%s", printescaped(sourcedir));
/* NOTREACHED */
}
if (stat(sourcedir, &sb)) {
! err(EXIT_FAILURE, "%s", printescaped(sourcedir));
/* NOTREACHED */
}
if (!S_ISDIR(sb.st_mode)) {
--- 125,145 ----
/* NOTREACHED */
}
/* ln target1 target2 directory */
sourcedir = argv[argc - 1];
if (hflag && lstat(sourcedir, &sb) == 0 && S_ISLNK(sb.st_mode)) {
! /*
! * We were asked not to follow symlinks, but found one at
! * the target--simulate "not a directory" error
! */
errno = ENOTDIR;
! err(EXIT_FAILURE, "%s",
! stderr_isatty ? printescaped(sourcedir) : sourcedir);
/* NOTREACHED */
}
if (stat(sourcedir, &sb)) {
! err(EXIT_FAILURE, "%s",
! stderr_isatty ? printescaped(sourcedir) : sourcedir);
/* NOTREACHED */
}
if (!S_ISDIR(sb.st_mode)) {
***************
*** 152,185 ****
struct stat sb;
char *p, path[MAXPATHLEN];
char *sn, *tn;
!
! sn = printescaped(source);
! tn = printescaped(target);
if (!sflag) {
/* If target doesn't exist, quit now. */
if (stat(target, &sb)) {
warn("%s", tn);
! free(sn);
! free(tn);
! return (1);
}
}
! /* If the source is a directory (and not a symlink if hflag),
! append the target's name. */
if (isdir ||
! (!lstat(source, &sb) && S_ISDIR(sb.st_mode)) ||
! (!hflag && !stat(source, &sb) && S_ISDIR(sb.st_mode))) {
if ((p = strrchr(target, '/')) == NULL)
p = target;
else
++p;
! p = printescaped(p);
! (void)snprintf(path, sizeof(path), "%s/%s", sn, p);
! free(p);
source = path;
}
/*
* If the file exists, and -f was specified, unlink it.
--- 158,195 ----
struct stat sb;
char *p, path[MAXPATHLEN];
char *sn, *tn;
! int rv = 1;
+ if (stderr_isatty)
+ tn = printescaped(target);
+ else
+ tn = target;
if (!sflag) {
/* If target doesn't exist, quit now. */
if (stat(target, &sb)) {
warn("%s", tn);
! goto out1;
}
}
! /*
! * If the source is a directory (and not a symlink if hflag),
! * append the target's name.
! */
if (isdir ||
! ((hflag ? lstat : stat)(source, &sb) == 0 &&
! S_ISDIR(sb.st_mode))) {
if ((p = strrchr(target, '/')) == NULL)
p = target;
else
++p;
! (void)snprintf(path, sizeof(path), "%s/%s", source, p);
source = path;
}
+ if (stderr_isatty)
+ sn = printescaped(source);
+ else
+ sn = source;
/*
* If the file exists, and -f was specified, unlink it.
***************
*** 187,203 ****
*/
if ((fflag && unlink(source) < 0 && errno != ENOENT) ||
(*linkf)(target, source)) {
! warn("%s", source);
! free(sn);
! free(tn);
! return (1);
}
! if (vflag)
! (void)printf("%s %c> %s\n", sn, linkch, tn);
! free(sn);
! free(tn);
! return (0);
}
void
--- 197,224 ----
*/
if ((fflag && unlink(source) < 0 && errno != ENOENT) ||
(*linkf)(target, source)) {
! warn("%s", sn);
! goto out2;
! }
! if (vflag) {
! if (stdout_isatty) {
! if (!stderr_isatty) {
! tn = printescaped(target);
! sn = printescaped(source);
! }
! (void)printf("%s %c> %s\n", sn, linkch, tn);
! } else
! (void)printf("%s %c> %s\n", source, linkch, target);
}
! rv = 0;
! out2:
! if (sn != source)
! free(sn);
! out1:
! if (tn != target)
! free(tn);
! return (rv);
}
void
***************
*** 205,211 ****
{
(void)fprintf(stderr,
! "Usage:\t%s [-fhns] file1 file2\n\t%s [-fhnsv] file ... directory\n",
getprogname(), getprogname());
exit(1);
/* NOTREACHED */
--- 226,233 ----
{
(void)fprintf(stderr,
! "Usage:\t%s [-fhns] file1 file2\n"
! "\t%s [-fhnsv] file ... directory\n",
getprogname(), getprogname());
exit(1);
/* NOTREACHED */
***************
*** 218,236 ****
char *retval;
len = strlen(src);
! if (len != 0 && SIZE_T_MAX/len <= 4) {
! errx(EXIT_FAILURE, "%s: name too long", src);
/* NOTREACHED */
}
! retval = (char *)malloc(4*len+1);
! if (retval != NULL) {
! if (stdout_ok)
! (void)strvis(retval, src, VIS_NL | VIS_CSTYLE);
! else
! (void)strlcpy(retval, src, 4 * len + 1);
! return retval;
! } else
! errx(EXIT_FAILURE, "out of memory!");
/* NOTREACHED */
}
--- 240,256 ----
char *retval;
len = strlen(src);
! if (len >= SIZE_T_MAX / 4) {
! errx(EXIT_FAILURE, "%s: name too long: %d", src, len);
/* NOTREACHED */
}
! retval = (char *)malloc(4 * len + 1);
! if (retval == NULL) {
! err(EXIT_FAILURE, "malloc(%d)", 4 * len + 1);
/* NOTREACHED */
+ }
+
+ (void)strvis(retval, src, VIS_NL | VIS_CSTYLE);
+ return (retval);
}