Merhaba. Mart sayımızla yine sizlerleyiz, bu sayımızın nasıl yapılır köşesinde; yama nedir ve nasıl yapılır konularını aydınlatırken, etkili yama yapımı hakkında ufak tüyoları da paylaşmaya çalışacağım.

Yama (Patch) Nedir?

“Need For Speed’in 1.3 patch’i çıkmış abi, artık online oyun çok rahatmış diyorlar.” şeklindeki bir cümleyi ilk duyuşta pek sevmesem de, evet aslında yama dediğimiz şeyin en basit anlatımı diyebiliriz :) Kısaca yama, bir programın ufak hatalarını birkaç değişiklikle düzeltmek için yapılan programcıkların genel adıdır. Hataları tamir ederler, grafikleri yükseltirler veya kullanılabilirliği arttırırlar. Her yama kendine özgüdür ve hangi programın neresini değiştireceğini bilir. Ayrıca kırma programları da (crack) yamalar gibi, ana programı değiştirerek bazı kısıtlamaları kaldırdıklarından ötürü bir çeşit yamadırlar. Bu yüzden kırma programları da programlara ve hatta programın sürümüne göre spesifiktir. İlk cümleye dönersem, demek ki NFS’in ilk sürümünde online oynamada bazı hatalar varmış; fakat bu düzeltilmiş ve 1.3 yaması sayesinde bu düzeltmeler oyunumuzun eski haline sorunsuzca uygulanabiliyormuş :)

Linux’ta Yama

Gelelim benim bugün değineceğim yamalara: genelde yamalar programcıklardır dedim, ancak bugün metin dosyalarına yapılacak olan yamalardan söz edeceğim. Bunlar da aslında yine bir programı güncelleme amaçlı yamalar; ancak kaynak koda bir komut sayesinde uygulandıkları için metin dosyası şeklindeler.

Diyelim bir kod yazdık ve çalıştığını düşünüyoruz. Bu şekilde bulunması gereken yere yükledik veya kullanmaya başladık. Ancak bir süre sonra gördük ki az sayıda girdi için de olsa hata veriyor kodumuz. Ne yapacağız? Tabi ki esas dosyamızın üzerinde de değişiklik yapabiliriz; ama geri dönüşü olmayabilir veya programa daha da zarar verebiliriz. İşte bu küçük örnekte ve daha birçok durumda bu dosyaya yama yapmamız gerekebilir.

Nasıl Yapılır?

Yamaların metin dosyalarından oluştuğunu söylemiştim. Kısaca açıklamak gerekirse, yama dosyaları sadece değişiklikleri kaydettiğimiz dosyalar. Eski dosyadan silinen ve ona eklenen satırların bulunduğu bu dosyaları birazdan örnekleyeceğim. Bu metin dosyalarını, başka metin dosyalarına uygulamak için (hatta yamamak için :) ), adını yani “patch” adlı komutu kullanıyoruz. Vi metin düzenleyicisinde bir dosya açalım ve adım adım ona yama uygulayalım:

ilke@external:~$ vi eskidosya.txt
deneme
surum 1.0

İlk dosyamıza bunu yazdıktan sonra, diyelim ki “deneme” değil de, “test” yazmak istiyorduk. Bunun için eski dosyamızı açıp, “deneme” yerine “test” yazıp, yenidosya.txt olarak kaydedelim. Yenidosya.txt dosyasının içeriği:

ilke@external:~$ cat yenidosya.txt
test
surum 1.0

Şimdi yeni ve çalışan dosyamız hazırsa yapmamız gereken bu iki dosya arasındaki farkları bulup bir yama dosyası hazırlamak. Bunu tabi ki formatına uygun olarak elle tek tek yazabiliriz (o zaman yama yapmaya gerek kalmazdı zaten :) ); ama parmaklarımızın ucunda gayet kullanışlı “diff” komutu varken ne gerek var. Diff, iki dosya arasındaki farkları bulup, aynen istediğimiz tarzda ekrana yazan komut. Ufak bir not düşeyim, diff komutu iki dizinin farkı için de kullanılabiliyor ve bu sefer iki dizinin dosyalarını karşılaştırıyor. Argüman olarak sırasıyla yamanın uygulanacağı dosyayı ve yeni dosyayı verdiğimizde:

ilke@external:~$ diff eskidosya.txt yenidosya.txt
1c1
< deneme
---
> test

görüldüğü gibi “<” işareti ile yamayı uyguladığımız dosyadan çıkardığımız satırları, “>” ile de eklenen satırları gösteriyor. Ayrıca her satırın üzerinde yazan numara o satırın dosyada uygulanacağı yeri belirtiyor. Sayıların ortasındaki harf ise üç seçeneğe sahip: “c” değişiklik, “a” ekleme, “d” silme anlamına geliyor. Yama dosyamız sadece bu çıktıdan ibaret :) Linux’ta bir komutun çıktısını “>” kullanarak bir dosyaya yazabildiğimiz için,

ilke@external:~$ diff eskidosya.txt yenidosya.txt > patch.txt

ile tek hamlede yama dosyamızı oluşturuyoruz. Bu yamayı uygulamak için ise, demin söylediğim patch komutunu kullanıyoruz. Yine aynı sırayla, yamanın uygulanacağı dosya ve yama argümanları ile:

ilke@external:~$ patch eskidosya.txt patch.txt
patching file eskidosya.txt
ilke@external:~$ vi eskidosya.txt
test
surum 1.0

Böylece dosyamız güncellenmiş, hatalarından arınmış oluyor :)

Verimli Yama Yapmak

Programlama yaparken tabi ki her açıdan “verimli” bir kod yazmak çok ideal bir durum, ancak çoğu zaman bir veya iki kıstasa göre bu verimin türünü ayarlıyoruz. Yamalar için de genellikle kolay uygulanabilir olması ve küçük olması verimliliği sağlayan koşullar olabiliyor. Yamayı yaparken, boyutunu göz önüne alacaksak aklımızda bulundurmamız gereken en önemli etken yamanın karakter karakter değil de, satır satır değişiklikleri içeriyor olması. Mesela bir satırdaki yüzlerce karakterinizden sadece birini değiştireceksiniz, bu yüzden o yüzlerce karakteri de boyuta katmak zorunda kalabilirsiniz, hem de eklenen ve çıkarılan olmak üzere iki kere! Bu konuda birkaç püf nokta göstermek istiyorum.

1) Gerek olmadıkça satır silmeyin/eklemeyin.

Boş satır silmek bile yama dosyanızı büyütür. Örneğin eskidosya.txt aynı kalsın, ama yenidosya.txt’de dosya sonunda bir satır atlayalım. Bu durumda eski yama dosyamızın büyüklüğü ile yenisi arasında:

ilke@external:~$ ls -la |grep patch
-rw-r--r-- 1 e1560044 130 24 2008-02-25 02:23 patch.txt
-rw-r--r-- 1 e1560044 130 31 2008-02-25 02:23 patchyeni.txt

Tam (31-24=)7 bytelık fark var! Ve bu sadece boş bir satırın farkı. Bu yüzden çok gerek olmadıkça, eklemelerinizi tek bir satırda yapmanız, zararsız satırlara da bulaşmamanız yamanızın boyutunu minimumda tutacaktır.

2) Bazen silmek yerine göz ardı etmek iyidir ;)

Diyelim karışık bir kodumuz var ve bir satırını değiştirmek istiyoruz. Bu satır: for(i=0;i<k&&i>j;i++) olsun. Ama daha sonra 0 yerine 1 koymamız gerektiğini fark ediyoruz. Sadece 0’ı silip, 1 yazdığımızda, yama dosyamızın boyutu 56 byte olmakla beraber, şöyle görünüyor:

ilke@external:~$ cat patch
1c1
< for(i=0;i<k&&i>j;i++)
---
> for(i=1;i<k&&i>j;i++)

Sadece bir karakter silmemize rağmen bütün satırı silinmiş gibi görüyor. Peki, bunun yerine, o satırı hiç silmesek ve saf dışı bıraksak? Yani bu bir C kodu olduğu için, silmemiz gereken yeri “/*” ve ”*/” ile yorum olarak göstersek ne olmasını beklersiniz? Yama dosyamızın boyutu 39 byte'a düşüyor ve:

ilke@external:~$ cat patch1
0a1
> /*
1a3
> /*for(i=1;i<k&&i>j;i++)

Kısaca eklediğimiz satırın yükünü hafifletemesek de, sildiğimiz satır yerine bir comment işareti bütün satırı imha ediyor :) Gerçekten yamanızın boyutunu minimumda tutmak istiyorsanız, bir süre sonra göreceksiniz ki bütün oklar size dönmüş (>) ve aslında hiçbir silme yapmadan bütün silmeler yerine comment kullanmışsınız :)

3) Diff ve patch komutlarının seçenekleri

Bu komutların duruma göre çok yararlı seçenekleri olabiliyor. Örneğin bazen yama dosyalarının sonunda “no new line at the end of file” şeklinde bir uyarı alınabilirken, bunu diff komutunu "–w" seçeneği ile kullanarak önleyebilir, böylece birçok byte kurtarabiliriz. Ayrıca "–i" ile büyük küçük harf duyarlılığını göz ardı edebiliriz. Veya patch komutunda "–b" seçeneği ile eski dosyanın bir yedeğini alarak yamamızı uygulayabilir, böylece yedekleme önlemimizi alabiliriz.

Bunların yanında, ayrıntılarda boğulmayıp sadece yama dosyamızın kaç byte olduğunu öğrenmek için “wc” (word count) komutu da çok faydalı olacaktır. Son yamamız için:

ilke@external:~$ diff eskidosya.txt yenidosya.txt | wc -c
39

Bir nasıl yapılır köşemizin daha sonuna geldik. Programlarınızın mümkün olduğunca yamaya gereksinim duymamasını dilerken, bütün öğrenci okuyucularımıza yeni dönemlerinde başarılar diliyorum, bizimle kalın =)