Toutes les versions antérieures à OS X 10.6 "Snow Leopard" présentent le problème de l'année 2038. La plupart des installations de la version 10.6 et toutes les installations de la version 10.7 "Lion" ont corrigé la cause principale du problème. Il a presque disparu, mais le bogue de l'année 2038 peut subsister dans quelques applications.
Mon vieux Mac PowerPC fonctionne sous OS X 10.4.11 "Tiger". Je suis allé dans Date & Heure dans les Préférences Système, et j'ai essayé d'entrer une date postérieure à 2038, mais la date a été réinitialisée au 31 décembre 2037. Il sait que quelque chose ne va pas en 2038.
OS X est dérivé d'Unix par l'intermédiaire de BSD. Les applications pour OS X utilisent les appels système BSD pour des choses telles que l'ouverture de fichiers et la connexion à l'internet. BSD a une longue histoire et certains de ses appels système datent des années 1980. L'un de ses appels système est gettimeofday()
qui est apparu pour la première fois dans 4.1cBSD. UC Berkeley a publié la version 4.1cBSD en 1982 soit plus d'un demi-siècle avant 2038. Le temps qui s'écoule entre gettimeofday()
est un entier de type time_t
. Il compte les secondes, où zéro correspond à l'époque Unix de 1970-01-01 00:00:00 UTC.
Dans mon vieux Mac PowerPC, time_t
est un entier signé de 32 bits. Cela pose le problème de l'année 2038. Un entier signé de 32 bits time_t
est compris entre -2147483648 et 2147483647. Elle ne peut contenir que les heures comprises entre 1901-12-13 20:45:52 UTC et 2038-01-19 03:14:07 UTC. En cas de dépassement, gettimeofday()
fera basculer la date du lundi 19 janvier 2038 à Vendredi 13 de décembre 1901.
La solution consiste à passer d'un système 32 bits time_t
à 64 bits time_t
. Pour OS X, cette transition s'est faite en même temps qu'une autre transition des pointeurs 32 bits vers les pointeurs 64 bits, mais les pointeurs 64 bits nécessitent un processeur 64 bits. Apple n'a fourni que des pointeurs 64 bits time_t
pour les processeurs 64 bits. Il est possible pour les processeurs 32 bits de traiter des données 64 bits. time_t
mais Apple n'a jamais fourni cette fonction.
Les compilateurs d'Apple prennent en charge les entiers 64 bits sur les processeurs 32 bits depuis OS X 10.0 "Cheetah", lorsque time_t
avait 32 bits et off_t
avait 64 bits. Dans Unix et BSD, off_t
est la taille d'un fichier ou d'un disque entier. Un fichier de 32 bits off_t
limiterait OS X aux disques de moins de 2 GiB. Apple a défini off_t
comme 64 bits, ce qui permet à OS X de fonctionner avec des disques plus grands. Apple a défini time_t
en 32 bits dans la version 10.0, de sorte qu'un passage à la version 64 bits de la time_t
devait se faire plus tard.
Pour mon vieux Mac PowerPC, le fichier d'en-tête <ppc/_types.h>
définit __darwin_time_t
comme long
. Pour les Mac Intel, l'en-tête <i386/_types.h>
fait de même. Dans OS X, long
a la même taille qu'un pointeur. Ainsi, lorsque les pointeurs sont devenus 64 bits, long
est également passé à 64 bits, et time_t
est également passé à 64 bits, ce qui a permis de résoudre la principale cause du problème de l'année 2038.
Apple's Guide de transition vers le 64 bits déclare : "Avant OS X v10.6, toutes les applications livrées avec le système d'exploitation étaient des applications 32 bits. À partir de la version 10.6, les applications livrées avec le système d'exploitation sont généralement des applications 64 bits." Je sais d'après Wikipedia (en anglais) que la version 10.6 nécessitait un processeur Intel et que la version 10.7 nécessitait un processeur Intel 64 bits. Un Mac fonctionnant avec la version 10.6 sur un processeur Intel 32 bits devait avoir des applications 32 bits. J'en conclus que la plupart des Macs fonctionnant sous 10.6 et tous les Macs fonctionnant sous 10.7 ont des applications 64 bits avec des pointeurs 64 bits et des time_t
. Apple a publié la version 10.7 en 2011, bien avant janvier 2038.
Avec 64-bit time_t
Le bug de l'année 2038 a presque disparu, mais il pourrait subsister dans quelques applications. Les anciennes applications 32 bits peuvent encore fonctionner sur des systèmes plus récents. De même, les applications 64 bits peuvent contenir des erreurs de codage ou des conceptions obsolètes, ce qui entraîne la conversion d'une application 64 bits en une application 64 bits. time_t
à 32 bits. C'est un problème pour tous les systèmes, et pas seulement pour MacOS.
Il y a aussi le temps Mach. Le noyau d'OS X est un mélange de BSD et de Mach. La plupart des applications obtiennent le temps de BSD à l'aide de gettimeofday()
mais il existe un moyen de contourner BSD et d'obtenir l'heure à partir de Mach. C'est plus difficile : le programme appellerait mach_host_self()
pour obtenir le port de l'hôte, puis host_get_clock_service()
pour obtenir le CALENDAR_CLOCK
et enfin clock_get_time()
.
Sur mon vieux Mac fonctionnant sous la version 10.4 "Tiger", <mach/clock_types.h>
déclare l'heure comme un unsigned int
(à l'intérieur struct mach_timespec
). Il s'agit d'un entier non signé de 32 bits, compris entre 0 et 4294967295, soit entre le 1970-01-01 00:00:00 UTC et le 2106-02-07 06:28:15 UTC. Le problème de l'année 2038 serait ainsi remplacé par celui de l'année 2106. Il ne peut pas atteindre l'année 29 940.
Je soupçonne que host_get_clock_service()
était obsolète depuis la version 10.0 "Cheetah", car Apple proposait des moyens plus rapides d'obtenir l'heure. Il s'agit des logiciels BSD gettimeofday()
pour l'heure du calendrier, et l'application mach_absolute_time()
pour un temps monotone. La préférence pour gettimeofday()
placer le problème en 2038, et non en 2106.