]> git.ipfire.org Git - people/teissler/ipfire-2.x.git/blame - src/patches/fireinfo-2.1.7-testing.patch
Squid: Enable support for zph-qos.
[people/teissler/ipfire-2.x.git] / src / patches / fireinfo-2.1.7-testing.patch
CommitLineData
a0010abd
MT
1diff --git a/.gitignore b/.gitignore
2index 0caee61..92aa5c5 100644
3--- a/.gitignore
4+++ b/.gitignore
5@@ -1,2 +1,31 @@
6-build
7+/Makefile
8+/build-aux
9+/libtool
10+/missing
11+/src/fireinfo/__init__.py
12 *.py[co]
13+/*.tar.bz2
14+/*.tar.gz
15+/*.tar.xz
16+*.log
17+*.a
18+*.cache
19+*.gmo
20+*.la
21+*.lo
22+*.o
23+*.stamp
24+*.trs
25+*~
26+.deps
27+.dirstamp
28+.libs
29+Makefile.in
30+aclocal.m4
31+config.h
32+config.h.in
33+config.log
34+config.status
35+configure
36+install-sh
37+stamp-*
38diff --git a/COPYING b/COPYING
39new file mode 100644
40index 0000000..94a9ed0
41--- /dev/null
42+++ b/COPYING
43@@ -0,0 +1,674 @@
44+ GNU GENERAL PUBLIC LICENSE
45+ Version 3, 29 June 2007
46+
47+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
48+ Everyone is permitted to copy and distribute verbatim copies
49+ of this license document, but changing it is not allowed.
50+
51+ Preamble
52+
53+ The GNU General Public License is a free, copyleft license for
54+software and other kinds of works.
55+
56+ The licenses for most software and other practical works are designed
57+to take away your freedom to share and change the works. By contrast,
58+the GNU General Public License is intended to guarantee your freedom to
59+share and change all versions of a program--to make sure it remains free
60+software for all its users. We, the Free Software Foundation, use the
61+GNU General Public License for most of our software; it applies also to
62+any other work released this way by its authors. You can apply it to
63+your programs, too.
64+
65+ When we speak of free software, we are referring to freedom, not
66+price. Our General Public Licenses are designed to make sure that you
67+have the freedom to distribute copies of free software (and charge for
68+them if you wish), that you receive source code or can get it if you
69+want it, that you can change the software or use pieces of it in new
70+free programs, and that you know you can do these things.
71+
72+ To protect your rights, we need to prevent others from denying you
73+these rights or asking you to surrender the rights. Therefore, you have
74+certain responsibilities if you distribute copies of the software, or if
75+you modify it: responsibilities to respect the freedom of others.
76+
77+ For example, if you distribute copies of such a program, whether
78+gratis or for a fee, you must pass on to the recipients the same
79+freedoms that you received. You must make sure that they, too, receive
80+or can get the source code. And you must show them these terms so they
81+know their rights.
82+
83+ Developers that use the GNU GPL protect your rights with two steps:
84+(1) assert copyright on the software, and (2) offer you this License
85+giving you legal permission to copy, distribute and/or modify it.
86+
87+ For the developers' and authors' protection, the GPL clearly explains
88+that there is no warranty for this free software. For both users' and
89+authors' sake, the GPL requires that modified versions be marked as
90+changed, so that their problems will not be attributed erroneously to
91+authors of previous versions.
92+
93+ Some devices are designed to deny users access to install or run
94+modified versions of the software inside them, although the manufacturer
95+can do so. This is fundamentally incompatible with the aim of
96+protecting users' freedom to change the software. The systematic
97+pattern of such abuse occurs in the area of products for individuals to
98+use, which is precisely where it is most unacceptable. Therefore, we
99+have designed this version of the GPL to prohibit the practice for those
100+products. If such problems arise substantially in other domains, we
101+stand ready to extend this provision to those domains in future versions
102+of the GPL, as needed to protect the freedom of users.
103+
104+ Finally, every program is threatened constantly by software patents.
105+States should not allow patents to restrict development and use of
106+software on general-purpose computers, but in those that do, we wish to
107+avoid the special danger that patents applied to a free program could
108+make it effectively proprietary. To prevent this, the GPL assures that
109+patents cannot be used to render the program non-free.
110+
111+ The precise terms and conditions for copying, distribution and
112+modification follow.
113+
114+ TERMS AND CONDITIONS
115+
116+ 0. Definitions.
117+
118+ "This License" refers to version 3 of the GNU General Public License.
119+
120+ "Copyright" also means copyright-like laws that apply to other kinds of
121+works, such as semiconductor masks.
122+
123+ "The Program" refers to any copyrightable work licensed under this
124+License. Each licensee is addressed as "you". "Licensees" and
125+"recipients" may be individuals or organizations.
126+
127+ To "modify" a work means to copy from or adapt all or part of the work
128+in a fashion requiring copyright permission, other than the making of an
129+exact copy. The resulting work is called a "modified version" of the
130+earlier work or a work "based on" the earlier work.
131+
132+ A "covered work" means either the unmodified Program or a work based
133+on the Program.
134+
135+ To "propagate" a work means to do anything with it that, without
136+permission, would make you directly or secondarily liable for
137+infringement under applicable copyright law, except executing it on a
138+computer or modifying a private copy. Propagation includes copying,
139+distribution (with or without modification), making available to the
140+public, and in some countries other activities as well.
141+
142+ To "convey" a work means any kind of propagation that enables other
143+parties to make or receive copies. Mere interaction with a user through
144+a computer network, with no transfer of a copy, is not conveying.
145+
146+ An interactive user interface displays "Appropriate Legal Notices"
147+to the extent that it includes a convenient and prominently visible
148+feature that (1) displays an appropriate copyright notice, and (2)
149+tells the user that there is no warranty for the work (except to the
150+extent that warranties are provided), that licensees may convey the
151+work under this License, and how to view a copy of this License. If
152+the interface presents a list of user commands or options, such as a
153+menu, a prominent item in the list meets this criterion.
154+
155+ 1. Source Code.
156+
157+ The "source code" for a work means the preferred form of the work
158+for making modifications to it. "Object code" means any non-source
159+form of a work.
160+
161+ A "Standard Interface" means an interface that either is an official
162+standard defined by a recognized standards body, or, in the case of
163+interfaces specified for a particular programming language, one that
164+is widely used among developers working in that language.
165+
166+ The "System Libraries" of an executable work include anything, other
167+than the work as a whole, that (a) is included in the normal form of
168+packaging a Major Component, but which is not part of that Major
169+Component, and (b) serves only to enable use of the work with that
170+Major Component, or to implement a Standard Interface for which an
171+implementation is available to the public in source code form. A
172+"Major Component", in this context, means a major essential component
173+(kernel, window system, and so on) of the specific operating system
174+(if any) on which the executable work runs, or a compiler used to
175+produce the work, or an object code interpreter used to run it.
176+
177+ The "Corresponding Source" for a work in object code form means all
178+the source code needed to generate, install, and (for an executable
179+work) run the object code and to modify the work, including scripts to
180+control those activities. However, it does not include the work's
181+System Libraries, or general-purpose tools or generally available free
182+programs which are used unmodified in performing those activities but
183+which are not part of the work. For example, Corresponding Source
184+includes interface definition files associated with source files for
185+the work, and the source code for shared libraries and dynamically
186+linked subprograms that the work is specifically designed to require,
187+such as by intimate data communication or control flow between those
188+subprograms and other parts of the work.
189+
190+ The Corresponding Source need not include anything that users
191+can regenerate automatically from other parts of the Corresponding
192+Source.
193+
194+ The Corresponding Source for a work in source code form is that
195+same work.
196+
197+ 2. Basic Permissions.
198+
199+ All rights granted under this License are granted for the term of
200+copyright on the Program, and are irrevocable provided the stated
201+conditions are met. This License explicitly affirms your unlimited
202+permission to run the unmodified Program. The output from running a
203+covered work is covered by this License only if the output, given its
204+content, constitutes a covered work. This License acknowledges your
205+rights of fair use or other equivalent, as provided by copyright law.
206+
207+ You may make, run and propagate covered works that you do not
208+convey, without conditions so long as your license otherwise remains
209+in force. You may convey covered works to others for the sole purpose
210+of having them make modifications exclusively for you, or provide you
211+with facilities for running those works, provided that you comply with
212+the terms of this License in conveying all material for which you do
213+not control copyright. Those thus making or running the covered works
214+for you must do so exclusively on your behalf, under your direction
215+and control, on terms that prohibit them from making any copies of
216+your copyrighted material outside their relationship with you.
217+
218+ Conveying under any other circumstances is permitted solely under
219+the conditions stated below. Sublicensing is not allowed; section 10
220+makes it unnecessary.
221+
222+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
223+
224+ No covered work shall be deemed part of an effective technological
225+measure under any applicable law fulfilling obligations under article
226+11 of the WIPO copyright treaty adopted on 20 December 1996, or
227+similar laws prohibiting or restricting circumvention of such
228+measures.
229+
230+ When you convey a covered work, you waive any legal power to forbid
231+circumvention of technological measures to the extent such circumvention
232+is effected by exercising rights under this License with respect to
233+the covered work, and you disclaim any intention to limit operation or
234+modification of the work as a means of enforcing, against the work's
235+users, your or third parties' legal rights to forbid circumvention of
236+technological measures.
237+
238+ 4. Conveying Verbatim Copies.
239+
240+ You may convey verbatim copies of the Program's source code as you
241+receive it, in any medium, provided that you conspicuously and
242+appropriately publish on each copy an appropriate copyright notice;
243+keep intact all notices stating that this License and any
244+non-permissive terms added in accord with section 7 apply to the code;
245+keep intact all notices of the absence of any warranty; and give all
246+recipients a copy of this License along with the Program.
247+
248+ You may charge any price or no price for each copy that you convey,
249+and you may offer support or warranty protection for a fee.
250+
251+ 5. Conveying Modified Source Versions.
252+
253+ You may convey a work based on the Program, or the modifications to
254+produce it from the Program, in the form of source code under the
255+terms of section 4, provided that you also meet all of these conditions:
256+
257+ a) The work must carry prominent notices stating that you modified
258+ it, and giving a relevant date.
259+
260+ b) The work must carry prominent notices stating that it is
261+ released under this License and any conditions added under section
262+ 7. This requirement modifies the requirement in section 4 to
263+ "keep intact all notices".
264+
265+ c) You must license the entire work, as a whole, under this
266+ License to anyone who comes into possession of a copy. This
267+ License will therefore apply, along with any applicable section 7
268+ additional terms, to the whole of the work, and all its parts,
269+ regardless of how they are packaged. This License gives no
270+ permission to license the work in any other way, but it does not
271+ invalidate such permission if you have separately received it.
272+
273+ d) If the work has interactive user interfaces, each must display
274+ Appropriate Legal Notices; however, if the Program has interactive
275+ interfaces that do not display Appropriate Legal Notices, your
276+ work need not make them do so.
277+
278+ A compilation of a covered work with other separate and independent
279+works, which are not by their nature extensions of the covered work,
280+and which are not combined with it such as to form a larger program,
281+in or on a volume of a storage or distribution medium, is called an
282+"aggregate" if the compilation and its resulting copyright are not
283+used to limit the access or legal rights of the compilation's users
284+beyond what the individual works permit. Inclusion of a covered work
285+in an aggregate does not cause this License to apply to the other
286+parts of the aggregate.
287+
288+ 6. Conveying Non-Source Forms.
289+
290+ You may convey a covered work in object code form under the terms
291+of sections 4 and 5, provided that you also convey the
292+machine-readable Corresponding Source under the terms of this License,
293+in one of these ways:
294+
295+ a) Convey the object code in, or embodied in, a physical product
296+ (including a physical distribution medium), accompanied by the
297+ Corresponding Source fixed on a durable physical medium
298+ customarily used for software interchange.
299+
300+ b) Convey the object code in, or embodied in, a physical product
301+ (including a physical distribution medium), accompanied by a
302+ written offer, valid for at least three years and valid for as
303+ long as you offer spare parts or customer support for that product
304+ model, to give anyone who possesses the object code either (1) a
305+ copy of the Corresponding Source for all the software in the
306+ product that is covered by this License, on a durable physical
307+ medium customarily used for software interchange, for a price no
308+ more than your reasonable cost of physically performing this
309+ conveying of source, or (2) access to copy the
310+ Corresponding Source from a network server at no charge.
311+
312+ c) Convey individual copies of the object code with a copy of the
313+ written offer to provide the Corresponding Source. This
314+ alternative is allowed only occasionally and noncommercially, and
315+ only if you received the object code with such an offer, in accord
316+ with subsection 6b.
317+
318+ d) Convey the object code by offering access from a designated
319+ place (gratis or for a charge), and offer equivalent access to the
320+ Corresponding Source in the same way through the same place at no
321+ further charge. You need not require recipients to copy the
322+ Corresponding Source along with the object code. If the place to
323+ copy the object code is a network server, the Corresponding Source
324+ may be on a different server (operated by you or a third party)
325+ that supports equivalent copying facilities, provided you maintain
326+ clear directions next to the object code saying where to find the
327+ Corresponding Source. Regardless of what server hosts the
328+ Corresponding Source, you remain obligated to ensure that it is
329+ available for as long as needed to satisfy these requirements.
330+
331+ e) Convey the object code using peer-to-peer transmission, provided
332+ you inform other peers where the object code and Corresponding
333+ Source of the work are being offered to the general public at no
334+ charge under subsection 6d.
335+
336+ A separable portion of the object code, whose source code is excluded
337+from the Corresponding Source as a System Library, need not be
338+included in conveying the object code work.
339+
340+ A "User Product" is either (1) a "consumer product", which means any
341+tangible personal property which is normally used for personal, family,
342+or household purposes, or (2) anything designed or sold for incorporation
343+into a dwelling. In determining whether a product is a consumer product,
344+doubtful cases shall be resolved in favor of coverage. For a particular
345+product received by a particular user, "normally used" refers to a
346+typical or common use of that class of product, regardless of the status
347+of the particular user or of the way in which the particular user
348+actually uses, or expects or is expected to use, the product. A product
349+is a consumer product regardless of whether the product has substantial
350+commercial, industrial or non-consumer uses, unless such uses represent
351+the only significant mode of use of the product.
352+
353+ "Installation Information" for a User Product means any methods,
354+procedures, authorization keys, or other information required to install
355+and execute modified versions of a covered work in that User Product from
356+a modified version of its Corresponding Source. The information must
357+suffice to ensure that the continued functioning of the modified object
358+code is in no case prevented or interfered with solely because
359+modification has been made.
360+
361+ If you convey an object code work under this section in, or with, or
362+specifically for use in, a User Product, and the conveying occurs as
363+part of a transaction in which the right of possession and use of the
364+User Product is transferred to the recipient in perpetuity or for a
365+fixed term (regardless of how the transaction is characterized), the
366+Corresponding Source conveyed under this section must be accompanied
367+by the Installation Information. But this requirement does not apply
368+if neither you nor any third party retains the ability to install
369+modified object code on the User Product (for example, the work has
370+been installed in ROM).
371+
372+ The requirement to provide Installation Information does not include a
373+requirement to continue to provide support service, warranty, or updates
374+for a work that has been modified or installed by the recipient, or for
375+the User Product in which it has been modified or installed. Access to a
376+network may be denied when the modification itself materially and
377+adversely affects the operation of the network or violates the rules and
378+protocols for communication across the network.
379+
380+ Corresponding Source conveyed, and Installation Information provided,
381+in accord with this section must be in a format that is publicly
382+documented (and with an implementation available to the public in
383+source code form), and must require no special password or key for
384+unpacking, reading or copying.
385+
386+ 7. Additional Terms.
387+
388+ "Additional permissions" are terms that supplement the terms of this
389+License by making exceptions from one or more of its conditions.
390+Additional permissions that are applicable to the entire Program shall
391+be treated as though they were included in this License, to the extent
392+that they are valid under applicable law. If additional permissions
393+apply only to part of the Program, that part may be used separately
394+under those permissions, but the entire Program remains governed by
395+this License without regard to the additional permissions.
396+
397+ When you convey a copy of a covered work, you may at your option
398+remove any additional permissions from that copy, or from any part of
399+it. (Additional permissions may be written to require their own
400+removal in certain cases when you modify the work.) You may place
401+additional permissions on material, added by you to a covered work,
402+for which you have or can give appropriate copyright permission.
403+
404+ Notwithstanding any other provision of this License, for material you
405+add to a covered work, you may (if authorized by the copyright holders of
406+that material) supplement the terms of this License with terms:
407+
408+ a) Disclaiming warranty or limiting liability differently from the
409+ terms of sections 15 and 16 of this License; or
410+
411+ b) Requiring preservation of specified reasonable legal notices or
412+ author attributions in that material or in the Appropriate Legal
413+ Notices displayed by works containing it; or
414+
415+ c) Prohibiting misrepresentation of the origin of that material, or
416+ requiring that modified versions of such material be marked in
417+ reasonable ways as different from the original version; or
418+
419+ d) Limiting the use for publicity purposes of names of licensors or
420+ authors of the material; or
421+
422+ e) Declining to grant rights under trademark law for use of some
423+ trade names, trademarks, or service marks; or
424+
425+ f) Requiring indemnification of licensors and authors of that
426+ material by anyone who conveys the material (or modified versions of
427+ it) with contractual assumptions of liability to the recipient, for
428+ any liability that these contractual assumptions directly impose on
429+ those licensors and authors.
430+
431+ All other non-permissive additional terms are considered "further
432+restrictions" within the meaning of section 10. If the Program as you
433+received it, or any part of it, contains a notice stating that it is
434+governed by this License along with a term that is a further
435+restriction, you may remove that term. If a license document contains
436+a further restriction but permits relicensing or conveying under this
437+License, you may add to a covered work material governed by the terms
438+of that license document, provided that the further restriction does
439+not survive such relicensing or conveying.
440+
441+ If you add terms to a covered work in accord with this section, you
442+must place, in the relevant source files, a statement of the
443+additional terms that apply to those files, or a notice indicating
444+where to find the applicable terms.
445+
446+ Additional terms, permissive or non-permissive, may be stated in the
447+form of a separately written license, or stated as exceptions;
448+the above requirements apply either way.
449+
450+ 8. Termination.
451+
452+ You may not propagate or modify a covered work except as expressly
453+provided under this License. Any attempt otherwise to propagate or
454+modify it is void, and will automatically terminate your rights under
455+this License (including any patent licenses granted under the third
456+paragraph of section 11).
457+
458+ However, if you cease all violation of this License, then your
459+license from a particular copyright holder is reinstated (a)
460+provisionally, unless and until the copyright holder explicitly and
461+finally terminates your license, and (b) permanently, if the copyright
462+holder fails to notify you of the violation by some reasonable means
463+prior to 60 days after the cessation.
464+
465+ Moreover, your license from a particular copyright holder is
466+reinstated permanently if the copyright holder notifies you of the
467+violation by some reasonable means, this is the first time you have
468+received notice of violation of this License (for any work) from that
469+copyright holder, and you cure the violation prior to 30 days after
470+your receipt of the notice.
471+
472+ Termination of your rights under this section does not terminate the
473+licenses of parties who have received copies or rights from you under
474+this License. If your rights have been terminated and not permanently
475+reinstated, you do not qualify to receive new licenses for the same
476+material under section 10.
477+
478+ 9. Acceptance Not Required for Having Copies.
479+
480+ You are not required to accept this License in order to receive or
481+run a copy of the Program. Ancillary propagation of a covered work
482+occurring solely as a consequence of using peer-to-peer transmission
483+to receive a copy likewise does not require acceptance. However,
484+nothing other than this License grants you permission to propagate or
485+modify any covered work. These actions infringe copyright if you do
486+not accept this License. Therefore, by modifying or propagating a
487+covered work, you indicate your acceptance of this License to do so.
488+
489+ 10. Automatic Licensing of Downstream Recipients.
490+
491+ Each time you convey a covered work, the recipient automatically
492+receives a license from the original licensors, to run, modify and
493+propagate that work, subject to this License. You are not responsible
494+for enforcing compliance by third parties with this License.
495+
496+ An "entity transaction" is a transaction transferring control of an
497+organization, or substantially all assets of one, or subdividing an
498+organization, or merging organizations. If propagation of a covered
499+work results from an entity transaction, each party to that
500+transaction who receives a copy of the work also receives whatever
501+licenses to the work the party's predecessor in interest had or could
502+give under the previous paragraph, plus a right to possession of the
503+Corresponding Source of the work from the predecessor in interest, if
504+the predecessor has it or can get it with reasonable efforts.
505+
506+ You may not impose any further restrictions on the exercise of the
507+rights granted or affirmed under this License. For example, you may
508+not impose a license fee, royalty, or other charge for exercise of
509+rights granted under this License, and you may not initiate litigation
510+(including a cross-claim or counterclaim in a lawsuit) alleging that
511+any patent claim is infringed by making, using, selling, offering for
512+sale, or importing the Program or any portion of it.
513+
514+ 11. Patents.
515+
516+ A "contributor" is a copyright holder who authorizes use under this
517+License of the Program or a work on which the Program is based. The
518+work thus licensed is called the contributor's "contributor version".
519+
520+ A contributor's "essential patent claims" are all patent claims
521+owned or controlled by the contributor, whether already acquired or
522+hereafter acquired, that would be infringed by some manner, permitted
523+by this License, of making, using, or selling its contributor version,
524+but do not include claims that would be infringed only as a
525+consequence of further modification of the contributor version. For
526+purposes of this definition, "control" includes the right to grant
527+patent sublicenses in a manner consistent with the requirements of
528+this License.
529+
530+ Each contributor grants you a non-exclusive, worldwide, royalty-free
531+patent license under the contributor's essential patent claims, to
532+make, use, sell, offer for sale, import and otherwise run, modify and
533+propagate the contents of its contributor version.
534+
535+ In the following three paragraphs, a "patent license" is any express
536+agreement or commitment, however denominated, not to enforce a patent
537+(such as an express permission to practice a patent or covenant not to
538+sue for patent infringement). To "grant" such a patent license to a
539+party means to make such an agreement or commitment not to enforce a
540+patent against the party.
541+
542+ If you convey a covered work, knowingly relying on a patent license,
543+and the Corresponding Source of the work is not available for anyone
544+to copy, free of charge and under the terms of this License, through a
545+publicly available network server or other readily accessible means,
546+then you must either (1) cause the Corresponding Source to be so
547+available, or (2) arrange to deprive yourself of the benefit of the
548+patent license for this particular work, or (3) arrange, in a manner
549+consistent with the requirements of this License, to extend the patent
550+license to downstream recipients. "Knowingly relying" means you have
551+actual knowledge that, but for the patent license, your conveying the
552+covered work in a country, or your recipient's use of the covered work
553+in a country, would infringe one or more identifiable patents in that
554+country that you have reason to believe are valid.
555+
556+ If, pursuant to or in connection with a single transaction or
557+arrangement, you convey, or propagate by procuring conveyance of, a
558+covered work, and grant a patent license to some of the parties
559+receiving the covered work authorizing them to use, propagate, modify
560+or convey a specific copy of the covered work, then the patent license
561+you grant is automatically extended to all recipients of the covered
562+work and works based on it.
563+
564+ A patent license is "discriminatory" if it does not include within
565+the scope of its coverage, prohibits the exercise of, or is
566+conditioned on the non-exercise of one or more of the rights that are
567+specifically granted under this License. You may not convey a covered
568+work if you are a party to an arrangement with a third party that is
569+in the business of distributing software, under which you make payment
570+to the third party based on the extent of your activity of conveying
571+the work, and under which the third party grants, to any of the
572+parties who would receive the covered work from you, a discriminatory
573+patent license (a) in connection with copies of the covered work
574+conveyed by you (or copies made from those copies), or (b) primarily
575+for and in connection with specific products or compilations that
576+contain the covered work, unless you entered into that arrangement,
577+or that patent license was granted, prior to 28 March 2007.
578+
579+ Nothing in this License shall be construed as excluding or limiting
580+any implied license or other defenses to infringement that may
581+otherwise be available to you under applicable patent law.
582+
583+ 12. No Surrender of Others' Freedom.
584+
585+ If conditions are imposed on you (whether by court order, agreement or
586+otherwise) that contradict the conditions of this License, they do not
587+excuse you from the conditions of this License. If you cannot convey a
588+covered work so as to satisfy simultaneously your obligations under this
589+License and any other pertinent obligations, then as a consequence you may
590+not convey it at all. For example, if you agree to terms that obligate you
591+to collect a royalty for further conveying from those to whom you convey
592+the Program, the only way you could satisfy both those terms and this
593+License would be to refrain entirely from conveying the Program.
594+
595+ 13. Use with the GNU Affero General Public License.
596+
597+ Notwithstanding any other provision of this License, you have
598+permission to link or combine any covered work with a work licensed
599+under version 3 of the GNU Affero General Public License into a single
600+combined work, and to convey the resulting work. The terms of this
601+License will continue to apply to the part which is the covered work,
602+but the special requirements of the GNU Affero General Public License,
603+section 13, concerning interaction through a network will apply to the
604+combination as such.
605+
606+ 14. Revised Versions of this License.
607+
608+ The Free Software Foundation may publish revised and/or new versions of
609+the GNU General Public License from time to time. Such new versions will
610+be similar in spirit to the present version, but may differ in detail to
611+address new problems or concerns.
612+
613+ Each version is given a distinguishing version number. If the
614+Program specifies that a certain numbered version of the GNU General
615+Public License "or any later version" applies to it, you have the
616+option of following the terms and conditions either of that numbered
617+version or of any later version published by the Free Software
618+Foundation. If the Program does not specify a version number of the
619+GNU General Public License, you may choose any version ever published
620+by the Free Software Foundation.
621+
622+ If the Program specifies that a proxy can decide which future
623+versions of the GNU General Public License can be used, that proxy's
624+public statement of acceptance of a version permanently authorizes you
625+to choose that version for the Program.
626+
627+ Later license versions may give you additional or different
628+permissions. However, no additional obligations are imposed on any
629+author or copyright holder as a result of your choosing to follow a
630+later version.
631+
632+ 15. Disclaimer of Warranty.
633+
634+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
635+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
636+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
637+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
638+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
639+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
640+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
641+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
642+
643+ 16. Limitation of Liability.
644+
645+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
646+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
647+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
648+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
649+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
650+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
651+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
652+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
653+SUCH DAMAGES.
654+
655+ 17. Interpretation of Sections 15 and 16.
656+
657+ If the disclaimer of warranty and limitation of liability provided
658+above cannot be given local legal effect according to their terms,
659+reviewing courts shall apply local law that most closely approximates
660+an absolute waiver of all civil liability in connection with the
661+Program, unless a warranty or assumption of liability accompanies a
662+copy of the Program in return for a fee.
663+
664+ END OF TERMS AND CONDITIONS
665+
666+ How to Apply These Terms to Your New Programs
667+
668+ If you develop a new program, and you want it to be of the greatest
669+possible use to the public, the best way to achieve this is to make it
670+free software which everyone can redistribute and change under these terms.
671+
672+ To do so, attach the following notices to the program. It is safest
673+to attach them to the start of each source file to most effectively
674+state the exclusion of warranty; and each file should have at least
675+the "copyright" line and a pointer to where the full notice is found.
676+
677+ <one line to give the program's name and a brief idea of what it does.>
678+ Copyright (C) <year> <name of author>
679+
680+ This program is free software: you can redistribute it and/or modify
681+ it under the terms of the GNU General Public License as published by
682+ the Free Software Foundation, either version 3 of the License, or
683+ (at your option) any later version.
684+
685+ This program is distributed in the hope that it will be useful,
686+ but WITHOUT ANY WARRANTY; without even the implied warranty of
687+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
688+ GNU General Public License for more details.
689+
690+ You should have received a copy of the GNU General Public License
691+ along with this program. If not, see <http://www.gnu.org/licenses/>.
692+
693+Also add information on how to contact you by electronic and paper mail.
694+
695+ If the program does terminal interaction, make it output a short
696+notice like this when it starts in an interactive mode:
697+
698+ <program> Copyright (C) <year> <name of author>
699+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
700+ This is free software, and you are welcome to redistribute it
701+ under certain conditions; type `show c' for details.
702+
703+The hypothetical commands `show w' and `show c' should show the appropriate
704+parts of the General Public License. Of course, your program's commands
705+might be different; for a GUI interface, you would use an "about box".
706+
707+ You should also get your employer (if you work as a programmer) or school,
708+if any, to sign a "copyright disclaimer" for the program, if necessary.
709+For more information on this, and how to apply and follow the GNU GPL, see
710+<http://www.gnu.org/licenses/>.
711+
712+ The GNU General Public License does not permit incorporating your program
713+into proprietary programs. If your program is a subroutine library, you
714+may consider it more useful to permit linking proprietary applications with
715+the library. If this is what you want to do, use the GNU Lesser General
716+Public License instead of this License. But first, please read
717+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
718diff --git a/MANIFEST b/MANIFEST
719deleted file mode 100644
720index 24ca115..0000000
721--- a/MANIFEST
722+++ /dev/null
723@@ -1,9 +0,0 @@
724-sendprofile
725-setup.py
726-fireinfo/__init__.py
727-fireinfo/cpu.py
728-fireinfo/device.py
729-fireinfo/hypervisor.py
730-fireinfo/network.py
731-fireinfo/system.py
732-src/fireinfo.c
733diff --git a/Makefile.am b/Makefile.am
734new file mode 100644
735index 0000000..260f14f
736--- /dev/null
737+++ b/Makefile.am
738@@ -0,0 +1,87 @@
739+###############################################################################
740+# #
741+# Pakfire - The IPFire package management system #
742+# Copyright (C) 2013 Pakfire development team #
743+# #
744+# This program is free software: you can redistribute it and/or modify #
745+# it under the terms of the GNU General Public License as published by #
746+# the Free Software Foundation, either version 3 of the License, or #
747+# (at your option) any later version. #
748+# #
749+# This program is distributed in the hope that it will be useful, #
750+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
751+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
752+# GNU General Public License for more details. #
753+# #
754+# You should have received a copy of the GNU General Public License #
755+# along with this program. If not, see <http://www.gnu.org/licenses/>. #
756+# #
757+###############################################################################
758+
759+ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
760+AM_MAKEFLAGS = --no-print-directory
761+AUTOMAKE_OPTIONS = color-tests
762+
763+# remove target it the command fails
764+.DELETE_ON_ERROR:
765+
766+# keep itermediate files
767+.SECONDARY:
768+
769+CLEANFILES =
770+DISTCLEANFILES =
771+EXTRA_DIST =
772+
773+AM_CPPFLAGS = \
774+ -include $(top_builddir)/config.h \
775+ -I $(top_srcdir)/include \
776+ $(OUR_CPPFLAGS)
777+
778+AM_CFLAGS = $(OUR_CFLAGS)
779+AM_LDFLAGS = $(OUR_LDFLAGS)
780+
781+pkgpyexec_LTLIBRARIES =
782+
783+# ------------------------------------------------------------------------------
784+
785+dist_doc_DATA = \
786+ COPYING
787+
788+# ------------------------------------------------------------------------------
789+
790+dist_bin_SCRIPTS = \
791+ src/sendprofile
792+
793+# ------------------------------------------------------------------------------
794+
795+fireinfo_PYTHON = \
796+ src/fireinfo/__init__.py \
797+ src/fireinfo/bios.py \
798+ src/fireinfo/cpu.py \
799+ src/fireinfo/device.py \
800+ src/fireinfo/hypervisor.py \
801+ src/fireinfo/network.py \
802+ src/fireinfo/system.py
803+
804+fireinfodir = $(pythondir)/fireinfo
805+
806+# ------------------------------------------------------------------------------
807+
808+pkgpyexec_LTLIBRARIES += \
809+ _fireinfo.la
810+
811+_fireinfo_la_SOURCES = \
812+ src/_fireinfo/fireinfo.c
813+
814+_fireinfo_la_CFLAGS = \
815+ $(AM_CFLAGS) \
816+ $(PYTHON_DEVEL_CFLAGS)
817+
818+_fireinfo_la_LDFLAGS = \
819+ $(AM_LDFLAGS) \
820+ -shared \
821+ -module \
822+ -avoid-version
823+
824+_fireinfo_la_LIBADD = \
825+ $(PYTHON_DEVEL_LIBS)
826diff --git a/autogen.sh b/autogen.sh
827new file mode 100755
828index 0000000..c08fadf
829--- /dev/null
830+++ b/autogen.sh
831@@ -0,0 +1,3 @@
832+#!/bin/sh
833+
834+autoreconf --force --install --symlink
835diff --git a/configure.ac b/configure.ac
836new file mode 100644
837index 0000000..4d5efef
838--- /dev/null
839+++ b/configure.ac
840@@ -0,0 +1,110 @@
841+###############################################################################
842+# #
843+# Pakfire - The IPFire package management system #
844+# Copyright (C) 2013 Pakfire development team #
845+# #
846+# This program is free software: you can redistribute it and/or modify #
847+# it under the terms of the GNU General Public License as published by #
848+# the Free Software Foundation, either version 3 of the License, or #
849+# (at your option) any later version. #
850+# #
851+# This program is distributed in the hope that it will be useful, #
852+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
853+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
854+# GNU General Public License for more details. #
855+# #
856+# You should have received a copy of the GNU General Public License #
857+# along with this program. If not, see <http://www.gnu.org/licenses/>. #
858+# #
859+###############################################################################
860+
861+AC_PREREQ([2.64])
862+
863+AC_INIT([fireinfo],
864+ [2.1.7],
865+ [info@ipfire.org],
866+ [fireinfo],
867+ [http://git.ipfire.org/?p=oddments/fireinfo.git;a=summary])
868+
869+AC_CONFIG_MACRO_DIR([m4])
870+AC_CONFIG_HEADERS([config.h])
871+AC_CONFIG_AUX_DIR([build-aux])
872+
873+AC_USE_SYSTEM_EXTENSIONS
874+AC_SYS_LARGEFILE
875+AC_PREFIX_DEFAULT([/usr])
876+
877+AM_INIT_AUTOMAKE([
878+ foreign
879+ 1.11
880+ -Wall
881+ -Wno-portability
882+ silent-rules
883+ tar-pax
884+ subdir-objects
885+])
886+AM_SILENT_RULES([yes])
887+LT_PREREQ(2.2)
888+LT_INIT([disable-static])
889+
890+# pkg-config
891+PKG_PROG_PKG_CONFIG
892+# This makes sure pkg.m4 is available.
893+m4_pattern_forbid([^_?PKG_[A-Z_]+$],[*** pkg.m4 missing, please install pkg-config])
894+
895+# C Compiler
896+AC_PROG_CC
897+AC_PROG_CC_C99
898+AC_PROG_CC_C_O
899+AC_PROG_GCC_TRADITIONAL
900+AC_OPENMP
901+
902+CC_CHECK_FLAGS_APPEND([with_cflags], [CFLAGS], [\
903+ -pipe \
904+ -Wall \
905+ -Wextra \
906+ -Wno-inline \
907+ -Wundef \
908+ "-Wformat=2 -Wformat-security -Wformat-nonliteral" \
909+ -Wno-unused-parameter \
910+ -Wno-unused-result \
911+ -fno-strict-aliasing \
912+ -ffunction-sections \
913+ -fdata-sections \
914+ -fstack-protector-all \
915+ --param=ssp-buffer-size=4])
916+AC_SUBST([OUR_CFLAGS], $with_cflags)
917+
918+AS_CASE([$CFLAGS], [*-O[[12345g\ ]]*],
919+ [CC_CHECK_FLAGS_APPEND([with_cppflags], [CPPFLAGS], [\
920+ -Wp,-D_FORTIFY_SOURCE=2])],
921+ [AC_MSG_RESULT([skipping -D_FORTIFY_SOURCE, optimization not enabled])])
922+AC_SUBST([OUR_CPPFLAGS], $with_cppflags)
923+
924+CC_CHECK_FLAGS_APPEND([with_ldflags], [LDFLAGS], [\
925+ -Wl,--as-needed \
926+ -Wl,--no-undefined \
927+ -Wl,--gc-sections \
928+ -Wl,-z,relro \
929+ -Wl,-z,now])
930+AC_SUBST([OUR_LDFLAGS], $with_ldflags)
931+
932+# Python
933+AM_PATH_PYTHON([2.7])
934+PKG_CHECK_MODULES([PYTHON_DEVEL], [python-${PYTHON_VERSION}])
935+
936+AC_CONFIG_FILES([
937+ Makefile
938+ src/fireinfo/__init__.py
939+])
940+
941+AC_OUTPUT
942+AC_MSG_RESULT([
943+ $PACKAGE_NAME $VERSION
944+
945+ CFLAGS: ${OUR_CFLAGS} ${CFLAGS}
946+ CPPFLAGS: ${OUR_CPPFLAGS} ${CPPFLAGS}
947+ LDFLAGS: ${OUR_LDFLAGS} ${LDFLAGS}
948+ PYTHON_CFLAGS: ${PYTHON_DEVEL_CFLAGS}
949+ PYTHON_LIBS: ${PYTHON_DEVEL_LIBS}
950+])
951diff --git a/fireinfo/__init__.py b/fireinfo/__init__.py
952deleted file mode 100644
953index 86fcc66..0000000
954--- a/fireinfo/__init__.py
955+++ /dev/null
956@@ -1,24 +0,0 @@
957-#!/usr/bin/python
958-###############################################################################
959-# #
960-# Fireinfo #
961-# Copyright (C) 2010, 2011 IPFire Team (www.ipfire.org) #
962-# #
963-# This program is free software: you can redistribute it and/or modify #
964-# it under the terms of the GNU General Public License as published by #
965-# the Free Software Foundation, either version 3 of the License, or #
966-# (at your option) any later version. #
967-# #
968-# This program is distributed in the hope that it will be useful, #
969-# but WITHOUT ANY WARRANTY; without even the implied warranty of #
970-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
971-# GNU General Public License for more details. #
972-# #
973-# You should have received a copy of the GNU General Public License #
974-# along with this program. If not, see <http://www.gnu.org/licenses/>. #
975-# #
976-###############################################################################
977-
978-__version__ = "2.1.7"
979-
980-from system import System
981diff --git a/fireinfo/cpu.py b/fireinfo/cpu.py
982deleted file mode 100644
983index 32d885d..0000000
984--- a/fireinfo/cpu.py
985+++ /dev/null
986@@ -1,194 +0,0 @@
987-#!/usr/bin/python
988-###############################################################################
989-# #
990-# Fireinfo #
991-# Copyright (C) 2010, 2011 IPFire Team (www.ipfire.org) #
992-# #
993-# This program is free software: you can redistribute it and/or modify #
994-# it under the terms of the GNU General Public License as published by #
995-# the Free Software Foundation, either version 3 of the License, or #
996-# (at your option) any later version. #
997-# #
998-# This program is distributed in the hope that it will be useful, #
999-# but WITHOUT ANY WARRANTY; without even the implied warranty of #
1000-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
1001-# GNU General Public License for more details. #
1002-# #
1003-# You should have received a copy of the GNU General Public License #
1004-# along with this program. If not, see <http://www.gnu.org/licenses/>. #
1005-# #
1006-###############################################################################
1007-
1008-import os
1009-
1010-import system
1011-
1012-PROC_CPUINFO = "/proc/cpuinfo"
1013-
1014-class CPU(object):
1015- """
1016- A class that represents the first CPU in a system.
1017-
1018- We get all information form the first CPU (or core) and assume that
1019- all other ones are equal.
1020- """
1021-
1022- __cpuinfo = {}
1023-
1024- def __init__(self):
1025- """
1026- Initialize this class by reading all data from /proc/cpuinfo.
1027- """
1028- self.__cpuinfo = self.read_cpuinfo()
1029-
1030- @property
1031- def system(self):
1032- return system.System()
1033-
1034- @staticmethod
1035- def read_cpuinfo():
1036- """
1037- Read information from PROC_CPUINFO and store
1038- it into a dictionary cpuinfo.
1039- """
1040- cpuinfo = {}
1041-
1042- f = open(PROC_CPUINFO)
1043- while True:
1044- line = f.readline()
1045-
1046- if not line:
1047- break
1048-
1049- try:
1050- key, val = line.split(":", 1)
1051- except ValueError:
1052- # We got a line without key, pass that.
1053- pass
1054-
1055- key = key.strip().replace(" ", "_")
1056- val = val.strip()
1057-
1058- cpuinfo[key] = val
1059-
1060- f.close()
1061-
1062- return cpuinfo
1063-
1064- @property
1065- def bogomips(self):
1066- """
1067- Return the bogomips of this CPU.
1068- """
1069- try:
1070- bogomips = self.__cpuinfo["bogomips"]
1071- except KeyError:
1072- bogomips = self.__cpuinfo["BogoMIPS"]
1073-
1074- return float(bogomips)
1075-
1076- @property
1077- def model(self):
1078- """
1079- Return the model id of this CPU.
1080- """
1081- try:
1082- model = int(self.__cpuinfo["model"])
1083- except KeyError:
1084- model = None
1085-
1086- return model
1087-
1088- @property
1089- def model_string(self):
1090- """
1091- Return the model string of this CPU.
1092- """
1093- try:
1094- return self.__cpuinfo["model_name"]
1095- except KeyError:
1096- return self.__cpuinfo["Processor"]
1097-
1098- @property
1099- def vendor(self):
1100- """
1101- Return the vendor string of this CPU.
1102- """
1103- try:
1104- vendor = self.__cpuinfo["vendor_id"]
1105- except KeyError:
1106- if self.system.arch.startswith("arm"):
1107- vendor = "ARM"
1108- else:
1109- vendor = ""
1110-
1111- return vendor
1112-
1113- @property
1114- def stepping(self):
1115- """
1116- Return the stepping id of this CPU.
1117- """
1118- try:
1119- stepping = int(self.__cpuinfo["stepping"])
1120- except KeyError:
1121- stepping = None
1122-
1123- return stepping
1124-
1125- @property
1126- def flags(self):
1127- """
1128- Return all flags of this CPU.
1129- """
1130- try:
1131- flags = self.__cpuinfo["flags"]
1132- except KeyError:
1133- flags = self.__cpuinfo["Features"]
1134-
1135- return flags.split()
1136-
1137- @property
1138- def speed(self):
1139- """
1140- Return the speed (in MHz) of this CPU.
1141- """
1142- try:
1143- speed = float(self.__cpuinfo["cpu_MHz"])
1144- except KeyError:
1145- speed = 0
1146-
1147- return speed
1148-
1149- @property
1150- def family(self):
1151- """
1152- Return the family id of this CPU.
1153- """
1154- try:
1155- family = int(self.__cpuinfo["cpu_family"])
1156- except KeyError:
1157- family = None
1158-
1159- return family
1160-
1161- @property
1162- def count(self):
1163- """
1164- Count number of CPUs (cores).
1165- """
1166- return os.sysconf("SC_NPROCESSORS_ONLN")
1167-
1168-
1169-if __name__ == "__main__":
1170- c = CPU()
1171-
1172- print "Vendor:", c.vendor
1173- print "Model:", c.model
1174- print "Stepping:", c.stepping
1175- print "Flags:", c.flags
1176- print "Bogomips:", c.bogomips
1177- print "Speed:", c.speed
1178- print "Family:", c.family
1179- print "Count:", c.count
1180- print "Model string:", c.model_string
1181diff --git a/fireinfo/device.py b/fireinfo/device.py
1182deleted file mode 100644
1183index 01338b2..0000000
1184--- a/fireinfo/device.py
1185+++ /dev/null
1186@@ -1,133 +0,0 @@
1187-#!/usr/bin/python
1188-###############################################################################
1189-# #
1190-# Fireinfo #
1191-# Copyright (C) 2010, 2011 IPFire Team (www.ipfire.org) #
1192-# #
1193-# This program is free software: you can redistribute it and/or modify #
1194-# it under the terms of the GNU General Public License as published by #
1195-# the Free Software Foundation, either version 3 of the License, or #
1196-# (at your option) any later version. #
1197-# #
1198-# This program is distributed in the hope that it will be useful, #
1199-# but WITHOUT ANY WARRANTY; without even the implied warranty of #
1200-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
1201-# GNU General Public License for more details. #
1202-# #
1203-# You should have received a copy of the GNU General Public License #
1204-# along with this program. If not, see <http://www.gnu.org/licenses/>. #
1205-# #
1206-###############################################################################
1207-
1208-import os.path
1209-
1210-class Device(object):
1211- """
1212- This is an abstract class that represents all devices in the system.
1213- Every single device has its own instance of this class.
1214- """
1215-
1216- def __init__(self, path):
1217- """
1218- Collect all information about the device by reading the
1219- "uevent" file and parsing it.
1220- """
1221-
1222- # Save the path in /sys to the device.
1223- self.path = path
1224-
1225- # Datastructure to store information we read.
1226- self._uevent = {}
1227-
1228- # Open the uevent file and parse all lines.
1229- with open(os.path.join(path, "uevent")) as f:
1230- for line in f.readlines():
1231- key, val = line.split("=")
1232- self._uevent[key] = val.rstrip().lower()
1233-
1234- @property
1235- def driver(self):
1236- """
1237- Get the driver/kernel module that device is driven by or return None.
1238- """
1239- return self._uevent.get("DRIVER", None)
1240-
1241-
1242-class PCIDevice(Device):
1243- """
1244- A class that represents all PCI (and PCIe) devices in a system.
1245- """
1246-
1247- subsystem = "pci"
1248-
1249- @property
1250- def model(self):
1251- """
1252- Return the PCI model id of this device.
1253- """
1254- return self._uevent['PCI_ID'].split(":")[1]
1255-
1256- @property
1257- def vendor(self):
1258- """
1259- Return the PCI vendor id of this device.
1260- """
1261- return self._uevent['PCI_ID'].split(":")[0]
1262-
1263- @property
1264- def deviceclass(self):
1265- """
1266- Return the PCI device class of this device.
1267- """
1268- return self._uevent['PCI_CLASS']
1269-
1270- @property
1271- def sub_vendor(self):
1272- """
1273- Return the PCI vendor sub id of this device.
1274- """
1275- return self._uevent["PCI_SUBSYS_ID"].split(":")[0]
1276-
1277- @property
1278- def sub_model(self):
1279- """
1280- Return the PCI model sub id of this device.
1281- """
1282- return self._uevent["PCI_SUBSYS_ID"].split(":")[1]
1283-
1284-
1285-class USBDevice(Device):
1286- """
1287- A class that represents all USB devices in a system.
1288- """
1289-
1290- subsystem = "usb"
1291-
1292- def pad(self, s):
1293- """
1294- A function to pad ids that have no leading zeroes.
1295- """
1296- while len(s) < 4:
1297- s = "0"+s
1298- return s
1299-
1300- @property
1301- def vendor(self):
1302- """
1303- Return the USB vendor id of this device.
1304- """
1305- return self.pad(self._uevent['PRODUCT'].split("/")[0])
1306-
1307- @property
1308- def model(self):
1309- """
1310- Return the USB model id of this device.
1311- """
1312- return self.pad(self._uevent['PRODUCT'].split("/")[1])
1313-
1314- @property
1315- def deviceclass(self):
1316- """
1317- Return the USB device class of this device.
1318- """
1319- return self._uevent.get("INTERFACE", None)
1320diff --git a/fireinfo/hypervisor.py b/fireinfo/hypervisor.py
1321deleted file mode 100644
1322index 9a3fb09..0000000
1323--- a/fireinfo/hypervisor.py
1324+++ /dev/null
1325@@ -1,149 +0,0 @@
1326-#!/usr/bin/python
1327-###############################################################################
1328-# #
1329-# Fireinfo #
1330-# Copyright (C) 2010, 2011 IPFire Team (www.ipfire.org) #
1331-# #
1332-# This program is free software: you can redistribute it and/or modify #
1333-# it under the terms of the GNU General Public License as published by #
1334-# the Free Software Foundation, either version 3 of the License, or #
1335-# (at your option) any later version. #
1336-# #
1337-# This program is distributed in the hope that it will be useful, #
1338-# but WITHOUT ANY WARRANTY; without even the implied warranty of #
1339-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
1340-# GNU General Public License for more details. #
1341-# #
1342-# You should have received a copy of the GNU General Public License #
1343-# along with this program. If not, see <http://www.gnu.org/licenses/>. #
1344-# #
1345-###############################################################################
1346-
1347-import _fireinfo
1348-import system
1349-
1350-class Hypervisor(object):
1351- def __init__(self):
1352- self.__info = _fireinfo.get_hypervisor()
1353-
1354- @property
1355- def system(self):
1356- """
1357- Return the current instance of the System class.
1358-
1359- We need to do that as a property because otherwise
1360- we get a recursion.
1361- """
1362- return system.System()
1363-
1364- @property
1365- def vendor(self):
1366- """
1367- Returns the name of the hypervisor vendor.
1368- """
1369- if not self.virtual:
1370- return None
1371-
1372- # Some of the hypervisors can be detected in a right way.
1373- # We can return them at this place.
1374- if self.__info["hypervisor"] in ("Xen", "VMWare", "KVM"):
1375- return self.__info["hypervisor"]
1376-
1377- # Citrix Xen says it is Microsoft Hv.
1378- if self.__info["hypervisor"] == "Microsoft" and \
1379- self.system.bios_vendor == "Xen":
1380- return "Xen"
1381-
1382- if not self.__info["hypervisor"]:
1383- # On VMWare systems, the bios vendor string contains "VMWare".
1384- if self.__is_hypervisor_vmware():
1385- return "VMWare"
1386-
1387- # VirtualBox got "innotek GmbH" as bios vendor.
1388- elif self.__is_hypervisor_virtualbox():
1389- return "VirtualBox"
1390-
1391- # Check for qemu.
1392- elif self.__is_hypervisor_qemu():
1393- return "Qemu"
1394-
1395- # Check for Microsoft.
1396- elif self.__is_hypervisor_microsoft():
1397- return "Microsoft"
1398-
1399- return "unknown"
1400-
1401- @property
1402- def type(self):
1403- """
1404- Returns if the host is running in full virt mode or
1405- if it is running in a paravirtualized environment.
1406- """
1407- if not self.virtual:
1408- return None
1409-
1410- if self.__info["virtype"]:
1411- return self.__info["virtype"]
1412-
1413- if self.vendor in ("Qemu", "KVM", "VirtualBox", "VMWare"):
1414- return "full"
1415-
1416- return "unknown"
1417-
1418- @property
1419- def virtual(self):
1420- """
1421- Returns true if the host is running in a virtual environment.
1422- Otherwise: false.
1423- """
1424- return _fireinfo.is_virtualized() or \
1425- "hypervisor" in self.system.cpu.flags or \
1426- self.__is_hypervisor_virtualbox() or \
1427- self.__is_hypervisor_vmware() or \
1428- self.__is_hypervisor_qemu() or \
1429- self.__is_hypervisor_microsoft()
1430-
1431- def __is_hypervisor_virtualbox(self):
1432- """
1433- Check for virtualbox hypervisor by comparing the bios vendor string
1434- to "innotek GmbH".
1435- """
1436- return self.system.bios_vendor == "innotek GmbH"
1437-
1438- def __is_hypervisor_vmware(self):
1439- """
1440- Check for the VMWare hypervisor by the VMWare Hypervisor port check.
1441-
1442- http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458
1443- """
1444- if self.system.vendor:
1445- return self.system.vendor.startswith("VMware")
1446-
1447- # XXX We should use _fireinfo.vmware_hypervisor_port_check() here, too.
1448- # This currently segfaults (and I have no clue why) on VMware player.
1449-
1450- def __is_hypervisor_qemu(self):
1451- """
1452- Check for old qemu emulator.
1453- """
1454- if self.system.bios_vendor:
1455- return self.system.bios_vendor == "Bochs"
1456-
1457- return False
1458-
1459- def __is_hypervisor_microsoft(self):
1460- """
1461- Check for Microsoft hypervisor.
1462- """
1463- if self.system.vendor:
1464- return "Microsoft" in self.system.vendor
1465-
1466- return False
1467-
1468-
1469-if __name__ == "__main__":
1470- h = Hypervisor()
1471-
1472- print "Vendor:", h.vendor
1473- print "Type:", h.type
1474- print "Virtual:", h.virtual
1475diff --git a/fireinfo/network.py b/fireinfo/network.py
1476deleted file mode 100644
1477index 063e9ec..0000000
1478--- a/fireinfo/network.py
1479+++ /dev/null
1480@@ -1,53 +0,0 @@
1481-#!/usr/bin/python
1482-###############################################################################
1483-# #
1484-# Fireinfo #
1485-# Copyright (C) 2010, 2011 IPFire Team (www.ipfire.org) #
1486-# #
1487-# This program is free software: you can redistribute it and/or modify #
1488-# it under the terms of the GNU General Public License as published by #
1489-# the Free Software Foundation, either version 3 of the License, or #
1490-# (at your option) any later version. #
1491-# #
1492-# This program is distributed in the hope that it will be useful, #
1493-# but WITHOUT ANY WARRANTY; without even the implied warranty of #
1494-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
1495-# GNU General Public License for more details. #
1496-# #
1497-# You should have received a copy of the GNU General Public License #
1498-# along with this program. If not, see <http://www.gnu.org/licenses/>. #
1499-# #
1500-###############################################################################
1501-
1502-import os
1503-
1504-SYS_CLASS_NET = "/sys/class/net"
1505-
1506-class Network(object):
1507- def __init__(self):
1508- self._devices = os.listdir(SYS_CLASS_NET)
1509-
1510- def has_green(self):
1511- return "green0" in self._devices
1512-
1513- def has_red(self):
1514- for i in ("red0", "ppp0"):
1515- if i in self._devices:
1516- return True
1517-
1518- return False
1519-
1520- def has_blue(self):
1521- return "blue0" in self._devices
1522-
1523- def has_orange(self):
1524- return "orange0" in self._devices
1525-
1526-
1527-if __name__ == "__main__":
1528- n = Network()
1529-
1530- print "has_green", n.has_green()
1531- print "has_red", n.has_red()
1532- print "has_blue", n.has_blue()
1533- print "has_orange", n.has_orange()
1534diff --git a/fireinfo/system.py b/fireinfo/system.py
1535deleted file mode 100644
1536index 6f02312..0000000
1537--- a/fireinfo/system.py
1538+++ /dev/null
1539@@ -1,449 +0,0 @@
1540-#!/usr/bin/python
1541-###############################################################################
1542-# #
1543-# Fireinfo #
1544-# Copyright (C) 2010, 2011 IPFire Team (www.ipfire.org) #
1545-# #
1546-# This program is free software: you can redistribute it and/or modify #
1547-# it under the terms of the GNU General Public License as published by #
1548-# the Free Software Foundation, either version 3 of the License, or #
1549-# (at your option) any later version. #
1550-# #
1551-# This program is distributed in the hope that it will be useful, #
1552-# but WITHOUT ANY WARRANTY; without even the implied warranty of #
1553-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
1554-# GNU General Public License for more details. #
1555-# #
1556-# You should have received a copy of the GNU General Public License #
1557-# along with this program. If not, see <http://www.gnu.org/licenses/>. #
1558-# #
1559-###############################################################################
1560-
1561-import hashlib
1562-import json
1563-import os
1564-import string
1565-
1566-import _fireinfo
1567-
1568-import cpu
1569-import device
1570-import hypervisor
1571-import network
1572-
1573-PROFILE_VERSION = 0
1574-
1575-SYS_CLASS_DMI = "/sys/class/dmi/id"
1576-SECRET_ID_FILE = "/etc/fireinfo-id"
1577-
1578-INVALID_ID_STRINGS = (
1579- "OEM", "O.E.M.", "o.e.m.",
1580- "N/A", "n/a",
1581- "12345", "54321", "202020",
1582- "Chassis", "chassis",
1583- "Not Applicable",
1584- "None", "empty",
1585- "01010101-0101-0101-0101-010101010101",
1586- "00020003-0004-0005-0006-000700080009",
1587- "03000200-0400-0500-0006-000700080009",
1588- "0000000", "00000000",
1589-)
1590-
1591-class Singleton(type):
1592- def __init__(cls, name, bases, dict):
1593- super(Singleton, cls).__init__(name, bases, dict)
1594- cls.instance = None
1595-
1596- def __call__(cls, *args, **kw):
1597- if cls.instance is None:
1598- cls.instance = super(Singleton, cls).__call__(*args, **kw)
1599-
1600- return cls.instance
1601-
1602-
1603-def read_from_file(filename):
1604- """
1605- Read all data from filename.
1606- """
1607- if not os.path.exists(filename):
1608- return
1609-
1610- try:
1611- with open(filename) as f:
1612- return f.read().strip()
1613- except IOError:
1614- pass
1615-
1616-class System(object):
1617- __metaclass__ = Singleton
1618-
1619- def __init__(self):
1620- # find all devices
1621- self.devices = []
1622- self.scan()
1623- self.cpu = cpu.CPU()
1624- self.hypervisor = hypervisor.Hypervisor()
1625-
1626- # Read /proc/cpuinfo for vendor information.
1627- self.__cpuinfo = self.cpu.read_cpuinfo()
1628-
1629- def profile(self):
1630- p = {}
1631- p["system"] = {
1632- # System information
1633- "model" : self.model,
1634- "vendor" : self.vendor,
1635-
1636- # Indicator if the system is running in a
1637- # virtual environment.
1638- "virtual" : self.virtual,
1639-
1640- # System language
1641- "language" : self.language,
1642-
1643- # Release information
1644- "release" : self.release,
1645- "kernel_release" : self.kernel_release,
1646-
1647- "memory" : self.memory,
1648- "root_size" : self.root_size,
1649- }
1650-
1651- p["devices"] = []
1652- for device in self.devices:
1653- d = {
1654- "subsystem" : device.subsystem.lower(),
1655- "vendor" : device.vendor.lower(),
1656- "model" : device.model.lower(),
1657- "deviceclass" : device.deviceclass,
1658- "driver" : device.driver,
1659- }
1660-
1661- # PCI devices provide subsystem information, USB don't.
1662- if d["subsystem"] == "pci":
1663- d["sub_model"] = device.sub_model
1664- d["sub_vendor"] = device.sub_vendor
1665-
1666- p["devices"].append(d)
1667-
1668- p["cpu"] = {
1669- "arch" : self.arch,
1670- "vendor" : self.cpu.vendor,
1671- "model" : self.cpu.model,
1672- "model_string" : self.cpu.model_string,
1673- "stepping" : self.cpu.stepping,
1674- "flags" : self.cpu.flags,
1675- "bogomips" : self.cpu.bogomips,
1676- "speed" : self.cpu.speed,
1677- "family" : self.cpu.family,
1678- "count" : self.cpu.count
1679- }
1680-
1681- p["network"] = {
1682- "green" : self.network.has_green(),
1683- "blue" : self.network.has_blue(),
1684- "orange" : self.network.has_orange(),
1685- "red" : self.network.has_red(),
1686- }
1687-
1688- # Only append hypervisor information if we are virtualized.
1689- if self.virtual:
1690- p["hypervisor"] = {
1691- "type" : self.hypervisor.type,
1692- "vendor" : self.hypervisor.vendor,
1693- }
1694-
1695- return {
1696- # Profile version
1697- "profile_version" : PROFILE_VERSION,
1698-
1699- # Identification and authorization codes
1700- "public_id" : self.public_id,
1701- "private_id" : self.private_id,
1702-
1703- # Actual profile data
1704- "profile" : p,
1705- }
1706-
1707-
1708- @property
1709- def arch(self):
1710- return os.uname()[4]
1711-
1712- @property
1713- def public_id(self):
1714- """
1715- This returns a globally (hopefully) ID to identify the host
1716- later (by request) in the database.
1717- """
1718- public_id = self.secret_id
1719- if not public_id:
1720- return "0" * 40
1721-
1722- return hashlib.sha1(public_id).hexdigest()
1723-
1724- @property
1725- def private_id(self):
1726- """
1727- The private ID is built out of the _unique_id and used to
1728- permit a host to do changes on the database.
1729-
1730- No one could ever guess this without access to the host.
1731- """
1732- private_id = ""
1733- for i in reversed(self.secret_id):
1734- private_id += i
1735-
1736- if not private_id:
1737- return "0" * 40
1738-
1739- return hashlib.sha1(private_id).hexdigest()
1740-
1741- @property
1742- def secret_id(self):
1743- """
1744- Read a "secret" ID from a file if available
1745- or calculate it from the hardware.
1746- """
1747- if os.path.exists(SECRET_ID_FILE):
1748- return read_from_file(SECRET_ID_FILE)
1749-
1750- return hashlib.sha1(self._unique_id).hexdigest()
1751-
1752- @property
1753- def _unique_id(self):
1754- """
1755- This is a helper ID which is generated out of some hardware information
1756- that is considered to be constant over a PC's lifetime.
1757-
1758- None of the data here is ever sent to the server.
1759- """
1760- ids = []
1761-
1762- # Virtual machines (for example) and some boards have a UUID
1763- # which is globally unique.
1764- for file in ("product_uuid", "product_serial", "chassis_serial"):
1765- id = read_from_file(os.path.join(SYS_CLASS_DMI, file))
1766- ids.append(id)
1767-
1768- # Sort out all bogous or invalid strings from the list.
1769- _ids = []
1770- for id in ids:
1771- if id is None:
1772- continue
1773-
1774- for i in INVALID_ID_STRINGS:
1775- if i in id:
1776- id = None
1777- break
1778-
1779- if id:
1780- _ids.append(id)
1781-
1782- ids = _ids
1783-
1784- # Use serial number from root disk (if available) and if
1785- # no other ID was found, yet.
1786- if not ids:
1787- root_disk_serial = self.root_disk_serial
1788- if root_disk_serial and not root_disk_serial.startswith("QM000"):
1789- ids.append(root_disk_serial)
1790-
1791- # As last resort, we use the UUID from pakfire.
1792- if not ids:
1793- id = read_from_file("/opt/pakfire/db/uuid")
1794- ids.append(id)
1795-
1796- return "#".join(ids)
1797-
1798- @property
1799- def language(self):
1800- """
1801- Return the language code of IPFire or "unknown" if we cannot get it.
1802- """
1803- # Return "unknown" if settings file does not exist.
1804- filename = "/var/ipfire/main/settings"
1805- if not os.path.exists(filename):
1806- return "unknown"
1807-
1808- with open(filename, "r") as f:
1809- for line in f.readlines():
1810- key, val = line.split("=", 1)
1811- if key == "LANGUAGE":
1812- return val.strip()
1813-
1814- @property
1815- def release(self):
1816- """
1817- Return the system release string.
1818- """
1819- return read_from_file("/etc/system-release") or "unknown"
1820-
1821- @property
1822- def bios_vendor(self):
1823- """
1824- Return the bios vendor name.
1825- """
1826- return read_from_file("/sys/class/dmi/id/bios_vendor")
1827-
1828- def vendor_model_tuple(self):
1829- try:
1830- s = self.__cpuinfo["Hardware"]
1831- except KeyError:
1832- return (None, None)
1833-
1834- if s.startswith("ARM-Versatile"):
1835- return ("ARM", s)
1836-
1837- try:
1838- v, m = s.split(" ", 1)
1839- except ValueError:
1840- if s.startswith("BCM"):
1841- v = "Broadcom"
1842- m = s
1843- else:
1844- v = None
1845- m = s
1846-
1847- return v, m
1848-
1849- @property
1850- def vendor(self):
1851- """
1852- Return the vendor string of this system (if any).
1853- """
1854- ret = None
1855- for file in ("sys_vendor", "board_vendor", "chassis_vendor",):
1856- ret = read_from_file(os.path.join(SYS_CLASS_DMI, file))
1857- if ret:
1858- break
1859-
1860- if ret is None:
1861- v, m = self.vendor_model_tuple()
1862- ret = v
1863-
1864- return ret
1865-
1866- @property
1867- def model(self):
1868- """
1869- Return the model string of this system (if any).
1870- """
1871- ret = None
1872- for file in ("product_name", "board_model", "chassis_model",):
1873- ret = read_from_file(os.path.join(SYS_CLASS_DMI, file))
1874- if ret:
1875- break
1876-
1877- if ret is None:
1878- v, m = self.vendor_model_tuple()
1879- ret = m
1880-
1881- return ret
1882-
1883- @property
1884- def memory(self):
1885- """
1886- Return the amount of memory in kilobytes.
1887- """
1888- with open("/proc/meminfo", "r") as f:
1889- firstline = f.readline().strip()
1890- return int(firstline.split()[1])
1891-
1892- @property
1893- def kernel_release(self):
1894- """
1895- Return the kernel release string.
1896- """
1897- return os.uname()[2]
1898-
1899- @property
1900- def root_disk(self):
1901- """
1902- Return the dev node of the root disk.
1903- """
1904- with open("/etc/mtab", "r") as f:
1905- dev, mountpoint, rest = f.readline().split(" ", 2)
1906- if mountpoint == "/":
1907- # Cut off /dev
1908- dev = dev[5:]
1909-
1910- # Handle raids and MMC cards like (mmcblk0p3).
1911- if dev[-2] == "p":
1912- return dev[:-2]
1913-
1914- # Otherwise cut off all digits at end of string
1915- while dev[-1] in string.digits:
1916- dev = dev[:-1]
1917-
1918- return dev
1919-
1920- @property
1921- def root_size(self):
1922- """
1923- Return the size of the root disk in kilobytes.
1924- """
1925- path = "/sys/block/%s/size" % self.root_disk
1926- if not os.path.exists(path):
1927- return
1928-
1929- with open(path, "r") as f:
1930- return int(f.readline()) * 512 / 1024
1931-
1932- @property
1933- def root_disk_serial(self):
1934- """
1935- Return the serial number of the root disk (if any).
1936- """
1937- serial = _fireinfo.get_harddisk_serial("/dev/%s" % self.root_disk)
1938-
1939- if serial:
1940- # Strip all spaces
1941- return serial.strip()
1942-
1943- def scan(self):
1944- """
1945- Scan for all devices (PCI/USB) in the system and append them
1946- to our list.
1947- """
1948- self.devices = []
1949-
1950- toscan = (
1951- ("/sys/bus/pci/devices", device.PCIDevice),
1952- ("/sys/bus/usb/devices", device.USBDevice)
1953- )
1954- for path, cls in toscan:
1955- if not os.path.exists(path):
1956- continue
1957-
1958- dirlist = os.listdir(path)
1959- for dir in dirlist:
1960- self.devices.append(cls(os.path.join(path, dir)))
1961-
1962- @property
1963- def virtual(self):
1964- """
1965- Say if the host is running in a virtual environment.
1966- """
1967- return self.hypervisor.virtual
1968-
1969- @property
1970- def network(self):
1971- """
1972- Reference to the network class.
1973- """
1974- return network.Network()
1975-
1976-
1977-if __name__ == "__main__":
1978- s=System()
1979- print s.arch
1980- print s.language
1981- print s.release
1982- print s.bios_vendor
1983- print s.memory
1984- print s.kernel
1985- print s.root_disk
1986- print s.root_size
1987- print "------------\n", s.devices, "\n------------\n"
1988- print json.dumps(s.profile(), sort_keys=True, indent=4)
1989diff --git a/m4/.gitignore b/m4/.gitignore
1990new file mode 100644
1991index 0000000..38066dd
1992--- /dev/null
1993+++ b/m4/.gitignore
1994@@ -0,0 +1,5 @@
1995+libtool.m4
1996+ltoptions.m4
1997+ltsugar.m4
1998+ltversion.m4
1999+lt~obsolete.m4
2000diff --git a/m4/attributes.m4 b/m4/attributes.m4
2001new file mode 100644
2002index 0000000..7e080da
2003--- /dev/null
2004+++ b/m4/attributes.m4
2005@@ -0,0 +1,288 @@
2006+dnl Macros to check the presence of generic (non-typed) symbols.
2007+dnl Copyright (c) 2006-2008 Diego Pettenò <flameeyes@gmail.com>
2008+dnl Copyright (c) 2006-2008 xine project
2009+dnl Copyright (c) 2012 Lucas De Marchi <lucas.de.marchi@gmail.com>
2010+dnl
2011+dnl This program is free software; you can redistribute it and/or modify
2012+dnl it under the terms of the GNU General Public License as published by
2013+dnl the Free Software Foundation; either version 2, or (at your option)
2014+dnl any later version.
2015+dnl
2016+dnl This program is distributed in the hope that it will be useful,
2017+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
2018+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2019+dnl GNU General Public License for more details.
2020+dnl
2021+dnl You should have received a copy of the GNU General Public License
2022+dnl along with this program; if not, write to the Free Software
2023+dnl Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
2024+dnl 02110-1301, USA.
2025+dnl
2026+dnl As a special exception, the copyright owners of the
2027+dnl macro gives unlimited permission to copy, distribute and modify the
2028+dnl configure scripts that are the output of Autoconf when processing the
2029+dnl Macro. You need not follow the terms of the GNU General Public
2030+dnl License when using or distributing such scripts, even though portions
2031+dnl of the text of the Macro appear in them. The GNU General Public
2032+dnl License (GPL) does govern all other use of the material that
2033+dnl constitutes the Autoconf Macro.
2034+dnl
2035+dnl This special exception to the GPL applies to versions of the
2036+dnl Autoconf Macro released by this project. When you make and
2037+dnl distribute a modified version of the Autoconf Macro, you may extend
2038+dnl this special exception to the GPL to apply to your modified version as
2039+dnl well.
2040+
2041+dnl Check if FLAG in ENV-VAR is supported by compiler and append it
2042+dnl to WHERE-TO-APPEND variable
2043+dnl CC_CHECK_FLAG_APPEND([WHERE-TO-APPEND], [ENV-VAR], [FLAG])
2044+
2045+AC_DEFUN([CC_CHECK_FLAG_APPEND], [
2046+ AC_CACHE_CHECK([if $CC supports flag $3 in envvar $2],
2047+ AS_TR_SH([cc_cv_$2_$3]),
2048+ [eval "AS_TR_SH([cc_save_$2])='${$2}'"
2049+ eval "AS_TR_SH([$2])='-Werror $3'"
2050+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([int a = 0; int main(void) { return a; } ])],
2051+ [eval "AS_TR_SH([cc_cv_$2_$3])='yes'"],
2052+ [eval "AS_TR_SH([cc_cv_$2_$3])='no'"])
2053+ eval "AS_TR_SH([$2])='$cc_save_$2'"])
2054+
2055+ AS_IF([eval test x$]AS_TR_SH([cc_cv_$2_$3])[ = xyes],
2056+ [eval "$1='${$1} $3'"])
2057+])
2058+
2059+dnl CC_CHECK_FLAGS_APPEND([WHERE-TO-APPEND], [ENV-VAR], [FLAG1 FLAG2])
2060+AC_DEFUN([CC_CHECK_FLAGS_APPEND], [
2061+ for flag in $3; do
2062+ CC_CHECK_FLAG_APPEND($1, $2, $flag)
2063+ done
2064+])
2065+
2066+dnl Check if the flag is supported by linker (cacheable)
2067+dnl CC_CHECK_LDFLAGS([FLAG], [ACTION-IF-FOUND],[ACTION-IF-NOT-FOUND])
2068+
2069+AC_DEFUN([CC_CHECK_LDFLAGS], [
2070+ AC_CACHE_CHECK([if $CC supports $1 flag],
2071+ AS_TR_SH([cc_cv_ldflags_$1]),
2072+ [ac_save_LDFLAGS="$LDFLAGS"
2073+ LDFLAGS="$LDFLAGS $1"
2074+ AC_LINK_IFELSE([int main() { return 1; }],
2075+ [eval "AS_TR_SH([cc_cv_ldflags_$1])='yes'"],
2076+ [eval "AS_TR_SH([cc_cv_ldflags_$1])="])
2077+ LDFLAGS="$ac_save_LDFLAGS"
2078+ ])
2079+
2080+ AS_IF([eval test x$]AS_TR_SH([cc_cv_ldflags_$1])[ = xyes],
2081+ [$2], [$3])
2082+])
2083+
2084+dnl define the LDFLAGS_NOUNDEFINED variable with the correct value for
2085+dnl the current linker to avoid undefined references in a shared object.
2086+AC_DEFUN([CC_NOUNDEFINED], [
2087+ dnl We check $host for which systems to enable this for.
2088+ AC_REQUIRE([AC_CANONICAL_HOST])
2089+
2090+ case $host in
2091+ dnl FreeBSD (et al.) does not complete linking for shared objects when pthreads
2092+ dnl are requested, as different implementations are present; to avoid problems
2093+ dnl use -Wl,-z,defs only for those platform not behaving this way.
2094+ *-freebsd* | *-openbsd*) ;;
2095+ *)
2096+ dnl First of all check for the --no-undefined variant of GNU ld. This allows
2097+ dnl for a much more readable commandline, so that people can understand what
2098+ dnl it does without going to look for what the heck -z defs does.
2099+ for possible_flags in "-Wl,--no-undefined" "-Wl,-z,defs"; do
2100+ CC_CHECK_LDFLAGS([$possible_flags], [LDFLAGS_NOUNDEFINED="$possible_flags"])
2101+ break
2102+ done
2103+ ;;
2104+ esac
2105+
2106+ AC_SUBST([LDFLAGS_NOUNDEFINED])
2107+])
2108+
2109+dnl Check for a -Werror flag or equivalent. -Werror is the GCC
2110+dnl and ICC flag that tells the compiler to treat all the warnings
2111+dnl as fatal. We usually need this option to make sure that some
2112+dnl constructs (like attributes) are not simply ignored.
2113+dnl
2114+dnl Other compilers don't support -Werror per se, but they support
2115+dnl an equivalent flag:
2116+dnl - Sun Studio compiler supports -errwarn=%all
2117+AC_DEFUN([CC_CHECK_WERROR], [
2118+ AC_CACHE_CHECK(
2119+ [for $CC way to treat warnings as errors],
2120+ [cc_cv_werror],
2121+ [CC_CHECK_CFLAGS_SILENT([-Werror], [cc_cv_werror=-Werror],
2122+ [CC_CHECK_CFLAGS_SILENT([-errwarn=%all], [cc_cv_werror=-errwarn=%all])])
2123+ ])
2124+])
2125+
2126+AC_DEFUN([CC_CHECK_ATTRIBUTE], [
2127+ AC_REQUIRE([CC_CHECK_WERROR])
2128+ AC_CACHE_CHECK([if $CC supports __attribute__(( ifelse([$2], , [$1], [$2]) ))],
2129+ AS_TR_SH([cc_cv_attribute_$1]),
2130+ [ac_save_CFLAGS="$CFLAGS"
2131+ CFLAGS="$CFLAGS $cc_cv_werror"
2132+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([$3])],
2133+ [eval "AS_TR_SH([cc_cv_attribute_$1])='yes'"],
2134+ [eval "AS_TR_SH([cc_cv_attribute_$1])='no'"])
2135+ CFLAGS="$ac_save_CFLAGS"
2136+ ])
2137+
2138+ AS_IF([eval test x$]AS_TR_SH([cc_cv_attribute_$1])[ = xyes],
2139+ [AC_DEFINE(
2140+ AS_TR_CPP([SUPPORT_ATTRIBUTE_$1]), 1,
2141+ [Define this if the compiler supports __attribute__(( ifelse([$2], , [$1], [$2]) ))]
2142+ )
2143+ $4],
2144+ [$5])
2145+])
2146+
2147+AC_DEFUN([CC_ATTRIBUTE_CONSTRUCTOR], [
2148+ CC_CHECK_ATTRIBUTE(
2149+ [constructor],,
2150+ [void __attribute__((constructor)) ctor() { int a; }],
2151+ [$1], [$2])
2152+])
2153+
2154+AC_DEFUN([CC_ATTRIBUTE_FORMAT], [
2155+ CC_CHECK_ATTRIBUTE(
2156+ [format], [format(printf, n, n)],
2157+ [void __attribute__((format(printf, 1, 2))) printflike(const char *fmt, ...) { fmt = (void *)0; }],
2158+ [$1], [$2])
2159+])
2160+
2161+AC_DEFUN([CC_ATTRIBUTE_FORMAT_ARG], [
2162+ CC_CHECK_ATTRIBUTE(
2163+ [format_arg], [format_arg(printf)],
2164+ [char *__attribute__((format_arg(1))) gettextlike(const char *fmt) { fmt = (void *)0; }],
2165+ [$1], [$2])
2166+])
2167+
2168+AC_DEFUN([CC_ATTRIBUTE_VISIBILITY], [
2169+ CC_CHECK_ATTRIBUTE(
2170+ [visibility_$1], [visibility("$1")],
2171+ [void __attribute__((visibility("$1"))) $1_function() { }],
2172+ [$2], [$3])
2173+])
2174+
2175+AC_DEFUN([CC_ATTRIBUTE_NONNULL], [
2176+ CC_CHECK_ATTRIBUTE(
2177+ [nonnull], [nonnull()],
2178+ [void __attribute__((nonnull())) some_function(void *foo, void *bar) { foo = (void*)0; bar = (void*)0; }],
2179+ [$1], [$2])
2180+])
2181+
2182+AC_DEFUN([CC_ATTRIBUTE_UNUSED], [
2183+ CC_CHECK_ATTRIBUTE(
2184+ [unused], ,
2185+ [void some_function(void *foo, __attribute__((unused)) void *bar);],
2186+ [$1], [$2])
2187+])
2188+
2189+AC_DEFUN([CC_ATTRIBUTE_SENTINEL], [
2190+ CC_CHECK_ATTRIBUTE(
2191+ [sentinel], ,
2192+ [void some_function(void *foo, ...) __attribute__((sentinel));],
2193+ [$1], [$2])
2194+])
2195+
2196+AC_DEFUN([CC_ATTRIBUTE_DEPRECATED], [
2197+ CC_CHECK_ATTRIBUTE(
2198+ [deprecated], ,
2199+ [void some_function(void *foo, ...) __attribute__((deprecated));],
2200+ [$1], [$2])
2201+])
2202+
2203+AC_DEFUN([CC_ATTRIBUTE_ALIAS], [
2204+ CC_CHECK_ATTRIBUTE(
2205+ [alias], [weak, alias],
2206+ [void other_function(void *foo) { }
2207+ void some_function(void *foo) __attribute__((weak, alias("other_function")));],
2208+ [$1], [$2])
2209+])
2210+
2211+AC_DEFUN([CC_ATTRIBUTE_MALLOC], [
2212+ CC_CHECK_ATTRIBUTE(
2213+ [malloc], ,
2214+ [void * __attribute__((malloc)) my_alloc(int n);],
2215+ [$1], [$2])
2216+])
2217+
2218+AC_DEFUN([CC_ATTRIBUTE_PACKED], [
2219+ CC_CHECK_ATTRIBUTE(
2220+ [packed], ,
2221+ [struct astructure { char a; int b; long c; void *d; } __attribute__((packed));],
2222+ [$1], [$2])
2223+])
2224+
2225+AC_DEFUN([CC_ATTRIBUTE_CONST], [
2226+ CC_CHECK_ATTRIBUTE(
2227+ [const], ,
2228+ [int __attribute__((const)) twopow(int n) { return 1 << n; } ],
2229+ [$1], [$2])
2230+])
2231+
2232+AC_DEFUN([CC_FLAG_VISIBILITY], [
2233+ AC_REQUIRE([CC_CHECK_WERROR])
2234+ AC_CACHE_CHECK([if $CC supports -fvisibility=hidden],
2235+ [cc_cv_flag_visibility],
2236+ [cc_flag_visibility_save_CFLAGS="$CFLAGS"
2237+ CFLAGS="$CFLAGS $cc_cv_werror"
2238+ CC_CHECK_CFLAGS_SILENT([-fvisibility=hidden],
2239+ cc_cv_flag_visibility='yes',
2240+ cc_cv_flag_visibility='no')
2241+ CFLAGS="$cc_flag_visibility_save_CFLAGS"])
2242+
2243+ AS_IF([test "x$cc_cv_flag_visibility" = "xyes"],
2244+ [AC_DEFINE([SUPPORT_FLAG_VISIBILITY], 1,
2245+ [Define this if the compiler supports the -fvisibility flag])
2246+ $1],
2247+ [$2])
2248+])
2249+
2250+AC_DEFUN([CC_FUNC_EXPECT], [
2251+ AC_REQUIRE([CC_CHECK_WERROR])
2252+ AC_CACHE_CHECK([if compiler has __builtin_expect function],
2253+ [cc_cv_func_expect],
2254+ [ac_save_CFLAGS="$CFLAGS"
2255+ CFLAGS="$CFLAGS $cc_cv_werror"
2256+ AC_COMPILE_IFELSE([AC_LANG_SOURCE(
2257+ [int some_function() {
2258+ int a = 3;
2259+ return (int)__builtin_expect(a, 3);
2260+ }])],
2261+ [cc_cv_func_expect=yes],
2262+ [cc_cv_func_expect=no])
2263+ CFLAGS="$ac_save_CFLAGS"
2264+ ])
2265+
2266+ AS_IF([test "x$cc_cv_func_expect" = "xyes"],
2267+ [AC_DEFINE([SUPPORT__BUILTIN_EXPECT], 1,
2268+ [Define this if the compiler supports __builtin_expect() function])
2269+ $1],
2270+ [$2])
2271+])
2272+
2273+AC_DEFUN([CC_ATTRIBUTE_ALIGNED], [
2274+ AC_REQUIRE([CC_CHECK_WERROR])
2275+ AC_CACHE_CHECK([highest __attribute__ ((aligned ())) supported],
2276+ [cc_cv_attribute_aligned],
2277+ [ac_save_CFLAGS="$CFLAGS"
2278+ CFLAGS="$CFLAGS $cc_cv_werror"
2279+ for cc_attribute_align_try in 64 32 16 8 4 2; do
2280+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([
2281+ int main() {
2282+ static char c __attribute__ ((aligned($cc_attribute_align_try))) = 0;
2283+ return c;
2284+ }])], [cc_cv_attribute_aligned=$cc_attribute_align_try; break])
2285+ done
2286+ CFLAGS="$ac_save_CFLAGS"
2287+ ])
2288+
2289+ if test "x$cc_cv_attribute_aligned" != "x"; then
2290+ AC_DEFINE_UNQUOTED([ATTRIBUTE_ALIGNED_MAX], [$cc_cv_attribute_aligned],
2291+ [Define the highest alignment supported])
2292+ fi
2293+])
2294diff --git a/runpychecker.sh b/runpychecker.sh
2295index 407b7d6..64366fd 100755
2296--- a/runpychecker.sh
2297+++ b/runpychecker.sh
2298@@ -5,4 +5,4 @@ pychecker --only --limit 1000 \
2299 --no-callinit --no-local --no-shadow --no-shadowbuiltin \
2300 --no-import --no-miximport --no-pkgimport --no-reimport \
2301 --no-argsused --no-varargsused --no-override \
2302- fireinfo/*.py
2303+ src/fireinfo/*.py
2304diff --git a/sendprofile b/sendprofile
2305deleted file mode 100644
2306index da480ce..0000000
2307--- a/sendprofile
2308+++ /dev/null
2309@@ -1,132 +0,0 @@
2310-#!/usr/bin/python
2311-###############################################################################
2312-# #
2313-# Fireinfo #
2314-# Copyright (C) 2010, 2011 IPFire Team (www.ipfire.org) #
2315-# #
2316-# This program is free software: you can redistribute it and/or modify #
2317-# it under the terms of the GNU General Public License as published by #
2318-# the Free Software Foundation, either version 3 of the License, or #
2319-# (at your option) any later version. #
2320-# #
2321-# This program is distributed in the hope that it will be useful, #
2322-# but WITHOUT ANY WARRANTY; without even the implied warranty of #
2323-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
2324-# GNU General Public License for more details. #
2325-# #
2326-# You should have received a copy of the GNU General Public License #
2327-# along with this program. If not, see <http://www.gnu.org/licenses/>. #
2328-# #
2329-###############################################################################
2330-
2331-import json
2332-import logging
2333-import logging.handlers
2334-import os
2335-import sys
2336-import urllib
2337-import urllib2
2338-
2339-import fireinfo
2340-
2341-ENABLED_FILE = "/var/ipfire/main/send_profile"
2342-PROXY_SETTINGS = "/var/ipfire/proxy/advanced/settings"
2343-
2344-log_level = logging.INFO
2345-if "-d" in sys.argv:
2346- log_level = logging.DEBUG
2347-
2348-# Setup logging
2349-log = logging.getLogger()
2350-log.setLevel(log_level)
2351-log.addHandler(logging.handlers.SysLogHandler("/dev/log"))
2352-log.addHandler(logging.StreamHandler(sys.stderr))
2353-for handler in log.handlers:
2354- handler.setLevel(log_level)
2355-
2356-PROFILE_URL = "http://fireinfo.ipfire.org/send/%(public_id)s"
2357-
2358-def get_upstream_proxy():
2359- if not os.path.exists(PROXY_SETTINGS):
2360- return {"host" : ""}
2361-
2362- proxy_settings = {}
2363- with open(PROXY_SETTINGS) as f:
2364- for line in f.readlines():
2365- k, v = line.split("=", 1)
2366- proxy_settings[k] = v.strip()
2367-
2368- return {
2369- "host" : proxy_settings.get("UPSTREAM_PROXY", ""),
2370- "user" : proxy_settings.get("UPSTREAM_USER", ""),
2371- "pass" : proxy_settings.get("UPSTREAM_PASSWORD", ""),
2372- }
2373-
2374-def send_profile(profile):
2375- logging.debug("Sending profile:")
2376- for line in json.dumps(profile, sort_keys=True, indent=4).splitlines():
2377- logging.debug(line)
2378-
2379- request = urllib2.Request(PROFILE_URL % profile,
2380- data = urllib.urlencode({"profile" : json.dumps(profile)}),
2381- )
2382- request.add_header("User-Agent", "fireinfo/%s" % fireinfo.__version__)
2383-
2384- # Set upstream proxy if we have one.
2385- # XXX this cannot handle authentication
2386- proxy = get_upstream_proxy()
2387- if proxy["host"]:
2388- request.set_proxy(proxy["host"], "http")
2389-
2390- try:
2391- urllib2.urlopen(request, timeout=60)
2392- except (urllib2.HTTPError, urllib2.URLError), e:
2393- reason = "Unknown reason"
2394-
2395- if isinstance(e, urllib2.HTTPError):
2396- reason = "%s" % e
2397- elif isinstance(e, urllib2.URLError):
2398- reason = e.reason
2399-
2400- logging.error("Profile was not sent propertly: %s" % reason)
2401- return
2402-
2403- logging.debug("Profile was sent successfully.")
2404-
2405-def main():
2406- # Collect system information
2407- system = fireinfo.System()
2408- profile = system.profile()
2409-
2410- # If --dump is passed -> only dump the output.
2411- if "--dump" in sys.argv:
2412- # Remove the private id when dumping the profile because
2413- # it contains no information and may confuse people.
2414- del profile["private_id"]
2415-
2416- print json.dumps(profile, sort_keys=True, indent=4)
2417- return 0
2418-
2419- if "--secret-id" in sys.argv:
2420- print system.secret_id
2421- return 0
2422-
2423- if "--hardware-string" in sys.argv:
2424- print system._unique_id
2425- return 0
2426-
2427- if "--public-id" in sys.argv:
2428- print system.public_id
2429- return 0
2430-
2431- if not os.path.exists(ENABLED_FILE):
2432- del profile["profile"]
2433-
2434- try:
2435- send_profile(profile)
2436- except urllib2.URLError:
2437- return 1
2438-
2439- return 0
2440-
2441-sys.exit(main())
2442diff --git a/setup.py b/setup.py
2443deleted file mode 100644
2444index 8149f0a..0000000
2445--- a/setup.py
2446+++ /dev/null
2447@@ -1,37 +0,0 @@
2448-#!/usr/bin/python
2449-###############################################################################
2450-# #
2451-# Fireinfo #
2452-# Copyright (C) 2010, 2011 IPFire Team (www.ipfire.org) #
2453-# #
2454-# This program is free software: you can redistribute it and/or modify #
2455-# it under the terms of the GNU General Public License as published by #
2456-# the Free Software Foundation, either version 3 of the License, or #
2457-# (at your option) any later version. #
2458-# #
2459-# This program is distributed in the hope that it will be useful, #
2460-# but WITHOUT ANY WARRANTY; without even the implied warranty of #
2461-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
2462-# GNU General Public License for more details. #
2463-# #
2464-# You should have received a copy of the GNU General Public License #
2465-# along with this program. If not, see <http://www.gnu.org/licenses/>. #
2466-# #
2467-###############################################################################
2468-
2469-from distutils.core import setup, Extension
2470-
2471-setup(
2472- name = "fireinfo",
2473- version = "2.1.7",
2474- description = "Hardware information gathering library.",
2475- license = "GPLv3",
2476- author = "IPFire.org Team",
2477- author_email = "info@ipfire.org",
2478- url = "https://bugzilla.ipfire.org/describecomponents.cgi?product=Fireinfo",
2479- ext_modules = [
2480- Extension("_fireinfo", ["src/fireinfo.c"])
2481- ],
2482- packages = ["fireinfo"],
2483- scripts = ["sendprofile"],
2484-)
2485diff --git a/src/_fireinfo/fireinfo.c b/src/_fireinfo/fireinfo.c
2486new file mode 100644
2487index 0000000..08d714b
2488--- /dev/null
2489+++ b/src/_fireinfo/fireinfo.c
2490@@ -0,0 +1,231 @@
2491+/*
2492+ * Fireinfo
2493+ * Copyright (C) 2010, 2011 IPFire Team (www.ipfire.org)
2494+ *
2495+ * This program is free software; you can redistribute it and/or modify
2496+ * it under the terms of the GNU General Public License as published by
2497+ * the Free Software Foundation; either version 3 of the License, or
2498+ * (at your option) any later version.
2499+ *
2500+ * This program is distributed in the hope that it will be useful,
2501+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2502+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2503+ * GNU General Public License for more details.
2504+ *
2505+ * You should have received a copy of the GNU General Public License
2506+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2507+ */
2508+
2509+#include <Python.h>
2510+
2511+#include <errno.h>
2512+#include <fcntl.h>
2513+#include <linux/hdreg.h>
2514+#include <stdbool.h>
2515+#include <string.h>
2516+#include <sys/ioctl.h>
2517+
2518+/* hypervisor vendors */
2519+enum hypervisors {
2520+ HYPER_NONE = 0,
2521+ HYPER_XEN,
2522+ HYPER_KVM,
2523+ HYPER_MSHV,
2524+ HYPER_VMWARE,
2525+ HYPER_OTHER,
2526+ HYPER_LAST /* for loop - must be last*/
2527+};
2528+
2529+const char *hypervisor_ids[] = {
2530+ [HYPER_NONE] = NULL,
2531+ [HYPER_XEN] = "XenVMMXenVMM",
2532+ [HYPER_KVM] = "KVMKVMKVM",
2533+ /* http://msdn.microsoft.com/en-us/library/ff542428.aspx */
2534+ [HYPER_MSHV] = "Microsoft Hv",
2535+ /* http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1009458 */
2536+ [HYPER_VMWARE] = "VMwareVMware",
2537+ [HYPER_OTHER] = NULL
2538+};
2539+
2540+const char *hypervisor_vendors[] = {
2541+ [HYPER_NONE] = NULL,
2542+ [HYPER_XEN] = "Xen",
2543+ [HYPER_KVM] = "KVM",
2544+ [HYPER_MSHV] = "Microsoft",
2545+ [HYPER_VMWARE] = "VMWare",
2546+ [HYPER_OTHER] = "other"
2547+};
2548+
2549+#define NEWLINE "\n\r"
2550+
2551+char *truncate_nl(char *s) {
2552+ assert(s);
2553+
2554+ s[strcspn(s, NEWLINE)] = 0;
2555+ return s;
2556+}
2557+
2558+int read_one_line_file(const char *filename, char **line) {
2559+ assert(filename);
2560+ assert(line);
2561+
2562+ FILE *f = NULL;
2563+ f = fopen(filename, "re");
2564+ if (!f)
2565+ return -errno;
2566+
2567+ char t[2048];
2568+ if (!fgets(t, sizeof(t), f)) {
2569+ if (ferror(f))
2570+ return errno ? -errno : -EIO;
2571+
2572+ t[0] = 0;
2573+ }
2574+
2575+ char *c = strdup(t);
2576+ if (!c)
2577+ return -ENOMEM;
2578+ truncate_nl(c);
2579+
2580+ *line = c;
2581+ return 0;
2582+}
2583+
2584+/*
2585+ * This CPUID leaf returns the information about the hypervisor.
2586+ * EAX : maximum input value for CPUID supported by the hypervisor.
2587+ * EBX, ECX, EDX : Hypervisor vendor ID signature. E.g. VMwareVMware.
2588+ */
2589+#define HYPERVISOR_INFO_LEAF 0x40000000
2590+
2591+int detect_hypervisor(int *hypervisor) {
2592+#if defined(__x86_64__) || defined(__i386__)
2593+ /* Try high-level hypervisor sysfs file first: */
2594+ char *hvtype = NULL;
2595+ int r = read_one_line_file("/sys/hypervisor/type", &hvtype);
2596+ if (r >= 0) {
2597+ if (strcmp(hvtype, "xen") == 0) {
2598+ *hypervisor = HYPER_XEN;
2599+ return 1;
2600+ }
2601+ } else if (r != -ENOENT)
2602+ return r;
2603+
2604+ /* http://lwn.net/Articles/301888/ */
2605+
2606+#if defined(__amd64__)
2607+#define REG_a "rax"
2608+#define REG_b "rbx"
2609+#elif defined(__i386__)
2610+#define REG_a "eax"
2611+#define REG_b "ebx"
2612+#endif
2613+
2614+ uint32_t eax = 1;
2615+ uint32_t ecx;
2616+ union {
2617+ uint32_t sig32[3];
2618+ char text[13];
2619+ } sig = {};
2620+
2621+ __asm__ __volatile__ (
2622+ /* ebx/rbx is being used for PIC! */
2623+ " push %%"REG_b" \n\t"
2624+ " cpuid \n\t"
2625+ " pop %%"REG_b" \n\t"
2626+
2627+ : "=a" (eax), "=c" (ecx)
2628+ : "0" (eax)
2629+ );
2630+
2631+ bool has_hypervisor = !!(ecx & 0x80000000U);
2632+
2633+ if (has_hypervisor) {
2634+ /* There is a hypervisor, see what it is... */
2635+ eax = 0x40000000U;
2636+ __asm__ __volatile__ (
2637+ " push %%"REG_b" \n\t"
2638+ " cpuid \n\t"
2639+ " mov %%ebx, %1 \n\t"
2640+ " pop %%"REG_b" \n\t"
2641+
2642+ : "=a" (eax), "=r" (sig.sig32[0]), "=c" (sig.sig32[1]), "=d" (sig.sig32[2])
2643+ : "0" (eax)
2644+ );
2645+ sig.text[12] = '\0';
2646+
2647+ *hypervisor = HYPER_OTHER;
2648+
2649+ int id;
2650+ for (id = HYPER_NONE + 1; id < HYPER_LAST; id++) {
2651+ if (strcmp(hypervisor_ids[id], sig.text) == 0) {
2652+ *hypervisor = id;
2653+ break;
2654+ }
2655+ }
2656+
2657+ return 1;
2658+ }
2659+#endif
2660+ return 0;
2661+}
2662+
2663+
2664+static PyObject *
2665+do_detect_hypervisor() {
2666+ /*
2667+ Get hypervisor from the cpuid command.
2668+ */
2669+ int hypervisor = HYPER_NONE;
2670+
2671+ int r = detect_hypervisor(&hypervisor);
2672+ if (r >= 1) {
2673+ const char* hypervisor_vendor = hypervisor_vendors[hypervisor];
2674+ if (!hypervisor_vendor)
2675+ Py_RETURN_NONE;
2676+
2677+ return PyString_FromString(hypervisor_vendor);
2678+ }
2679+
2680+ Py_RETURN_NONE;
2681+}
2682+
2683+static PyObject *
2684+do_get_harddisk_serial(PyObject *o, PyObject *args) {
2685+ /*
2686+ Python wrapper around read_harddisk_serial.
2687+ */
2688+ static struct hd_driveid hd;
2689+ int fd;
2690+ char *device;
2691+
2692+ if (!PyArg_ParseTuple(args, "s", &device))
2693+ return NULL;
2694+
2695+ if ((fd = open(device, O_RDONLY | O_NONBLOCK)) < 0)
2696+ return NULL;
2697+
2698+ if (!ioctl(fd, HDIO_GET_IDENTITY, &hd)) {
2699+ char serial[21];
2700+ strncpy(serial, (const char *)hd.serial_no, sizeof(serial));
2701+
2702+ if (serial[0])
2703+ return PyString_FromString(serial);
2704+ }
2705+
2706+ Py_RETURN_NONE;
2707+}
2708+
2709+static PyMethodDef fireinfoModuleMethods[] = {
2710+ { "detect_hypervisor", (PyCFunction) do_detect_hypervisor, METH_NOARGS, NULL },
2711+ { "get_harddisk_serial", (PyCFunction) do_get_harddisk_serial, METH_VARARGS, NULL },
2712+ { NULL, NULL, 0, NULL }
2713+};
2714+
2715+void init_fireinfo(void) {
2716+ PyObject *m;
2717+
2718+ m = Py_InitModule("_fireinfo", fireinfoModuleMethods);
2719+ if (m == NULL)
2720+ return;
2721+}
2722diff --git a/src/fireinfo.c b/src/fireinfo.c
2723deleted file mode 100644
2724index 25b5333..0000000
2725--- a/src/fireinfo.c
2726+++ /dev/null
2727@@ -1,427 +0,0 @@
2728-/*
2729- * Fireinfo
2730- * Copyright (C) 2010, 2011 IPFire Team (www.ipfire.org)
2731- *
2732- * This program is free software; you can redistribute it and/or modify
2733- * it under the terms of the GNU General Public License as published by
2734- * the Free Software Foundation; either version 3 of the License, or
2735- * (at your option) any later version.
2736- *
2737- * This program is distributed in the hope that it will be useful,
2738- * but WITHOUT ANY WARRANTY; without even the implied warranty of
2739- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2740- * GNU General Public License for more details.
2741- *
2742- * You should have received a copy of the GNU General Public License
2743- * along with this program. If not, see <http://www.gnu.org/licenses/>.
2744- */
2745-
2746-#include <Python.h>
2747-
2748-#include <fcntl.h>
2749-#include <linux/hdreg.h>
2750-#include <stdbool.h>
2751-#include <sys/ioctl.h>
2752-
2753-/*
2754- Big parts of this were taken from
2755- http://git.kernel.org/?p=utils/util-linux-ng/util-linux-ng.git;a=blob;f=sys-utils/lscpu.c
2756-*/
2757-
2758-/* /sys paths */
2759-#define _PATH_PROC_XEN "/proc/xen"
2760-#define _PATH_PROC_XENCAP _PATH_PROC_XEN "/capabilities"
2761-#define _PATH_PROC_PCIDEVS "/proc/bus/pci/devices"
2762-
2763-/* Used for the vmware hypervisor port detection */
2764-#define VMWARE_HYPERVISOR_MAGIC 0x564D5868
2765-#define VMWARE_HYPERVISOR_PORT 0x5658
2766-
2767-#define VMWARE_PORT_CMD_GETVERSION 10
2768-
2769-/* virtualization types */
2770-enum {
2771- VIRT_NONE = 0,
2772- VIRT_PARA,
2773- VIRT_FULL
2774-};
2775-const char *virt_types[] = {
2776- [VIRT_NONE] = "none",
2777- [VIRT_PARA] = "para",
2778- [VIRT_FULL] = "full"
2779-};
2780-
2781-/* hypervisor vendors */
2782-enum {
2783- HYPER_NONE = 0,
2784- HYPER_XEN,
2785- HYPER_KVM,
2786- HYPER_MSHV,
2787- HYPER_VMWARE
2788-};
2789-const char *hv_vendors[] = {
2790- [HYPER_NONE] = NULL,
2791- [HYPER_XEN] = "Xen",
2792- [HYPER_KVM] = "KVM",
2793- [HYPER_MSHV] = "Microsoft",
2794- [HYPER_VMWARE] = "VMWare"
2795-};
2796-
2797-struct hypervisor_desc {
2798- int hyper; /* hypervisor vendor ID */
2799- int virtype; /* VIRT_PARA|FULL|NONE ? */
2800-};
2801-
2802-static size_t sysrootlen;
2803-static char pathbuf[PATH_MAX];
2804-
2805-static FILE *path_fopen(const char *mode, const char *path, ...)
2806- __attribute__ ((__format__ (__printf__, 2, 3)));
2807-static int path_exist(const char *path, ...)
2808- __attribute__ ((__format__ (__printf__, 1, 2)));
2809-
2810-static const char *
2811-path_vcreate(const char *path, va_list ap)
2812-{
2813- if (sysrootlen)
2814- vsnprintf(pathbuf + sysrootlen,
2815- sizeof(pathbuf) - sysrootlen, path, ap);
2816- else
2817- vsnprintf(pathbuf, sizeof(pathbuf), path, ap);
2818- return pathbuf;
2819-}
2820-
2821-static FILE *
2822-path_vfopen(const char *mode, const char *path, va_list ap)
2823-{
2824- const char *p = path_vcreate(path, ap);
2825-
2826- return fopen(p, mode);
2827-}
2828-
2829-static FILE *
2830-path_fopen(const char *mode, const char *path, ...)
2831-{
2832- FILE *fd;
2833- va_list ap;
2834-
2835- va_start(ap, path);
2836- fd = path_vfopen(mode, path, ap);
2837- va_end(ap);
2838-
2839- return fd;
2840-}
2841-
2842-static int
2843-path_exist(const char *path, ...)
2844-{
2845- va_list ap;
2846- const char *p;
2847-
2848- va_start(ap, path);
2849- p = path_vcreate(path, ap);
2850- va_end(ap);
2851-
2852- return access(p, F_OK) == 0;
2853-}
2854-
2855-static int
2856-has_pci_device(int vendor, int device)
2857-{
2858- FILE *f;
2859- int num, fn, ven, dev;
2860- int res = 1;
2861-
2862- f = path_fopen("r", _PATH_PROC_PCIDEVS);
2863- if (!f)
2864- return 0;
2865-
2866- /* for more details about bus/pci/devices format see
2867- * drivers/pci/proc.c in linux kernel
2868- */
2869- while(fscanf(f, "%02x%02x\t%04x%04x\t%*[^\n]",
2870- &num, &fn, &ven, &dev) == 4) {
2871-
2872- if (ven == vendor && dev == device)
2873- goto found;
2874- }
2875-
2876- res = 0;
2877-found:
2878- fclose(f);
2879- return res;
2880-}
2881-
2882-#if defined(__x86_64__) || defined(__i386__)
2883-
2884-/*
2885- * This CPUID leaf returns the information about the hypervisor.
2886- * EAX : maximum input value for CPUID supported by the hypervisor.
2887- * EBX, ECX, EDX : Hypervisor vendor ID signature. E.g. VMwareVMware.
2888- */
2889-#define HYPERVISOR_INFO_LEAF 0x40000000
2890-
2891-static inline void
2892-cpuid(unsigned int op, unsigned int *eax, unsigned int *ebx,
2893- unsigned int *ecx, unsigned int *edx)
2894-{
2895- __asm__(
2896-#if defined(__PIC__) && defined(__i386__)
2897- /* x86 PIC cannot clobber ebx -- gcc bitches */
2898- "pushl %%ebx;"
2899- "cpuid;"
2900- "movl %%ebx, %%esi;"
2901- "popl %%ebx;"
2902- : "=S" (*ebx),
2903-#else
2904- "cpuid;"
2905- : "=b" (*ebx),
2906-#endif
2907- "=a" (*eax),
2908- "=c" (*ecx),
2909- "=d" (*edx)
2910- : "1" (op), "c"(0));
2911-}
2912-
2913-static void
2914-read_hypervisor_cpuid(struct hypervisor_desc *desc)
2915-{
2916- unsigned int eax = 0, ebx = 0, ecx = 0, edx = 0;
2917- char hyper_vendor_id[13];
2918-
2919- memset(hyper_vendor_id, 0, sizeof(hyper_vendor_id));
2920-
2921- cpuid(HYPERVISOR_INFO_LEAF, &eax, &ebx, &ecx, &edx);
2922- memcpy(hyper_vendor_id + 0, &ebx, 4);
2923- memcpy(hyper_vendor_id + 4, &ecx, 4);
2924- memcpy(hyper_vendor_id + 8, &edx, 4);
2925- hyper_vendor_id[12] = '\0';
2926-
2927- if (!hyper_vendor_id[0])
2928- return;
2929-
2930- if (!strncmp("XenVMMXenVMM", hyper_vendor_id, 12))
2931- desc->hyper = HYPER_XEN;
2932- else if (!strncmp("KVMKVMKVM", hyper_vendor_id, 9))
2933- desc->hyper = HYPER_KVM;
2934- else if (!strncmp("Microsoft Hv", hyper_vendor_id, 12))
2935- desc->hyper = HYPER_MSHV;
2936- else if (!strncmp("VMwareVMware", hyper_vendor_id, 12))
2937- desc->hyper = HYPER_VMWARE;
2938-}
2939-
2940-#else /* ! __x86_64__ */
2941-static void
2942-read_hypervisor_cpuid(struct hypervisor_desc *desc)
2943-{
2944-}
2945-#endif
2946-
2947-static void
2948-read_hypervisor(struct hypervisor_desc *desc)
2949-{
2950- read_hypervisor_cpuid(desc);
2951-
2952- if (desc->hyper)
2953- /* hvm */
2954- desc->virtype = VIRT_FULL;
2955-
2956- else if (path_exist(_PATH_PROC_XEN)) {
2957- /* Xen para-virt or dom0 */
2958- FILE *fd = path_fopen("r", _PATH_PROC_XENCAP);
2959- int dom0 = 0;
2960-
2961- if (fd) {
2962- char buf[256];
2963-
2964- if (fscanf(fd, "%s", buf) == 1 &&
2965- !strcmp(buf, "control_d"))
2966- dom0 = 1;
2967- fclose(fd);
2968- }
2969- desc->virtype = dom0 ? VIRT_NONE : VIRT_PARA;
2970- desc->hyper = HYPER_XEN;
2971-
2972- } else if (has_pci_device(0x5853, 0x0001)) {
2973- /* Xen full-virt on non-x86_64 */
2974- desc->hyper = HYPER_XEN;
2975- desc->virtype = VIRT_FULL;
2976- }
2977-}
2978-
2979-static void
2980-read_harddisk_serial(char *device, char *serial) {
2981- static struct hd_driveid hd;
2982- int fd;
2983-
2984- if ((fd = open(device, O_RDONLY | O_NONBLOCK)) < 0) {
2985- return;
2986- }
2987-
2988- if (!ioctl(fd, HDIO_GET_IDENTITY, &hd)) {
2989- strncpy(serial, (const char *)hd.serial_no, 20);
2990- }
2991-}
2992-
2993-#if defined(__x86_64__) || defined(__i386__)
2994-static bool
2995-is_virtualized() {
2996- unsigned int eax, ebx, ecx, edx;
2997-
2998- cpuid(0x1, &eax, &ebx, &ecx, &edx);
2999-
3000- /*
3001- Bitwise detection of the 31st bit.
3002- This indicates if a host runs in a virtual environment.
3003- */
3004- if (ecx & (1<<31))
3005- return true;
3006-
3007- return false;
3008-}
3009-
3010-void
3011-hypervisor_port(unsigned int cmd, unsigned int *eax, unsigned int *ebx,
3012- unsigned int *ecx, unsigned int *edx)
3013-{
3014- __asm__(
3015-#if defined(__PIC__) && defined(__i386__)
3016- /* x86 PIC really cannot clobber ebx */
3017- "pushl %%ebx;"
3018- "inl (%%dx);"
3019- "movl %%ebx, %%esi;"
3020- "popl %%ebx;"
3021- : "=S" (*ebx),
3022-#else
3023- "inl (%%dx);"
3024- : "=b" (*ebx),
3025-#endif
3026- "=a" (*eax),
3027- "=c" (*ecx),
3028- "=d" (*edx)
3029- : "0" (VMWARE_HYPERVISOR_MAGIC),
3030- "1" (cmd),
3031- "2" (VMWARE_HYPERVISOR_PORT),
3032- "3" (UINT_MAX)
3033- : "memory"
3034- );
3035-}
3036-#else
3037-static bool
3038-is_virtualized() {
3039- /*
3040- Always return false, because other architectures
3041- do not support the virtualization bit.
3042- */
3043- return false;
3044-}
3045-
3046-void
3047-hypervisor_port(unsigned int cmd, unsigned int *eax, unsigned int *ebx,
3048- unsigned int *ecx, unsigned int *edx)
3049-{
3050-}
3051-#endif
3052-
3053-int
3054-hypervisor_port_check(void) {
3055- uint32_t eax, ebx, ecx, edx;
3056-
3057- hypervisor_port(VMWARE_PORT_CMD_GETVERSION, &eax, &ebx, &ecx, &edx);
3058-
3059- if (ebx == VMWARE_HYPERVISOR_MAGIC)
3060- return 1; // Success - running under VMware
3061- else
3062- return 0;
3063-}
3064-
3065-static PyObject *
3066-do_get_hypervisor() {
3067- /*
3068- Get hypervisor from the cpuid command.
3069- */
3070- struct hypervisor_desc _desc, *desc = &_desc;
3071- memset(desc, 0, sizeof(*desc));
3072-
3073- read_hypervisor(desc);
3074-
3075- PyObject *d = PyDict_New();
3076- PyObject *o;
3077-
3078- /* Hypervisor */
3079- if (desc->hyper == HYPER_NONE) {
3080- o = Py_None;
3081- } else {
3082- o = PyString_FromString((const char *)hv_vendors[desc->hyper]);
3083- }
3084- PyDict_SetItemString(d, "hypervisor", o);
3085-
3086- /* Virtualization type */
3087- if (desc->virtype == VIRT_NONE) {
3088- o = Py_None;
3089- } else {
3090- o = PyString_FromString((const char *)virt_types[desc->virtype]);
3091- }
3092- PyDict_SetItemString(d, "virtype", o);
3093-
3094- return d;
3095-}
3096-
3097-static PyObject *
3098-do_is_virtualized() {
3099- /*
3100- Python wrapper around is_virtualized().
3101- */
3102-
3103- if (is_virtualized())
3104- return Py_True;
3105-
3106- return Py_False;
3107-}
3108-
3109-static PyObject *
3110-do_get_harddisk_serial(PyObject *o, PyObject *args) {
3111- /*
3112- Python wrapper around read_harddisk_serial.
3113- */
3114-
3115- char serial[21];
3116- memset(serial, 0, sizeof(serial));
3117-
3118- char *device;
3119- if (!PyArg_ParseTuple(args, "s", &device))
3120- return NULL;
3121-
3122- read_harddisk_serial(device, serial);
3123-
3124- if (serial[0])
3125- return PyString_FromString(serial);
3126-
3127- return Py_None;
3128-}
3129-
3130-static PyObject *
3131-do_hypervisor_port_check() {
3132- /*
3133- Python wrapper around hypervisor_port_check().
3134- */
3135-
3136- if (hypervisor_port_check())
3137- return Py_True;
3138-
3139- return Py_False;
3140-}
3141-
3142-static PyMethodDef fireinfoModuleMethods[] = {
3143- { "get_hypervisor", (PyCFunction) do_get_hypervisor, METH_NOARGS, NULL },
3144- { "is_virtualized", (PyCFunction) do_is_virtualized, METH_NOARGS, NULL },
3145- { "get_harddisk_serial", (PyCFunction) do_get_harddisk_serial, METH_VARARGS, NULL },
3146- { "vmware_hypervisor_port_check", (PyCFunction) do_hypervisor_port_check, METH_NOARGS, NULL },
3147- { NULL, NULL, 0, NULL }
3148-};
3149-
3150-void init_fireinfo(void) {
3151- PyObject *m;
3152-
3153- m = Py_InitModule("_fireinfo", fireinfoModuleMethods);
3154-}
3155diff --git a/src/fireinfo/__init__.py.in b/src/fireinfo/__init__.py.in
3156new file mode 100644
3157index 0000000..05c520e
3158--- /dev/null
3159+++ b/src/fireinfo/__init__.py.in
3160@@ -0,0 +1,24 @@
3161+#!/usr/bin/python
3162+###############################################################################
3163+# #
3164+# Fireinfo #
3165+# Copyright (C) 2010, 2011 IPFire Team (www.ipfire.org) #
3166+# #
3167+# This program is free software: you can redistribute it and/or modify #
3168+# it under the terms of the GNU General Public License as published by #
3169+# the Free Software Foundation, either version 3 of the License, or #
3170+# (at your option) any later version. #
3171+# #
3172+# This program is distributed in the hope that it will be useful, #
3173+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
3174+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
3175+# GNU General Public License for more details. #
3176+# #
3177+# You should have received a copy of the GNU General Public License #
3178+# along with this program. If not, see <http://www.gnu.org/licenses/>. #
3179+# #
3180+###############################################################################
3181+
3182+__version__ = "@PACKAGE_VERSION@"
3183+
3184+from system import System
3185diff --git a/src/fireinfo/bios.py b/src/fireinfo/bios.py
3186new file mode 100644
3187index 0000000..56e3af0
3188--- /dev/null
3189+++ b/src/fireinfo/bios.py
3190@@ -0,0 +1,50 @@
3191+#!/usr/bin/python
3192+###############################################################################
3193+# #
3194+# Fireinfo #
3195+# Copyright (C) 2013 IPFire Team (www.ipfire.org) #
3196+# #
3197+# This program is free software: you can redistribute it and/or modify #
3198+# it under the terms of the GNU General Public License as published by #
3199+# the Free Software Foundation, either version 3 of the License, or #
3200+# (at your option) any later version. #
3201+# #
3202+# This program is distributed in the hope that it will be useful, #
3203+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
3204+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
3205+# GNU General Public License for more details. #
3206+# #
3207+# You should have received a copy of the GNU General Public License #
3208+# along with this program. If not, see <http://www.gnu.org/licenses/>. #
3209+# #
3210+###############################################################################
3211+
3212+import os.path
3213+
3214+DMI_VENDORS = [
3215+ "/sys/class/dmi/id/sys_vendor",
3216+ "/sys/class/dmi/id/board_vendor",
3217+ "/sys/class/dmi/id/bios_vendor",
3218+]
3219+
3220+class BIOS(object):
3221+ def __init__(self, system):
3222+ self.system = system
3223+
3224+ def check_vendor(self, vendor, startswith=True):
3225+ for file in DMI_VENDORS:
3226+ if not os.path.exists(file):
3227+ continue
3228+
3229+ with open(file, "r") as f:
3230+ v = f.read()
3231+
3232+ # Strip the vendor string.
3233+ v = v.strip()
3234+
3235+ if startswith and v.startswith(vendor):
3236+ return True
3237+ elif v == vendor:
3238+ return True
3239+
3240+ return False
3241diff --git a/src/fireinfo/cpu.py b/src/fireinfo/cpu.py
3242new file mode 100644
3243index 0000000..32d885d
3244--- /dev/null
3245+++ b/src/fireinfo/cpu.py
3246@@ -0,0 +1,194 @@
3247+#!/usr/bin/python
3248+###############################################################################
3249+# #
3250+# Fireinfo #
3251+# Copyright (C) 2010, 2011 IPFire Team (www.ipfire.org) #
3252+# #
3253+# This program is free software: you can redistribute it and/or modify #
3254+# it under the terms of the GNU General Public License as published by #
3255+# the Free Software Foundation, either version 3 of the License, or #
3256+# (at your option) any later version. #
3257+# #
3258+# This program is distributed in the hope that it will be useful, #
3259+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
3260+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
3261+# GNU General Public License for more details. #
3262+# #
3263+# You should have received a copy of the GNU General Public License #
3264+# along with this program. If not, see <http://www.gnu.org/licenses/>. #
3265+# #
3266+###############################################################################
3267+
3268+import os
3269+
3270+import system
3271+
3272+PROC_CPUINFO = "/proc/cpuinfo"
3273+
3274+class CPU(object):
3275+ """
3276+ A class that represents the first CPU in a system.
3277+
3278+ We get all information form the first CPU (or core) and assume that
3279+ all other ones are equal.
3280+ """
3281+
3282+ __cpuinfo = {}
3283+
3284+ def __init__(self):
3285+ """
3286+ Initialize this class by reading all data from /proc/cpuinfo.
3287+ """
3288+ self.__cpuinfo = self.read_cpuinfo()
3289+
3290+ @property
3291+ def system(self):
3292+ return system.System()
3293+
3294+ @staticmethod
3295+ def read_cpuinfo():
3296+ """
3297+ Read information from PROC_CPUINFO and store
3298+ it into a dictionary cpuinfo.
3299+ """
3300+ cpuinfo = {}
3301+
3302+ f = open(PROC_CPUINFO)
3303+ while True:
3304+ line = f.readline()
3305+
3306+ if not line:
3307+ break
3308+
3309+ try:
3310+ key, val = line.split(":", 1)
3311+ except ValueError:
3312+ # We got a line without key, pass that.
3313+ pass
3314+
3315+ key = key.strip().replace(" ", "_")
3316+ val = val.strip()
3317+
3318+ cpuinfo[key] = val
3319+
3320+ f.close()
3321+
3322+ return cpuinfo
3323+
3324+ @property
3325+ def bogomips(self):
3326+ """
3327+ Return the bogomips of this CPU.
3328+ """
3329+ try:
3330+ bogomips = self.__cpuinfo["bogomips"]
3331+ except KeyError:
3332+ bogomips = self.__cpuinfo["BogoMIPS"]
3333+
3334+ return float(bogomips)
3335+
3336+ @property
3337+ def model(self):
3338+ """
3339+ Return the model id of this CPU.
3340+ """
3341+ try:
3342+ model = int(self.__cpuinfo["model"])
3343+ except KeyError:
3344+ model = None
3345+
3346+ return model
3347+
3348+ @property
3349+ def model_string(self):
3350+ """
3351+ Return the model string of this CPU.
3352+ """
3353+ try:
3354+ return self.__cpuinfo["model_name"]
3355+ except KeyError:
3356+ return self.__cpuinfo["Processor"]
3357+
3358+ @property
3359+ def vendor(self):
3360+ """
3361+ Return the vendor string of this CPU.
3362+ """
3363+ try:
3364+ vendor = self.__cpuinfo["vendor_id"]
3365+ except KeyError:
3366+ if self.system.arch.startswith("arm"):
3367+ vendor = "ARM"
3368+ else:
3369+ vendor = ""
3370+
3371+ return vendor
3372+
3373+ @property
3374+ def stepping(self):
3375+ """
3376+ Return the stepping id of this CPU.
3377+ """
3378+ try:
3379+ stepping = int(self.__cpuinfo["stepping"])
3380+ except KeyError:
3381+ stepping = None
3382+
3383+ return stepping
3384+
3385+ @property
3386+ def flags(self):
3387+ """
3388+ Return all flags of this CPU.
3389+ """
3390+ try:
3391+ flags = self.__cpuinfo["flags"]
3392+ except KeyError:
3393+ flags = self.__cpuinfo["Features"]
3394+
3395+ return flags.split()
3396+
3397+ @property
3398+ def speed(self):
3399+ """
3400+ Return the speed (in MHz) of this CPU.
3401+ """
3402+ try:
3403+ speed = float(self.__cpuinfo["cpu_MHz"])
3404+ except KeyError:
3405+ speed = 0
3406+
3407+ return speed
3408+
3409+ @property
3410+ def family(self):
3411+ """
3412+ Return the family id of this CPU.
3413+ """
3414+ try:
3415+ family = int(self.__cpuinfo["cpu_family"])
3416+ except KeyError:
3417+ family = None
3418+
3419+ return family
3420+
3421+ @property
3422+ def count(self):
3423+ """
3424+ Count number of CPUs (cores).
3425+ """
3426+ return os.sysconf("SC_NPROCESSORS_ONLN")
3427+
3428+
3429+if __name__ == "__main__":
3430+ c = CPU()
3431+
3432+ print "Vendor:", c.vendor
3433+ print "Model:", c.model
3434+ print "Stepping:", c.stepping
3435+ print "Flags:", c.flags
3436+ print "Bogomips:", c.bogomips
3437+ print "Speed:", c.speed
3438+ print "Family:", c.family
3439+ print "Count:", c.count
3440+ print "Model string:", c.model_string
3441diff --git a/src/fireinfo/device.py b/src/fireinfo/device.py
3442new file mode 100644
3443index 0000000..01338b2
3444--- /dev/null
3445+++ b/src/fireinfo/device.py
3446@@ -0,0 +1,133 @@
3447+#!/usr/bin/python
3448+###############################################################################
3449+# #
3450+# Fireinfo #
3451+# Copyright (C) 2010, 2011 IPFire Team (www.ipfire.org) #
3452+# #
3453+# This program is free software: you can redistribute it and/or modify #
3454+# it under the terms of the GNU General Public License as published by #
3455+# the Free Software Foundation, either version 3 of the License, or #
3456+# (at your option) any later version. #
3457+# #
3458+# This program is distributed in the hope that it will be useful, #
3459+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
3460+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
3461+# GNU General Public License for more details. #
3462+# #
3463+# You should have received a copy of the GNU General Public License #
3464+# along with this program. If not, see <http://www.gnu.org/licenses/>. #
3465+# #
3466+###############################################################################
3467+
3468+import os.path
3469+
3470+class Device(object):
3471+ """
3472+ This is an abstract class that represents all devices in the system.
3473+ Every single device has its own instance of this class.
3474+ """
3475+
3476+ def __init__(self, path):
3477+ """
3478+ Collect all information about the device by reading the
3479+ "uevent" file and parsing it.
3480+ """
3481+
3482+ # Save the path in /sys to the device.
3483+ self.path = path
3484+
3485+ # Datastructure to store information we read.
3486+ self._uevent = {}
3487+
3488+ # Open the uevent file and parse all lines.
3489+ with open(os.path.join(path, "uevent")) as f:
3490+ for line in f.readlines():
3491+ key, val = line.split("=")
3492+ self._uevent[key] = val.rstrip().lower()
3493+
3494+ @property
3495+ def driver(self):
3496+ """
3497+ Get the driver/kernel module that device is driven by or return None.
3498+ """
3499+ return self._uevent.get("DRIVER", None)
3500+
3501+
3502+class PCIDevice(Device):
3503+ """
3504+ A class that represents all PCI (and PCIe) devices in a system.
3505+ """
3506+
3507+ subsystem = "pci"
3508+
3509+ @property
3510+ def model(self):
3511+ """
3512+ Return the PCI model id of this device.
3513+ """
3514+ return self._uevent['PCI_ID'].split(":")[1]
3515+
3516+ @property
3517+ def vendor(self):
3518+ """
3519+ Return the PCI vendor id of this device.
3520+ """
3521+ return self._uevent['PCI_ID'].split(":")[0]
3522+
3523+ @property
3524+ def deviceclass(self):
3525+ """
3526+ Return the PCI device class of this device.
3527+ """
3528+ return self._uevent['PCI_CLASS']
3529+
3530+ @property
3531+ def sub_vendor(self):
3532+ """
3533+ Return the PCI vendor sub id of this device.
3534+ """
3535+ return self._uevent["PCI_SUBSYS_ID"].split(":")[0]
3536+
3537+ @property
3538+ def sub_model(self):
3539+ """
3540+ Return the PCI model sub id of this device.
3541+ """
3542+ return self._uevent["PCI_SUBSYS_ID"].split(":")[1]
3543+
3544+
3545+class USBDevice(Device):
3546+ """
3547+ A class that represents all USB devices in a system.
3548+ """
3549+
3550+ subsystem = "usb"
3551+
3552+ def pad(self, s):
3553+ """
3554+ A function to pad ids that have no leading zeroes.
3555+ """
3556+ while len(s) < 4:
3557+ s = "0"+s
3558+ return s
3559+
3560+ @property
3561+ def vendor(self):
3562+ """
3563+ Return the USB vendor id of this device.
3564+ """
3565+ return self.pad(self._uevent['PRODUCT'].split("/")[0])
3566+
3567+ @property
3568+ def model(self):
3569+ """
3570+ Return the USB model id of this device.
3571+ """
3572+ return self.pad(self._uevent['PRODUCT'].split("/")[1])
3573+
3574+ @property
3575+ def deviceclass(self):
3576+ """
3577+ Return the USB device class of this device.
3578+ """
3579+ return self._uevent.get("INTERFACE", None)
3580diff --git a/src/fireinfo/hypervisor.py b/src/fireinfo/hypervisor.py
3581new file mode 100644
3582index 0000000..0c07cfa
3583--- /dev/null
3584+++ b/src/fireinfo/hypervisor.py
3585@@ -0,0 +1,119 @@
3586+#!/usr/bin/python
3587+###############################################################################
3588+# #
3589+# Fireinfo #
3590+# Copyright (C) 2010, 2011 IPFire Team (www.ipfire.org) #
3591+# #
3592+# This program is free software: you can redistribute it and/or modify #
3593+# it under the terms of the GNU General Public License as published by #
3594+# the Free Software Foundation, either version 3 of the License, or #
3595+# (at your option) any later version. #
3596+# #
3597+# This program is distributed in the hope that it will be useful, #
3598+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
3599+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
3600+# GNU General Public License for more details. #
3601+# #
3602+# You should have received a copy of the GNU General Public License #
3603+# along with this program. If not, see <http://www.gnu.org/licenses/>. #
3604+# #
3605+###############################################################################
3606+
3607+import _fireinfo
3608+import system
3609+
3610+class Hypervisor(object):
3611+ def __init__(self):
3612+ self.__hypervisor = _fireinfo.detect_hypervisor()
3613+
3614+ @property
3615+ def system(self):
3616+ """
3617+ Return the current instance of the System class.
3618+
3619+ We need to do that as a property because otherwise
3620+ we get a recursion.
3621+ """
3622+ return system.System()
3623+
3624+ @property
3625+ def vendor(self):
3626+ """
3627+ Returns the name of the hypervisor vendor.
3628+ """
3629+ # Citrix Xen says it is Microsoft Hv.
3630+ if self.__hypervisor == "Microsoft" and self.system.bios_vendor == "Xen":
3631+ return "Xen"
3632+
3633+ # Some of the hypervisors can be detected in a right way.
3634+ # We can return them at this place.
3635+ if self.__hypervisor:
3636+ return self.__hypervisor
3637+
3638+ # Check DMI and BIOS information...
3639+ if self.__bios_is_bochs():
3640+ return "Bochs"
3641+ elif self.__bios_is_microsoft():
3642+ return "Microsoft"
3643+ elif self.__bios_is_qemu():
3644+ return "Qemu"
3645+ elif self.__bios_is_virtualbox():
3646+ return "VirtualBox"
3647+ elif self.__bios_is_vmware():
3648+ return "VMWare"
3649+ elif self.__bios_is_xen():
3650+ return "Xen"
3651+
3652+ @property
3653+ def virtual(self):
3654+ """
3655+ Returns true if the host is running in a virtual environment.
3656+ Otherwise: false.
3657+ """
3658+ if self.vendor:
3659+ return True
3660+
3661+ return False
3662+
3663+ def __bios_is_bochs(self):
3664+ """
3665+ Check for Bochs emulator.
3666+ """
3667+ return self.system.bios.check_vendor("Bochs")
3668+
3669+ def __bios_is_microsoft(self):
3670+ """
3671+ Check for Microsoft hypervisor.
3672+ """
3673+ return self.system.bios.check_vendor("Microsoft Corporation")
3674+
3675+ def __bios_is_qemu(self):
3676+ """
3677+ Check for qemu emulator.
3678+ """
3679+ return self.system.bios.check_vendor("QEMU")
3680+
3681+ def __bios_is_virtualbox(self):
3682+ """
3683+ Check for virtualbox hypervisor by comparing the bios vendor string
3684+ to "innotek GmbH".
3685+ """
3686+ return self.system.bios.check_vendor("innotek GmbH")
3687+
3688+ def __bios_is_vmware(self):
3689+ if self.system.bios.check_vendor("VMware-"):
3690+ return True
3691+ elif self.system.bios.check_vendor("VMW"):
3692+ return True
3693+
3694+ return False
3695+
3696+ def __bios_is_xen(self):
3697+ return self.system.bios.check_vendor("Xen")
3698+
3699+
3700+if __name__ == "__main__":
3701+ h = Hypervisor()
3702+
3703+ print "Vendor:", h.vendor
3704+ print "Virtual:", h.virtual
3705diff --git a/src/fireinfo/network.py b/src/fireinfo/network.py
3706new file mode 100644
3707index 0000000..063e9ec
3708--- /dev/null
3709+++ b/src/fireinfo/network.py
3710@@ -0,0 +1,53 @@
3711+#!/usr/bin/python
3712+###############################################################################
3713+# #
3714+# Fireinfo #
3715+# Copyright (C) 2010, 2011 IPFire Team (www.ipfire.org) #
3716+# #
3717+# This program is free software: you can redistribute it and/or modify #
3718+# it under the terms of the GNU General Public License as published by #
3719+# the Free Software Foundation, either version 3 of the License, or #
3720+# (at your option) any later version. #
3721+# #
3722+# This program is distributed in the hope that it will be useful, #
3723+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
3724+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
3725+# GNU General Public License for more details. #
3726+# #
3727+# You should have received a copy of the GNU General Public License #
3728+# along with this program. If not, see <http://www.gnu.org/licenses/>. #
3729+# #
3730+###############################################################################
3731+
3732+import os
3733+
3734+SYS_CLASS_NET = "/sys/class/net"
3735+
3736+class Network(object):
3737+ def __init__(self):
3738+ self._devices = os.listdir(SYS_CLASS_NET)
3739+
3740+ def has_green(self):
3741+ return "green0" in self._devices
3742+
3743+ def has_red(self):
3744+ for i in ("red0", "ppp0"):
3745+ if i in self._devices:
3746+ return True
3747+
3748+ return False
3749+
3750+ def has_blue(self):
3751+ return "blue0" in self._devices
3752+
3753+ def has_orange(self):
3754+ return "orange0" in self._devices
3755+
3756+
3757+if __name__ == "__main__":
3758+ n = Network()
3759+
3760+ print "has_green", n.has_green()
3761+ print "has_red", n.has_red()
3762+ print "has_blue", n.has_blue()
3763+ print "has_orange", n.has_orange()
3764diff --git a/src/fireinfo/system.py b/src/fireinfo/system.py
3765new file mode 100644
3766index 0000000..0a60bcc
3767--- /dev/null
3768+++ b/src/fireinfo/system.py
3769@@ -0,0 +1,451 @@
3770+#!/usr/bin/python
3771+###############################################################################
3772+# #
3773+# Fireinfo #
3774+# Copyright (C) 2010, 2011 IPFire Team (www.ipfire.org) #
3775+# #
3776+# This program is free software: you can redistribute it and/or modify #
3777+# it under the terms of the GNU General Public License as published by #
3778+# the Free Software Foundation, either version 3 of the License, or #
3779+# (at your option) any later version. #
3780+# #
3781+# This program is distributed in the hope that it will be useful, #
3782+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
3783+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
3784+# GNU General Public License for more details. #
3785+# #
3786+# You should have received a copy of the GNU General Public License #
3787+# along with this program. If not, see <http://www.gnu.org/licenses/>. #
3788+# #
3789+###############################################################################
3790+
3791+import hashlib
3792+import json
3793+import os
3794+import string
3795+
3796+import _fireinfo
3797+
3798+import bios
3799+import cpu
3800+import device
3801+import hypervisor
3802+import network
3803+
3804+PROFILE_VERSION = 0
3805+
3806+SYS_CLASS_DMI = "/sys/class/dmi/id"
3807+SECRET_ID_FILE = "/etc/fireinfo-id"
3808+
3809+INVALID_ID_STRINGS = (
3810+ "OEM", "O.E.M.", "o.e.m.",
3811+ "N/A", "n/a",
3812+ "12345", "54321", "202020",
3813+ "Chassis", "chassis",
3814+ "Not Applicable",
3815+ "None", "empty",
3816+ "01010101-0101-0101-0101-010101010101",
3817+ "00020003-0004-0005-0006-000700080009",
3818+ "03000200-0400-0500-0006-000700080009",
3819+ "0000000", "00000000",
3820+)
3821+
3822+class Singleton(type):
3823+ def __init__(cls, name, bases, dict):
3824+ super(Singleton, cls).__init__(name, bases, dict)
3825+ cls.instance = None
3826+
3827+ def __call__(cls, *args, **kw):
3828+ if cls.instance is None:
3829+ cls.instance = super(Singleton, cls).__call__(*args, **kw)
3830+
3831+ return cls.instance
3832+
3833+
3834+def read_from_file(filename):
3835+ """
3836+ Read all data from filename.
3837+ """
3838+ if not os.path.exists(filename):
3839+ return
3840+
3841+ try:
3842+ with open(filename) as f:
3843+ return f.read().strip()
3844+ except IOError:
3845+ pass
3846+
3847+class System(object):
3848+ __metaclass__ = Singleton
3849+
3850+ def __init__(self):
3851+ self.bios = bios.BIOS(self)
3852+
3853+ # find all devices
3854+ self.devices = []
3855+ self.scan()
3856+ self.cpu = cpu.CPU()
3857+ self.hypervisor = hypervisor.Hypervisor()
3858+
3859+ # Read /proc/cpuinfo for vendor information.
3860+ self.__cpuinfo = self.cpu.read_cpuinfo()
3861+
3862+ def profile(self):
3863+ p = {}
3864+ p["system"] = {
3865+ # System information
3866+ "model" : self.model,
3867+ "vendor" : self.vendor,
3868+
3869+ # Indicator if the system is running in a
3870+ # virtual environment.
3871+ "virtual" : self.virtual,
3872+
3873+ # System language
3874+ "language" : self.language,
3875+
3876+ # Release information
3877+ "release" : self.release,
3878+ "kernel_release" : self.kernel_release,
3879+
3880+ "memory" : self.memory,
3881+ "root_size" : self.root_size,
3882+ }
3883+
3884+ p["devices"] = []
3885+ for device in self.devices:
3886+ d = {
3887+ "subsystem" : device.subsystem.lower(),
3888+ "vendor" : device.vendor.lower(),
3889+ "model" : device.model.lower(),
3890+ "deviceclass" : device.deviceclass,
3891+ "driver" : device.driver,
3892+ }
3893+
3894+ # PCI devices provide subsystem information, USB don't.
3895+ if d["subsystem"] == "pci":
3896+ d["sub_model"] = device.sub_model
3897+ d["sub_vendor"] = device.sub_vendor
3898+
3899+ p["devices"].append(d)
3900+
3901+ p["cpu"] = {
3902+ "arch" : self.arch,
3903+ "vendor" : self.cpu.vendor,
3904+ "model" : self.cpu.model,
3905+ "model_string" : self.cpu.model_string,
3906+ "stepping" : self.cpu.stepping,
3907+ "flags" : self.cpu.flags,
3908+ "bogomips" : self.cpu.bogomips,
3909+ "speed" : self.cpu.speed,
3910+ "family" : self.cpu.family,
3911+ "count" : self.cpu.count
3912+ }
3913+
3914+ p["network"] = {
3915+ "green" : self.network.has_green(),
3916+ "blue" : self.network.has_blue(),
3917+ "orange" : self.network.has_orange(),
3918+ "red" : self.network.has_red(),
3919+ }
3920+
3921+ # Only append hypervisor information if we are virtualized.
3922+ if self.virtual:
3923+ p["hypervisor"] = {
3924+ "vendor" : self.hypervisor.vendor,
3925+ }
3926+
3927+ return {
3928+ # Profile version
3929+ "profile_version" : PROFILE_VERSION,
3930+
3931+ # Identification and authorization codes
3932+ "public_id" : self.public_id,
3933+ "private_id" : self.private_id,
3934+
3935+ # Actual profile data
3936+ "profile" : p,
3937+ }
3938+
3939+
3940+ @property
3941+ def arch(self):
3942+ return os.uname()[4]
3943+
3944+ @property
3945+ def public_id(self):
3946+ """
3947+ This returns a globally (hopefully) ID to identify the host
3948+ later (by request) in the database.
3949+ """
3950+ public_id = self.secret_id
3951+ if not public_id:
3952+ return "0" * 40
3953+
3954+ return hashlib.sha1(public_id).hexdigest()
3955+
3956+ @property
3957+ def private_id(self):
3958+ """
3959+ The private ID is built out of the _unique_id and used to
3960+ permit a host to do changes on the database.
3961+
3962+ No one could ever guess this without access to the host.
3963+ """
3964+ private_id = ""
3965+ for i in reversed(self.secret_id):
3966+ private_id += i
3967+
3968+ if not private_id:
3969+ return "0" * 40
3970+
3971+ return hashlib.sha1(private_id).hexdigest()
3972+
3973+ @property
3974+ def secret_id(self):
3975+ """
3976+ Read a "secret" ID from a file if available
3977+ or calculate it from the hardware.
3978+ """
3979+ if os.path.exists(SECRET_ID_FILE):
3980+ return read_from_file(SECRET_ID_FILE)
3981+
3982+ return hashlib.sha1(self._unique_id).hexdigest()
3983+
3984+ @property
3985+ def _unique_id(self):
3986+ """
3987+ This is a helper ID which is generated out of some hardware information
3988+ that is considered to be constant over a PC's lifetime.
3989+
3990+ None of the data here is ever sent to the server.
3991+ """
3992+ ids = []
3993+
3994+ # Virtual machines (for example) and some boards have a UUID
3995+ # which is globally unique.
3996+ for file in ("product_uuid", "product_serial", "chassis_serial"):
3997+ id = read_from_file(os.path.join(SYS_CLASS_DMI, file))
3998+ ids.append(id)
3999+
4000+ # Sort out all bogous or invalid strings from the list.
4001+ _ids = []
4002+ for id in ids:
4003+ if id is None:
4004+ continue
4005+
4006+ for i in INVALID_ID_STRINGS:
4007+ if i in id:
4008+ id = None
4009+ break
4010+
4011+ if id:
4012+ _ids.append(id)
4013+
4014+ ids = _ids
4015+
4016+ # Use serial number from root disk (if available) and if
4017+ # no other ID was found, yet.
4018+ if not ids:
4019+ root_disk_serial = self.root_disk_serial
4020+ if root_disk_serial and not root_disk_serial.startswith("QM000"):
4021+ ids.append(root_disk_serial)
4022+
4023+ # As last resort, we use the UUID from pakfire.
4024+ if not ids:
4025+ id = read_from_file("/opt/pakfire/db/uuid")
4026+ ids.append(id)
4027+
4028+ return "#".join(ids)
4029+
4030+ @property
4031+ def language(self):
4032+ """
4033+ Return the language code of IPFire or "unknown" if we cannot get it.
4034+ """
4035+ # Return "unknown" if settings file does not exist.
4036+ filename = "/var/ipfire/main/settings"
4037+ if not os.path.exists(filename):
4038+ return "unknown"
4039+
4040+ with open(filename, "r") as f:
4041+ for line in f.readlines():
4042+ key, val = line.split("=", 1)
4043+ if key == "LANGUAGE":
4044+ return val.strip()
4045+
4046+ @property
4047+ def release(self):
4048+ """
4049+ Return the system release string.
4050+ """
4051+ return read_from_file("/etc/system-release") or "unknown"
4052+
4053+ @property
4054+ def bios_vendor(self):
4055+ """
4056+ Return the bios vendor name.
4057+ """
4058+ return read_from_file("/sys/class/dmi/id/bios_vendor")
4059+
4060+ def vendor_model_tuple(self):
4061+ try:
4062+ s = self.__cpuinfo["Hardware"]
4063+ except KeyError:
4064+ return (None, None)
4065+
4066+ if s.startswith("ARM-Versatile"):
4067+ return ("ARM", s)
4068+
4069+ try:
4070+ v, m = s.split(" ", 1)
4071+ except ValueError:
4072+ if s.startswith("BCM"):
4073+ v = "Broadcom"
4074+ m = s
4075+ else:
4076+ v = None
4077+ m = s
4078+
4079+ return v, m
4080+
4081+ @property
4082+ def vendor(self):
4083+ """
4084+ Return the vendor string of this system (if any).
4085+ """
4086+ ret = None
4087+ for file in ("sys_vendor", "board_vendor", "chassis_vendor",):
4088+ ret = read_from_file(os.path.join(SYS_CLASS_DMI, file))
4089+ if ret:
4090+ break
4091+
4092+ if ret is None:
4093+ v, m = self.vendor_model_tuple()
4094+ ret = v
4095+
4096+ return ret
4097+
4098+ @property
4099+ def model(self):
4100+ """
4101+ Return the model string of this system (if any).
4102+ """
4103+ ret = None
4104+ for file in ("product_name", "board_model", "chassis_model",):
4105+ ret = read_from_file(os.path.join(SYS_CLASS_DMI, file))
4106+ if ret:
4107+ break
4108+
4109+ if ret is None:
4110+ v, m = self.vendor_model_tuple()
4111+ ret = m
4112+
4113+ return ret
4114+
4115+ @property
4116+ def memory(self):
4117+ """
4118+ Return the amount of memory in kilobytes.
4119+ """
4120+ with open("/proc/meminfo", "r") as f:
4121+ firstline = f.readline().strip()
4122+ return int(firstline.split()[1])
4123+
4124+ @property
4125+ def kernel_release(self):
4126+ """
4127+ Return the kernel release string.
4128+ """
4129+ return os.uname()[2]
4130+
4131+ @property
4132+ def root_disk(self):
4133+ """
4134+ Return the dev node of the root disk.
4135+ """
4136+ with open("/etc/mtab", "r") as f:
4137+ dev, mountpoint, fs, rest = f.readline().split(" ", 3)
4138+ if mountpoint == "/" and not fs == "rootfs":
4139+ # Cut off /dev
4140+ dev = dev[5:]
4141+
4142+ # Handle raids and MMC cards like (mmcblk0p3).
4143+ if dev[-2] == "p":
4144+ return dev[:-2]
4145+
4146+ # Otherwise cut off all digits at end of string
4147+ while dev[-1] in string.digits:
4148+ dev = dev[:-1]
4149+
4150+ return dev
4151+
4152+ @property
4153+ def root_size(self):
4154+ """
4155+ Return the size of the root disk in kilobytes.
4156+ """
4157+ path = "/sys/block/%s/size" % self.root_disk
4158+ if not os.path.exists(path):
4159+ return
4160+
4161+ with open(path, "r") as f:
4162+ return int(f.readline()) * 512 / 1024
4163+
4164+ @property
4165+ def root_disk_serial(self):
4166+ """
4167+ Return the serial number of the root disk (if any).
4168+ """
4169+ serial = _fireinfo.get_harddisk_serial("/dev/%s" % self.root_disk)
4170+
4171+ if serial:
4172+ # Strip all spaces
4173+ return serial.strip()
4174+
4175+ def scan(self):
4176+ """
4177+ Scan for all devices (PCI/USB) in the system and append them
4178+ to our list.
4179+ """
4180+ self.devices = []
4181+
4182+ toscan = (
4183+ ("/sys/bus/pci/devices", device.PCIDevice),
4184+ ("/sys/bus/usb/devices", device.USBDevice)
4185+ )
4186+ for path, cls in toscan:
4187+ if not os.path.exists(path):
4188+ continue
4189+
4190+ dirlist = os.listdir(path)
4191+ for dir in dirlist:
4192+ self.devices.append(cls(os.path.join(path, dir)))
4193+
4194+ @property
4195+ def virtual(self):
4196+ """
4197+ Say if the host is running in a virtual environment.
4198+ """
4199+ return self.hypervisor.virtual
4200+
4201+ @property
4202+ def network(self):
4203+ """
4204+ Reference to the network class.
4205+ """
4206+ return network.Network()
4207+
4208+
4209+if __name__ == "__main__":
4210+ s=System()
4211+ print s.arch
4212+ print s.language
4213+ print s.release
4214+ print s.bios_vendor
4215+ print s.memory
4216+ print s.kernel
4217+ print s.root_disk
4218+ print s.root_size
4219+ print "------------\n", s.devices, "\n------------\n"
4220+ print json.dumps(s.profile(), sort_keys=True, indent=4)
4221diff --git a/src/sendprofile b/src/sendprofile
4222new file mode 100644
4223index 0000000..da480ce
4224--- /dev/null
4225+++ b/src/sendprofile
4226@@ -0,0 +1,132 @@
4227+#!/usr/bin/python
4228+###############################################################################
4229+# #
4230+# Fireinfo #
4231+# Copyright (C) 2010, 2011 IPFire Team (www.ipfire.org) #
4232+# #
4233+# This program is free software: you can redistribute it and/or modify #
4234+# it under the terms of the GNU General Public License as published by #
4235+# the Free Software Foundation, either version 3 of the License, or #
4236+# (at your option) any later version. #
4237+# #
4238+# This program is distributed in the hope that it will be useful, #
4239+# but WITHOUT ANY WARRANTY; without even the implied warranty of #
4240+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
4241+# GNU General Public License for more details. #
4242+# #
4243+# You should have received a copy of the GNU General Public License #
4244+# along with this program. If not, see <http://www.gnu.org/licenses/>. #
4245+# #
4246+###############################################################################
4247+
4248+import json
4249+import logging
4250+import logging.handlers
4251+import os
4252+import sys
4253+import urllib
4254+import urllib2
4255+
4256+import fireinfo
4257+
4258+ENABLED_FILE = "/var/ipfire/main/send_profile"
4259+PROXY_SETTINGS = "/var/ipfire/proxy/advanced/settings"
4260+
4261+log_level = logging.INFO
4262+if "-d" in sys.argv:
4263+ log_level = logging.DEBUG
4264+
4265+# Setup logging
4266+log = logging.getLogger()
4267+log.setLevel(log_level)
4268+log.addHandler(logging.handlers.SysLogHandler("/dev/log"))
4269+log.addHandler(logging.StreamHandler(sys.stderr))
4270+for handler in log.handlers:
4271+ handler.setLevel(log_level)
4272+
4273+PROFILE_URL = "http://fireinfo.ipfire.org/send/%(public_id)s"
4274+
4275+def get_upstream_proxy():
4276+ if not os.path.exists(PROXY_SETTINGS):
4277+ return {"host" : ""}
4278+
4279+ proxy_settings = {}
4280+ with open(PROXY_SETTINGS) as f:
4281+ for line in f.readlines():
4282+ k, v = line.split("=", 1)
4283+ proxy_settings[k] = v.strip()
4284+
4285+ return {
4286+ "host" : proxy_settings.get("UPSTREAM_PROXY", ""),
4287+ "user" : proxy_settings.get("UPSTREAM_USER", ""),
4288+ "pass" : proxy_settings.get("UPSTREAM_PASSWORD", ""),
4289+ }
4290+
4291+def send_profile(profile):
4292+ logging.debug("Sending profile:")
4293+ for line in json.dumps(profile, sort_keys=True, indent=4).splitlines():
4294+ logging.debug(line)
4295+
4296+ request = urllib2.Request(PROFILE_URL % profile,
4297+ data = urllib.urlencode({"profile" : json.dumps(profile)}),
4298+ )
4299+ request.add_header("User-Agent", "fireinfo/%s" % fireinfo.__version__)
4300+
4301+ # Set upstream proxy if we have one.
4302+ # XXX this cannot handle authentication
4303+ proxy = get_upstream_proxy()
4304+ if proxy["host"]:
4305+ request.set_proxy(proxy["host"], "http")
4306+
4307+ try:
4308+ urllib2.urlopen(request, timeout=60)
4309+ except (urllib2.HTTPError, urllib2.URLError), e:
4310+ reason = "Unknown reason"
4311+
4312+ if isinstance(e, urllib2.HTTPError):
4313+ reason = "%s" % e
4314+ elif isinstance(e, urllib2.URLError):
4315+ reason = e.reason
4316+
4317+ logging.error("Profile was not sent propertly: %s" % reason)
4318+ return
4319+
4320+ logging.debug("Profile was sent successfully.")
4321+
4322+def main():
4323+ # Collect system information
4324+ system = fireinfo.System()
4325+ profile = system.profile()
4326+
4327+ # If --dump is passed -> only dump the output.
4328+ if "--dump" in sys.argv:
4329+ # Remove the private id when dumping the profile because
4330+ # it contains no information and may confuse people.
4331+ del profile["private_id"]
4332+
4333+ print json.dumps(profile, sort_keys=True, indent=4)
4334+ return 0
4335+
4336+ if "--secret-id" in sys.argv:
4337+ print system.secret_id
4338+ return 0
4339+
4340+ if "--hardware-string" in sys.argv:
4341+ print system._unique_id
4342+ return 0
4343+
4344+ if "--public-id" in sys.argv:
4345+ print system.public_id
4346+ return 0
4347+
4348+ if not os.path.exists(ENABLED_FILE):
4349+ del profile["profile"]
4350+
4351+ try:
4352+ send_profile(profile)
4353+ except urllib2.URLError:
4354+ return 1
4355+
4356+ return 0
4357+
4358+sys.exit(main())