Bug afeta todas as distros

Quer ver se o seu Linux tem o bug? Digite no terminal: "date -d 01/19/2038". Veja o resultado e depois digite: "date -d 01/20/2038". Quer concertar? Veja o artigo.

[ Hits: 18.078 ]

Por: M4iir1c10 em 04/03/2008 | Blog: https://github.com/mauricioph


A solução



Esse é um programa que deve ser colocado na pasta /bin após a compilação, ao criar um programa que se baseie em tempo envés de usar a função gmtime(), você deve escrever o seu código com privotal_gmtime().

/*bug 2038 vai acontecer em 19 de Janeiro de 2038*/

const char pivotal_gmtime_r_stamp[] =
    "pivotal_gmtime_r. Copyright (C) 2005  Paul Sheer. Terms and "
    "conditions apply. Visit http://2038bug.com/ for more info.";

/*

pivotal_gmtime_r() retorna o mesmo resultado que gmtime() até 19 de Janeiro de 2038,  a partir daí o resultado será o esperado e não haverá o retorno para 01 de Janeiro de 1901.

*/


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

static const int days[4][13] = {
    {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
    {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
    {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365},
    {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366},
};

#define LEAP_CHECK(n) ((!(((n) + 1900) % 400) || (!(((n) + 1900) % 4) && (((n) + 1900) % 100))) != 0)
#define WRAP(a,b,m) ((a) = ((a) <  0  ) ? ((b)--, (a) + (m)) : (a))

long long pivot_time_t (const time_t * now, long long *_t)
{
    long long t;
    t = *_t;
    if (now && sizeof (time_t) == 4) {
        time_t _now;
        _now = *now;
        if (_now < 1106500000 /* Jan 23 2005 - date of writing */ )
            _now = 2147483647;
        if ((long long) t + ((long long) 1 << 31) < (long long) _now)
            t += (long long) 1 << 32;
    }
    return t;
}

static struct tm *_gmtime64_r (const time_t * now, long long *_t, struct tm *p)
{
    int v_tm_sec, v_tm_min, v_tm_hour, v_tm_mon, v_tm_wday, v_tm_tday;
    int leap;
    long long t;
    long m;
    t = pivot_time_t (now, _t);
    v_tm_sec = ((long long) t % (long long) 60);
    t /= 60;
    v_tm_min = ((long long) t % (long long) 60);
    t /= 60;
    v_tm_hour = ((long long) t % (long long) 24);
    t /= 24;
    v_tm_tday = t;
    WRAP (v_tm_sec, v_tm_min, 60);
    WRAP (v_tm_min, v_tm_hour, 60);
    WRAP (v_tm_hour, v_tm_tday, 24);
    if ((v_tm_wday = (v_tm_tday + 4) % 7) < 0)
        v_tm_wday += 7;
    m = (long) v_tm_tday;
    if (m >= 0) {
        p->tm_year = 70;
        leap = LEAP_CHECK (p->tm_year);
        while (m >= (long) days[leap + 2][12]) {
            m -= (long) days[leap + 2][12];
            p->tm_year++;
            leap = LEAP_CHECK (p->tm_year);
        }
        v_tm_mon = 0;
        while (m >= (long) days[leap][v_tm_mon]) {
            m -= (long) days[leap][v_tm_mon];
            v_tm_mon++;
        }
    } else {
        p->tm_year = 69;
        leap = LEAP_CHECK (p->tm_year);
        while (m < (long) -days[leap + 2][12]) {
            m += (long) days[leap + 2][12];
            p->tm_year--;
            leap = LEAP_CHECK (p->tm_year);
        }
        v_tm_mon = 11;
        while (m < (long) -days[leap][v_tm_mon]) {
            m += (long) days[leap][v_tm_mon];
            v_tm_mon--;
        }
        m += (long) days[leap][v_tm_mon];
    }
    p->tm_mday = (int) m + 1;
    p->tm_yday = days[leap + 2][v_tm_mon] + m;
    p->tm_sec = v_tm_sec, p->tm_min = v_tm_min, p->tm_hour = v_tm_hour,
        p->tm_mon = v_tm_mon, p->tm_wday = v_tm_wday;
    return p;
}

struct tm *gmtime64_r (const long long *_t, struct tm *p)
{
    long long t;
    t = *_t;
    return _gmtime64_r (NULL, &t, p);
}

struct tm *pivotal_gmtime_r (const time_t * now, const time_t * _t, struct tm *p)
{
    long long t;
    t = *_t;
    return _gmtime64_r (now, &t, p);
}

long long mktime64 (struct tm *t)
{
    int i, y;
    long day = 0;
    long long r;
    if (t->tm_year < 70) {
        y = 69;
        do {
            day -= 365 + LEAP_CHECK (y);
            y--;
        } while (y >= t->tm_year);
    } else {
        y = 70;
        while (y < t->tm_year) {
            day += 365 + LEAP_CHECK (y);
            y++;
        }
    }
    for (i = 0; i < t->tm_mon; i++)
        day += days[LEAP_CHECK (t->tm_year)][i];
    day += t->tm_mday - 1;
    t->tm_wday = (int) ((day + 4) % 7);
    r = (long long) day *86400;
    r += t->tm_hour * 3600;
    r += t->tm_min * 60;
    r += t->tm_sec;
    return r;
}

static struct tm *THIS_FUNCTION_DOES_NOT_WORK_FOR_DAYLIGHT_SAVINGS_localtime64_r (const time_t * now, long long *_t, struct tm *p)
{
    long long tl;
    time_t t;
    struct tm tm, tm_localtime, tm_gmtime;
    _gmtime64_r (now, _t, &tm);
    if (tm.tm_year > (2037 - 1900))
        tm.tm_year = 2037 - 1900;
    t = mktime64 (&tm);
    localtime_r (&t, &tm_localtime);
    gmtime_r (&t, &tm_gmtime);
    tl = *_t;
    tl += (mktime64 (&tm_localtime) - mktime64 (&tm_gmtime));
    _gmtime64_r (now, &tl, p);
    p->tm_isdst = tm_localtime.tm_isdst;
    return p;
}

struct tm *pivotal_localtime_r (const time_t * now, const time_t * _t, struct tm *p)
{
    long long tl;
    tl = *_t;
    return _localtime64_r (now, &tl, p);
}

struct tm *localtime64_r (const long long *_t, struct tm *p)
{
    long long tl;
    tl = *_t;
    return _localtime64_r (NULL, &tl, p);
}

E isso aí pessoal, um grande abraço do seu amigo Mauricio.



Página anterior    

Páginas do artigo
   1. Explicação
   2. A solução
Outros artigos deste autor

Instalando Beryl no Windows XP

Letras brilhantes com Gimp

Máquina Enigma e encriptação em XOR

Servidor de Mídia com 128 MB de RAM

Instalando e configurando um dock igual ao Mac Leopard no KDE

Leitura recomendada

Desenvolvendo para microcontroladores em GNU/Linux

Estudando recursividade direta e indireta

Ponteiros - Saindo de Pesadelos

Tratamento de exceções na linguagem C

A duplicação do buffer de saída na chamada de sistema fork() do Linux

  
Comentários
[1] Comentário enviado por elgio em 04/03/2008 - 10:42h

Parabéns pela didática!
Excelente!

Me fez lembrar do bug que a primeira versão do NT tinha: eles usaram uma variável de 32 bits para contar o número de milisegundos que a máquina estava ligada. Em 49 dias esta variável entrava em overflow e o computador se resetava :-O

Mas não se preocupem, foi sem impacto. Ninguém conseguia ficar com um Windows tanto tempo ligado sem ter que reiniciá-lo por outros motivos :-D

hehehehe

[2] Comentário enviado por hellnux em 04/03/2008 - 10:47h

Opa,

Interessante o artigo. No BUG de 2000 nem conhecia Linux e nem windows direito.... e do NT nem sabia x]

Vi algo que pode estar errado, acho que seja assim:

0 = 000
1 = 001
2 = 010
3 = 011
4 = 100
5 = 101

[]´s

[3] Comentário enviado por hlegius em 04/03/2008 - 11:11h

Em 64bits parece que o erro não ocorre mais ...

[[email protected] ~]$ date -d 01/19/2038
Ter Jan 19 00:00:00 BRST 2038
[[email protected] ~]$ date -d 01/20/2038
Qua Jan 20 00:00:00 BRST 2038

Acho que a limitação está na plataforma 32bits...

[4] Comentário enviado por m4tri_x em 04/03/2008 - 11:15h

Valeuu...

[]´s

[5] Comentário enviado por M4iir1c10 em 04/03/2008 - 11:41h

Obrigado pela dica hlegius, eu esqueci de colocar esse detalhe no artigo o bug e em plataformas 32bits.

hellnux esse sitema binario e coisa de computador mesmo... olha so eu erei uma conta de 1 a 5, k-ra-k.... valeu pela correcao.

[6] Comentário enviado por removido em 04/03/2008 - 11:56h

gostei cara,
muito interessante !!!!!!!!!!!!!!!!!!

[7] Comentário enviado por Teixeira em 04/03/2008 - 13:19h

Valeu, muito bom o artigo.
O que eu iria comentar os colegas já comentaram.
( Tá passeando em Sydney? "Gudái, máite!..." Tem "snáiks" por aí?... hehehe!)

[8] Comentário enviado por removido em 04/03/2008 - 14:36h

só uma observação gramatical na introdução...

Seria Consertar, Concertar vêm de Concerto, de Orquestra, música e tal. =)

[9] Comentário enviado por removido em 04/03/2008 - 18:59h

Convenhamos, né cambada... A gente nem sabe se daqui a 32 anos a informática base-ar-se-á (gostaram ?????) em 111110000 e, então, sem exageros.....

Agora, que ficou um muuuuuuuust os códigos mudando constantemente na página, isso ficou..


Aaaaaaaaiiiiiiiiiiiiiii, gamei!!! ;-)

[10] Comentário enviado por M4iir1c10 em 05/03/2008 - 07:48h

Desculpe Rodrigo Campelini mais eu escrevi consertar ou concertar? Eu acho que foi com s e nao com c... qual eu devo usar ? Desculpem pelos erros ja tem um tempo que eu estou sem falar portugues, ai ja viu ne? o verbo to be em portugues "Eu estarei indo comprar chocolate"...rsrsrs


Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner
Linux banner
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts