Μεταφράστε

Translate to EnglishÜbersetzen Sie zum Deutsch/GermanΜεταφράστε στα ελληνικά/GreekПереведите к русскому/RussianOversetter til Norsk/NorwegianÖversätta till Svensk/Swedishहिन्दी अनुवाद करने के लिए/Hindi
Tradueix al català/CatalanTulkot uz latviešu/LatvianPreložiť do slovenčiny/SlovakVertaal aan het Nederlands/Dutchترجمة الى العربية/ArabicTraduzca al Español/SpanishTraduisez au Français/French
Traduca ad Italiano/ItalianTraduza ao Português/Portuguese日本語に翻訳しなさい /Japanese한국어에게 번역하십시오/Korean中文翻译/Chinese Simplified中文翻译/Chinese TraditionalПереклад на українську/Ukrainian
Εικόνα των εννοιών λειτουργικών συστημάτων
Εικόνα της αρχής Google Maps API 3
Εικόνα της ανάπτυξης πυρήνων Linux (3$η έκδοση)
Εικόνα XSLT 2.0 και XPath 2.0 αναφορά του προγραμματιστή (προγραμματιστής στον προγραμματιστή)

Το Programmatically ανακτά τις λεπτομέρειες συσκευασίας περιστροφής/λεπτό

Πρόσφατα, έπρεπε να ανακτήσω τις λεπτομέρειες για τα πακέτα λογισμικού που εγκαταστάθηκαν σε Fedora 15, τη Red Hat Enterprise Linux, CentOS και άλλες διανομές που διανέμουν τα πακέτα λογισμικού τους χρησιμοποιώντας το διευθυντή πακέτων περιστροφής/λεπτό. Στην έκπληξή μου, τι πρέπει να είναι ένας σχετικά απλός στόχος που αποδεικνύεται αρκετά ακατάστατος λόγω των αλλαγών στη βιβλιοθήκη APIs περιστροφής/λεπτό και του εσωτερικού σχήματος κατά τη διάρκεια των τελευταίων ετών. Σε αυτήν την θέση, καταδεικνύω πώς να ανακτήσω τις πληροφορίες για τις συσκευασίες περιστροφής/λεπτό χρησιμοποιώντας το Γ και Python.

Η περιστροφή/λεπτό είναι μια εντολή-γραμμή ή προσανατολισμένο προς ένα το API σύστημα διαχείρισης πακέτων ικανή, και Linux ή τον πακέτου λογισμικού της Unix. Κάθε πακέτο λογισμικού αποτελείται από ένα αρχείο των αρχείων μαζί με τις πληροφορίες για το πακέτο όπως ο αριθμός έκδοσής του, μια περίληψη και μια περιγραφή, και οι πληροφορίες εξάρτησης. Υπάρχει επίσης μια βιβλιοθήκη API για να επιτρέψει στους υπεύθυνους για την ανάπτυξη για να διαχειριστεί τέτοιες συναλλαγές από τις συνταγμένες γλώσσες προγραμματισμού όπως το Γ ή τις γλώσσες σεναριογραφιών τέτοιο Python. Τα αρχεία συσκευασίας γράφονται στο δίσκο στη διαταγή ψηφιολέξεων δικτύων. Εάν είναι απαραίτητο, η περιστροφή/λεπτό μετατρέπει αυτόματα τα στοιχεία στη διαταγή ψηφιολέξεων οικοδεσποτών όταν διαβάζεται το αρχείο συσκευασίας.

Η περιστροφή/λεπτό αναπτύχθηκε αρχικά το 1997 από το Erik Troan και Marc Ewing for χρήση στη διανομή του Red Hat Linux. Για πολλά έτη ήταν ένα πρόγραμμα opensource που δεν έλαβε πολλή αγάπη ή προσοχή. Εκείνη η εικόνα άλλαξε στις αρχές του 2007 όταν χωρίζουν δύο (και ανταγωνιστικός) τις Νοτιοαφρικανικές Κοινότητες Ανάπτυξης προωθήθηκαν.

Η πιό προεξέχουσα Νοτιοαφρικανική Κοινότητα Ανάπτυξης περιστροφής/λεπτό είναι το rpm.org που οδηγείται από το Red Hat. Σύμφωνα με τον ιστοχώρο τους:

Μετά από ένα μακροχρόνιο σπάσιμο ανάπτυξης το rpm.org ξανάρχισαν το 2007 με το στόχο για να πάρει τη θέση ως προς τα πάνω σπίτι της περιστροφής/λεπτό. Σαν πρώτο βήμα τα μπαλώματα που είχαν συσσωρεύσει επάνω στις διαφορετικές διανομές έχουν ενσωματωθεί στη βάση κώδικα όσο το δυνατόν περισσότερο. Θέλουμε την περιστροφή/λεπτό να μην είμαστε η επαρχία μιας επιχείρησης, ή ένα μικρό σύνολο υπεύθυνων για την ανάπτυξη. Πρέπει να αναπτυχθεί σε μια ανοικτή κοινότητα, να καταναλωθεί και να συμβληθεί από πολλούς επιχειρήσεις, χρήστες, διανομές, και υπεύθυνους για την ανάπτυξη. Επομένως καλωσορίζουμε οποιων δήποτε και όλους τους συνεισφέροντες.
….
Η περιστροφή/λεπτό θα μείνει οπίσθια - συμβατό σύστημα 4.4.2 για αρκετά έναν μακροπρόθεσμο. Είναι ουσιαστικό ότι οι συσκευασίες τρίτων μπορούν να εγκατασταθούν χωρίς την ανάγκη σε recompile αυτοί - ειδικά για τις επιχειρηματικές διανομές.

Μαΐου 2007 το Red Hat μίσθωσε Panu Matilainen για να λειτουργήσει στο πρόγραμμα περιστροφής/λεπτό. Η πρώτη σημαντική αναθεώρηση κώδικα ήταν Ιουλίου 2007 η έκδοση 4.8 κυκλοφόρησαν Ιανουαρίου 2010, και 4.9 Μαρτίου 2011. Αυτή η έκδοση χρησιμοποιείται από τις διανομές όπως Fedora, η Red Hat Enterprise Linux, openSUSE, η επιχείρηση SUSE Linux και CentOS.

Η άλλη Νοτιοαφρικανική Κοινότητα Ανάπτυξης περιστροφής/λεπτό είναι το rpm5.org που είναι μόλυβδος από Jeff Johnson που ήταν maintainer της περιστροφής/λεπτό ενώ ένας υπάλληλος του Red Hat. Η έκδοση περιστροφής/λεπτό 5.0 κυκλοφόρησε Μαΐου 2007. Η πιό πρόσφατη έκδοσή τους είναι της 5.3.11 χρονολογημένα 02-Jun-2011. Αυτή η έκδοση της περιστροφής/λεπτό χρησιμοποιείται από τις διανομές όπως η ενότητα Linux και τα cAos Linux, και επίσης από το πρόγραμμα OpenPKG που παρέχει τις συσκευασίες για κάποια άλλη Unix-όπως τις πλατφόρμες. Προφανώς Mandriva έχει μεταπηδήσει πρόσφατα σε το επίσης αν και φαίνεται να υπάρχει κάποια διαμάχη για εκείνη την ιδιαίτερη απόφαση.

Το σχήμα μιας συσκευασίας περιστροφής/λεπτό είναι δυαδικό και συνίσταται τριών τμημάτων στην ακόλουθη διαταγή:

  • Το τμήμα μολύβδου προσδιορίζει το αρχείο ως αρχείο περιστροφής/λεπτό. Περιέχει διάφορες ξεπερασμένες επιγραφές που στις προηγούμενες προηγούμενες εκδόσεις της περιστροφής/λεπτό χρησιμοποιήθηκαν για να αποθηκεύσουν τις πληροφορίες που χρησιμοποιήθηκαν εσωτερικά από την περιστροφή/λεπτό. Σήμερα, εντούτοις, ο μόνος σκοπός του τμήματος μολύβδου είναι να κατασταθεί εύκολο να προσδιορίσει ένα αρχείο συσκευασίας περιστροφής/λεπτό.
  • Το τμήμα υπογραφών περιέχει τις πληροφορίες που μπορούν να χρησιμοποιηθούν για να ελέγξουν την ακεραιότητα, και προαιρετικά, η αυθεντικότητα της πλειοψηφίας της συσκευασίας. Αυτό το τμήμα εφαρμόζεται χρησιμοποιώντας μια δομή επιγραφών (δείτε κατωτέρω).
  • Το τμήμα επιγραφών περιέχει τα μεταδεδομένα συσκευασίας όπως το όνομα, έκδοση, αρχιτεκτονική, κατάλογος αρχείων συμπεριλαμβανόμενων και suchlike. Επίσης εφαρμόζεται ως δομή επιγραφών.
  • Το τελικό τμήμα θορίου περιέχει το πραγματικό αρχείο αρχείων, το οποίο είναι συνήθως με το σχήμα cpio, που συμπιέζεται με το gzip αλλά οι πιό πρόσφατες εκδόσεις της περιστροφής/λεπτό μπορούν επίσης να χρησιμοποιήσουν bzip2, το lzma ή xz η συμπίεση και xar (αρχείο XML) υποστηρίζεται από την περιστροφή/λεπτό 5.0.

Εδώ είναι τι ο μόλυβδος περιέχει. Μην χρησιμοποιήστε τίποτα από το μόλυβδο εκτός από το σημαντικότερο τύπο αριθμού και υπογραφών.

struct rpmlead_s {
    unsigned char magic[4];
    unsigned char major;
    unsigned char minor;
    short type;
    short archnum;
    char name[66];
    short osnum;
    short signature_type;       /*!< Signature header type (RPMSIG_HEADERSIG) */
    char reserved[16];          /*!< Pad to 96 bytes -- 8 byte aligned! */
};


Η έννοια δομών επιγραφών είναι λύση της περιστροφής/λεπτό στο πρόβλημα εύκολα τις πληροφορίες με έναν τυποποιημένο τρόπο. Ο σκοπός μιας δομής επιγραφών είναι να περιληφθούν μηά ή περισσότερα κομμάτια των στοιχείων. Υπάρχουν τρία τμήματα σε κάθε δομή επιγραφών. Το πρώτο τμήμα είναι γνωστό ως επιγραφή δομών επιγραφών. Η επιγραφή δομών επιγραφών χρησιμοποιείται για να προσδιορίσει την έναρξη μιας δομής επιγραφών, του μεγέθους της, και του αριθμού στοιχείων στοιχείων που περιέχει. Μετά από τη δομή επιγραφών η επιγραφή είναι μια περιοχή αποκαλούμενη δείκτη.

Ο δείκτης της δομής επιγραφών αποτελείται από μηές ή περισσότερες καταχωρήσεις δεικτών. Κάθε είσοδος είναι δέκα έξι ψηφιολέξεις μακριές. Οι πρώτες τέσσερις ψηφιολέξεις περιέχουν μια ετικέττα - μια αριθμητική αξία που προσδιορίζει ποιος τύπος στοιχείων δείχνεται από την είσοδο. Υπάρχει ένας μεγάλος αριθμός ετικεττών επιγραφών που καθορίζεται σε rpmtag.h. Εδώ είναι μερικοί από τους:

typedef enum rpmTag_e {
    ....
    RPMTAG_NAME                 = 1000, /* s */
    RPMTAG_VERSION              = 1001, /* s */
    RPMTAG_RELEASE              = 1002, /* s */
    RPMTAG_EPOCH                = 1003, /* i */
    RPMTAG_SUMMARY              = 1004, /* s{} */
    RPMTAG_DESCRIPTION          = 1005, /* s{} */
    RPMTAG_BUILDTIME            = 1006, /* i */
    RPMTAG_BUILDHOST            = 1007, /* s */
    RPMTAG_INSTALLTIME          = 1008, /* i */
    RPMTAG_SIZE                 = 1009, /* i */
    RPMTAG_DISTRIBUTION         = 1010, /* s */
    RPMTAG_VENDOR               = 1011, /* s */
    .....
   /* tags 1997-4999 reserved */
    RPMTAG_FILENAMES            = 5000, /* s[] extension */
    RPMTAG_FILEPROVIDE          = 5001, /* s[] extension */
    RPMTAG_FILEREQUIRE          = 5002, /* s[] extension */
    RPMTAG_FSNAMES              = 5003, /* s[] (unimplemented) */
    RPMTAG_FSSIZES              = 5004, /* l[] (unimplemented) */
    RPMTAG_TRIGGERCONDS         = 5005, /* s[] extension */
    RPMTAG_TRIGGERTYPE          = 5006, /* s[] extension */
    RPMTAG_ORIGFILENAMES        = 5007, /* s[] extension */
    RPMTAG_LONGFILESIZES        = 5008, /* l[] */
    RPMTAG_LONGSIZE             = 5009, /* l */
} rpmTag;


Μετά από κάθε ετικέττα, είναι ένας τύπος τέσσερις-ψηφιολέξεων, ο οποίος είναι μια αριθμητική αξία που περιγράφει το σχήμα των στοιχείων που δείχνονται από την είσοδο. Εδώ είναι ο τρέχων κατάλογος τύπων που καθορίζονται σε rpmtag.h:

typedef enum rpmTagType_e {
    RPM_NULL_TYPE               =  0,
    RPM_CHAR_TYPE               =  1,
    RPM_INT8_TYPE               =  2,
    RPM_INT16_TYPE              =  3,
    RPM_INT32_TYPE              =  4,
    RPM_INT64_TYPE              =  5,
    RPM_STRING_TYPE             =  6,
    RPM_BIN_TYPE                =  7,
    RPM_STRING_ARRAY_TYPE       =  8,
    RPM_I18NSTRING_TYPE         =  9,
} rpmTagType;


Οι περισσότεροι από αυτούς τους τύπους πρέπει να είναι αυτεξήγητοι. Η διαφορά μεταξύ ενός τύπου ΣΕΙΡΑΣ και ενός τύπου STRING_ARRAY είναι ότι το πρώτο είναι μια κανονική κενή ολοκληρωμένη σειρά χαρακτήρων ενώ το τελευταίο είναι μια συλλογή των σειρών. RPM_I18NSTRING_TYPE υποτιμάται.

Έπειτα είναι μια αξία όφσετ 4 ψηφιολέξεων που περιέχει την πραγματική θέση των στοιχείων, σχετικά με την αρχή του καταστήματος. Τέλος, υπάρχει μια αρίθμηση τέσσερις-ψηφιολέξεων που περιέχει τον αριθμό στοιχείων στοιχείων που δείχνονται από την είσοδο δεικτών. Το στοιχείο ΣΕΙΡΑΣ έχει πάντα μια αρίθμηση 1, ενώ το στοιχείο STRING_ARRAY έχει μια αρίθμηση ίση με τον αριθμό σειρών που περιλαμβάνονται στο κατάστημα.

Αφότου έρχεται ο δείκτης το κατάστημα. Είναι στο κατάστημα ότι τα πραγματικά στοιχεία στοιχείων κρατιούνται. Το στοιχείο στο κατάστημα συσκευάζεται μαζί όσο το δυνατόν περισσότερο στη διαταγή ψηφιολέξεων δικτύων, δηλ. σημαντικότερη ψηφιολέξη πρώτα. Το στοιχείο ΣΕΙΡΑΣ ολοκληρώνεται με μια μηδενική ψηφιολέξη. Το στοιχείο ακέραιων αριθμών αποθηκεύεται στο φυσικό όριο για τον τύπο του, δηλ. ένας τριανταδυάμπιτος ακέραιος αριθμός αποθηκεύεται σε ένα όριο 4 ψηφιολέξεων.

Εντάξει, χρόνος να μιλήσει για το πώς να έχει πρόσβαση programmatically στις συσκευασίες περιστροφής/λεπτό. Εντούτοις προτού να αρχίσετε τη βιβλιοθήκη περιστροφής/λεπτό, πρέπει να υπολογίσετε ποια έκδοση της βιβλιοθήκης περιστροφής/λεπτό χρησιμοποιείτε. Εάν γράφετε ένα χειρόγραφο κοχυλιών, αυτό είναι εύκολο να καθεί. Παραδείγματος χάριν σε Fedora 15:

$ /usr/lib/rpm/rpmdeps --version
RPM version 4.9.0


Η βιβλιοθήκη περιστροφής/λεπτό από το rpm5.org έχει το rpmlibVersion API που μπορεί να χρησιμοποιηθεί για να ανακτήσει την έκδοση βιβλιοθηκών ή μπορείτε απλά να έχετε πρόσβαση στη σειρά RPMVERSION όπως παρουσιάζεται κατωτέρω.

#include <stdio.h>
#include <rpm/rpmlib.h>

int
main()
{
    fprintf(stderr, "RPM Version: %s\n", RPMVERSION);
}


Δυστυχώς η βιβλιοθήκη περιστροφής/λεπτό από το rpm.org δεν έχει τίποτα παρόμοιο. Σημείωση στους υπεύθυνους για την ανάπτυξη του rpm.org! Παρακαλώ προσθέτει rpmlibVersion API σας κατάλογος υποστηριγμένος δημόσιος APIs έτσι ώστε εφαρμογή που πρέπει να έχει πρόσβαση programmatically στις συσκευασίες περιστροφής/λεπτό και οι βάσεις δεδομένων μπορούν εύκολα να υπολογίσουν που αρωματίζουν και απελευθέρωση μιας βιβλιοθήκης περιστροφής/λεπτό που εξετάζουν και ρυθμίζουν τον κώδικά τους αναλόγως.

Σε Fedora 15, η σειρά έκδοσης που επιστρέφεται είναι 4.9.0 που δείχνει μια έκδοση της περιστροφής/λεπτό που κυκλοφόρησε Μαρτίου 2011. Σε CentOS 5.6, η σειρά έκδοσης που επιστρέφεται είναι το 4.4.2.3 που δείχνει μια σημαντικά παλαιότερη έκδοση της περιστροφής/λεπτό που απελευθερώνεται Απριλίου 2008. Υπάρχει σημαντικός και μεγαλύτερες διαφορές μεταξύ αυτών των εκδόσεων. In particular ο κώδικας Γ που γράφεται για μια από αυτές τις δύο ιδιαίτερες εκδόσεις περιστροφής/λεπτό πιθανώς δεν θα λειτουργήσει για την άλλη έκδοση χωρίς τροποποίηση.

Παίρνει χειρότερα, επ'ευκαιρία ως Fedora 15 και Red Hat Enterprise Linux 6 χρήση η νεώτερη βιβλιοθήκη περιστροφής/λεπτό που περιλαμβάνει επίσης ένα νέα σχήμα και hash SHA. Αυτό προκαλεί τα προβλήματα όταν προσπαθείτε να εγκαταστήσετε μια περιστροφή/λεπτό που στηρίζεται σε μια από αυτές τις πλατφόρμες σε μια παλαιότερη πλατφόρμα όπως CentOS 5.6 που δεν ξέρει για το νέα σχήμα και hash. Κατά συνέπεια, CentOS 5.6 θα παραπονεθεί ότι δεν μπορεί να επιβεβαιώσει την ακεραιότητα της συσκευασίας περιστροφής/λεπτό.

Πρέπει επίσης να είστε σε θέση να καθορίσετε ποια χαρακτηριστικά γνωρίσματα μια ιδιαίτερη έκδοση της περιστροφής/λεπτό υποστηρίζει. Εδώ είναι μονόδρομος να κάνει το:

#include <stdio.h>
#include <stdlib.h>

#include <rpm/rpmlib.h>
#include <rpm/rpmds.h>

int
main(int argc, char *argv[])
{
    const char *DNEVR;
    rpmds ds = NULL;
    int rc;

    rpmReadConfigFiles(NULL, NULL);

    rc = rpmdsRpmlib(&ds, NULL);
    ds = rpmdsInit(ds);

    fprintf(stdout, "Supported features:\n");
    while (rpmdsNext(ds) >= 0) {
        if ((DNEVR = rpmdsDNEVR(ds)) != NULL)
            fprintf(stdout, "%s\n", DNEVR + 2);
    }
    ds = rpmdsFree(ds);

    exit(0);
}


Πρέπει να εγκαταστήσετε τη συσκευασία ανάπτυξης περιστροφής/λεπτό (περιστροφή/λεπτό -περιστροφή/λεπτό-devel) προκειμένου να είστε σε θέση να συντάξετε τον ανωτέρω κώδικα.

Αυτός ο κώδικας τυπώνει απλά - έξω το υποστηριγμένο σύνολο χαρακτηριστικών γνωρισμάτων περιστροφής/λεπτό. Εδώ είναι τι είναι για τη βιβλιοθήκη περιστροφής/λεπτό σε Fedora 15:

Supported features:
rpmlib(BuiltinLuaScripts) = 4.2.2-1
rpmlib(CompressedFileNames) = 3.0.4-1
rpmlib(ConcurrentAccess) = 4.1-1
rpmlib(ExplicitPackageProvide) = 4.0-1
rpmlib(FileCaps) = 4.6.1-1
rpmlib(FileDigests) = 4.6.0-1
rpmlib(HeaderLoadSortsTags) = 4.0.1-1
rpmlib(PartialHardlinkSets) = 4.0.4-1
rpmlib(PayloadFilesHavePrefix) = 4.0-1
rpmlib(PayloadIsBzip2) = 3.0.5-1
rpmlib(PayloadIsLzma) = 4.4.2-1
rpmlib(PayloadIsXz) = 5.2-1
rpmlib(ScriptletExpansion) = 4.9.0-1
rpmlib(ScriptletInterpreterArgs) = 4.0.3-1
rpmlib(VersionedDependencies) = 3.0.3-1


Επ'ευκαιρία υπάρχει τεκμηρίωση σχεδίων για έναν οδηγό περιστροφής/λεπτό σχετικά με τον ιστοχώρο προγράμματος Fedora. Δεν ξέρω πότε αυτός ο οδηγός παρήχθη (πιθανώς 2003) αλλά η πιό πρόσφατη σημείωση πνευματικών δικαιωμάτων περιλαμβάνει το 2010. Δεν μπορώ να μιλήσω για το υπόλοιπο αυτού του οδηγού αλλά τα κεφάλαια σχετικά με τον προγραμματισμό της περιστροφής/λεπτό με το Γ και τον προγραμματισμό της περιστροφής/λεπτό με Python είναι ειλικρινά σκουπίδια και ειλικρινής παραπλάνηση.

Παραδείγματος χάριν, η απαρίθμηση 16-1 (rpm1.c), που παρουσιάζεται κατωτέρω, δεν θα συντάξει ακόμη και σε Fedora 15 ή ακόμα και σε Centos 5.6 που έχει μια πολύ παλαιότερη έκδοση της περιστροφής/λεπτό.

#include <stdio.h>
#include <stdlib.h>
#include <rpmlib.h>

int
main(int argc, char * argv[])
{
   int status = rpmReadConfigFiles( (const char*) NULL, (const char*) NULL);
   if (status != 0) {
      printf("Error reading RC files.\n");
      exit(-1);
   } else {
      printf("Read RC OK\n");
   }

   rpmSetVerbosity(RPMMESS_NORMAL);
   rpmShowRC( stdout );

   exit(0);
}


Η λίστα δεν είναι ακόμη και αρκετά σχηματοποιημένη στον οδηγό. Η ανωτέρω μορφοποίηση είναι όλο το ορυχείο. Το RPMMESS_* καθορίζει ήταν αφαιρούμενος τρόπος πίσω το 2007. Σαν παραλειπόμενα, πού η χρήση συμβάσεων βγήκε (- 1) προερχόμενος από; Αυτός φαίνεται περισσότερος όπως κάτι από τον κόσμο του Microsoft Windows! Οι οδηγίες σύνταξης είναι επίσης παράξενες.

$ cc -I/usr/include/rpm -o rpm1 rpm1.c -lrpm -lrpmdb -lrpmio –lpopt


Γιατί η ανάγκη στην αναφορά lrpmdb και libpopt; Καμία ρουτίνα από καθεμία αυτών των βιβλιοθηκών δεν χρησιμοποιείται στον ανωτέρω κώδικα.

Εδώ είναι το ανωτέρω παράδειγμα που ξαναγράφεται για να εργαστεί σε Fedora 15:

#include <stdio.h>
#include <stdlib.h>
#include <rpm/rpmlib.h>
#include <rpm/rpmlog.h>

int
main(int argc, char * argv[])
{
    int status;

    if ((status = rpmReadConfigFiles( (const char*) NULL, (const char*) NULL))) {
       printf("ERROR: reading RC files\n");
       exit(1);
    }

    rpmSetVerbosity(RPMLOG_NOTICE);
    rpmShowRC(stdout);

    exit(0);
}


Μπορείτε να συντάξετε τον ανωτέρω κώδικα χρησιμοποιώντας το GCC - ο rpm1 rpm1.c - lrpm - lrpmio.

Το ακόλουθο παράδειγμα ανοίγει το δρόμο ότι θα δείτε παραδοσιακά χρησιμοπομένος για να παραγάγετε έναν κατάλογο των εγκατεστημένων συσκευασιών περιστροφής/λεπτό σε ένα σύστημα εάν κάνετε μια αναζήτηση τέτοιου κώδικα στο διαδίκτυο.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>

#include <rpm/rpmlib.h>
#include <rpm/header.h>
#include <rpm/rpmdb.h>

int
main(int argc, char *argv[])
{
    rpmdbMatchIterator mi;
    int type, count;
    char *name;
    rpmdb db;
    Header h;

    rpmReadConfigFiles( NULL, NULL );
    if (rpmdbOpen( "", &db, O_RDONLY, 0644 ) != 0) {
        fprintf( stderr, "ERROR: Cannot open RPM database\n");
        exit(1);
    }

    mi = rpmdbInitIterator(db, RPMDBI_PACKAGES, NULL, 0);
    while ((h = rpmdbNextIterator(mi))) {
        headerGetEntry(h, RPMTAG_NAME, &type, (void **) &name, &count);
        printf("%s\n", name);
    }

    rpmdbFreeIterator(mi);
    rpmdbClose(db);

    exit(0);
}


Χρησιμοποιεί και rpmdbClose σε ανοικτό και κλείνει τη βάση δεδομένων περιστροφής/λεπτό, και ένα rpmdbMatchInterator για να επαναλάβει μέσω της περιστροφής/λεπτό τη βάση δεδομένων ψάχνοντας τις ταιριάζοντας με καταχωρήσεις για RPMTAG_NAME.

Αυτή η εργασία για CentOS 5.6 αλλά δεν υποστηρίζεται σε Fedora 15. Στην περιστροφή/λεπτό 4.9.0, σχεδόν όλες οι χαμηλού επιπέδου λειτουργίες χειρισμού rpmdb συμπεριλαμβανομένου, rpmdbClose και οι ρουτίνες rpmdbMatchInterator χρησιμοποιούμενες ανωτέρω αφαιρέθηκαν ή εσωτερικοποιήθηκαν. Δείτε τις σημειώσεις έκδοσης περιστροφής/λεπτό 4.9.0 για τα πλήρη στοιχεία.

Το ακόλουθο παράδειγμα λειτουργεί σε Fedora 15 και τα αποτελέσματα έναν κατάλογο του ονόματος (RPMTAG_NAME) και μεγέθους (RPMTAG_SIZE) κάθε εγκατεστημένης συσκευασίας.

#include <stdio.h>
#include <stdlib.h>

#include <rpm/rpmlib.h>
#include <rpm/header.h>
#include <rpm/rpmts.h>
#include <rpm/rpmdb.h>

int
main()
{
    rpmts ts = NULL;
    Header h;
    rpmdbMatchIterator mi;
    rpmtd td, tn;
    char time_buffer[512];
    int rc1, rc2;

    td = rpmtdNew();
    tn = rpmtdNew();
    ts = rpmtsCreate();

    rpmReadConfigFiles( NULL, NULL );

   mi = rpmtsInitIterator( ts, RPMDBI_PACKAGES, NULL, 0);
    while (NULL != (h = rpmdbNextIterator(mi))) {

        h = headerLink(h);
        rc1 = headerGet(h, RPMTAG_NAME, tn, HEADERGET_EXT);
        rc2 = headerGet(h, RPMTAG_SIZE, td, HEADERGET_EXT);

        // output installed package name and size
        fprintf(stdout, "%s (%llu)\n", rpmtdGetString(tn), rpmtdGetNumber(td));

        rpmtdReset(td);
        rpmtdReset(tn);
        headerFree(h);
    }

    rpmdbFreeIterator(mi);
    rpmtsFree(ts);

    exit(0);
}


Το ακόλουθο παράδειγμα επιδεικνύει πώς να εκτυπώσει περισσότερες πληροφορίες για των εγκατεστημένων συσκευασιών στο σύστημά σας.

#include <stdio.h>
#include <stdlib.h>

#include <rpm/rpmlib.h>
#include <rpm/header.h>
#include <rpm/rpmts.h>
#include <rpm/rpmdb.h>

int
main(int argc, char *argv[])
{
    rpmts ts = NULL;
    Header h;
    rpmdbMatchIterator mi;
    char *n, *v, *r, *g, *a;

    ts = rpmtsCreate();
    rpmReadConfigFiles( NULL, NULL );

    mi = rpmtsInitIterator( ts, RPMDBI_PACKAGES, NULL, 0);
    while (NULL != (h = rpmdbNextIterator(mi))) {
        h = headerLink( h );
        headerGetEntry( h, RPMTAG_NAME, NULL, (void**)&n, NULL);
        headerGetEntry( h, RPMTAG_VERSION, NULL, (void**)&v, NULL);
        headerGetEntry( h, RPMTAG_RELEASE, NULL, (void**)&r, NULL);
        headerGetEntry( h, RPMTAG_GROUP, NULL, (void**)&g, NULL);
        headerGetEntry( h, RPMTAG_ARCH, NULL, (void**)&a, NULL);

        fprintf(stdout, "%s-%s-%s.%s\n", n, v, r, a);

        headerFree(h);
    }
    rpmdbFreeIterator(mi);
    rpmtsFree(ts);

    exit(0);
}


Αυτό το παράδειγμα λειτουργεί και σε CentOS 5.6 και σε Fedora 15. Εδώ είναι κάποια παραγωγή δειγμάτων:

iso-codes-0.53-1.noarch
zlib-1.2.3-3.x86_64
libstdc++-4.1.2-50.el5.x86_64
db4-4.3.29-10.el5_5.2.x86_64
info-4.8-14.el5.x86_64
gawk-3.1.5-14.el5.x86_64
libgcrypt-1.4.4-5.el5.x86_64
libfontenc-1.0.2-2.2.el5.x86_64
libieee1284-0.2.9-4.el5.x86_64
grep-2.5.1-55.el5.x86_64
....


Επ'ευκαιρία η περιστροφή/λεπτό έχει την υποστήριξη Python, Perl και Lua. Εδώ είναι ο ισοδύναμος κώδικας που γράφεται σε Python:

#!/usr/bin/python

import rpm

ts=rpm.ts()

mi=ts.dbMatch()
for hdr in mi:
    print "%s-%s-%s.%s" % (hdr['name'], hdr['version'], hdr['release'], hdr['arch'])


Όπως μπορείτε να δει Python μπορεί πολύ να απλοποιήσει τα πράγματα όταν επιθυμείτε να εργαστείτε με τις συσκευασίες περιστροφής/λεπτό.

Το ακόλουθο παράδειγμα καταδεικνύει πώς να εκτυπώσει διάφορες ετικέττες με το σχήμα XML για κάθε εγκατεστημένη συσκευασία.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>

#include <rpm/rpmlib.h>
#include <rpm/header.h>
#include <rpm/rpmts.h>
#include <rpm/rpmdb.h>

struct tag {
   int  tagno;
   char *element;
};

truct tag tags[] = {
   { RPMTAG_NAME, "Name"},
   { RPMTAG_VERSION, "Version" },
   { RPMTAG_RELEASE, "Release" },
   { RPMTAG_SUMMARY, "Summary" },
   { RPMTAG_BUILDTIME, "BuildTime"},
   { RPMTAG_BUILDHOST, "BuildHost" },
   { RPMTAG_INSTALLTIME, "InstallTime" },
   { RPMTAG_SIZE, "Size" },
   { RPMTAG_LICENSE, "License"},
   { RPMTAG_URL, "SourceUrl" },
   { RPMTAG_PAYLOADFORMAT, "PayloadFormat" },
   { RPMTAG_PAYLOADCOMPRESSOR, "PayloadCompressor" }
};

#define NTAGS (sizeof(tags)/sizeof(struct tag))

int
main(int argc, char *argv[])
{
    rpmdbMatchIterator mi;
    rpmts ts = NULL;
    rpmtd td;
    Header h;
    int i;

    td = rpmtdNew();
    ts = rpmtsCreate();
    rpmReadConfigFiles(NULL, NULL);

    printf("<InstalledPackages>\n");
    mi = rpmtsInitIterator( ts, RPMDBI_PACKAGES, NULL, 0);
    while (NULL != (h = rpmdbNextIterator(mi))) {
        h = headerLink(h);
        printf("   <Package>\n");
        for ( i = 0; i < NTAGS; i++) {
            headerGet(h, (rpm_tag_t)tags[i].tagno, td, HEADERGET_ALLOC | HEADERGET_EXT);
            if (td->data) {
                switch(td->type) {
                    case RPM_NULL_TYPE:
                        break;
                    case RPM_CHAR_TYPE:
                        printf("      <%s>%s</%s>\n", tags[i].element, td->data, tags[i].element);
                        break;
                    case RPM_INT8_TYPE:
                    case RPM_INT16_TYPE:
                        printf("      <%s>%d</%s>\n", tags[i].element, td->data, tags[i].element);
                        break;
                    case RPM_INT32_TYPE:
                        if ((tags[i].tagno == RPMTAG_BUILDTIME) ||
                           (tags[i].tagno == RPMTAG_INSTALLTIME)) {
                             printf("      <%s>%s</%s>\n", tags[i].element, rpmtdFormat(td, RPMTD_FORMAT_DATE , NULL), tags[i].element);
                        } else if (tags[i].tagno == RPMTAG_SIZE) {
                             printf("      <%s>%" PRIu64 "<%s>\n", tags[i].element, rpmtdGetNumber(td), tags[i].element);
                        } else {
                             printf("      <%s>%u</%s>\n", tags[i].element, td->data, tags[i].element);
                        }
                        break;
                    case RPM_INT64_TYPE:
                        printf("      <%s>%" PRIu64 "</%s>\n", tags[i].element, rpmtdGetNumber(td), tags[i].element);
                        break;
                    case RPM_STRING_TYPE:
                        printf("      <%s>%s</%s>\n", tags[i].element, rpmtdGetString(td), tags[i].element);
                        break;
                    case RPM_BIN_TYPE:
                        printf("      <%s>%x</%s>\n", tags[i].element, td->data, tags[i].element);
                        break;
                    case RPM_STRING_ARRAY_TYPE:
                    default:
                        break;
                }
            }

            rpmtdReset(td);
        }
        headerFree(h);

        printf("   </Package>\n");
    }
    printf("</InstalledPackages>\n");

    rpmdbFreeIterator(mi);
    rpmtsFree(ts);

    exit(0);
}


Αυτή η εργασία για Fedora 15. Εδώ είναι η παραγωγή παραδείγματος:

<InstalledPackages>
   <Package>
      <Name>file-roller</Name>
      <Version>3.0.2</Version>
      <Release>1.fc15</Release>
      <Summary>Tool for viewing and creating archives</Summary>
      <BuildTime>Wed May 25 19:57:10 2011</BuildTime>
      <BuildHost>x86-06.phx2.fedoraproject.org</BuildHost>
      <InstallTime>Thu Jun  2 17:45:29 2011</InstallTime>
      <Size>5928015<Size>
      <License>GPLv2+</License>
      <SourceUrl>http://download.gnome.org/sources/file-roller/</SourceUrl>
      <PayloadFormat>cpio</PayloadFormat>
      <PayloadCompressor>xz</PayloadCompressor>
   </Package>
   <Package>
      <Name>expect</Name>
      <Version>5.45</Version>
      <Release>3.fc15</Release>
      <Summary>A program-script interaction and testing utility</Summary>
      <BuildTime>Wed Mar 16 09:58:49 2011</BuildTime>
      <BuildHost>x86-12.phx2.fedoraproject.org</BuildHost>
      <InstallTime>Mon Jun 13 10:24:25 2011</InstallTime>
      <Size>559676<Size>
      <License>Public Domain</License>
      <SourceUrl>http://expect.nist.gov/</SourceUrl>
      <PayloadFormat>cpio</PayloadFormat>
      <PayloadCompressor>xz</PayloadCompressor>
   </Package>
   .....
   <Package>
      <Name>libxkbfile-devel</Name>
      <Version>1.0.7</Version>
      <Release>2.fc15</Release>
      <Summary>X.Org X11 libxkbfile development package</Summary>
      <BuildTime>Tue Feb  8 08:03:57 2011</BuildTime>
      <BuildHost>x86-13.phx2.fedoraproject.org</BuildHost>
      <InstallTime>Thu Jun  2 17:56:48 2011</InstallTime>
      <Size>38055<Size>
      <License>MIT</License>
      <SourceUrl>http://www.x.org</SourceUrl>
      <PayloadFormat>cpio</PayloadFormat>
      <PayloadCompressor>xz</PayloadCompressor>
   </Package>
</InstalledPackages>


Σημειώστε ότι η έκδοση της περιστροφής/λεπτό σε CentOS 5.6 δεν υποστηρίζει RPM_INT64_TYPE. Κατά συνέπεια χρονολογεί και suchlike αποθηκεύεται σε ένα RPM_INT32_TYPE.

Να γυρίσει τώρα στο πώς να εξετάσει τις μεμονωμένες συσκευασίες περιστροφής/λεπτό. Το ακόλουθο απλό παράδειγμα σας παρουσιάζει πώς να ρωτήσει ένα αρχείο συσκευασίας:

#include <stdio.h>
#include <stdlib.h>

#include <rpm/rpmlib.h>
#include <rpm/header.h>
#include <rpm/rpmts.h>
#include <rpm/rpmdb.h>
#include <rpm/rpmlog.h>

int
main(int argc, char *argv[])
{
    int i;
    rpmts ts;

    FD_t fd;
    rpmRC rc;
    Header hdr;
    char *pkg_name, *pkg_version, *pkg_release;
    rpmVSFlags vsflags = 0;

    rc = rpmReadConfigFiles(NULL, NULL);
    if (rc != RPMRC_OK) {
        rpmlog(RPMLOG_NOTICE, "Unable to read RPM configuration.\n");
        exit(1);
    }

    fd = Fopen(argv[1], "r.ufdio");
    if ((!fd) || Ferror(fd)) {
       rpmlog(RPMLOG_NOTICE, "Failed to open package file (%s)\n", Fstrerror(fd));
       if (fd) {
           Fclose(fd);
       }
       exit(1);
    }

    ts = rpmtsCreate();

    vsflags |= _RPMVSF_NODIGESTS;
    vsflags |= _RPMVSF_NOSIGNATURES;
    vsflags |= RPMVSF_NOHDRCHK;
    (void) rpmtsSetVSFlags(ts, vsflags);

    rc = rpmReadPackageFile(ts, fd, argv[1], &hdr);
    if (rc != RPMRC_OK) {
       rpmlog(RPMLOG_NOTICE, "Could not read package file\n");
        Fclose(fd);
        exit(1);
     }
     Fclose(fd);

    if (headerNVR(hdr, (const char **) &pkg_name,
                       (const char **) &pkg_version,
                       (const char **) &pkg_release))
    {
         rpmlog(RPMLOG_NOTICE, "Header read failed\n");
    } else {
         printf("Package is: %s-%s-%s\n", pkg_name, pkg_version, pkg_release);
         headerFreeData(pkg_name, RPM_STRING_TYPE);
         headerFreeData(pkg_version, RPM_STRING_TYPE);
         headerFreeData(pkg_release, RPM_STRING_TYPE);
    }

    headerFree(hdr);
    rpmtsFree(ts);

    exit(0);
}


Μπορείτε να συντάξετε το ανωτέρω παράδειγμα χρησιμοποιώντας το GCC - παράδειγμα example.c ο - lrpm - lrpmio. Αυτό συντάσσει χωρίς τα λάθη ή τις προειδοποιήσεις σε CentOS 5.6 αλλά εκδίδει μια προειδοποίηση που headerNVR υποτιμιέται σε Fedora 15.

Υποθέστε θέλετε να ανακαλύψετε τον κατάλογο απαιτήσεων μια ιδιαίτερη εγκατεστημένη συσκευασία περιστροφής/λεπτό έχει. Μονόδρομη είναι να χρησιμοποιήσει την περιστροφή/λεπτό - qR . Ένας άλλος τρόπος είναι να χρησιμοποιήσει εύρημα-απαιτεί ή rpmdeps όπως παρουσιάζεται κατωτέρω:

$ rpm -ql rpm-devel | /usr/lib/rpm/find-requires
libacl.so.1()(64bit)
libbz2.so.1()(64bit)
libcap.so.2()(64bit)
libc.so.6()(64bit)
libc.so.6(GLIBC_2.14)(64bit)
libc.so.6(GLIBC_2.2.5)(64bit)
libc.so.6(GLIBC_2.3.4)(64bit)
libdb-4.8.so()(64bit)
libdl.so.2()(64bit)
libelf.so.1()(64bit)
liblua-5.1.so()(64bit)
liblzma.so.5()(64bit)
libm.so.6()(64bit)
libnss3.so()(64bit)
libpopt.so.0()(64bit)
libpthread.so.0()(64bit)
librpmio.so.2()(64bit)
librpm.so.2()(64bit)
librt.so.1()(64bit)
libselinux.so.1()(64bit)
libz.so.1()(64bit)

$ rpm -ql rpm-devel | /usr/lib/rpm/rpmdeps -R
/usr/bin/pkg-config
libacl.so.1()(64bit)
libbz2.so.1()(64bit)
libc.so.6()(64bit)
libc.so.6(GLIBC_2.14)(64bit)
libc.so.6(GLIBC_2.2.5)(64bit)
libc.so.6(GLIBC_2.3.4)(64bit)
libcap.so.2()(64bit)
libdb-4.8.so()(64bit)
libdl.so.2()(64bit)
libelf.so.1()(64bit)
liblua-5.1.so()(64bit)
liblzma.so.5()(64bit)
libm.so.6()(64bit)
libnss3.so()(64bit)
libpopt.so.0()(64bit)
libpopt.so.0(LIBPOPT_0)(64bit)
libpthread.so.0()(64bit)
librpm.so.2()(64bit)
librpmbuild.so.2()(64bit)
librpmio.so.2()(64bit)
librpmsign.so.0()(64bit)
librt.so.1()(64bit)
libselinux.so.1()(64bit)
libz.so.1()(64bit)
rtld(GNU_HASH)


Εδώ είναι ένα παράδειγμα του προγράμματος εναλλασσόμενου ρεύματος που θα εκτυπώσει τις ισοδύναμες πληροφορίες μαζί με τα εγκατεστημένα αρχεία, συγκρούσεις και obsoletes:

#include <stdio.h>
#include <stdlib.h>

#include <rpm/rpmlib.h>
#include <rpm/rpmds.h>
#include <rpm/rpmts.h>
#include <rpm/rpmdb.h>

int
main(int argc, char *argv[])
{
    const char *DNEVR;
    rpmdbMatchIterator mi;
    rpmds ds = NULL;
    Header h;
    rpmtd td_name, td_version, td_release, td_size, td_group, td_installtime;
    rpmts ts = NULL;
    rpmfi fi;

    if (argc != 2) {
        fprintf(stderr, "ERROR: No RPM specified on command line.\n");
        exit(1);
    }

    td_name = rpmtdNew();
    td_version = rpmtdNew();
    td_release = rpmtdNew();
    td_size = rpmtdNew();
    td_group = rpmtdNew();
    td_installtime = rpmtdNew();

   ts = rpmtsCreate();

    rpmReadConfigFiles(NULL, NULL);

    mi = rpmtsInitIterator(ts, RPMTAG_NAME, argv[1], 0);
    if (NULL != (h = rpmdbNextIterator(mi))) {
        h = headerLink(h);
        headerGet(h, RPMTAG_NAME, td_name, HEADERGET_EXT);
        headerGet(h, RPMTAG_VERSION, td_version, HEADERGET_EXT);
        headerGet(h, RPMTAG_RELEASE, td_release, HEADERGET_EXT);
        headerGet(h, RPMTAG_SIZE, td_size, HEADERGET_EXT);
        headerGet(h, RPMTAG_GROUP, td_group, HEADERGET_EXT);
        headerGet(h, RPMTAG_INSTALLTIME, td_installtime, HEADERGET_EXT);

        printf("%-20s: %s-%s-%s\n", "Package", rpmtdGetString(td_name), rpmtdGetString(td_version), rpmtdGetString(td_release));
        printf("%-20s: %s\n", "Group", rpmtdGetString(td_group));
        printf("%-20s: %llu\n", "Size", rpmtdGetNumber(td_size));
        printf("%-20s: %s\n", "Installed on", rpmtdFormat(td_installtime, RPMTD_FORMAT_DATE, NULL));

        fi = rpmfiNew(NULL, h, RPMTAG_BASENAMES, RPMFI_KEEPHEADER);
        if (fi) {
            fprintf(stdout, "\nFiles Provided:\n");
            while (rpmfiNext(fi) != -1)
                 fprintf(stdout, "  %s\n", rpmfiFN(fi));
            fi = rpmfiFree(fi);
        }

#if EXTRA
        ds = rpmdsNew(h, RPMTAG_PROVIDENAME, 0);
        if (ds) {
            fprintf(stdout, "\nProvides:\n");
            while (rpmdsNext(ds) >= 0) {
                 if ((DNEVR = rpmdsDNEVR(ds)) != NULL)
                    fprintf(stdout, "  %s\n", DNEVR + 1);
            }
            ds = rpmdsFree(ds);
        }
#endif

        ds = rpmdsNew(h, RPMTAG_REQUIRENAME, 0);
        if (ds) {
            fprintf(stdout, "\nRequires:\n");
            while (rpmdsNext(ds) >= 0) {
                 if ((DNEVR = rpmdsDNEVR(ds)) != NULL)
                    fprintf(stdout, "  %s\n", DNEVR + 1);
            }
            ds = rpmdsFree(ds);
        }

        ds = rpmdsNew(h, RPMTAG_OBSOLETENAME, 0);
        if (ds) {
            fprintf(stdout, "\nObsoletes:\n");
            while (rpmdsNext(ds) >= 0) {
                 if ((DNEVR = rpmdsDNEVR(ds)) != NULL)
                    fprintf(stdout, "  %s\n", DNEVR + 1);
            }
            ds = rpmdsFree(ds);
        }

        ds = rpmdsNew(h, RPMTAG_CONFLICTNAME, 0);
        if (ds) {
            fprintf(stdout, "\nConflicts:\n");
            while (rpmdsNext(ds) >= 0) {
                 if ((DNEVR = rpmdsDNEVR(ds)) != NULL)
                    fprintf(stdout, "  %s\n", DNEVR + 1);
            }
            ds = rpmdsFree(ds);
        }

        headerFree(h);
    }

    rpmdbFreeIterator(mi);
    rpmtsFree(ts);

    exit(0);
}


Αυτή η εργασία για Fedora 15 αλλά όχι για CentOS 5.6. Εντούτοις, είναι σχετικά εύκολο να τροποποιήσει για να το πάρει για να λειτουργήσει σε CentOS 5.6 και έτσι θα φύγω ότι ως άσκηση για σας. Οι κύριες αλλαγές αφορούν τη χρήση του τύπου rpmtd. Αυτοί πρέπει να αποβληθούν δεδομένου ότι η έκδοση της περιστροφής/λεπτό σε CentOS 5.6 δεν υποστηρίζει τον τύπο rpmtd.

Εδώ είναι τι είναι για τη συσκευασία xorg-x11-xkb-utils:

./rpminfo.py xorg-x11-xkb-utils
Package             : xorg-x11-xkb-utils-7.5-3.fc15
Group               : User Interface/X
Size                : 199629
Installed on        : Thu Jun  2 17:39:31 2011

Files Provided:
  /usr/bin/setxkbmap
  /usr/bin/xkbcomp
  /usr/share/man/man1/setxkbmap.1.gz
  /usr/share/man/man1/xkbcomp.1.gz

Requires:
   libX11.so.6()(64bit)
   libc.so.6()(64bit)
   libc.so.6(GLIBC_2.2.5)(64bit)
   libc.so.6(GLIBC_2.3)(64bit)
   libc.so.6(GLIBC_2.3.4)(64bit)
   libc.so.6(GLIBC_2.4)(64bit)
   libc.so.6(GLIBC_2.7)(64bit)
   libxkbfile.so.1()(64bit)
   rpmlib(CompressedFileNames) <= 3.0.4-1
   rpmlib(FileDigests) <= 4.6.0-1
   rpmlib(PayloadFilesHavePrefix) <= 4.0-1
   rtld(GNU_HASH)
   rpmlib(PayloadIsXz) <= 5.2-1

Obsoletes:
   XFree86
   xorg-x11


Εδώ είναι πώς να κάνει το ίδιο πράγμα που χρησιμοποιεί Python. Είναι αόριστα βασισμένο στο παράδειγμα που δίνεται στη λίστα 17-3 στο Fedora οδηγό προγράμματος περιστροφή/λεπτό που επ'ευκαιρία δεν λειτουργεί ούτε, υποψιάζομαι, ελειτούργησε πάντα! Η παραγωγή που παράγεται από αυτό το χειρόγραφο είναι κάπως περιεκτικότερη από αυτή της έκδοσης Γ ακόμα κι αν το χειρόγραφο έχει λιγότερες γραμμές κώδικα.

#!/usr/bin/python

import rpm, sys

def stringfromds(ds):
    retlist=[]
    for dataset in ds:
        t=dataset[0]
        values=t.split(" ")[1:]
        retlist.append(" ".join(values))
    return retlist

def printEntry(header, label, format, extra):
    value = header.sprintf(format).strip()
    print "%-20s: %s %s" % (label, value, extra)

def printHeader(h):
    if h[rpm.RPMTAG_SOURCEPACKAGE]:
        extra = " source package"
    else:
        extra = " binary package"

    printEntry(h, 'Package', "%{NAME}-%{VERSION}-%{RELEASE}", extra)
    printEntry(h, 'Group', "%{GROUP}", '')
    printEntry(h, 'Summary', "%{Summary}", '')
    printEntry(h, 'Arch-OS-Platform', "%{ARCH}-%{OS}-%{PLATFORM}", '')
    printEntry(h, 'Vendor', "%{Vendor}", '')
    printEntry(h, 'URL', "%{URL}", '')
    printEntry(h, 'Size', "%{Size}", '')
    printEntry(h, 'Installed on', "%{INSTALLTID:date}", '')
    print "%-20s: %s" % ("Description", h['Description'])

    print "\nFiles Provided:"
    for fi in h.fiFromHeader():
        print "  ", fi[0], "  ", fi[1], "  ", fi[12]

    ds = rpm.ds(h, 'requires')
    if ds:
        print "\nRequires:"
        for d in stringfromds(ds):
            print "  ", d

    ds = rpm.ds(h, 'obsoletes')
    if ds:
        print "\nObsoletes:"
        for d in stringfromds(ds):
            print "  ", d

    ds = rpm.ds(h, 'conflicts')
    if ds:
        print "\nConflicts:"
        for d in stringfromds(ds):
            print "  ", d

def main(argv):
    ts = rpm.TransactionSet()
    for h in ts.dbMatch( 'name', argv[1]):
        printHeader(h)

if __name__ == "__main__":
    if len(sys.argv) == 1:
        print "ERROR: No RPM specified on command line."
        sys.exit(1)
    else:
        main(sys.argv)


Εδώ είναι τι είναι για τη συσκευασία xorg-x11-xkb-utils:

$ ./rpminfo.py xorg-x11-xkb-utils
Package             : xorg-x11-xkb-utils-7.5-3.fc15  binary package
Group               : User Interface/X
Summary             : X.Org X11 xkb utilities
Arch-OS-Platform    : x86_64-linux-x86_64-redhat-linux-gnu
Vendor              : Fedora Project
URL                 : http://www.x.org
Size                : 199629
Installed on        : Thu Jun  2 17:38:11 2011
Description         : X.Org X11 xkb core utilities

Files Provided:
   /usr/bin/setxkbmap    19224    e5e5757d15ca331474c43a0319d0307920fb17b3ed9d04c041e13b56c4aa08e4
   /usr/bin/xkbcomp    176960    e6b265d05cd6432859d7a24fb8f6d6ccec3cbd668abd54afd9606322d3dd9a9e
   /usr/share/man/man1/setxkbmap.1.gz    1753    4a91c43a425699e4209880cf80a28eeae565763ece6cffaa8308a92139fd3250
   /usr/share/man/man1/xkbcomp.1.gz    1692    29d16f6c864bf62b7f3e3e0400e121def3f85e6d64676dffb6d92c54503a0c76

Requires:
   libX11.so.6()(64bit)
   libc.so.6()(64bit)
   libc.so.6(GLIBC_2.2.5)(64bit)
   libc.so.6(GLIBC_2.3)(64bit)
   libc.so.6(GLIBC_2.3.4)(64bit)
   libc.so.6(GLIBC_2.4)(64bit)
   libc.so.6(GLIBC_2.7)(64bit)
   libxkbfile.so.1()(64bit)
   rpmlib(CompressedFileNames) <= 3.0.4-1
   rpmlib(FileDigests) <= 4.6.0-1
   rpmlib(PayloadFilesHavePrefix) <= 4.0-1
   rtld(GNU_HASH)
   rpmlib(PayloadIsXz) <= 5.2-1

Obsoletes:
   XFree86
   xorg-x11


Άλλη μια φορά, μπορείτε να δείτε αυτό είστε πολύ ευκολότεροι να χρησιμοποιήσετε Python από το Γ κατά την εργασία με τα internals συσκευασίας περιστροφής/λεπτό.

Προτού να υπογράψω μακριά σε αυτήν την θέση, πρέπει να πω ότι ο κόσμος Linux δεν χρειάζεται δύο διαφορετικές Νοτιοαφρικανικές Κοινότητες Ανάπτυξης γύρω από την περιστροφή/λεπτό. Ναι, ο ανταγωνισμός μεταξύ των δύο Νοτιοαφρικανικών Κοινοτήτων Ανάπτυξης περιστροφής/λεπτό είχε το προβάδισμα σε μερικές βελτιώσεις στο διευθυντή συσκευασίας περιστροφής/λεπτό αλλά έχει επίσης το προβάδισμα καλά - γνωστό τεκμηριωμένο APIs όπως και rpmdbClose αφαιμένος στις πρόσφατες απελευθερώσεις. Αυτές οι δύο κοινότητες πρέπει να θάψουν το τσεκούρι και να συγχωνεύσουν τις προσπάθειές τους. Μερικές φορές να καρφώσει τα κοινοτικά προγράμματα με τη διχάλα είναι καλό και οδηγεί στην πραγματικά χρήσιμη καινοτομία. Σε αυτήν την περίπτωση είναι η άποψή μου ότι δεν είναι!

Πρέπει επίσης να πω ότι η τεκμηρίωση για τη χρησιμοποίηση της βιβλιοθήκης APIs περιστροφής/λεπτό είναι ειλικρινά άγρια και και οι δύο κοινότητες υπεύθυνων για την ανάπτυξη περιστροφής/λεπτό φαίνονται να μην κάνουν καμία σοβαρή προσπάθεια να ενημερώσουν τους χρήστες των βιβλιοθηκών τους για τις σημαντικές αλλαγές σε APIs εκτός από τις σκοτεινές αναφορές στις αλλαγές στις αντίστοιχες σημειώσεις έκδοσής τους. Αυτό πρέπει να διορθωθεί. Ένα βήμα στη σωστή κατεύθυνση θα ήταν να παρασχεθούν τα απλά παραδείγματα της χρήσης API όταν εισάγεται ένα νέο API ή ένα παλαιό API αφαιρούμενος.

Απολαύστε!

Αφήστε μια απάντηση