27 Mayıs 2014 Salı

Firefox 29 Güncellemesinden Sonra Eski Eklentilere Yeniden Kavuşun


Firefox 29 (Kaynak)
Yakın zaman önce Firefox'un 29. sürümü çıktı. Firefox, otomatik güncelleştirme seçeneği zaten açık olarak geliyor ve internetle çok fazla haşır neşir bir program olduğundan otomatik güncelleştirmenin her zaman açık olması bir yandan da güvenlik açısından vazgeçilmez bir durum. Diğer taraftan Mozilla, bu son sürümde Firefox'un görünümünü Australis adında bir "theme" kullanarak bir parça değiştirdi ve eski eklentilerin bazıları bu güncellemeyle kullanılmaz hale geldi. Bunun başlıcası da eski eklenti çubuğu (Add-on Bar). Eklenti çubuğunun yeni hali bize ne getirir ne getirmez bilmiyorum ama eskiden eklenti çubuğunda yer alan uygulamalar artık buraya yerleşemiyor. Buradaki uygulamaların yeni sürümleri çıkmadıysa bir çoğu şu an byte çöpü durumunda. Peki güncellenmeyen, geliştirilmesi durmuş yada acilen ihtiyacımız olan eklentilere ne olacak, işte bunun çözümünü anlatacağım.

Öncelikle belirteyim ki burada anlatacağım yöntemin her uygulama için çözüm olma garantisi olmadığı gibi çalışıp çalışmaması da kullandığınız eski eklentinin yapısıyla ilgili. 

Herneyse, Firefox 29 kurulduktan sonra bu sürümle uyumlu olmayan bütün eklentileri kapatıyor ancak eski sürümlerde bunlar elle tekrar açılabiliyordu. Şimdi bunu kaldırmışlar. İlk iş olarak Google'a "force firefox add on compatibility" diye aratıp çıkan sonuçlara baktım. Bu anlatacağım çalışmadı ancak eski sürümlerde çalışıyor olması lazım. Sıkça karşıma çıkan çözüm şurada anlatıldığı gibi Firefox'un registry'si olan about:config'e girip, burada extensions.checkCompatibility.x.y adında bir ikili anahtar (boolean key) oluşturup değerini "false" olarak vermek. x.y, uygulamaların denetleneceği minimum Firefox sürümü oluyor. Örneğin uygulamaların uyumluluğunu 13.0 sürümüne göre denetlenmesi istenirse oluşturulacak anahtar extensions.checkCompatibility.13.0 ve değerinin de "false" olması gerekiyor. Daha sonra her ihtimale karşı bir de Firefox'u tekrar başlatıyorsunuz. Fakat paragrafın başında da söylediğim gibi 29. sürümde bu şekilde çalışmıyor.

Asıl çözüme gelmeden önce bazı önkoşullardan bahsedeceğim. Normalde 64bit işletim sistemi kullanıyorum ve bu nedenle kullandığım bütün yazılımların da 64bitlik olmasına özen gösteriyorum. Diğer taraftan da hiçbir zaman alfa yada beta sürüm kullanmam. Kullandığım yazılımların mutlaka "stable" olan denenmiş sürümlerini hatta güvenlik açıkları yoksa "stable"dan da bir eski sürümlerini tercih ederim. Bu nedenle Firefox beni bir ikileme soktu. Anladığım kadarıyla Firefox 64bit'i yalnızca Nightly sürümlerinde destekliyor ancak bunlar için stabilite garantisi vermiyor. Stabil Firefox'ların tamamı 32bit. Bu nedenle ben Nightly değil stabil ama 32bitlik sürümü tercih ettim. Çalışan Firefox'un kaç bitlik olduğuna Görev Yöneticisi'nden bakılabilir.

Bunu anlattım çünkü eklenti uyumluluğunu kapatmak için "Nightly Tester Tools" adında bir eklenti kullandım. İlk başta adına aldanıp Nightly için bu, benimki 32bit dememe rağmen daha sonradan başka bir çözüm bulamayınca yükledim. Sorunsuz çalıştı. Bu eklentiyi kullanarak uyumsuz olduğu söylenen eklentileri çalıştırmak olanaklı. Nighty'i yükledikten sonra


"Force Addon Compatibility"yi açınca eski eklentilerinize kavuşuyorsunuz. Yada en azından artık uyumsuzluk nedeniyle pasifleştirilmiş eklentileri açabiliyorsunuz diyelim. Bu eklentiyi bir forum sitesinde gördüm. Forum başlığının ileriki mesajlarında Nightly Tester Tools'dan farklı bir eklentiden daha bahsedilmiş. Ben Nightly'i denedim sorun olmadı.

Buraya kadar eski eklentiyi sorunsuz çalıştırabildiyseniz sorun yok ancak yukarıdaki ekran görüntüsünden de görüleceği üzere örneğin WeatherForecast eklentisi eklenti çubuğuna yerleşiyor ve sadece WeatherForecast'i aktif hale getirince sorun çözülmüyor çünkü daha önce de bahsettiğim gibi artık gördüğünüz eklentiler çubuğu eski eklentiler çubuğu değil, öyle görünse bile. Mozilla'nın kendi sitesinde eklenti çubuğunu değiştirdiklerini kendileri de yazmışlar zaten. Eski eklenti çubuğunu geri getirmek için "The Addon Bar (restored)" adındaki bir eklenti daha gerekli. Bunu da Eklentilerin bulunduğu siteden yükleyince örneğin WeatherForecast eklentisi gibi eski eklenti çubuğunu kullanan eklentiler sorunsuz çalışmaya başladı.

Buraya kadar herşey tamamsa bir ince ayar kalıyor. Eğer yeni Firefox'ların garip pencere ve sekme görüntülerinden zerre hoşlanmıyorsanız üçüncü sürüm Firefox gibi görünmesini sağlamak için iki tane daha eklenti var. Birisi "Classic Theme Restorer". Bununla sekmelerin görüntülerini eski güzel görünümlerine geri döndürmek olanaklı. Bu eklentiyi yükledikten sonra Araçlar menüsü altında kendi kullanıcı arabirimine ulaşılabiliyor. En üstteki Firefox görüntüsünün kaynağında (yani şurada) bu eklentiyle ilgili İngilizce bir kaynak daha var. Diğer ikinci eklenti de "Classic Toolbar Buttons", eski sürüm Firefox düğmelerini kullanabilmek için. Bunun ayarları da eklentiler sayfasından (about:addons) eklentinin kendi ayar sayfasından yapılıyor. 

Elbette görünüm için iki ayrı eklenti kullanmak en azından benim için, ayarlar içerisinde kaybolmaya neden olabiliyor. Daha önceden Firefox için "Classic Compact" kullanıyordum ancak bu eklenti de Firefox 29. sürümle uyumlu olmadığından Firefox tarafından kapatıldı. Yukarıda anlattığım yöntemle bu eklentiyi de açtığım halde eklenti çalışıyor görünmesine rağmen yaptığım değişiklikleri uygulamadı. Bu nedenle Classic Compact yerine artık diğer ikisini kullanıyorum.

16 Mayıs 2014 Cuma

Unrar Kütüphanesiyle Paralel Şifre Bulucu #3


Herşeyden önce Soma'daki kömür madeni kazasından ötürü herkese baş sağlığı dileyerek başlıyorum.

Birşeyler yazmayalı ve yayınlamayalı çok uzun zaman olmuştu. Bu zaman zarfında, bilgisayarı yenileyince başta Euro Truck Simulator gibi her erkeğin hayali olan saçma sapan oyunlar yada eski bilgisayarımda çalışmayan ve uzun zamandır oynamak istediğim oyunlardan dolayı hemen hiçbirşey yapmadığım gibi yazmaya da zaman ayırmadım. O nedenle neredeyse üzerinden bir yıl geçecek olan yazı dizisine hiçbirşey olmamış gibi devam ediyorum. Bir de 4-5 hafta sonrasına yazılması gereken bir rapor var, onu yazmamak için blog yazayım dedim.

Önce seri sürümünün kodunu açıklayacağım. Daha önceki yazılarda da söyledim, benim yazdığım seri sürümden çok daha iyi (ve hızlı) sürümler internette de bulunabilir. Benim yaptığım tek yenilik sözlük dosyasını bilgisayarlar arasında bölüp işlemi paralelleştirmek oldu.

Kodla ilgili açıklamaları yine kodun içerisinde açıklama satırlarında yaptım. Bölük pörçük olmaması için kodu bölen başka bir açıklama girmeyeceğim. Uzun yorum satırları bölünmesin diye karakter boyutunu küçülttüm. İnceleyecek olan zaten kodu Notepad++ yada gedit gibi bir programda inceleyebilirse daha iyi olur.


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

// unrar kutuphanesine ait header dosyalari
#include<raros.hpp>
#include<dll.hpp>


void DosyaCoz(char *arsiv, int sira)    {
    // dosya adlari acik, dosya sifreliyse cozme islemi
    HANDLE PASCAL hArsiv;
    struct RAROpenArchiveData *AcmaVerisi;    // RAR dosyayla ilgili veriler
    struct RARHeaderData *Baslik;    // RAR icerisindeki dosyalarla ilgili veriler
    char sozluk[] = "sozluk.txt";    // sozluk.txt denenecek kelimelerin oldugu dosya
    char kelime[256];
    FILE *hDosya;
    int status, k1, k2 = 0;

    hDosya = fopen(sozluk, "r");

    AcmaVerisi = (struct RAROpenArchiveData *)malloc(sizeof(struct RAROpenArchiveData));
    Baslik     = (struct RARHeaderData *)malloc(sizeof(struct RARHeaderData));

    while(!feof(hDosya))        {
    // sozlukten bir kelime oku
        fscanf(hDosya, "%s", kelime);

    // RAR kutuphanesinin dosya acmak icin kullandigi yapi
        AcmaVerisi->ArcName    = arsiv;
        AcmaVerisi->OpenMode   = RAR_OM_EXTRACT;
        AcmaVerisi->CmtBuf     = NULL;
        AcmaVerisi->CmtBufSize = 0;

    // RAR dosyasini ac.
        hArsiv = RAROpenArchive(AcmaVerisi);
        Baslik->CmtBuf   = NULL;

        for(k1 = 0; k1 < (sira - 1); k1++)    {
            // ilk sifreli dosyaya kadar oku, yalnizca bazi dosyalar sifrelenmis
            // olabilir.
            RARReadHeader(hArsiv, Baslik);
            RARProcessFile(hArsiv, RAR_SKIP, NULL, NULL);
        }

        // ilk sifreli dosyayi oku
        RARReadHeader(hArsiv, Baslik);
        RARSetPassword(hArsiv, kelime);

        // sifreyle birlikte dosyayi test et. eger sifir dondururse sifre dogrudur.
        status = RARProcessFile(hArsiv, RAR_TEST, NULL, NULL);
        fprintf(stdout, "%8d", ++k2);
        fflush(stdout);

        if(status == 0)    break;  // dogru sifre bulunduysa donguyu sonlandir.

        RARCloseArchive(hArsiv);
    }

    // sozluk.txt'nin sonuna gelinmemisse (break ile cikildiysa) sifre bulunmustur
    if(!feof(hDosya))
        // sifre bulunduysa ekrana yaz
        printf("Sifre: %s\n", kelime);
    else
        printf("Sifre bulunamadi.\n\n");

    fclose(hDosya);

    return;

}


void ArsivCoz(char *arsiv)    {
    // dosya adlari sifrelenmisse cozme altprogrami
    HANDLE PASCAL hArsiv;
    struct RAROpenArchiveData *AcmaVerisi;    // RAR dosyayla ilgili veriler
    struct RARHeaderData *Baslik;    // RAR icerisindeki dosyalarla ilgili veriler
    char sozluk[] = "sozluk.txt";    // sozluk.txt denenecek kelimelerin oldugu dosya
    char kelime[256];
    FILE *hDosya;
    int status;

    hDosya = fopen(sozluk, "r");

    AcmaVerisi = (struct RAROpenArchiveData *)malloc(sizeof(struct RAROpenArchiveData));
    Baslik     = (struct RARHeaderData *)malloc(sizeof(struct RARHeaderData));

    while(!feof(hDosya))    {
        // sozlukten bir kelime oku
        fscanf(hDosya, "%s", kelime);

        // RAR kutuphanesinin dosya acmak icin kullandigi yapiyi doldur:
        AcmaVerisi->ArcName    = arsiv;
        AcmaVerisi->OpenMode   = RAR_OM_EXTRACT;
        AcmaVerisi->CmtBuf     = NULL;
        AcmaVerisi->CmtBufSize = 0;

        // doldurulan verilerle RAR dosyayi ac
        hArsiv = RAROpenArchive(AcmaVerisi);

        Baslik->CmtBuf   = NULL;
        RARSetPassword(hArsiv, kelime);
        // sifreyi belirttikten sonra RAR dosya basligini oku
        status = RARReadHeader(hArsiv, Baslik);
   
        // eger baslik okuma isi basariyla sonlanmissa status'da sifir degeri
        // doner. yani sifre bulunmus olur. bu durumda donguyu sonlandir.
        if(status == 0)    break;   

        RARCloseArchive(hArsiv);
    }

   // sozluk.txt'nin sonuna gelinmemisse (break ile cikildiysa) sifre bulunmustur
    if(!feof(hDosya))
        // sifre bulunduysa ekrana yaz
        printf("Sifre: %s\n", kelime);
    else
        printf("Sifre bulunamadi.\n\n");

    fclose(hDosya);
    return;
}


int main(int argc, char *argv[])    {
    HANDLE PASCAL hArsiv;
    struct RAROpenArchiveData *AcmaVerisi;
    struct RARHeaderData *Baslik;
    char dosyaadi[] = "deneme1.rar";   
    // programa parametre olarak herhangi bir dosya adi belirtilmezse bu dosya
    // adindaki RAR dosyayi acmaya calisir.
    int status, k1 = 0, k2 = 1;

    // RAR dosyanin acma verisi icin bellek ayir. malloc'un sonucunu kontrol
    // ettirmedim, ancak istenirse bu kontrol eklenebilir.
    AcmaVerisi = (struct RAROpenArchiveData *)malloc(sizeof(struct RAROpenArchiveData));

    // programa bir arguman dosya adi verildiyse bu dosya adini ac.
    if(argc > 1)    strcpy(dosyaadi, argv[1]);

    AcmaVerisi->ArcName    = dosyaadi;
    AcmaVerisi->OpenMode   = RAR_OM_EXTRACT;
    AcmaVerisi->CmtBuf     = NULL;
    AcmaVerisi->CmtBufSize = 0;
   
    if((hArsiv = RAROpenArchive(AcmaVerisi)) == NULL)    {
        // dosyayi bulamazsa
        printf("Arsivi acma basarisiz oldu.\n");
        return 1;
    }

    // RAR dosyayi ac, baslik icin gereken yapilari bellekte ayir.
    Baslik = (struct RARHeaderData *)malloc(sizeof(struct RARHeaderData));
    Baslik->CmtBuf   = NULL;    // RAR dosyadaki yorumlar okunmayacak

    while(1)    {
        // RAR dosya icerisindeki dosya bilgilerini oku
        status = RARReadHeader(hArsiv, Baslik);
        // eger RAR dosyanin sonuna gelindiyse while'i sonlandir.
        if(status == ERAR_END_ARCHIVE)    break;
        // dosya adlari sifrelenmisse ArsivCoz fonksiyonu cagirilacak
        if(status == ERAR_MISSING_PASSWORD)    {
            printf("Dosya adlari sifrelenmis.\n");
            ArsivCoz(dosyaadi);
            break;
        }

        k1 = k1 + k2;    // ilk adimda k1 = 0, k2 = 1. eger bir tane sifrelenmis
                        // dosya varsa k2 = 0 olacak, sayma islemi sonlandirilacak.
        printf("Arsivdeki dosyanin adi: %s", Baslik->ArcName);
        if(Baslik->Flags & 0x04)    {    // flags'da 3. bitin set edilmesi dosyanin
            printf("*\n");                // sifrelendigini gosterir. sifrelenmis
            k2 = 0;                        // dosyayi yaninda * ile ekrana yazip dosya
        }                                // sayimini sonlandir.
        else    printf("\n");            // dosya sifrelenmemisse * koyma

        status = RARProcessFile(hArsiv, RAR_SKIP, NULL, NULL);    // bir sonraki dosyaya gec
        if(status != 0)    printf("Dosyalari islerken birseyler oldu (%d).\n", status);
    }

    RARCloseArchive(hArsiv);

    // k1'de ilk sifreli dosyanin numarasi var.
    if(status != ERAR_MISSING_PASSWORD)
    // eger MISSING_PASSWORD varsa zaten tum dosya sifrelidir.
    // tek bir dosya sifreliyse DosyaCoz fonksiyonunu cagir.
        DosyaCoz(dosyaadi, k1);

    return 0;
}


Bu arada program kodunu vim'de yazıp Notepad++'ya aktardım. Vim'de tabstop 8, Notepad++'da 4 karakter. Bu nedenle de kodun bazı yerlerinde hizalama (indentation) kaydı. Beni suçlamak yerine alıcılarınızın ayarlarıyla oynayın lütfen.

Gelelim bilgisayarına MPI kuracaklar veya hesaplama kümesi erişimi olanlar için asıl olay paralel koda:


#include<stdlib.h>
#include<string.h>
#include<stdio.h>
#include<mpi.h>

// unrar kutuphanesine ait header dosyalari
#include<raros.hpp>
#include<dll.hpp>

#define MAX_PASS_LENGTH 16
#define MAX_NAME_LENGTH 256        // olabilecek en uzun dosya adi.
#define CALL_ArsivCoz   0x04
#define CALL_DosyaCoz   0x08
#define TAG             0x10

void DosyaCoz(char *arsiv, char *sozluk, int blksiz, int ofset, int sira)    {
    /*
        DosyaCoz(...): Dosya adlari acik, dosya sifreliyse cozme islemi
        arsiv:    RAR dosyanin adini tutan string.
        sozluk:   Sifrelerin listelendigi sozluk dosyasinin adini tutan string
        blksiz:   her bir islemciye sozluk dosyasindan dusen kelime sayisi
        ofset:    her islemcinin sozluk dosyasinin hangi satirini okuyacagi
        sira:     sifresi cozulecek dosyanin arsiv dosyasindaki sirasi
    */
    HANDLE PASCAL hArsiv;
    struct RAROpenArchiveData *AcmaVerisi;    // RAR dosyayla ilgili veriler
    struct RARHeaderData *Baslik;  // RAR icerisindeki dosyalarla ilgili veriler
    char kelime[MAX_PASS_LENGTH];
    FILE *hDosya;
    int status, k1, k2, rank;
    double sure;

    MPI_Comm_rank(MPI_COMM_WORLD, &rank);    // MPI uzayinda kacinci islemciyim?
    sure = MPI_Wtime();        // sure olcumunu baslat

#ifdef DEBUG
        printf("(%d): blok buyuklugu: %d, ofset: %d\n", rank, blksiz, ofset);
#endif

    hDosya = fopen(sozluk, "r");
        for(k2 = 0; k2 < ofset; k2++)
            fgets(kelime, MAX_PASS_LENGTH, hDosya);
            // her islemci kendi okuyacagi yere kadar gelsin

    // RAR dosya ve icindeki verileri acmak icin gerekli yapilari bellekte ayir
    AcmaVerisi = (struct RAROpenArchiveData *)malloc(sizeof(struct RAROpenArchiveData));
    Baslik     = (struct RARHeaderData *)malloc(sizeof(struct RARHeaderData));
    // burada malloc'un dondurdugu degerlerin test edilmesi eksik
   
    k2 = 0;
    while(k2 < blksiz)        {
        // sozlukten bir kelime oku
        fscanf(hDosya, "%s", kelime);

#ifdef DEBUG
            printf("(%d): (sayac %d) denenen kelime: %s\n", rank, k2, kelime);
            fflush(stdout);
#endif

        // RAR kutuphanesinin dosya acmak icin kullandigi yapi
        AcmaVerisi->ArcName    = arsiv;
        AcmaVerisi->OpenMode   = RAR_OM_EXTRACT;
        AcmaVerisi->CmtBuf     = NULL;
        AcmaVerisi->CmtBufSize = 0;

        // RAR dosyasini ac
        hArsiv = RAROpenArchive(AcmaVerisi);
        Baslik->CmtBuf   = NULL;

        for(k1 = 0; k1 < (sira - 1); k1++)      {
        // ilk sifreli dosyaya kadar oku, yalnizca bazi dosyalar sifrelenmis
        // olabilir.
        RARReadHeader(hArsiv, Baslik);
        RARProcessFile(hArsiv, RAR_SKIP, NULL, NULL);
        }

        // ilk sifreli dosyayi oku
        RARReadHeader(hArsiv, Baslik);
        RARSetPassword(hArsiv, kelime);

        // sifreyle birlikte dosyayi test et. eger sifir dondururse sifre dogrudur.
        status = RARProcessFile(hArsiv, RAR_TEST, NULL, NULL);

        if(status == 0)    break;    // dogru sifre bulunduysa donguyu sonlandir

        RARCloseArchive(hArsiv);
        k2++;
    }

    if(k2 < blksiz)     {    // dongu bitiminde islemci kendisine dusen blogun
        // sonuna gelmemisse arada bir yerde sifreyi buldu demektir.
        printf("Sifre: %s\n", kelime);
        MPI_Abort(MPI_COMM_WORLD, 8);
    }
    else
        printf("Sifre bulunamadi.\n\n");

        printf("Islemci %d icin calisma suresi %f saniye.\n", rank, MPI_Wtime() - sure);
    fclose(hDosya);

    return;

}

void ArsivCoz(char *arsiv, char *sozluk, int blksiz, int ofset)    {
    /*
        ArsivCoz(...): Dosya adlari sifrelenmisse cozme algoritmasi
        arsiv:    RAR dosyanin adini tutan string.
        sozluk:   Sifrelerin listelendigi sozluk dosyasinin adini tutan string
        blksiz:   her bir islemciye sozluk dosyasindan dusen kelime sayisi
        ofset:    her islemcinin sozluk dosyasinin hangi satirini okuyacagi
    */

    HANDLE PASCAL hArsiv;
    struct RAROpenArchiveData *AcmaVerisi;    // RAR dosyasiyla ilgili veriler
    struct RARHeaderData *Baslik; // RAR icerisindeki dosyalarla ilgili veriler
    char kelime[MAX_PASS_LENGTH];
    FILE *hDosya;
    int status, k1, rank;
    double sure;

    MPI_Comm_rank(MPI_COMM_WORLD, &rank);    // MPI uzayinda kacinci islemciyim?
    sure = MPI_Wtime();  // sure olcumunu baslat..

#ifdef DEBUG
    printf("(%d): blok buyuklugu: %d, ofset: %d\n", rank, blksiz, ofset);
#endif

    hDosya = fopen(sozluk, "r");

        for(k1 = 0; k1 < ofset; k1++)
            fgets(kelime, MAX_PASS_LENGTH, hDosya);
            // herkes sozluk dosyasinda kendi okuyacagi yere kadar gelsin

    // RAR dosya ve icindeki verileri acmak icin gerekli yapilari bellekte ayir
    AcmaVerisi = (struct RAROpenArchiveData *)malloc(sizeof(struct RAROpenArchiveData));
    Baslik     = (struct RARHeaderData *)malloc(sizeof(struct RARHeaderData));
    // burada malloc'un dondurdugu degerlerin test edilmesi eksik

    k1 = 0;
    while(k1 < blksiz)        {
        // sozlukten bir kelime oku
            fgets(kelime, MAX_PASS_LENGTH, hDosya);

#ifdef DEBUG
        printf("(%d): (sayac %d) denenen kelime: %s\n", rank, k1, kelime);
        fflush(stdout);
#endif

        // RAR kutuphanesinin dosya acmak icin kullandigi yapiyi doldur
        AcmaVerisi->ArcName    = arsiv;
        AcmaVerisi->OpenMode   = RAR_OM_EXTRACT;
        AcmaVerisi->CmtBuf     = NULL;
        AcmaVerisi->CmtBufSize = 0;

        // doldurulan verilerle RAR dosyayi ac
        hArsiv = RAROpenArchive(AcmaVerisi);

        // CommentBuffer = NULL : Comment'leri okuma
        Baslik->CmtBuf   = NULL;
        RARSetPassword(hArsiv, kelime);
        // sifreyi belirttikten sonra RAR dosya basligini oku
        status = RARReadHeader(hArsiv, Baslik);

        // eger baslik okuma isi basariyla sonlanmissa status'da sifir degeri
        // doner yani sifre bulunmus olur. bu durumda donguyu sonlandir.
        if(status == 0) break;

        RARCloseArchive(hArsiv);
        k1++;
    }

    if(k1 < blksiz)       {    // dongu bitiminde islemci kendisine dusen blogun
        // sonuna gelmemisse arada bir yerde sifreyi buldu demektir.
        printf("Sifre: %s\n", kelime);
        MPI_Abort(MPI_COMM_WORLD, 9);
    }
    else
        printf("Sifre bulunamadi.\n\n");

    printf("Islemci %d icin calisma suresi %f saniye.\n", rank, MPI_Wtime() - sure);
    fclose(hDosya);

        return;
}

int main(int argc, char *argv[])    {
    FILE *hSozluk;
    int size, rank, nsatir, krkt, mesaj, blksiz, ofset, status;
    int k1 = 0, k2 = 1;
    HANDLE PASCAL *hArsiv;
    struct RAROpenArchiveData *AcmaVerisi;
    struct RARHeaderData *Baslik;
    char dosyaadi[MAX_NAME_LENGTH];
    char sozluk[MAX_NAME_LENGTH] = "sozluk.txt";
    char tmp[MAX_PASS_LENGTH];
    double sure;

    MPI_Init(&argc, &argv);
    // MPI'i initle, islemci sayisini ve sira sayilarini al.
    MPI_Comm_size(MPI_COMM_WORLD, &size);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    sure = MPI_Wtime();

    if(argc > 1)    {
        // RAR dosyanin adi programa arguman olarak verilir.
        strcpy(dosyaadi, argv[1]);
        // eger birden fazla arguman verilmisse ikinci arguman sozluk dosyasidir
        if(argc > 2)    strcpy(sozluk, argv[2]);
    }
    else    {
        if(rank == 0)   printf("Kullanim: rarsolve <dosyaadi.rar> [sozluk.txt]\n");
        MPI_Abort(MPI_COMM_WORLD, 1);
        return 1;
    }

    if(rank == 0)    {
        // sifirinci islemci sozlugun satir sayisini belirler
        hSozluk = fopen(sozluk, "r");

        nsatir = 0;

        do    {
        krkt = fgetc(hSozluk);
        if(krkt == '\n')    nsatir++;
        } while(krkt != EOF);

        fclose(hSozluk);
    }

    // satir sayisini butun islemcilere bildir.
    MPI_Bcast(&nsatir, 1, MPI_INT, 0, MPI_COMM_WORLD);
   
    blksiz = nsatir / size;
    ofset  = rank * blksiz;
    // herkes kendine dusen sozluk blogunu ve ilk kelimesini bulsun

    if((nsatir % size) && (rank == (size - 1)))
        blksiz = nsatir - (blksiz * size - blksiz);
        // tamsayi duzenlemeleri

    if(rank == 0)    {
        // RAR dosyanin acma verisi icin bellekte yer ayir.
        AcmaVerisi = (struct RAROpenArchiveData *)malloc(sizeof(struct RAROpenArchiveData));

        AcmaVerisi->ArcName    = dosyaadi;
        AcmaVerisi->OpenMode   = RAR_OM_EXTRACT;
        AcmaVerisi->CmtBuf     = NULL;
        AcmaVerisi->CmtBufSize = 0;

        if((hArsiv = RAROpenArchive(AcmaVerisi)) == NULL)   {
            // dosyayi bulamazsa
            printf("Arsivi acma basarisiz oldu.\n");
            MPI_Abort(MPI_COMM_WORLD, 2);
            return 2;
        }

        // RAR dosyayi ac, baslik icin gereken yapilari bellekte ayir.
        Baslik = (struct RARHeaderData *)malloc(sizeof(struct RARHeaderData));
        Baslik->CmtBuf   = NULL;    // RAR dosyadaki yorumlar okunmayacak

        while(1)    {
            // RAR arsivi icerisindeki dosya bilgilerini oku.
            status = RARReadHeader(hArsiv, Baslik);
            // eger RAR dosyanin sonuna gelindiyse while'i sonlandir.
            if(status == ERAR_END_ARCHIVE)  break;
            // dosya adlari sifrelenmisse ArsivCoz fonksiyonu cagirilacak.
            if(status == ERAR_MISSING_PASSWORD)     {
                printf("Dosya adlari sifrelenmis.\n");
                mesaj = CALL_ArsivCoz;
                for(krkt = 1; krkt < size; krkt++)
                    // sifirinci butun islemcilere ArsivCoz fonksiyonunun
                    // cagirilacagini mesajla bildiriyor.
                    MPI_Send(&mesaj, 1, MPI_INT, krkt, TAG, MPI_COMM_WORLD);
                // sifirinci islemcinin kendisi de ArsivCoz'u cagiriyor.
                ArsivCoz(dosyaadi, sozluk, blksiz, ofset);
                break;
            }

            k1 = k1 + k2;   // ilk adimda k1 = 0, k2 = 1. eger bir tane sifrelenmis dosya varsa
                            // k2 = 0 olacak, sayma islemi sonlandirilacak.
            printf("Arsiv adi: %s", Baslik->ArcName);
            if(Baslik->Flags & 0x04)  {     // flags'da 3. bitin set edilmesi
                printf("*\n");          // dosyanin sifrelendigini gosterir.
                k2 = 0;                  // sifrelenmis dosyayi yaninda * ile yaz
            }
            else    printf("\n");

            status = RARProcessFile(hArsiv, RAR_SKIP, NULL, NULL);  // bir sonraki dosyaya gec
            if(status != 0) printf("Dosyalari islerken birseyler oldu (%d).\n", status);
        }

        RARCloseArchive(hArsiv);

        // k1'de ilk sifreli dosyanin numarasi var.
        if(status != ERAR_MISSING_PASSWORD)    {
        // eger MISSING_PASSWORD varsa zaten tum dosya sifrelidir.
                mesaj = CALL_DosyaCoz;
            // sifirinci islemci diger islemcilere DosyaCoz fonksiyonunun
            // cagirilacagini mesajla bildiriyor
                for(krkt = 1; krkt < size; krkt++)
                    MPI_Send(&mesaj, 1, MPI_INT, krkt, TAG, MPI_COMM_WORLD);
                // sifirinci islemcinin kendisi de ArsivCoz'u cagiriyor.
                DosyaCoz(dosyaadi, sozluk, blksiz, ofset, k1);
            }
    }

    else    {
        // sifirinci islemci haricindeki islemciler sifirincidan mesaj bekliyor
        MPI_Recv(&mesaj, 1, MPI_INT, 0, TAG, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
        if(mesaj == CALL_ArsivCoz)   
            ArsivCoz(dosyaadi, sozluk, blksiz, ofset);
        else if(mesaj == CALL_DosyaCoz)
            DosyaCoz(dosyaadi, sozluk, blksiz, ofset, k1);
    }

    if(rank == 0)
        printf("Toplam %f saniyede %d kelime denendi.\n", MPI_Wtime() - sure, nsatir);
   
    MPI_Finalize();

    return 0;
}



Son olarak herşey tamamsa son bir soru kalıyor: "Sözlük dosyaları nasıl oluşturulacak?" Onun için de basit bir MATLAB kodu yazdım. Yaptığı tek şey belirli kriterlere göre 5 ile 10 karakter arası rastgele kelimeler üretip bunları sozluk.txt dosyasina yazıyor. Aslında bunun için daha amaca daha yönelik araçlar yazılabilir. Örneğin sozluk.txt olarak imla kılavuzunu alıp imla kılavuzundaki kelimelerin başına yada sonuna sayılar eklemek gibi. Matlab kodu görece basit olduğundan pek açıklama yazmayacağım ancak onunla ilgili tek söyleyebileceğim 33 ve 36. satırlardaki iki for döngüsü yüzünden bir hayli yavaş çalıştığı. 


kucuk_harfler = true;
buyuk_harfler = false;
sayilar       = true;
karakterler   = false;
kel_sayi = 200000;        % 200bin kelime uret

kHavuz = [ ];
bharf_tablo = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
kharf_tablo = 'abcdefghijklmnopqrstuvwxyz';
sayi_tablo  = '0123456789';
karak_tablo = '!#$%&()*+,-./:;<=>?@_';

if(kucuk_harfler)
    kHavuz = strcat(kHavuz, kharf_tablo);
end

if(buyuk_harfler)
    kHavuz = strcat(kHavuz, bharf_tablo);
end

if(sayilar)
    kHavuz = strcat(kHavuz, sayi_tablo);
end

if(karakterler)
    kHavuz = strcat(kHavuz, karak_tablo);
end

lHavuz = length(kHavuz);
hSozluk = fopen('sozluk.txt', 'w');

for k1 = 1:kel_sayi
    kelime = [ ];
    uzunluk = floor(rand * 5 + 5);    % kelime uzunluklari rastgele
    for k2 = 1:uzunluk
        Havuz_ptr = floor(rand * lHavuz + 1);
        kelime = strcat(kelime, kHavuz(Havuz_ptr));
    end
    fprintf(hSozluk, '%s\n', kelime);
   
end

fclose(hSozluk);



Buraya kadar kodlardan ötürü bir hayli uzunca bir yazı oldu. Bu ara tekrar yazmak için zaman bulabilirsem gerçekten ne kadar gereksiz işlerle uğraştığımı anlatan bir yazı daha yayınlayabilirim.