5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * CDDL HEADER START
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland *
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * The contents of this file are subject to the terms of the
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Common Development and Distribution License (the "License").
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * You may not use this file except in compliance with the License.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland *
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * or http://www.opensolaris.org/os/licensing.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * See the License for the specific language governing permissions
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * and limitations under the License.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland *
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * When distributing Covered Code, include this CDDL HEADER in each
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * If applicable, add the following below this CDDL HEADER, with the
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * fields enclosed by brackets "[]" replaced with your own identifying
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * information: Portions Copyright [yyyy] [name of copyright owner]
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland *
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * CDDL HEADER END
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Use is subject to license terms.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/* All Rights Reserved */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <stdio.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <ctype.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <dirent.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <limits.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <stdlib.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <unistd.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <string.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <sys/types.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <sys/stat.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <pkgstrct.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <errno.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <locale.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <libintl.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include <pkglib.h>
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include "libadm.h"
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#include "libinst.h"
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandextern int holdcinfo;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define WRN_SCARYLINK "WARNING: <%s>, target of symlink <%s>, does not exist."
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define ERR_PATHLONG "path argument too long"
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define ERR_CLASSLONG "classname argument too long"
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define ERR_CLASSCHAR "bad character in classname"
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define ERR_STAT "unable to stat <%s>"
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define ERR_WRITE "write of entry failed"
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define ERR_POPEN "unable to create pipe to <%s>"
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define ERR_PCLOSE "unable to close pipe to <%s>"
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define ERR_RDLINK "unable to read link for <%s>"
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define ERR_MEMORY "memory allocation failure, errno=%d"
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define LINK 1
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandstruct link {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland char *path;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland ino_t ino;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland dev_t dev;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland struct link *next;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland};
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandstatic struct link *firstlink = (struct link *)0;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandstatic struct link *lastlink = (struct link *)0;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandstatic char *scan_raw_ln(char *targ_name, char *link_name);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandstatic char *def_class = "none";
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandstatic int errflg = 0;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandstatic int iflag = 0; /* follow symlinks */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandstatic int xflag = 0; /* confirm contents of files */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandstatic int nflag = 0;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandstatic char construction[PATH_MAX], mylocal[PATH_MAX];
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandstatic void findlink(struct cfent *ept, char *path, char *svpath);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandstatic void follow(char *path);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandstatic void output(char *path, int n, char *local);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandstatic void usage(void);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandint
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandmain(int argc, char *argv[])
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland{
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int c;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland char *pt, path[PATH_MAX];
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland char *abi_sym_ptr;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland extern char *optarg;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland extern int optind;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) setlocale(LC_ALL, "");
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#define TEXT_DOMAIN "SYS_TEST"
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland#endif
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) textdomain(TEXT_DOMAIN);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) set_prog_name(argv[0]);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland while ((c = getopt(argc, argv, "xnic:?")) != EOF) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland switch (c) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland case 'x': /* include content info */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland xflag++;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland break;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland case 'n':
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland nflag++;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland break;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland case 'c': /* assign class */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland def_class = optarg;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* validate that classname is acceptable */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (strlen(def_class) > (size_t)CLSSIZ) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland progerr(gettext(ERR_CLASSLONG));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland exit(1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland for (pt = def_class; *pt; pt++) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (!isalpha(*pt) && !isdigit(*pt)) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland progerr(gettext(ERR_CLASSCHAR));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland exit(1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland break;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland case 'i': /* follow symlinks */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland iflag++;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland break;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland default:
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland usage();
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (iflag) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* follow symlinks */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland set_nonABI_symlinks();
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland } else {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* bug id 4244631, not ABI compliant */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland abi_sym_ptr = getenv("PKG_NONABI_SYMLINKS");
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (abi_sym_ptr && strncasecmp(abi_sym_ptr, "TRUE", 4) == 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland set_nonABI_symlinks();
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland holdcinfo = !xflag;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (optind == argc) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* take path list from stdin */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland while (fgets(path, sizeof (path), stdin) != (char *)NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland output(path, 0, NULL);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland } else {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland while (optind < argc) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland follow(argv[optind++]);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (errflg ? 1 : 0);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland}
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandstatic void
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandoutput(char *path, int n, char *local)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland{
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland char mypath[PATH_MAX];
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int len;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int s;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland struct cfent entry;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * remove any trailing newline characters from the end of path
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland len = strlen(path);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland while ((len > 0) && (path[len-1] == '\n')) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland path[--len] = '\0';
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland entry.volno = 0;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland entry.ftype = '?';
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland entry.path = mypath;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) strlcpy(entry.pkg_class, def_class, sizeof (entry.pkg_class));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) strlcpy(entry.path, path, PATH_MAX);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland entry.ainfo.local = NULL;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland entry.ainfo.mode = BADMODE;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) strlcpy(entry.ainfo.owner, BADOWNER, sizeof (entry.ainfo.owner));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) strlcpy(entry.ainfo.group, BADGROUP, sizeof (entry.ainfo.group));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland errflg = 0;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (xflag) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland entry.ftype = '?';
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (cverify(0, &entry.ftype, path, &entry.cinfo, 1)) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland errflg++;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland logerr(gettext("ERROR: %s"), path);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland logerr(getErrbufAddr());
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Use averify to figure out the attributes. This has trouble
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * divining the identity of a symlink which points to a
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * non-existant target. For that reason, if it comes back as
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * an existence problem, we fake in a symlink and see if averify
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * likes that. If it does, all we have is a risky symlink.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if ((s = averify(0, &entry.ftype, path, &entry.ainfo)) == VE_EXIST &&
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland !iflag) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland entry.ftype = 's'; /* try again assuming symlink */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* try to read what it points to */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if ((s = readlink(path, mylocal, PATH_MAX)) > 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland mylocal[s] = '\000'; /* terminate it */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland entry.ainfo.local = mylocal;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (averify(0, &entry.ftype, path, &entry.ainfo)) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland errflg++;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland } else
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* It's a link to a file not in this package. */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland ptext(stderr, gettext(WRN_SCARYLINK),
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland mylocal, path);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland } else {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland errflg++;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland } else if (s != 0 && s != VE_CONT)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland errflg++;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (errflg) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland logerr(gettext("ERROR: %s"), path);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland logerr(getErrbufAddr());
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (n) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* replace first n characters with 'local' */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (strchr("fev", entry.ftype)) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland entry.ainfo.local = mylocal;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) strlcpy(entry.ainfo.local, entry.path,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland PATH_MAX);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland canonize(entry.ainfo.local);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (local[0]) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland entry.ainfo.local = mylocal;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) strlcpy(entry.path, local, PATH_MAX);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) strcat(entry.path, path+n);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland } else
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) strlcpy(entry.path,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (path[n] == '/') ? path+n+1 : path+n,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland PATH_MAX);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland canonize(entry.path);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (entry.path[0]) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland findlink(&entry, path, entry.path);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (strchr("dcbp", entry.ftype) ||
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (nflag && !strchr("sl", entry.ftype)))
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland entry.ainfo.local = NULL;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (ppkgmap(&entry, stdout)) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland progerr(gettext(ERR_WRITE));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland exit(99);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland}
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandstatic void
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandfollow(char *path)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland{
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland struct stat stbuf;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland FILE *pp;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland char *pt,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland local[PATH_MAX],
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland newpath[PATH_MAX],
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland cmd[PATH_MAX+32];
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int n;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland errflg = 0;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (pt = strchr(path, '=')) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland *pt++ = '\0';
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland n = ((unsigned int)pt - (unsigned int)path - 1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (n >= PATH_MAX) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland progerr(gettext(ERR_PATHLONG));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland errflg++;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland n = strlen(pt);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (n < PATH_MAX) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) strlcpy(local, pt, sizeof (local));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland n = strlen(path);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland } else {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland progerr(gettext(ERR_PATHLONG));
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland errflg++;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland } else {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland n = 0;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland local[0] = '\0';
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (stat(path, &stbuf)) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland progerr(gettext(ERR_STAT), path);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland errflg++;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (stbuf.st_mode & S_IFDIR) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) snprintf(cmd, sizeof (cmd), "find %s -print", path);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if ((pp = popen(cmd, "r")) == NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland progerr(gettext(ERR_POPEN), cmd);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland exit(1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland while (fscanf(pp, "%[^\n]\n", newpath) == 1)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland output(newpath, n, local);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (pclose(pp)) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland progerr(gettext(ERR_PCLOSE), cmd);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland errflg++;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland } else
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland output(path, n, local);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland}
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland/*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Scan a raw link for origination errors. Given
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * targ_name = hlink/path/file1
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * and
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * link_name = hlink/path/file2
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * we don't want the link to be verbatim since link_name must be relative
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * to it's source. This functions checks for identical directory paths
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * and if it's clearly a misplaced relative path, the duplicate
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * directories are stripped. This is necessary because pkgadd is actually
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * in the source directory (hlink/path) when it creates the link.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland *
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * NOTE : The buffer we get with targ_name is going to be used later
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * and cannot be modified. That's why we have yet another PATH_MAX
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * size buffer in this function.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandstatic char *
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandscan_raw_ln(char *targ_name, char *link_name)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland{
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland char *const_ptr; /* what we return */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland char *file_name; /* name of the file in link_name */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland char *this_dir; /* current directory in targ_name */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland char *next_dir; /* next directory in targ_name */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland char *targ_ptr; /* current character in targ_name */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland const_ptr = targ_name; /* Point to here 'til we know it's different. */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * If the link is absolute or it is in the current directory, no
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * further testing necessary.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (RELATIVE(targ_name) &&
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (file_name = strrchr(link_name, '/')) != NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * This will be walked down to the highest directory
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * not common to both the link and the target.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland targ_ptr = targ_name;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * At this point targ_name is a relative path through at
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * least one directory.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland this_dir = targ_ptr; /* first directory in targ_name */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland file_name++; /* point to the name not the '/' */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Scan across the pathname until we reach a different
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * directory or the final file name.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland do {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland size_t str_size;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland next_dir = strchr(targ_ptr, '/');
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (next_dir)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland next_dir++; /* point to name not '/' */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland else /* point to the end of the string */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland next_dir = targ_ptr+strlen(targ_ptr);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* length to compare */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland str_size = ((ptrdiff_t)next_dir - (ptrdiff_t)this_dir);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * If both paths begin with the same directory, then
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * skip that common directory in both the link and
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * the target.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (strncmp(this_dir, link_name, str_size) == 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* point to the target so far */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland const_ptr = this_dir = next_dir;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* Skip past it in the target */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland targ_ptr = (char *)(targ_ptr+str_size);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* Skip past it in the link */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland link_name = (char *)(link_name+str_size);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * If these directories don't match then the
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * directory above is the lowest common directory. We
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * need to construct a relative path from the lowest
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * child up to that directory.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland } else {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int d = 0;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland char *dptr = link_name;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /* Count the intermediate directories. */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland while ((dptr = strchr(dptr, '/')) != NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland dptr++;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland d++;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * Now targ_ptr is pointing to the fork in
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * the path and dptr is pointing to the lowest
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * child in the link. We now insert the
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * appropriate number of "../'s" to get to
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * the first common directory. We'll
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * construct this in the construction
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland * buffer.
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (d) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland char *tptr;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland const_ptr = tptr = construction;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland while (d--) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) strlcpy(tptr,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland "../", PATH_MAX);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland tptr += 3;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) strlcpy(tptr, targ_ptr,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland PATH_MAX);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland break; /* done */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland } while (link_name != file_name); /* at file name */
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return (const_ptr);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland}
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandstatic void
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandfindlink(struct cfent *ept, char *path, char *svpath)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland{
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland struct stat statbuf;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland struct link *link, *new;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland char buf[PATH_MAX];
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland int n;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (lstat(path, &statbuf)) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland progerr(gettext(ERR_STAT), path);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland errflg++;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if ((statbuf.st_mode & S_IFMT) == S_IFLNK) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (!iflag) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland ept->ainfo.local = mylocal;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland ept->ftype = 's';
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland n = readlink(path, buf, PATH_MAX);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (n <= 0) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland progerr(gettext(ERR_RDLINK), path);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland errflg++;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) strlcpy(ept->ainfo.local,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland "unknown", PATH_MAX);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland } else {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) strncpy(ept->ainfo.local, buf, n);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland ept->ainfo.local[n] = '\0';
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (stat(path, &statbuf))
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (statbuf.st_nlink <= 1)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland for (link = firstlink; link; link = link->next) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if ((statbuf.st_ino == link->ino) &&
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (statbuf.st_dev == link->dev)) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland ept->ftype = 'l';
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland ept->ainfo.local = mylocal;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) strlcpy(ept->ainfo.local,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland scan_raw_ln(link->path, ept->path),
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland PATH_MAX);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland return;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if ((new = (struct link *)calloc(1, sizeof (struct link))) == NULL) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland progerr(gettext(ERR_MEMORY), errno);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland exit(1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland }
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland if (firstlink) {
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland lastlink->next = new;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland lastlink = new;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland } else
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland firstlink = lastlink = new;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland new->path = strdup(svpath);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland new->ino = statbuf.st_ino;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland new->dev = statbuf.st_dev;
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland}
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandstatic void
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterlandusage(void)
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland{
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland (void) fprintf(stderr,
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland gettext("usage: %s [-i] [-c class] [path ...]\n"), get_prog_name());
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland exit(1);
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland /*NOTREACHED*/
5c51f1241dbbdf2656d0e10011981411ed0c9673Moriah Waterland}