Introduce pkg_updating(1) which scans for installed ports and shows
all ports/UPDATING entries that affect one of the installed ports, and are relevant on the given machine. PR: bin/117564 Submitted by: Beat Gaetzi <beat@chruetertee.ch> MFC after: 14 days
This commit is contained in:
parent
8003dd03de
commit
cc8b585463
@ -2,7 +2,7 @@
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
SUBDIR= lib add create delete info ${_sign} version
|
||||
SUBDIR= lib add create delete info ${_sign} updating version
|
||||
|
||||
.if ${MK_OPENSSL} != "no"
|
||||
_sign= sign
|
||||
|
11
usr.sbin/pkg_install/updating/Makefile
Normal file
11
usr.sbin/pkg_install/updating/Makefile
Normal file
@ -0,0 +1,11 @@
|
||||
# $FreeBSD$
|
||||
|
||||
PROG= pkg_updating
|
||||
SRCS= main.c
|
||||
|
||||
CFLAGS+= -I${.CURDIR}/../lib
|
||||
|
||||
WARNS?= 6
|
||||
WFORMAT?= 1
|
||||
|
||||
.include <bsd.prog.mk>
|
257
usr.sbin/pkg_install/updating/main.c
Normal file
257
usr.sbin/pkg_install/updating/main.c
Normal file
@ -0,0 +1,257 @@
|
||||
/*-
|
||||
* ----------------------------------------------------------------------------
|
||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||
* <beat@chruetertee.ch> wrote this file. As long as you retain this notice you
|
||||
* can do whatever you want with this stuff. If we meet some day, and you think
|
||||
* this stuff is worth it, you can buy me a beer in return. Beat Gätzi
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/param.h> /* For MAXPATHLEN */
|
||||
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sysexits.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "pathnames.h"
|
||||
|
||||
typedef struct installedport {
|
||||
struct installedport *next; /* List of installed ports. */
|
||||
char name[LINE_MAX]; /* Name of the installed port. */
|
||||
} INSTALLEDPORT;
|
||||
|
||||
int usage(void);
|
||||
|
||||
/*
|
||||
* Parse /usr/port/UPDATING for corresponding entries. If no argument is
|
||||
* passed to pkg_updating all entries for all installed ports are displayed.
|
||||
* If a list of portnames is passed to pkg_updating only entries for the
|
||||
* given portnames are displayed. Use the -d option to define that only newer
|
||||
* entries as this date are shown.
|
||||
*/
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
/* Keyword for searching portname in UPDATING. */
|
||||
const char *affects = "AFFECTS";
|
||||
/* Indicate a date -> end of a entry. Will fail on 2100-01-01... */
|
||||
const char *end = "20";
|
||||
/* Keyword for searching origin portname of installed port. */
|
||||
const char *origin = "@comment ORIGIN:";
|
||||
const char *pkgdbpath = LOG_DIR; /* Location of pkgdb */
|
||||
const char *updatingfile = UPDATING; /* Location of UPDATING */
|
||||
|
||||
char *date = NULL; /* Passed -d argument */
|
||||
char *dateline = NULL; /* Saved date of an entry */
|
||||
/* Tmp lines for parsing file */
|
||||
char *tmpline1 = NULL;
|
||||
char *tmpline2 = NULL;
|
||||
|
||||
char originline[LINE_MAX]; /* Line of +CONTENTS */
|
||||
/* Temporary variable to create path to +CONTENTS for installed ports. */
|
||||
char tmp_file[MAXPATHLEN];
|
||||
char updatingline[LINE_MAX]; /* Line of UPDATING */
|
||||
|
||||
int ch; /* Char used by getopt */
|
||||
int found = 0; /* Found an entry */
|
||||
int linelength; /* Length of parsed line */
|
||||
int maxcharperline = LINE_MAX; /* Max chars per line */
|
||||
int dflag = 0; /* -d option set */
|
||||
/* If pflag = 0 UPDATING will be checked for all installed ports. */
|
||||
int pflag = 0;
|
||||
|
||||
size_t n; /* Offset to create path */
|
||||
|
||||
struct dirent *pkgdbdir; /* pkgdb directory */
|
||||
struct stat attribute; /* attribute of pkgdb element */
|
||||
|
||||
/* Needed nodes for linked list with installed ports. */
|
||||
INSTALLEDPORT *head = (INSTALLEDPORT *) NULL;
|
||||
INSTALLEDPORT *curr = (INSTALLEDPORT *) NULL;
|
||||
|
||||
DIR *dir;
|
||||
FILE *fd;
|
||||
|
||||
while ((ch = getopt(argc, argv, "f:p:d:")) != -1) {
|
||||
switch (ch) {
|
||||
case 'd':
|
||||
dflag = 1;
|
||||
date = optarg;
|
||||
break;
|
||||
case 'f':
|
||||
updatingfile = optarg;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
/* Check if passed date has a correct format. */
|
||||
if (dflag == 1) {
|
||||
linelength = strlen(date);
|
||||
if (linelength != 8)
|
||||
exit(EX_DATAERR);
|
||||
if (strspn(date, "0123456789") != 8) {
|
||||
fprintf(stderr, "unknown date format: %s\n", date);
|
||||
exit(EX_DATAERR);
|
||||
}
|
||||
}
|
||||
|
||||
/* Save the list of passed portnames. */
|
||||
if (argc != 0) {
|
||||
pflag = 1;
|
||||
while (*argv) {
|
||||
if((curr = (INSTALLEDPORT *)
|
||||
malloc(sizeof(INSTALLEDPORT))) == NULL)
|
||||
(void)exit(EXIT_FAILURE);
|
||||
strlcpy (curr->name, *argv, strlen(*argv) + 1);
|
||||
curr->next = head;
|
||||
head = curr;
|
||||
(void)*argv++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* UPDATING will be parsed for all installed ports
|
||||
* if no portname is passed.
|
||||
*/
|
||||
if (pflag == 0) {
|
||||
/* Open /var/db/pkg and search for all installed ports. */
|
||||
if((dir = opendir(pkgdbpath)) != NULL) {
|
||||
while ((pkgdbdir = readdir(dir)) != NULL) {
|
||||
if (strcmp(pkgdbdir->d_name, ".") != 0 &&
|
||||
strcmp(pkgdbdir->d_name, "..") !=0) {
|
||||
|
||||
/* Create path to +CONTENTS file for each installed port */
|
||||
n = strlcpy(tmp_file, pkgdbpath, strlen(pkgdbpath)+1);
|
||||
n = strlcpy(tmp_file + n, "/", sizeof(tmp_file) - n);
|
||||
n = strlcat(tmp_file + n, pkgdbdir->d_name,
|
||||
sizeof(tmp_file) - n);
|
||||
if(stat(tmp_file, &attribute) == -1) {
|
||||
fprintf(stderr, "can't open %s: %s\n",
|
||||
tmp_file, strerror(errno));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if(attribute.st_mode & S_IFREG)
|
||||
continue;
|
||||
(void)strlcat(tmp_file + n, "/+CONTENTS",
|
||||
sizeof(tmp_file) - n);
|
||||
|
||||
/* Open +CONTENT file */
|
||||
fd = fopen(tmp_file, "r");
|
||||
if(fd == NULL) {
|
||||
fprintf(stderr, "warning: can't open %s: %s\n",
|
||||
tmp_file, strerror(errno));
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parses +CONTENT for ORIGIN line and
|
||||
* put element into linked list.
|
||||
*/
|
||||
while(fgets(originline, maxcharperline, fd) != NULL) {
|
||||
tmpline1 = strstr(originline, origin);
|
||||
if( tmpline1 != NULL ) {
|
||||
/* Tmp variable to store port name. */
|
||||
char *pname;
|
||||
pname = strrchr(originline, (int)':');
|
||||
pname++;
|
||||
if((curr = (INSTALLEDPORT *)
|
||||
malloc(sizeof(INSTALLEDPORT))) == NULL)
|
||||
(void)exit(EXIT_FAILURE);
|
||||
strlcpy (curr->name, pname, strlen(pname)+1);
|
||||
curr->next = head;
|
||||
head = curr;
|
||||
}
|
||||
}
|
||||
|
||||
if(ferror(fd)) {
|
||||
fprintf(stderr, "error reading input\n");
|
||||
exit(EX_IOERR);
|
||||
}
|
||||
|
||||
(void)fclose(fd);
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
}
|
||||
}
|
||||
|
||||
/* Open UPDATING file */
|
||||
fd = fopen(updatingfile, "r");
|
||||
if(fd == NULL) {
|
||||
fprintf(stderr, "can't open %s: %s\n",
|
||||
updatingfile, strerror(errno));
|
||||
exit(EX_UNAVAILABLE);
|
||||
}
|
||||
|
||||
/* Parse opened UPDATING file. */
|
||||
while(fgets(updatingline, maxcharperline, fd) != NULL) {
|
||||
/* No entry is found so far */
|
||||
if (found == 0) {
|
||||
/* Search for AFFECTS line to parse the portname. */
|
||||
tmpline1 = strstr(updatingline, affects);
|
||||
|
||||
if( tmpline1 != NULL ) {
|
||||
curr = head;
|
||||
while(curr != NULL) {
|
||||
tmpline2 = strstr(updatingline, curr->name);
|
||||
if( tmpline2 != NULL )
|
||||
break;
|
||||
curr = curr->next;
|
||||
}
|
||||
if( tmpline2 != NULL ) {
|
||||
/* If -d is set, check if entry is newer than the date. */
|
||||
if ( (dflag == 1) && (strncmp(dateline, date, 8) < 0))
|
||||
continue;
|
||||
printf("%s", dateline);
|
||||
printf("%s", updatingline);
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Search for the end of an entry, if not found print the line. */
|
||||
else {
|
||||
tmpline1 = strstr(updatingline, end);
|
||||
if( tmpline1 == NULL )
|
||||
printf("%s", updatingline);
|
||||
else {
|
||||
linelength = strlen(updatingline);
|
||||
if (linelength == 10)
|
||||
found = 0;
|
||||
else
|
||||
printf("%s", updatingline);
|
||||
}
|
||||
}
|
||||
/* Save the actual line, it could be a date. */
|
||||
dateline = strdup(updatingline);
|
||||
}
|
||||
|
||||
if(ferror(fd)) {
|
||||
fprintf(stderr, "error reading input\n");
|
||||
exit(EX_IOERR);
|
||||
}
|
||||
(void)fclose(fd);
|
||||
|
||||
exit(EX_OK);
|
||||
}
|
||||
|
||||
int
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"usage: pkg_updating [-d YYYYMMDD] [-f file] [portname ...]\n");
|
||||
exit(EX_USAGE);
|
||||
}
|
28
usr.sbin/pkg_install/updating/pathnames.h
Normal file
28
usr.sbin/pkg_install/updating/pathnames.h
Normal file
@ -0,0 +1,28 @@
|
||||
/*-
|
||||
* ----------------------------------------------------------------------------
|
||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||
* <beat@chruetertee.ch> wrote this file. As long as you retain this notice you
|
||||
* can do whatever you want with this stuff. If we meet some day, and you think
|
||||
* this stuff is worth it, you can buy me a beer in return. Beat Gätzi
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* $FreeBSD$
|
||||
*
|
||||
*/
|
||||
|
||||
/* Copy from ../version/version.h */
|
||||
|
||||
/* Where the ports lives by default */
|
||||
#define DEF_PORTS_DIR "/usr/ports/UPDATING"
|
||||
/* just in case we change the environment variable name */
|
||||
#define PORTSDIR "PORTSDIR"
|
||||
/* macro to get name of directory where we put logging information */
|
||||
#define UPDATING (getenv(PORTSDIR) ? strcat(getenv(PORTSDIR), \
|
||||
"/UPDATING") : DEF_PORTS_DIR)
|
||||
|
||||
/* Where we put logging information by default, else ${PKG_DBDIR} if set */
|
||||
#define DEF_LOG_DIR "/var/db/pkg"
|
||||
/* just in case we change the environment variable name */
|
||||
#define PKG_DBDIR "PKG_DBDIR"
|
||||
/* macro to get name of directory where we put logging information */
|
||||
#define LOG_DIR (getenv(PKG_DBDIR) ? getenv(PKG_DBDIR) : DEF_LOG_DIR)
|
88
usr.sbin/pkg_install/updating/pkg_updating.1
Normal file
88
usr.sbin/pkg_install/updating/pkg_updating.1
Normal file
@ -0,0 +1,88 @@
|
||||
.\"
|
||||
.\" FreeBSD updating - Scan the installed ports and show all UPDATING entries
|
||||
.\" that affect one of the installed ports. Alternative a list of portnames
|
||||
.\" could be passed to pkg_updating
|
||||
.\"
|
||||
.\" "THE BEER-WARE LICENSE" (Revision 42):
|
||||
.\" <beat@chruetertee.ch> wrote this file. As long as you retain this notice you
|
||||
.\" can do whatever you want with this stuff. If we meet some day, and you think
|
||||
.\" this stuff is worth it, you can buy me a beer in return. Beat Gätzi
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd November 2, 2007
|
||||
.Dt PKG_UPDATING 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm pkg_updating
|
||||
.Nd a utility for displaying UPDATING entries of software packages
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl d Ar date
|
||||
.Op Fl f Ar file
|
||||
.Op Ar pkg-name ...
|
||||
.Nm
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
command scans the installed ports and show all UPDATING entries that affect one
|
||||
of the installed ports. Alternative a list of pkg-names could be passed.
|
||||
.Sh OPTIONS
|
||||
The following command line options are supported:
|
||||
.Bl -tag -width indent
|
||||
.It Ar pkg-name ...
|
||||
UPDATING entries for the named packages are displayed.
|
||||
.It Fl d Ar date
|
||||
Only entries newer than this date are shown. Use a YYYYMMDD date format.
|
||||
.It Fl f Ar UPDATING file
|
||||
Defines a alternative location of the UPDATING file.
|
||||
.El
|
||||
.Sh EXAMPLES
|
||||
.Bl -tag -width indent
|
||||
.Dl pkg_updating
|
||||
.Pp
|
||||
Shows all entries of all installed ports.
|
||||
.Pp
|
||||
.Dl pkg_updating -d 20070101
|
||||
.Pp
|
||||
Shows all entries of all installed ports since 2007-01-01.
|
||||
.Pp
|
||||
.Dl pkg_updating apache mysql
|
||||
.Pp
|
||||
Shows all entries for all apache and mysql ports.
|
||||
.Pp
|
||||
.Dl pkg_updating -d 20060101 apache
|
||||
.Pp
|
||||
Shows all apache entries since 2006-01-01.
|
||||
.Pp
|
||||
.Dl pkg_updating -f /tmp/UPDATING
|
||||
.Pp
|
||||
Defines that the UPDATING file is in /tmp and shows all entries of all
|
||||
installed ports
|
||||
.Pp
|
||||
.El
|
||||
.Sh ENVIRONMENT
|
||||
.Bl -tag -width PKG_DBDIR
|
||||
.It Ev PKG_DBDIR
|
||||
Specifies an alternative location for the installed package database.
|
||||
.It Ev PORTSDIR
|
||||
Location of the ports tree.
|
||||
.El
|
||||
.Sh FILES
|
||||
.Bl -tag -width /var/db/pkg -compact
|
||||
.It Pa /var/db/pkg
|
||||
Default location of the installed package database.
|
||||
.It Pa /usr/ports
|
||||
The default ports directory and default location of the UPDATING file
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr pkg_add 1 ,
|
||||
.Xr pkg_create 1 ,
|
||||
.Xr pkg_delete 1 ,
|
||||
.Xr pkg_version 1
|
||||
.Sh AUTHORS
|
||||
.An Beat Gätzi Aq beat@chruetertee.ch
|
||||
.Sh CONTRIBUTORS
|
||||
.An Martin Tournoij Aq carpetsmoker@xs4all.nl
|
||||
.Sh BUGS
|
||||
Sure to be some.
|
Loading…
Reference in New Issue
Block a user