cppp: Gelişmiş cp programı (cp++)

Katılım
15 Nisan 2021
Mesajlar
7.750
Makaleler
22
Çözümler
279
Daha fazla  
Sistem Özellikleri
Laptop: ASUS TUF Gaming F15 FX506LHB-HN323
İşlemci: i5-10300H
Ekran kartı: GTX 1650
RAM: 16 GB 3200 MHz DDR4 Laptop
Dahili Depolama: Intel SSDPEKNU512GZ
Cinsiyet
Erkek
Meslek
Öğrenci

Giriş​

Bu projeyle birlikte amacım aslında zaten işlevsel olan cp uygulamasını kendime göre daha iyi olacağını düşündüğüm özellikler ekleyerek tekrar şekillendiriyorum denebilir. Proje şu an emekleme döneminde, o yüzden daha kaynak kodlarını açmadım. Günlük kullanıma uygun olduğunu düşündüğüm zaman GitHub deposunu herkese açacağım.

cppp, kopyalanacak olan dosyayı kullanıcının belirlediği kadar parçaya bölüp parça parça kopyalayan bir araç. Dosya parçalara bölünerek kopyalandığı için kopyalanan parçada bir sorun oluştuğunda o parçanın yerine doğru olan parça eklenip kopyalama işlemi devam edecek. En son dosya kopyalandığında, kaynak hedefteki dosyanın SHA256 hash değeri ile hedef konumdaki dosyanın SHA256 hash değeri karşılaştırılacak ve bir problem yoksa işlem sonlandırılacak.

Özellikler​

Gelelim özelliklere.

1. Kopyalama Sırasında SHA256 Hash Kontrolü (sha256.h)​

Veri güvenliği açısından eğer dosya kopyalanırken bir hata oluşursa diye SHA256 hash kontrolü program tarafından yapılıyor.

C:
int calculate_sha256(const char *file_name, char hash_str[HASH_STR_LEN]);

Kaynak kodumuzdaki bu fonksiyon bizim işimizi görüyor. Kısaca C programı içinde file_name olarak verdiğiniz dosya isminin SHA256 hash değerini char hash_str[HASH_STR_LENG] değişkeninin içine yazıyor ve işlem başarılıysa EXIT_SUCCESS, değilse EXIT_FAILURE dönüyor. Performans açısından sha256sum programıyla kıyası aşağıdaki fotoğrafta görebilirsiniz. sample_file dosyası şu komutla oluşturulmuş 30 GB boyutunda bir dosya:

Bash:
dd if=/dev/urandom of=sample_file bs=1G count=30 status=progress

1750352613364.png


2. Dosyayı İstenilen Kadar Parçaya Ayırmak (split.h)​


C:
int split_file(const char* file_name, off_t num_parts);

Daha tanımlanmamış olan kopyalama fonksiyonu dosyaları parçalara bölerken bu fonksiyonu kullanacak. Burada file_name ile verdiğimiz dosyayı num_parts kadar parçaya bölebiliyoruz. Tabi dosyayı bölerken düzgün bölebilmek için dosyanın bilgilerini tutabileceğimiz bir struct yapımız var:

C:
struct file_info {
       off_t file_size;
       off_t part_size;
       off_t last_part_size;
       off_t num_parts;
       mode_t permissions;
};

struct file_info get_file_info(const char* file_name, off_t num_parts);

get_file_info fonksiyonu bizim için file_name'de verilen dosyanın num_parts kadar parçaya bölüneceği zaman boyut değerlerinin nasıl olmasını gerektiğini ve o dosyanın hangi izinlere sahip olduğunu bizim için döndürüyor. Gerçekten düzgün çalışıp çalışmadığını görmek için aşağıdaki örneğe bakabiliriz:

1750352770441.png


Gördüğünüz gibi sonuçlar böyle. Şöyle düşünüyor olabilirsiniz: "Eğer parça sayısı bayt sayısından büyük olursa ne olacak?" Yani mesela 1 bayt'lık dosyayı 10 parçaya nasıl bölecek? O durumda da part_size 0, last_part_size ise dosyanın kendi boyutunda oluyor.

Bu kısmın belki açıkları olabilir o yüzden "şimdilik" işe yaradığını söyleyebilirim. Kontrolleri elimden geldiğince yapmaya çalıştım burada. Kaynak kodlar açılınca bu durumu incelemek isteyenler ve sorun bulursa düzeltilmesi için yardımda bulunmak isteyenleri seve seve karşılıyorum :)

3. Dosya Birleştirme (merge.h)​

Adından da anlaşılacağı üzere dosyaları birleştirmeyi sağlıyor.

C:
int merge_files(const char *first_file, const char *second_file);

first_file'in sonunda second_file'ın verilerini eklemekle sorumlu bu fonksiyon. Çok komplike bir yanı yok.

4. Veri Ekleme (insert.h)​


C:
int insert_data(const char *file_name, off_t num_parts, off_t part_location, const char *new_data_file_name);

Bu fonksiyonu yazarken çok eğlendim açıkçası. Yaptığı şey, file_name'i veriyoruz, daha sonra bu dosyanın num_parts kadar parçaya ayrıldığını söylüyoruz ve part_location verdikten sonra new_data_file_name veriyoruz. Bu bilgilerden sonra file_name'in part_location'dan sonraki parçasına new_data_file_name'i yazıyor. Görsel ile açıklayayım:

1750353108918.png


Bu işlem gerçekleşirken fonksiyon num_parts ve part_location değerlerini kontrol ediyor. Eğer part_location değeri num_parts değerinden büyükse, böyle bir şey imkansız olduğu için hata veriyor ve işlem durduruluyor. Eğer part_location ve num_parts eşitse, merge_files() fonksiyonu çağrılıyor ve direkt dosyanın sonuna ekleniyor. Eğer part_location değeri num_parts değerinden küçükse, başlanacak konum part_size * part_location değeriyle byte cinsinden belirleniyor.

Şimdilik özelliklerimiz bu kadar. Eğer gelse güzel olur dediğiniz mantıklı bir özellik varsa belirtmekten çekinmeyin.

Eklenmesi Düşünülen Özellikler​

  • Multi-thread kopyalama işlemi
  • İşlem sırasında bir parça yanlış kopyalandıysa, o hata tespit edilip otomatik olarak hatayı düzeltecek şekilde işlemleri gerçekleştirmek
  • Klasör kopyalama

Son​

Şimdilik bu kadardı. Gelişmeler oldukça buraya yazmaya çalışacağım. Önerilerinizi ve görüşlerinizi bekliyorum. Başta belirttiğim gibi kaynak kodlar kullanıma hazır olduğunu düşündüğüm anda açılacak. Ayrıca Windows'a destek verir miyim bilmiyorum. MinGW ile doğrudan çalışırsa ekstra bir çaba sarf etmeye gerek kalmadan orada da dağıtılması sağlanabilir.

 
Son düzenleme:
Özellikle arayüz daha uğraştırıcı geldiği için dosya işlemlerini görsel işlemler haricinde terminalden yapan biri olarak oldukça beğendim. Ellerine sağlık hocam.
 
Özellikle arayüz daha uğraştırıcı geldiği için dosya işlemlerini görsel işlemler haricinde terminalden yapan biri olarak oldukça beğendim. Ellerine sağlık hocam.

Arayüzü programlamak da uğraştırıcı 🙂 Komut satırı her derdin devası.
 

Giriş​

Bu projeyle birlikte amacım aslında zaten işlevsel olan cp uygulamasını kendime göre daha iyi olacağını düşündüğüm özellikler ekleyerek tekrar şekillendiriyorum denebilir. Proje şu an emekleme döneminde, o yüzden daha kaynak kodlarını açmadım. Günlük kullanıma uygun olduğunu düşündüğüm zaman GitHub deposunu herkese açacağım.

cppp, kopyalanacak olan dosyayı kullanıcının belirlediği kadar parçaya bölüp parça parça kopyalayan bir araç. Dosya parçalara bölünerek kopyalandığı için kopyalanan parçada bir sorun oluştuğunda o parçanın yerine doğru olan parça eklenip kopyalama işlemi devam edecek. En son dosya kopyalandığında, kaynak hedefteki dosyanın SHA256 hash değeri ile hedef konumdaki dosyanın SHA256 hash değeri karşılaştırılacak ve bir problem yoksa işlem sonlandırılacak.

Özellikler​

Gelelim özelliklere.

1. Kopyalama Sırasında SHA256 Hash Kontrolü (sha256.h)​

Veri güvenliği açısından eğer dosya kopyalanırken bir hata oluşursa diye SHA256 hash kontrolü program tarafından yapılıyor.

C:
int calculate_sha256(const char *file_name, char hash_str[HASH_STR_LEN]);

Kaynak kodumuzdaki bu fonksiyon bizim işimizi görüyor. Kısaca C programı içinde file_name olarak verdiğiniz dosya isminin SHA256 hash değerini char hash_str[HASH_STR_LENG] değişkeninin içine yazıyor ve işlem başarılıysa EXIT_SUCCESS, değilse EXIT_FAILURE dönüyor. Performans açısından sha256sum programıyla kıyası aşağıdaki fotoğrafta görebilirsiniz. sample_file dosyası şu komutla oluşturulmuş 30 GB boyutunda bir dosya:

Bash:
dd if=/dev/urandom of=sample_file bs=1G count=30 status=progress

Eki Görüntüle 2516340

2. Dosyayı İstenilen Kadar Parçaya Ayırmak (split.h)​


C:
int split_file(const char* file_name, off_t num_parts);

Daha tanımlanmamış olan kopyalama fonksiyonu dosyaları parçalara bölerken bu fonksiyonu kullanacak. Burada file_name ile verdiğimiz dosyayı num_parts kadar parçaya bölebiliyoruz. Tabi dosyayı bölerken düzgün bölebilmek için dosyanın bilgilerini tutabileceğimiz bir struct yapımız var:

C:
struct file_info {
       off_t file_size;
       off_t part_size;
       off_t last_part_size;
       off_t num_parts;
       mode_t permissions;
};

struct file_info get_file_info(const char* file_name, off_t num_parts);

get_file_info fonksiyonu bizim için file_name'de verilen dosyanın num_parts kadar parçaya bölüneceği zaman boyut değerlerinin nasıl olmasını gerektiğini ve o dosyanın hangi izinlere sahip olduğunu bizim için döndürüyor. Gerçekten düzgün çalışıp çalışmadığını görmek için aşağıdaki örneğe bakabiliriz:

Eki Görüntüle 2516342

Gördüğünüz gibi sonuçlar böyle. Şöyle düşünüyor olabilirsiniz: "Eğer parça sayısı bayt sayısından büyük olursa ne olacak?" Yani mesela 1 bayt'lık dosyayı 10 parçaya nasıl bölecek? O durumda da part_size 0, last_part_size ise dosyanın kendi boyutunda oluyor.

Bu kısmın belki açıkları olabilir o yüzden "şimdilik" işe yaradığını söyleyebilirim. Kontrolleri elimden geldiğince yapmaya çalıştım burada. Kaynak kodlar açılınca bu durumu incelemek isteyenler ve sorun bulursa düzeltilmesi için yardımda bulunmak isteyenleri seve seve karşılıyorum :)

3. Dosya Birleştirme (merge.h)​

Adından da anlaşılacağı üzere dosyaları birleştirmeyi sağlıyor.

C:
int merge_files(const char *first_file, const char *second_file);

first_file'in sonunda second_file'ın verilerini eklemekle sorumlu bu fonksiyon. Çok komplike bir yanı yok.

4. Veri Ekleme (insert.h)​


C:
int insert_data(const char *file_name, off_t num_parts, off_t part_location, const char *new_data_file_name);

Bu fonksiyonu yazarken çok eğlendim açıkçası. Yaptığı şey, file_name'i veriyoruz, daha sonra bu dosyanın num_parts kadar parçaya ayrıldığını söylüyoruz ve part_location verdikten sonra new_data_file_name veriyoruz. Bu bilgilerden sonra file_name'in part_location'dan sonraki parçasına new_data_file_name'i yazıyor. Görsel ile açıklayayım:

Eki Görüntüle 2516354

Bu işlem gerçekleşirken fonksiyon num_parts ve part_location değerlerini kontrol ediyor. Eğer part_location değeri num_parts değerinden büyükse, böyle bir şey imkansız olduğu için hata veriyor ve işlem durduruluyor. Eğer part_location ve num_parts eşitse, merge_files() fonksiyonu çağrılıyor ve direkt dosyanın sonuna ekleniyor. Eğer part_location değeri num_parts değerinden küçükse, başlanacak konum part_size * part_location değeriyle byte cinsinden belirleniyor.

Şimdilik özelliklerimiz bu kadar. Eğer gelse güzel olur dediğiniz mantıklı bir özellik varsa belirtmekten çekinmeyin.

Eklenmesi Düşünülen Özellikler​

  • Multi-thread kopyalama işlemi
  • İşlem sırasında bir parça yanlış kopyalandıysa, o hata tespit edilip otomatik olarak hatayı düzeltecek şekilde işlemleri gerçekleştirmek
  • Klasör kopyalama

Son​

Şimdilik bu kadardı. Gelişmeler oldukça buraya yazmaya çalışacağım. Önerilerinizi ve görüşlerinizi bekliyorum. Başta belirttiğim gibi kaynak kodlar kullanıma hazır olduğunu düşündüğüm anda açılacak. Ayrıca Windows'a destek verir miyim bilmiyorum. MinGW ile doğrudan çalışırsa ekstra bir çaba sarf etmeye gerek kalmadan orada da dağıtılması sağlanabilir.

Konuyu takibe aldım.
Eline sağlık hocam.
 

Yeni Güncelleme!​

Eklenen özellikler:
  1. Seç ve Birleştir (Select and Merge)
  2. Yerine Koy (Replace)
  3. İlerleme Çubuğu (Progress Bar)

1. Seç ve Birleştir (select_and_merge.h)​

C:
int select_and_merge(const char *file_name, off_t num_parts, int parts[], int count)

Bu özellik sayesinde dosyadaki num_parts kadar parçanın içinden istediğimiz parçaları seçip yeni bir dosyada birleştirebiliyoruz.

num_parts = 16
parts = {1, 3, 4, 6, 8, 10, 13}

Fonksiyon dosyayı matematiksel değerler olarak 16 parçaya bölüyor ve o parçaları dosyadan okuyup yeni bir dosyaya tek tek yazıyor.

2. Yerine Koy (replace.h)​

C:
int replace(const char *file_name, off_t num_parts, off_t position, const char *new_data_file_name);

Bu fonksiyon "Veri Ekleme (insert)" gibi çalışıyor ama bir fark var. Bu fonksiyon seçilen parçanın üzerine doğrudan veriyi yazıyor. Yani dosya eğer 16 parçaysa yine 16 parça olarak kalmaya devam ediyor.

parts_data = {a, b, c, d, e, f, g, h, j, k, l, m, n, o, p, r, s}

C:
new_data_file = 'z';
replace(file, 16, 4, new_data_file);

parts_data = {a, b, c, z, e, f, g, h, j, k, l, m, n, o, p, r, s}
Bu şekilde çalışıyor.

3. İlerleme Çubuğu (progress_bar.h)​

Şu an için birkaç işlem için koydum ilerleme çubuğunu ve hedefim bunu isteğe bağlı yapmak. Çünkü işlem süresini uzatıyor. İsteyen istediği gibi aktif edebilsin diye uğraşacağım.

Mesela SHA256 hash değeri kontrolü yaparken işlemin ne kadar uzun süreceği dosya boyutuna bağlı olarak değişiyor. Biz de en azından ilerlemenin ne durumda olduğunu görebileceğiz. Bu yüzden kullanışlı olduğunu düşünüyorum.

1752149920219.png


1752149951391.png


Bu şekilde gözüküyor. Tasarım konusunda öneriniz varsa mesaj olarak bekliyorum.

YENİ GÜNCELLEME!​

Bir sürü özellik şu an ekli durumda ancak CLI üzerinden kontrol edilmeye hazır değil. Onları da implemente ettikten sonra artık hazır durumda!

Kaynak kodunu nihayet açabildim. Aşağıdaki GitHub adresinden gidip kontrol edebilir, sisteminizde derleyebilir ve kullanmaya başlayabilirsiniz!


@Bayram Tempest, @Maomao, @Disty
 
Son düzenleme:
Birde bana kodlar biraz uzun geldi, alternatif kodlar eklemeyi düşünüyor musunuz?

Kodlar uzun geldi derken, nasıl yani? Argümanları mı diyorsunuz?

Bash:
# -p parametresi isteğe bağlı
cppp -i <files> -o <output> -p 20

Bunu diyorsanız oldukça kısa bence.

Hocam uygulamaya tui yazmayı planlıyor musunuz? Hash çıktısı ile yükleme barı arasına ufak bir çizgisi çekebilirseniz daha anlaşılır olabilir. Alttaki görseldeki gibi ise.

O fotoğraftaki gibi değil, güncelledim o kısmı. Deneyip görseniz daha iyi olur. Ayrıca şu an için TUI yazma gibi bir planım yok. Eğer yaparsanız PR atmayı unutmayın.
 

Technopat Haberler

Yeni konular

Geri
Yukarı