Nouvelles du Libre

Un OpenDataCamp le 16 avril à Paris

Toolinux - jeu, 10/04/2014 - 23:15

Un OpenDataCamp aura lieu le mercredi 16 avril lors de la 3ème édition de la conférence Devoxx France.

- Evénements et séminaires
Catégories: Nouvelles du Libre

IBM présente de nouvelles offres Cloud, Mobile et Hadoop

Toolinux - jeu, 10/04/2014 - 23:05

Big Blue lance une série de nouvelles offres de Cloud Computing pour le mainframe, notamment la première solution intégrée à base de System z, l'IBM Enterprise Cloud System.

- Services
Catégories: Nouvelles du Libre

Une nouvelle édition du tremplin linuxembedded.fr

Toolinux - mer, 09/04/2014 - 23:47

Ce concours a pour vocation d'organiser un rendez-vous dédié à l'Open source pour les systèmes embarqués.

- Evénements et séminaires
Catégories: Nouvelles du Libre

Le Cloud Computing pour tout et pour tout le monde ?

Toolinux - mer, 09/04/2014 - 23:25

Depuis un certain nombre d'années, tout ou presque a déjà été dit à propos du Cloud Computing. Ses bénéfices sont multiples. Ils incluent notamment une accessibilité rapide en libre-service et à la demande, une mutualisation des services et une facturation à l'usage. Un portrait séduisant qui peut légitimer toutes les ambitions de basculer sur le Cloud. Mais est-ce pour autant une solution universelle qui réponde à tous les besoins ?

- Revue de presse
Catégories: Nouvelles du Libre

Une solution de sécurité pour les clients légers/zéro IGEL

Toolinux - mer, 09/04/2014 - 23:20

Après une intégration dans ses clients légers SoC, IGEL a décidé d'équiper également tous ses autres modèles basés sur des processeurs x86 de la solution Imprivata OneSign ProveID Embedded.

- Matériels
Catégories: Nouvelles du Libre

Open Food Facts sera créé la semaine prochaine

Toolinux - mer, 09/04/2014 - 23:15

Dans l'esprit "libre", la création de l'association Open Food Facts et son assemblée constitutive est annoncée au NUMA à Paris le 11 avril prochain.

- Evénements et séminaires
Catégories: Nouvelles du Libre

Mirantis OpenStack intégrée à Parallels Automation

Toolinux - mer, 09/04/2014 - 23:10

Mirantis et Parallels annoncent cette semaine une collaboration portant sur l'intégration de Mirantis OpenStack à la plate-forme Parallels Automation.

- Services
Catégories: Nouvelles du Libre

Talend conclut un partenariat avec Blue Yonder

Toolinux - mer, 09/04/2014 - 23:05

Les deux entreprises présenteront leur portefeuille commun de solutions lors du congrès Datalympics, les 1er et 2 juillet à Francfort.

- Services
Catégories: Nouvelles du Libre

Quid de la production annuelle de données en 2014 ?

Toolinux - mer, 09/04/2014 - 23:00

EMC dévoilait hier les résultats de la 7ème édition de son étude Digital Universe, qui dresse le portrait de l'évolution de la production annuelle de données.

- 06. Matériel
Catégories: Nouvelles du Libre

Données d'entreprise et applications grand public : un mélange dangereux

Toolinux - mar, 08/04/2014 - 23:25

Suite au rachat de WhatsApp par Facebook pour 16 milliards de dollars récemment, un certain nombre de spécialistes ont fait remarquer que Facebook ne déboursait pas une telle somme uniquement pour acquérir 450 millions de nouveaux utilisateurs, mais plutôt que le réseau social offrait 35 dollars pour récupérer le répertoire téléphonique de chacun de ces 450 millions d'individus.

- Logiciels
Catégories: Nouvelles du Libre

Une fondation .Net, le scénario du pire pour le logiciel libre ?

Toolinux - mar, 08/04/2014 - 23:25

Bientôt, tous les acteurs du numérique auront adopté d'une manière ou d'une autre le développement à code source ouvert pour leurs services et logiciels propriétaires. Nos utilisateurs en seront toujours au même point que sous l'époque de l'hégémonie de Microsoft. Nous surferons peut-être tous sur GoogleNet dont nous serons les otages dociles et volontaires.

- Revue de presse
Catégories: Nouvelles du Libre

Un datacenter pour chaque entreprise

Toolinux - mar, 08/04/2014 - 23:15

Celeste lance le StarDC, le mini-datacenter haute-densité et écologique pour les entreprises.

- Services
Catégories: Nouvelles du Libre

Linutop 13.10 disponible pour "tous les PC"

Toolinux - mar, 08/04/2014 - 23:10

L'éditeur français sort cette semaine une nouvelle version 13.10 dusSystème d'exploitation (OS) PC basé sur Linux et Ubuntu.

- Logiciels
Catégories: Nouvelles du Libre

Rust s’oxyde en version 0.10

Linuxfr - mar, 08/04/2014 - 20:27

Mozilla et la communauté Rust ont annoncé la version 0.10 de Rust le 3 avril. Rust est un langage de programmation développé par Mozilla. La version 0.1 a été annoncée par Mozilla le 20 janvier 2012. Pour découvrir le langage, on peut se référer au nouveau site web sur lequel on peut lire :

Rust est un langage de programmation système qui est extrêmement rapide, empêche presque tous les plantages et élimine les accès concurrent.

Rust se veut donc une alternative à C/C++, comme D et Go, et possède tout comme ces derniers un ramasse-miettes, mais qui est optionnel. Sa syntaxe est proche de celle du C/C++/Java tout en étant beaucoup plus expressif. Sa force est de mélanger les fonctionnalités de différents paradigmes, beaucoup venant du fonctionnel (immuabilité par défaut, modèle objet proche de celui d'Haskell, fermetures, etc). Il met l'accent sur la sûreté d'exécution, notamment grâce à son système élaboré de pointeurs intelligents et son système de types forts, sans sacrifier les performances.

Depuis la version 0.9, qui a fait l’objet d’une dépêche, les efforts ont notamment porté au cours des 1500 changements sur la simplification du langage. Le langage Rust n'est pas stabilisé, cela viendra avec la version 1.0.

Cette itération de développement a apporté le découpage de la bibliothèque libextra, introduit des extensions de syntaxe inter crate, amélioré la manipulation des pointeurs avec le trait Deref et la gestion des erreurs des entrées/sorties.
En dehors du compilateur, cette nouvelle version a vu l'introduction d'un nouveau processus de RFC ainsi que la construction quotidienne des installateurs binaires.

Des améliorations ont été données à l'infrastructure de tests et aux scripts de construction. Des installeurs sont désormais disponibles pour Linux, MacOS et Windows. Même si certains font tourner Rust sur ARM, ce n'est pas une architecture proposée dans la documentation.

Comme pour les précédentes versions, cette version 0.10 doit être considérée comme une version alpha, appropriée pour les adopteurs précoces et les amateurs de langages.

Sommaire Changements du langage

Vous pouvez consulter les notes de version officielles, mais ne vous inquiétez pas, on vous résume tout plus bas.

Syntaxe #![feature(default_type_params)] struct Foo<T = char> { a: T } struct Bar<A, B = int, C = (int,char)> { field1: A, field2: B, field3: C } match s.as_slice() { "a" => do_a(), "b" => do_b(), _ => fail!("autre") }
  • Déplacement de la macro debug! dans la bibliothèque log.
  • Modifications de la syntaxe des attributs de crate. Par exemple, au lieu de #[license = "MIT/ASL2"];, il faut utiliser #![license = "MIT/ASL2"] (sans point-virgule).
  • Suppression de Vec::map(), il faut utiliser les fonctions anonymes ou .iter().map().
  • Suppression de collections::List. On peut utiliser à la place Vec ou collections::DList si on veut vraiment une liste chainée.
Suppression des conditions

Les conditions ont été supprimées, cela change donc la façon de gérer les erreurs d’entrée/sortie.

Les conditions permettaient de gérer les erreurs un peu à la manière des exceptions en Java et C++, mais de manière sûre. Néanmoins c’était plus complexe à utiliser, et il était difficile de deviner quand la bibliothèque standard utilisait les Option/Result ou les conditions pour gérer les erreurs.

Dans la plupart des cas, il faut maintenant utiliser le filtrage par motif (pattern matching) sur les résultats des opérations. Par exemple, pour supprimer un fichier :

let path = Path::new("chemin/vers/fichier.txt"); match fs::unlink(&path) { Err(e) => fail!("L'ouverture de {:?} a échoué: {}.", path, e), _ => debug!("L'ouverture de {:?} a réussi.", path) }

En effet, désormais toutes les opérations d’entrées/sorties renvoient un IoResult (qui est un petit alias de type : type IoResult<T> = Result<T, IoError>;).

On peut aussi utiliser la macro try!, qui arrêtera immédiatement le programme si la récupération du résultat échoue. Cela donne un code plus court dans les cas où l’arrêt du programme n’est pas un souci/est préférable :

let path = Path::new("chemin/vers/fichier.txt"); let file = try!(fs::unlink(&path)); Les traits Deref et DerefMut

Ce sont globalement une surcharge à l’opérateur *. Par exemple :

struct Foo { a: int } impl Deref<int> for Foo { fn deref<'a>(&'a self) -> &'a int { &self.a } } let test = Foo { a: 3 }; println!("{}", *test); // affiche « 3 » let borrowed: &int = &*test; // déréférence, mais ne déplace pas println!("{}", *borrowed);

Le trait DerefMut permet la surcharge de la forme *test = value;, ainsi que de prendre une adresse mutable du contenu comme &mut *test.

Ces deux traits participent à la fonctionnalité d’auto-déréférencement du compilateur, rendant les pointeurs intelligents beaucoup plus faciles à utiliser. C’est une étape très importante, car après la disparation du pointeur @, on a commencé à utiliser les alternatives dans la bibliothèque standard qui étaient beaucoup moins pratiques, comme Rc<T>. Leur utilisation est maintenant beaucoup moins verbeuse et devient, dans plusieurs cas, transparente.

Modifications des durées de vie des valeurs temporaires let slot = RefCell::new(1); *slot.borrow_mut() = 4; println!("{}", *slot.borrow());

Ce code ne compilait pas précédemment car l’information de durée de vie liée de la valeur renvoyée par slot.borrow_mut() n’était pas désallouée ; la slot.borrow() échouait alors (on ne peut emprunter (borrow) plusieurs fois une même variable en Rust). Désormais, l’information de durée de vie liée à une valeur temporaire est désallouée le plus tôt possible, c’est-à-dire ici à la fin de la ligne.

Modification du traitement des valeurs static
  • Les expressions static ne doivent pas être d’un type qui a un destructeur défini par l’utilisateur,
  • ne doivent pas avoir une valeur qui elle-même requiert un destructeur,
  • celles qui contiennent un Unsafe<T> ne peuvent avoir leur adresse prise,
  • enfin, les expression static mut ne doivent pas avoir de type qui nécessite un destructeur (défini par l’utilisateur ou non).
Bibliothèque standard Extensions de syntaxe

Il est désormais possible de créer des extensions de syntaxe dans une crate et de l’utiliser dans une autre : c’est une limitation très ennuyeuse qui disparait ! Les extensions de syntaxe définies par l’utilisateur sont appelées macros et permettent de faire de la méta-programmation. Elles sont donc un outil puissant et non du sucre syntaxique !

Pour rappel, les extensions de syntaxe sont par exemple utilisées dans print! et println! pour la syntaxe « à la Python », il y a également des exemples dans la section d’au-dessus et d’en dessous !

DST

Depuis quelques temps, un travail est en cours pour prendre en charge les Dynamically-sized types (DST) dans Rust.

  • std::vec a été réécrite (dépréciée un temps au profit de std::vec_ng), et ~[T] a disparu.
Découpage

Afin d'avoir une séparation nette des fonctionnalités entre les modules et de pouvoir n'utiliser que les fonctionnalités nécessaires dans un module, std et extra sont découpées. On a donc désormais un std plus petit, et les modules résultant seront à terme gérés sur leur propre dépôt.

La documentation pour ces bibliothèques a ainsi été séparée.

libextra a été supprimée. Ses différentes fonctionnalités ont été séparées en plusieurs crates :

  • libarena
  • libcollections (dans laquelle a été migré std::trie ainsi que les types std::HashMap, std::HashSet et EnumSet)
  • libflate
  • libgetopts
  • libglob
  • libnum (contient désormais le trait Integer)
  • libsemver
  • libserialize (on y trouvera serialize::json qui a gagné une API à la JackonJSON).
  • libsync (modules de programmation concurrentielle)
  • libterm
  • libtest
  • libtime
  • libuuid
  • liburl
  • libworkcache

En outre, deux modules ont été extraits de la libstd :

  • librand
  • liblog

Ces découpages permettent également d’éviter les dépendances circulaires et donc de compiler plus de bibliothèques en parallèle. Cela devrait également améliorer légèrement les temps de compilation.

Compilateur
  • Avertissement pour les Result non-utilisés (désactivé par défaut).
  • Beaucoup d’options ont été enlevées et ajoutées, notamment ici.
  • Quelques optimisations sur la taille des binaires générés.
  • Les opérateurs composés (comme +=) ne peuvent plus être utilisés avec des variables potentiellement non-initialisées.
  • Le déréférencement est maintenant surchargeable. C’est une autre partie des changements sur les pointeurs intelligents. Un code tel que let x = *Rc::new(5) est maintenant valide. Il y a une pull request complémentaire qui déréférencera automatiquement les pointeurs intelligents lorsque approprié, pour éviter les expressions du type foo.borrow().get().borrow_mut().get() (ce qui facilitera l’utilisation des pointeurs de la bibliothèque standard qui remplacent @ et @mut).

LLVM aura bientôt un ramasse-miettes précis, le courriel annonce même que l’implémentation arrivera dans quelques mois (« pas dans quelques semaines ni dans quelques années ! »). Cela pourrait fournir une base solide à une implémentation d’un ramasse-miettes dans Rust.

Plateformes prises en charge

Rust fonctionne désormais sous Windows (7, Server 2008 R2) seulement x86, Linux (diverses distributions) ARM, x86 et x86-64, OSX 10.6 ("Snow Leopard") et ultérieurs x86 et x86-64, ainsi que Android.

Les procédures d'installation déjà en place pour la version 0.8 (pour Windows, Ubuntu, Arch Linux et Gentoo) décrites dans la dépêche adhoc sont toujours valables et ont été mises à jour pour cette version. Dès l'annonce, les paquets pour Ubuntu ont été générés dans le PPA hansjorg/rust, une compilation pour Arch est disponible dans le dépôt [community] et pour Gentoo, l'overlay rust contient un ebuild pour cette version. Le tutoriel détaille aussi l'installation sur les différentes plateformes.

Autres outils Autour du langage

Nick Cameron — alias nrc — a rejoint l'équipe de Mozilla dédiée à Rust, qui compterait désormais 6 personnes (discussion au MozSpace du 25 février). Nick a un doctorat en théorie des langages de programmation du Imperial College London (thèse intitulée Existential Types for Variance - Java Wildcards and Ownership Types), il travaillait depuis deux ans sur la composition et les graphiques de Gecko. Depuis, Aaron Turon a rejoint Mozilla Research à San Francisco. Une douzaine d’employés de Samsung s'occupent d’une autre partie du travail.

Un programme de triage de bugs a été lancé : si on s’inscrit, on reçoit une liste des plus vieux bugs afin de vérifier qu’ils sont toujours d’actualité, s’il y a des doublons, voire corriger le bug.

La façon dont sont traitées les RFC va évoluer, en effet la maturation du projet et l’activité toujours grandissante autour du langage nécessitaient un processus un peu plus rigoureux pour évaluer et implémenter les fonctionnalités de manière organisée.

Nouveau site web

Le thème du site web de Rust a été mis à jour, avec une présentation plus accrocheuse. On peut désormais télécharger des installateurs pour les plateformes Windows et Mac, et des binaires pour Mac ainsi que GNU/Linux, des versions 0.10 et nocturne.

Informations techniques

Une question a été posée sur Reddit : quels sont les types d’optimisation possibles en Rust ? (la plupart n’ayant malheureusement pas encore été implémentés, faute de temps)

La non-mutabilité par défaut permet de nombreuses optimisations, par exemple :

fn f(x: &int) { let y = *x; g(); let z = *x; println(z.to_str()); }

L’optimiseur peut transformer cela de manière valide en :

fn f(x: &int) { let y = *x; g(); println(y.to_str()); }

Et ce quelle que soit l’opération qu’effectue g(); car ici x est non-mutable (rappel : le mot mut doit être explicitement utilisé, comme ceci : fn f(mut x: &int)).

D’autre part, cela permettra aussi de faire des optimisations dans certaines boucles, par exemple en C/C++ :

int x = 0; foo(&x); for(int i = 0; i < x; i++) bar();

on ne sait pas si &x a été récupéré autre part depuis foo, ou si bar la modifie, on est donc obligé de recharger la valeur de x à chaque tour de boucle. En Rust, le compilateur sait si x a été emprunté ou pas. Remarque : ça n’est pas le plus beau bout de code que vous ayez vu mais il montre bien l’idée.

Vous pouvez aussi consulter une autre discussion à propos d’optimisations.

Chiffres

Depuis la dernière dépêche, Ohloh a mis à jour ses statistiques sur Rust. On peut ainsi voir que le nombre de personnes qui modifient du code Rust est relativement faible mais augmente (121 projets dans les projets recensés sur Ohloh). 1428 projets sont recensés sur GitHub.

Rust est le deuxième dépôt sur Github en nombre de tickets fermés sur l’année 2013, un chiffre très impressionnant qui donne une petite idée de l’énorme travail en cours sur le langage. Espérons que cette année soit au moins aussi fantastique pour Rust !

Computer Language Benchmark Game

Rust fait son entrée dans le fameux Computer Language Benchmark Game. Déjà avec un très bon benchmark, fasta. En effet, sur ce banc d’essai, Rust est aussi rapide que C++ en prenant moins de mémoire sans « tricher » (utiliser de bloc unsafe), contrairement à l’implémentation Haskell par exemple, qui utilise des unsafeUseAsCString et unsafeIndex.

D’autre part, on a aussi un mauvais banc d’essai, pidigits car l’implémentation de Rust, selon un des développeurs, « extra::bigint n’est pas tellement optimisé ni maintenu et est très très lent » et malgré un commit pour améliorer les performances de bigint (20× plus rapide). Il convient néanmoins de préciser que les meilleurs résultats sur ce benchmark sont réalisés par des programmes utilisant GMP.

Vous pouvez consulter la comparaison avec le C et le C++ sur X86-64. En comparant les résultats sur X86, on voit que les écarts sont moindres sur plateforme 64 bits. Rust n’a pas encore été vraiment optimisé (LLVM ne peut notamment pas effectuer certaines optimisations car on doit lui fournir plus d’informations), ce qui explique l’écart de performance encore important avec le C ou le C++, dont les compilateurs ont quand même plusieurs dizaines d’années d’optimisation derrière eux. De plus, la différence de performance avec un code lambda (qui ne sollicite pas de manière intensive la machine comme lors de ces bancs d’essai) est beaucoup plus faible.

Anecdotes

Sur Reddit, plusieurs utilisateurs indiquent pourquoi ils ont choisi Rust plutôt que d’autres langages.

Il a été de nombreuses fois demandé si Rust prendrait en charge les tail call optimizations, c’est-à-dire l’optimisation des récursions terminales. C’est une fonctionnalité présente dans les langages fonctionnels, qui transforme l’appel récursif en itération (donc série d’étapes séquentielles) lors de la compilation, ce qui est bien plus performant et sauve de la place sur la pile. Un courriel envoyé sur la liste de diffusion du projet explique pourquoi elle ne sera jamais implémentée.

Il arrive régulièrement que quelqu’un poste, sur le sous-reddit (sous-partie du site web Reddit) consacré à Rust, un sujet en rapport avec le jeu Rust, un jeu de survie en développement également, et disponible sur GNU/Linux! (exemples : ici, ici, ici).

Du coup, le sous-Reddit a été renommé récemment (et temporairement?) en Rust is not a game where naked men murder each other with hatchets (« Rust n’est pas un jeu où des hommes nus s’entretuent avec des haches »).

Servo

Servo est un moteur de rendu HTML et CSS expérimental développé en Rust par Mozilla, Samsung le porte sur Android et les processeurs ARM. L'objectif est de tester un moteur fortement parallélisé dans tous ses aspects (rendu, mise en page, analyse HTML, lecture d'image) en utilisant les tâches isolées. Mozilla ne prévoit pas de sortie immédiate de Servo, puisque son succès repose sur la finalisation de Rust.

Le nom du moteur de rendu vient du robot Tom Servo de la série télévisée américaine Mystery Science Theater 3000.

À noter que les sources de Servo incluent une version figée de Rust. Au 3 avril, c'est la version du 24 février de Rust qui est utilisée.

Feuille de route

Bien qu'il ne soit pas prévu d'intégrer ce moteur dans les projets Mozilla, le projet est avancé et quelques captures d'écran ont été publiées. Pour 2014, la feuille de route est ambitieuse :

  • 1er trimestre, pouvoir naviguer sur Wikipédia (passer le test Acid2, gestion des appareils à haute densité de pixels (HiDPI)…),
  • 2nd trimestre, prendre en charge des applications web simples (passer le test Acid3, gérer le Javascript et Ajax, le webgl…),
  • 3ème trimestre, ajouter des fonctionnalités et tests architecturaux (TLS/SSL, système de cache, canvas, web animations…),
  • 4ème trimestre, ajouter une interface (multiprocessus, isolation (sandboxing), marques-pages, historiques, témoins (cookies), extensions, etc.).

En mars, Mozilla a publié trois nouvelles offres d'emploi pour travailler sur Servo.

Évolutions Liens

Comme dans les précédentes dépêches, sauf indication contraire, les contenus liés sont en anglais. Et il y en a un nombre certain.

Notes de version Récapitulatifs This Week in Rust

Si vous voulez suivre le mouvement de tout ce qui se passe à propos de Rust sans avoir à lire le détail des commits, des annonces sur la liste de diffusion ou de Reddit, le blog This Week in Rust fait une synthèse hebdomadaire des nouveautés et actualités autour de Rust :

Vous pouvez voir que désormais sont indiqués les nouveaux contributeurs rejoignant le projet, et le moins que l’on puisse dire c’est qu’il y en a beaucoup !

Meeting Weekly

Les employés de Mozilla se rencontrent (par IRC) chaque mardi à 10h du matin, heure du pacifique (UTC-8). C’est ensuite enregistré sur Etherpad et archivé sur le wiki de Rust (sur Github).

  • 14/01 (Friend of the Tree; statics on traits; env pointers; lang freeze; iterator naming; statics; docs on primitives)
  • 21/01 (primitive impl lang items; env ptrs; boehm; fmt::Default; foo_opt => foo; \xNN; #[no_mangle]; crate_type="lib")
  • 28/01 (Friend of the Tree; default type params; allocators; dylib to extra; unused Result warning; attributes; I/O; visit_glue)
  • 04/02 (libprim; operator overloading; using system LLVM)
  • 11/02 (Friend of the Tree; binding in struct patterns; rules on static values; crate keyword; pizza; finally macro; implicit trait bounds)
  • 18/02 (if_ok!, issue numbers in commits, debug assertions, hash trait, vector syntax)
  • 27/02 (Friend of the Tree; TotalEq; weak extern fn; channel names; relative paths)
  • 11/03 (self argument destructuring; type hints; coercion rules; unsafe ptrs)
  • 18/03 (Friend of the Tree; RFCs; 0.10; documentation; RFC review)
Évènements Présentations

Diaporama et/ou vidéos de présentations concernant Rust.

Tutoriels et documentation Projets

rust-ci, le projet indépendant qui liste les projets Rust qui utilisent Travis-CI comme plateforme d'intégration continue, a subi quelques mises à jour : catégorisation des projets, envoi de la documentation lors de l'exécution du projet dans Travis-CI.

Il y a un projet qui existe depuis un moment mais qui n’a jamais été présenté ici, c’est un compilateur de Rust vers Javascript.

Nouveaux projets

Voici maintenant la liste des nouveaux projets écrits en Rust. La majorité sont petits et sont très souvent dans un état de développement pas très avancé. En effet, ce sont souvent des projets personnels pour apprendre et tester le langage.

Futur Conclusion

Un énorme réusinage et nettoyage qui permet d’envisager l’avenir de Rust plus sereinement, avec un code plus simple et mieux organisé, mais qui nécessitera encore une fois un peu de boulot pour les projets programmés en Rust.

Télécharger ce contenu au format Epub

Lire les commentaires

Catégories: Nouvelles du Libre

SimpleCRM OsUX : Linux ranime votre ancien "Pentium"

Toolinux - mar, 08/04/2014 - 00:00

SimpleCRMOsUX entend transformer un "vieux PC" en station de travail bureautique. Un travail "made in France".

- Logiciels
Catégories: Nouvelles du Libre

Syndiquer le contenu