hier mal ein kleines Tool um den apt cache (normalerweise /var/cache/apt/*) etwas aufzuräumen.
Es ist eine Kombination aus einem Python-Script und einem kleinen C-Programm zum Versionsvergleich.
Ich habe diese beiden Tools einfach mal kombiniert
Teil 1: Python Script apt-smartclean.py
Teil 2a: C-Programm rvc.c
Teil 2b: rvc.h
Teil 2c: Makefile
Installation:
Das C-Programm wird umgewandelt mit dem Aufruf make. Dadurch wird ein Programm rvc erstellt.
Wer seinen apt-cache in einem anderen Verzeichnis stehen hat als /var/apt/cache sollte in dem Python-Script den Pfad anpassen.
Beide Programmteile dann nach /usr/local/bin kopieren
cp rvc /usr/local/bin
cp apt-smartclean.py /usr/local/bin
Der Aufruf
zeigt an was obsolet im Cache rumsteht. Mit dem Aufruf
werden die obsoleten RPMs aus dem cache gelöscht.
Ich finde ein schönes Beispiel wie man zwei vorhandene Tools einfach kombiniert und schnell ein brauchbares Ergebnis erzielt.
Dieses Script hat für mich wunderbar funktioniert. Aber ich übernehme keine Haftung für die Anwendung und evtl Schäden an eurem System.
Es ist eine Kombination aus einem Python-Script und einem kleinen C-Programm zum Versionsvergleich.
Ich habe diese beiden Tools einfach mal kombiniert
Teil 1: Python Script apt-smartclean.py
Code:
#! /usr/bin/python
# GPL v2 code. Radim Kolar <hsn/at/cybermail.net>
# http://home.tiscali.cz/~cz210552/
# modified for rpm Distris by oc2pus
#
# APT-SMARTCLEAN
#
# This programs cleans APT package cache directory. Unlike apt-get autoclean,
# it leaves in cache directory only last version of package even if this
# package is no longer available for download. This is less aggressive
# cleaning than autoclean does.
#
# ARGUMENTS -s ... dry run
#
# Changelog
#
# VERSION 1 - 18 Aug 2003 First version
# VERSION 1.1 - 14 Dec 2004 modifications for rpm based distris
import os
import sys
def cleanaptcache(dryrun=0,dirs=('/var/cache/apt/archives/','/var/cache/apt/archives/partial/')):
for dir in dirs:
packages={} # versions
fnames={} # file names
for file in os.listdir(dir):
if file[-4:] != '.rpm': continue
parsed=file.split('_')
if len(parsed) != 3: continue
parsed[1]=parsed[1].replace('%3a',':')
if packages.has_key(parsed[0]):
print 'Found',parsed[0],parsed[1],'have',packages[parsed[0]]
# 1: a is newer than b
# 0: a and b are the same version
# -1: b is newer than a
# 2: wrong arguments number
argz=['rvc',parsed[1],packages[parsed[0]]]
rc=os.spawnvp(os.P_WAIT,'./rvc',argz)
if rc==0:
print "skipping",fnames[parsed[0]]
continue
if rc==255:
print "\tDeleting",dir+file
if not dryrun: os.unlink(dir+file)
continue
elif rc==1:
print "\tDeleting",dir+fnames[parsed[0]]
if not dryrun: os.unlink(dir+fnames[parsed[0]])
packages[parsed[0]]=parsed[1]
fnames[parsed[0]]=file
if __name__=="__main__":
sys.stdout.write("Running on SuSE\n")
sys.stdout.flush()
if len(sys.argv)>1 and sys.argv[1]=='-s':
dryrun=1
print "Dry run is enabled. Not deleting anything."
else:
dryrun=0
cleanaptcache(dryrun)
Teil 2a: C-Programm rvc.c
Code:
/*
* $Id: rvc.c,v 1.5 2002/10/27 18:27:23 luigi Exp $
******
* rvc.c - RPM Version Compare
* Given two strings representing a different version and release
* of a single rpm package, it returns which one is newer or,
* alternatively, an error.
*
* parameters
* two strings (a and b) structured in the following way:
* <RPM_version>-<RPM_release>.
*
* return values
* 1: a is newer than b
* 0: a and b are the same version
* -1: b is newer than a
* 2: wrong arguments number
*
* The assumption the two strings to compare are "logically coherent"
* is made, otherwise you will probably end up being told that b is
* newer than a (something which happens in this kind of situation)..
* The rpmvercmp function is "borrowed" from the Redhat package manager
* (RPM 4.1), as are all the inline functions in the header file
* (rpmvercmp.h).
*
******
*
* Copyright 2002 Luigi Bitonti
*
* Copyright 2002 Redhat Inc.
*
* This file is part of rvc (RPM version compare).
*
* rvc is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* rvc is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with rvc; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include "rvc.h"
int
main(int argc, char **argv)
{
/* We need exactly two arguments for the comparison */
if (argc != 3)
{
fprintf(stderr, "Usage: %s <RPM_versionA>-<RPM_releaseA> <RPM_versionB>-<RPM_releaseB>", argv[0]);
return 2;
}
return rpmvercmp(argv[1], argv[2]);
}
/* compare alpha and numeric segments of two versions */
/* return 1: a is newer than b */
/* 0: a and b are the same version */
/* -1: b is newer than a */
int
rpmvercmp(const char * a, const char * b)
{
char oldch1, oldch2;
char * str1, * str2;
char * one, * two;
int rc;
int isnum;
/* easy comparison to see if versions are identical */
if (!strcmp(a, b)) return 0;
str1 = alloca(strlen(a) + 1);
str2 = alloca(strlen(b) + 1);
strcpy(str1, a);
strcpy(str2, b);
one = str1;
two = str2;
/* loop through each version segment of str1 and str2 and compare them */
while (*one && *two)
{
while (*one && !xisalnum(*one)) one++;
while (*two && !xisalnum(*two)) two++;
str1 = one;
str2 = two;
/* grab first completely alpha or completely numeric segment */
/* leave one and two pointing to the start of the alpha or numeric */
/* segment and walk str1 and str2 to end of segment */
if (xisdigit(*str1))
{
while (*str1 && xisdigit(*str1)) str1++;
while (*str2 && xisdigit(*str2)) str2++;
isnum = 1;
} else {
while (*str1 && xisalpha(*str1)) str1++;
while (*str2 && xisalpha(*str2)) str2++;
isnum = 0;
}
/* save character at the end of the alpha or numeric segment */
/* so that they can be restored after the comparison */
oldch1 = *str1;
*str1 = '\0';
oldch2 = *str2;
*str2 = '\0';
/* take care of the case where the two version segments are */
/* different types: one numeric, the other alpha (i.e. empty) */
if (one == str1) return -1; /* arbitrary */
if (two == str2) return -1;
if (isnum)
{
/* this used to be done by converting the digit segments */
/* to ints using atoi() - it's changed because long */
/* digit segments can overflow an int - this should fix that. */
/* throw away any leading zeros - it's a number, right? */
while (*one == '0') one++;
while (*two == '0') two++;
/* whichever number has more digits wins */
if (strlen(one) > strlen(two)) return 1;
if (strlen(two) > strlen(one)) return -1;
}
/* strcmp will return which one is greater - even if the two */
/* segments are alpha or if they are numeric. don't return */
/* if they are equal because there might be more segments to */
/* compare */
rc = strcmp(one, two);
if (rc < 0)
return -1;
else if (rc > 0)
return 1;
/* restore character that was replaced by null above */
*str1 = oldch1;
one = str1;
*str2 = oldch2;
two = str2;
}
/* this catches the case where all numeric and alpha segments have */
/* compared identically but the segment sepparating characters were */
/* different */
if ((!*one) && (!*two)) return 0;
/* whichever version still has characters left over wins */
if (!*one) return -1; else return 1;
}
Teil 2b: rvc.h
Code:
/*
* $Id: rvc.h,v 1.4 2002/10/27 18:28:00 luigi Exp $
**
* rvc.h - include file for rvc.c
*
* Copyright 2002 Luigi Bitonti
*
* Copyright 2002 Redhat Inc.
*
* This file is part of rvc (RPM version compare).
*
* rvc is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* rvc is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with rvc; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
int rpmvercmp(const char *, const char *);
static inline int xislower(int c) {
return (c >= 'a' && c <= 'z');
}
static inline int xisupper(int c) {
return (c >= 'A' && c <= 'Z');
}
static inline int xisalpha(int c) {
return (xislower(c) || xisupper(c));
}
static inline int xisdigit(int c) {
return (c >= '0' && c <= '9');
}
static inline int xisalnum(int c) {
return (xisalpha(c) || xisdigit(c));
}
static inline int xisblank(int c) {
return (c == ' ' || c == '\t');
}
static inline int xisspace(int c) {
return (xisblank(c) || c == '\n' || c == '\r' || c == '\f' || c == '\v');
}
static inline int xtolower(int c) {
return ((xisupper(c)) ? (c | ('a' - 'A')) : c);
}
static inline int xtoupper(int c) {
return ((xislower(c)) ? (c & ~('a' - 'A')) : c);
}
Teil 2c: Makefile
Code:
# $Id: Makefile,v 1.2 2003/03/06 17:54:19 luigi Exp $
# Makefile for rvc (RPM version compare)
CC = gcc
CFLAGS = -Wall
all : rvc
rvc : rvc.c rvc.h
${CC} ${CFLAGS} -o $@ $<
Installation:
Das C-Programm wird umgewandelt mit dem Aufruf make. Dadurch wird ein Programm rvc erstellt.
Wer seinen apt-cache in einem anderen Verzeichnis stehen hat als /var/apt/cache sollte in dem Python-Script den Pfad anpassen.
Beide Programmteile dann nach /usr/local/bin kopieren
cp rvc /usr/local/bin
cp apt-smartclean.py /usr/local/bin
Der Aufruf
Code:
apt-smartclean.py -s
Code:
apt-smartclean.py
Ich finde ein schönes Beispiel wie man zwei vorhandene Tools einfach kombiniert und schnell ein brauchbares Ergebnis erzielt.
Dieses Script hat für mich wunderbar funktioniert. Aber ich übernehme keine Haftung für die Anwendung und evtl Schäden an eurem System.