]> git.ipfire.org Git - people/teissler/ipfire-2.x.git/blob - src/patches/fireinfo-2.1.7-testing.patch
Merge remote-tracking branch 'origin/next' into fifteen
[people/teissler/ipfire-2.x.git] / src / patches / fireinfo-2.1.7-testing.patch
1 diff --git a/.gitignore b/.gitignore
2 index 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-*
38 diff --git a/COPYING b/COPYING
39 new file mode 100644
40 index 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>.
718 diff --git a/MANIFEST b/MANIFEST
719 deleted file mode 100644
720 index 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
733 diff --git a/Makefile.am b/Makefile.am
734 new file mode 100644
735 index 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)
826 diff --git a/autogen.sh b/autogen.sh
827 new file mode 100755
828 index 0000000..c08fadf
829 --- /dev/null
830 +++ b/autogen.sh
831 @@ -0,0 +1,3 @@
832 +#!/bin/sh
833 +
834 +autoreconf --force --install --symlink
835 diff --git a/configure.ac b/configure.ac
836 new file mode 100644
837 index 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 +])
951 diff --git a/fireinfo/__init__.py b/fireinfo/__init__.py
952 deleted file mode 100644
953 index 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
981 diff --git a/fireinfo/cpu.py b/fireinfo/cpu.py
982 deleted file mode 100644
983 index 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
1181 diff --git a/fireinfo/device.py b/fireinfo/device.py
1182 deleted file mode 100644
1183 index 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)
1320 diff --git a/fireinfo/hypervisor.py b/fireinfo/hypervisor.py
1321 deleted file mode 100644
1322 index 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
1475 diff --git a/fireinfo/network.py b/fireinfo/network.py
1476 deleted file mode 100644
1477 index 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()
1534 diff --git a/fireinfo/system.py b/fireinfo/system.py
1535 deleted file mode 100644
1536 index 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)
1989 diff --git a/m4/.gitignore b/m4/.gitignore
1990 new file mode 100644
1991 index 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
2000 diff --git a/m4/attributes.m4 b/m4/attributes.m4
2001 new file mode 100644
2002 index 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 +])
2294 diff --git a/runpychecker.sh b/runpychecker.sh
2295 index 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
2304 diff --git a/sendprofile b/sendprofile
2305 deleted file mode 100644
2306 index 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())
2442 diff --git a/setup.py b/setup.py
2443 deleted file mode 100644
2444 index 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 -)
2485 diff --git a/src/_fireinfo/fireinfo.c b/src/_fireinfo/fireinfo.c
2486 new file mode 100644
2487 index 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 +}
2722 diff --git a/src/fireinfo.c b/src/fireinfo.c
2723 deleted file mode 100644
2724 index 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 -}
3155 diff --git a/src/fireinfo/__init__.py.in b/src/fireinfo/__init__.py.in
3156 new file mode 100644
3157 index 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
3185 diff --git a/src/fireinfo/bios.py b/src/fireinfo/bios.py
3186 new file mode 100644
3187 index 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
3241 diff --git a/src/fireinfo/cpu.py b/src/fireinfo/cpu.py
3242 new file mode 100644
3243 index 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
3441 diff --git a/src/fireinfo/device.py b/src/fireinfo/device.py
3442 new file mode 100644
3443 index 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)
3580 diff --git a/src/fireinfo/hypervisor.py b/src/fireinfo/hypervisor.py
3581 new file mode 100644
3582 index 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
3705 diff --git a/src/fireinfo/network.py b/src/fireinfo/network.py
3706 new file mode 100644
3707 index 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()
3764 diff --git a/src/fireinfo/system.py b/src/fireinfo/system.py
3765 new file mode 100644
3766 index 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)
4221 diff --git a/src/sendprofile b/src/sendprofile
4222 new file mode 100644
4223 index 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())