1/*	$NetBSD: pl.c,v 1.5 2021/04/10 19:49:59 nia Exp $	*/
2
3#ifdef HAVE_NBTOOL_CONFIG_H
4#include "nbtool_config.h"
5#else
6#if HAVE_CONFIG_H
7#include "config.h"
8#endif
9#include <nbcompat.h>
10#if HAVE_SYS_CDEFS_H
11#include <sys/cdefs.h>
12#endif
13#endif
14__RCSID("$NetBSD: pl.c,v 1.5 2021/04/10 19:49:59 nia Exp $");
15
16/*
17 * FreeBSD install - a package for the installation and maintainance
18 * of non-core utilities.
19 *
20 * Redistribution and use in source and binary forms, with or without
21 * modification, are permitted provided that the following conditions
22 * are met:
23 * 1. Redistributions of source code must retain the above copyright
24 *    notice, this list of conditions and the following disclaimer.
25 * 2. Redistributions in binary form must reproduce the above copyright
26 *    notice, this list of conditions and the following disclaimer in the
27 *    documentation and/or other materials provided with the distribution.
28 *
29 * Jordan K. Hubbard
30 * 18 July 1993
31 *
32 * Routines for dealing with the packing list.
33 *
34 */
35
36#include "lib.h"
37#include "create.h"
38#if HAVE_ERR_H
39#include <err.h>
40#endif
41#ifndef NETBSD
42#include <nbcompat/md5.h>
43#else
44#include <md5.h>
45#endif
46
47/*
48 * Check that any symbolic link is relative to the prefix
49 */
50static void
51CheckSymlink(char *name, char *prefix, size_t prefixcc)
52{
53	char    newtgt[MaxPathSize];
54	char    oldtgt[MaxPathSize];
55	char   *slash;
56	int     slashc;
57	int     cc;
58	int     i;
59
60	if ((cc = readlink(name, oldtgt, sizeof(oldtgt) - 1)) > 0) {
61		oldtgt[cc] = 0;
62		if (strncmp(oldtgt, prefix, prefixcc) == 0 && oldtgt[prefixcc] == '/') {
63			for (slashc = 0, slash = &name[prefixcc + 1]; (slash = strchr(slash, '/')) != (char *) NULL; slash++, slashc++) {
64			}
65			for (cc = i = 0; i < slashc; i++) {
66				strlcpy(&newtgt[cc], "../", sizeof(newtgt) - cc);
67				cc += 3;
68			}
69			strlcpy(&newtgt[cc], &oldtgt[prefixcc + 1], sizeof(newtgt) - cc);
70			(void) fprintf(stderr, "Full pathname symlink `%s' is target of `%s' - adjusting to `%s'\n", oldtgt, name, newtgt);
71			if (unlink(name) != 0) {
72				warn("can't unlink `%s'", name);
73			} else if (symlink(newtgt, name) != 0) {
74				warn("can't symlink `%s' called `%s'", newtgt, name);
75			}
76		}
77	}
78}
79
80/*
81 * Check a list for files that require preconversion
82 */
83void
84check_list(package_t *pkg, const char *PkgName)
85{
86	struct stat st;
87	plist_t *tmp;
88	plist_t *p;
89	char    buf[ChecksumHeaderLen + LegibleChecksumLen];
90	char    target[MaxPathSize + SymlinkHeaderLen];
91	char    name[MaxPathSize];
92	char   *cwd = NULL;
93	char   *pkgname = NULL;
94	int	cc;
95
96	for (p = pkg->head; p; p = p->next) {
97		switch (p->type) {
98		case PLIST_CWD:
99			cwd = p->name;
100			break;
101		case PLIST_NAME:
102			pkgname = p->name;
103			break;
104		case PLIST_IGNORE:
105			p = p->next;
106			break;
107		case PLIST_PKGDIR:
108			if (cwd == NULL)
109				errx(2, "@pkgdir without preceding @cwd found");
110			if (pkgname == NULL)
111				errx(2, "@pkgdir without preceding @name found");
112			break;
113		case PLIST_FILE:
114			if (cwd == NULL)
115				errx(2, "file without preceding @cwd found");
116			(void) snprintf(name, sizeof(name), "%s%s%s",
117				cwd,
118				(strcmp(cwd, "/") == 0) ? "" : "/",
119				p->name);
120			if (lstat(name, &st) < 0) {
121				warnx("can't stat `%s'", name);
122				continue;
123			}
124			switch (st.st_mode & S_IFMT) {
125			case S_IFDIR:
126				warnx("Warning - directory `%s' in PLIST", name);
127				break;
128			case S_IFLNK:
129				if (RelativeLinks) {
130					CheckSymlink(name, cwd, strlen(cwd));
131				}
132				(void) strlcpy(target, SYMLINK_HEADER,
133				    sizeof(target));
134				if ((cc = readlink(name, &target[SymlinkHeaderLen],
135					  sizeof(target) - SymlinkHeaderLen - 1)) < 0) {
136					warnx("can't readlink `%s'", name);
137					continue;
138				}
139				target[SymlinkHeaderLen + cc] = 0x0;
140				tmp = new_plist_entry();
141				tmp->name = xstrdup(target);
142				tmp->type = PLIST_COMMENT;
143				tmp->next = p->next;
144				tmp->prev = p;
145				if (p == pkg->tail) {
146					pkg->tail = tmp;
147				}
148				p->next = tmp;
149				p = tmp;
150				break;
151			case S_IFCHR:
152				warnx("Warning - char special device `%s' in PLIST", name);
153				break;
154			case S_IFBLK:
155				warnx("Warning - block special device `%s' in PLIST", name);
156				break;
157			default:
158				(void) strlcpy(buf, CHECKSUM_HEADER,
159				    sizeof(buf));
160				if (MD5File(name, &buf[ChecksumHeaderLen]) != (char *) NULL) {
161					tmp = new_plist_entry();
162					tmp->name = xstrdup(buf);
163					tmp->type = PLIST_COMMENT;	/* PLIST_MD5 - HF */
164					tmp->next = p->next;
165					tmp->prev = p;
166					if (p == pkg->tail) {
167						pkg->tail = tmp;
168					}
169					p->next = tmp;
170					p = tmp;
171				}
172				break;
173			}
174			break;
175		default:
176			break;
177		}
178	}
179}
180