<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>Dobrica Pavlinušić&apos;s Weblog / Blog</title>
    <link rel="alternate" type="text/html" href="http://blog.rot13.org/" />
    <link rel="self" type="application/atom+xml" href="http://blog.rot13.org/atom.xml" />
    <id>tag:blog.rot13.org,2009-06-21://1</id>
    <updated>2010-02-01T19:29:52Z</updated>
    <subtitle>Personal weblog about technology, Open Source, perl, GNU etc...</subtitle>
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type 4.32-en</generator>

<entry>
    <title>Using btrfs snapshots for incremental backup</title>
    <link rel="alternate" type="text/html" href="http://blog.rot13.org/2010/02/using_btrfs_snapshots_for_incremental_backup.html" />
    <id>tag:blog.rot13.org,2010://1.683</id>

    <published>2010-02-01T17:06:16Z</published>
    <updated>2010-02-01T19:29:52Z</updated>

    <summary> You have heard of Apple Time Capsule, and zfs&apos;s snapshots which provide nice way to produce incremental backups which you can use to quickly recover a rm -Rf typo or compare changes... You can&apos;t really use LVM snapshots for that because they have fixed size of snapshot. ZFS has copy-on-write snapshots, but zfs-fuse isn&apos;t fastest solution on Linux. I decided to give btrfs another try. On Debian 2.6.32-trunk kernels, it stills have problems with 686 kernel, but amd64 version (even with 32-bit users-pace) seems to work stable so far. Let&apos;s take a look at example usage on /dev/vg/koha-btrfs logical volume. create filesystem root@mlin:~# mkfs.btrfs /dev/vg/koha-btrfs create subvolume which we will use for data root@mlin:~# btrfsctl -S koha-2010-01-25 /virtual.btrfs/ populate it with some data root@mlin:~# time cp -ra /virtual.clone/koha-2010-01-25 /virtual.btrfs/ real 15m32.507s user 0m1.288s sys 0m54.519s create base snapshot root@mlin:~# btrfsctl -s /virtual.btrfs/koha-2010-01-25.mlin /virtual.btrfs/koha-2010-01-25 There is convention here: since snapshot directories have to be on same btrfs volume, I decided to use base_name(dot)something as convention for my snapshots. make some changes on base directory root@mlin:~# time rsync -ravH --numeric-ids --sparse --delete --exclude &apos;backup*&apos; 10.60.0.90:/opl/clone/koha-2010-01-25/ /virtual.btrfs/koha-2010-01-25/ sent 1538957 bytes received 381670534 bytes 964049.03 bytes/sec total size is 18912566086 speedup is 49.35 real 6m37.539s user 0m59.524s sys 1m23.633s make another snapshot for this version root@mlin:~# btrfsctl -s /virtual.btrfs/koha-2010-01-25.opr /virtual.btrfs/koha-2010-01-25 Following this, we now have three directories which share same data (tanks to copy-on-write feature in btrfs) and look like ordinary directories: dpavlin@mlin:~$ ls -ald /virtual.btrfs/koha-2010-01-25* drwxr-xr-x 1 root root 256 Dec 29 19:38 /virtual.btrfs/koha-2010-01-25 drwxr-xr-x 1 root root 256 Dec 29 19:38 /virtual.btrfs/koha-2010-01-25.mlin drwxr-xr-x 1 root root 256 Dec 29 19:38 /virtual.btrfs/koha-2010-01-25.opr After a while, you will run out of disk space, but since we are on LVM, extending filesystem is really easy: dpavlin@mlin:~$ mount -t btrfs /dev/mapper/vg-koha--btrfs on /virtual.btrfs type btrfs (rw,noatime) root@mlin:~# lvdisplay /dev/vg/koha-btrfs --- Logical volume --- LV Name /dev/vg/koha-btrfs VG Name vg LV UUID kl4QUc-IyK2-IM8m-0DKD-eI5k-H2T1-HySIwE LV Write Access read/write LV Status available # open 1 LV Size 40.00 GB Current LE 10240 Segments 1 Allocation inherit Read ahead sectors auto - currently set to 256 Block device 253:1 root@mlin:~# lvextend -L +10G /dev/vg/koha-btrfs Extending logical volume koha-btrfs to 50.00 GB Logical volume koha-btrfs successfully resized root@mlin:~# btrfsctl -r max /virtual.btrfs/ Hopefully this will help you to get started with btrfs snapshots. I still don&apos;t consider it super stable (especially since i did saw few kernel oopses using 2.6.32-trunk-686) but for quick experiments with Linux containers (or anything stored on filesystem for that matter) it proved more than adequate....</summary>
    <author>
        <name>Dobrica Pavlinušić</name>
        <uri>http://www.rot13.org/~dpavlin/</uri>
    </author>
    
        <category term="hack-of-the-week" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="btrfs" label="btrfs" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://blog.rot13.org/">
        <![CDATA[<p>
You have heard of Apple Time Capsule, and zfs's snapshots which provide nice way to produce incremental backups which you can use to quickly recover a rm -Rf typo or compare changes... You can't really use LVM snapshots for that because they have fixed size of snapshot. ZFS has copy-on-write snapshots, but zfs-fuse isn't fastest solution on Linux.
<p>
I decided to give <a href="http://blog.rot13.org/2009/05/btrfs_kernel_warning_about_alpha_state_is_there_for_a_reason.html">btrfs</a> another try. On Debian 2.6.32-trunk kernels, it stills have problems with 686 kernel, but amd64 version (even with 32-bit users-pace) seems to work stable so far.
</p>
<p>
Let's take a look at example usage on /dev/vg/koha-btrfs logical volume.
<ol>
<li>create filesystem
<pre>
root@mlin:~# mkfs.btrfs /dev/vg/koha-btrfs
</pre>
<li>create subvolume which we will use for data
<pre>
root@mlin:~# btrfsctl -S koha-2010-01-25 /virtual.btrfs/
</pre>
<li>populate it with some data
<pre>
root@mlin:~# time cp -ra /virtual.clone/koha-2010-01-25 /virtual.btrfs/

real    15m32.507s
user    0m1.288s
sys     0m54.519s
</pre>
<li>create base snapshot
<pre>
root@mlin:~# btrfsctl -s /virtual.btrfs/koha-2010-01-25.mlin /virtual.btrfs/koha-2010-01-25
</pre>
There is convention here: since snapshot directories have to be on same btrfs volume, I decided to use base_name(dot)something as convention for my snapshots.
<li>make some changes on base directory
<pre>
root@mlin:~# time rsync -ravH --numeric-ids --sparse --delete --exclude 'backup*' 10.60.0.90:/opl/clone/koha-2010-01-25/ /virtual.btrfs/koha-2010-01-25/

sent 1538957 bytes  received 381670534 bytes  964049.03 bytes/sec
total size is 18912566086  speedup is 49.35

real    6m37.539s
user    0m59.524s
sys     1m23.633s
</pre>
<li>make another snapshot for this version
<pre>
root@mlin:~# btrfsctl -s /virtual.btrfs/koha-2010-01-25.opr /virtual.btrfs/koha-2010-01-25
</pre>
</ol>

Following this, we now have three directories which share same data (tanks to copy-on-write feature in btrfs) and look like ordinary directories:
<pre>
dpavlin@mlin:~$ ls -ald /virtual.btrfs/koha-2010-01-25*
drwxr-xr-x 1 root root 256 Dec 29 19:38 /virtual.btrfs/koha-2010-01-25
drwxr-xr-x 1 root root 256 Dec 29 19:38 /virtual.btrfs/koha-2010-01-25.mlin
drwxr-xr-x 1 root root 256 Dec 29 19:38 /virtual.btrfs/koha-2010-01-25.opr
</pre>

After a while, you will run out of disk space, but since we are on LVM, extending filesystem is really easy:
<pre>
dpavlin@mlin:~$ mount -t btrfs
/dev/mapper/vg-koha--btrfs on /virtual.btrfs type btrfs (rw,noatime)


root@mlin:~# lvdisplay /dev/vg/koha-btrfs 
  --- Logical volume ---
  LV Name                /dev/vg/koha-btrfs
  VG Name                vg
  LV UUID                kl4QUc-IyK2-IM8m-0DKD-eI5k-H2T1-HySIwE
  LV Write Access        read/write
  LV Status              available
  # open                 1
  LV Size                40.00 GB
  Current LE             10240
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     256
  Block device           253:1

   
root@mlin:~# lvextend -L +10G /dev/vg/koha-btrfs
  Extending logical volume koha-btrfs to 50.00 GB
  Logical volume koha-btrfs successfully resized


root@mlin:~# btrfsctl -r max /virtual.btrfs/
</pre>

<p>
Hopefully this will help you to get started with btrfs snapshots. I still don't consider it super stable (especially since i did saw few kernel oopses using 2.6.32-trunk-686) but for quick experiments with Linux containers (or anything stored on filesystem for that matter) it proved more than adequate.
</p>
]]>
        
    </content>
</entry>

<entry>
    <title>It&apos;s about system, stupid!</title>
    <link rel="alternate" type="text/html" href="http://blog.rot13.org/2010/01/its_about_system_stupid.html" />
    <id>tag:blog.rot13.org,2010://1.682</id>

    <published>2010-01-28T13:30:00Z</published>
    <updated>2010-01-29T13:11:33Z</updated>

    <summary> When you are working as system architect or systems librarian, your job is to design systems. My initial idea was to create small Google out of 12 machines which are dedicated to be web kiosks. I decided to strictly follow loosely coupled principle, mostly to provide horizontal scaling for my data processing needs. I wanted to be able to add machine or two if my query is too slow... This easily translates into &quot;now long will I have to wait for my page to generate results&quot;.... I decided to split my system into three logical parts: network booting, data store, and quick reporting. So, let&apos;s take a look at each component separately: PXElator supported protocols: bootp, dhcp, tftp, http, amt, wol, syslog boot kiosks using Webconverger (Debian Live based kiosk distribution) provides web user interface for overview of network segment for audit configuration is stored as files on disk, suitable for management with git or other source control management MongoDB NoSQL storage component which support ad-hoc queries, indexes and other goodies simple store for perl hashes from PXElator generated every time we see network packet from one of clients using one of supported protocols Sack fastest possible way to execute snippet of perl code over multiple machines this involves sharing information to nodes, executing code on all of them and collecting results back, all in sub 3 second mark! web user interface for cloud overview and graph generation using gnuplot When I started implementing this system last summer, I decided to use CouchDB for storage layer. This wasn&apos;t really good choice, since I didn&apos;t need transactions, MVCC or replication. Hack, I even implemented forking for document stored in CouchDB to provide faster response to clients in PXElator. Moving to much faster MongoDB I got ad-hoc queries which are usable (as in I can wait for them to finish) and if that&apos;s too slow, I can move data to Sack and query it directly from memory. As a happy side effect, making shards from MongoDB is much faster than using CouchDB bulk HTTP API, and it will allow me to feed shards directly from MongoDB to Sack nodes, without first creating shards on disk. I&apos;m quite happy how it all turned out. I can configure any host using small snippet of perl code in PXElator, issue ad-hoc queries on audit data on it in MongoDB or move data to Sack if I want to do data munging using perl. As you noticed by now, I&apos;m using live distribution for kiosks, and machines do have hard drivers in them. Idea was to use those disks as storage with something like Sheepdog. seems like perfect fit. With it in place, I will have real distributed, building size computer :-)....</summary>
    <author>
        <name>Dobrica Pavlinušić</name>
        <uri>http://www.rot13.org/~dpavlin/</uri>
    </author>
    
        <category term="PXElator" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Sack" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="couchdb" label="CouchDB" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="mongodb" label="MongoDB" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="pxelator" label="PXElator" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="sack" label="Sack" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl" label="perl" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://blog.rot13.org/">
        <![CDATA[<p>

<img alt="lib-architecture-v2.png" src="http://blog.rot13.org/2010/01/27/lib-architecture-v2.png" width="291" height="318" class="mt-image-right" style="float: right; margin: 0 0 20px 20px;" />

When you are working as system architect or systems librarian, your job is to design systems. My initial idea was to create small Google out of 12 machines which are dedicated to be web kiosks. I decided to strictly follow <em>loosely coupled</em> principle, mostly to provide horizontal scaling for my data processing needs. I wanted to be able to add machine or two if my query is too slow... This easily translates into "now long will I have to wait for my page to generate results"....
</p>

<p>
I decided to split my system into three logical parts: network booting, data store, and quick reporting. So, let's take a look at each component separately:

<ul>

<li><a href="https://www.ohloh.net/p/PXElator">PXElator</a>
<ul>
<li>supported protocols: bootp, dhcp,  tftp, http, amt, wol, syslog
<li>boot kiosks using <a href="http://webconverger.com/">Webconverger</a> (<a href="http://debian-live.alioth.debian.org/">Debian Live</a> based kiosk distribution)
<li>provides web user interface for overview of network segment for audit
<li>configuration is stored as files on disk, suitable for management with git or other source control management
</ul>

<li><a href="http://www.mongodb.org">MongoDB</a>
<ul>
<li>NoSQL storage component which support ad-hoc queries, indexes and other goodies
<li>simple store for perl hashes from PXElator generated every time we see network packet from one of clients using one of supported protocols
</ul>

<li><a href="https://www.ohloh.net/p/Sack-perl">Sack</a>
<ul>
<li>fastest possible way to execute snippet of perl code over multiple machines
<li>this involves sharing information to nodes, executing code on all of them and collecting results back, all in sub 3 second mark!
<li>web user interface for cloud overview and graph generation using gnuplot
</ul>

</ul>

</p>

<p>
When I started implementing this system last summer, I decided to use <a href="http://couchdb.apache.org/">CouchDB</a> for storage layer. This wasn't really good choice, since I didn't need transactions, MVCC or replication. Hack, I even implemented forking for document stored in CouchDB to provide faster response to clients in PXElator.
</p>
<p>
Moving to much faster MongoDB I got ad-hoc queries which are usable (as in <em>I can wait for them to finish</em>) and if that's too slow, I can move data to Sack and query it directly from memory. As a happy side effect, making shards from MongoDB is much faster than using CouchDB bulk HTTP API, and it will allow me to feed shards directly from MongoDB to Sack nodes, without first creating shards on disk.
</p>

<p>
I'm quite happy how it all turned out. I can configure any host using small snippet of perl code in PXElator, issue ad-hoc queries on audit data on it in MongoDB or move data to Sack if I want to do data munging using perl.
</p>

<p>
As you noticed by now, I'm using live distribution for kiosks, and machines do have hard drivers in them. Idea was to use those disks as storage with something like <a href="http://www.osrg.net/sheepdog/faq.html">Sheepdog</a>. seems like perfect fit. With it in place, I will have real distributed, building size computer <tt>:-)</tt>.
</p>
]]>
        
    </content>
</entry>

<entry>
    <title>MongoDB - so you want fast NoSQL database which you can grok</title>
    <link rel="alternate" type="text/html" href="http://blog.rot13.org/2010/01/mongodb_-_so_you_want_fast_nosql_database_which_you_can_grok.html" />
    <id>tag:blog.rot13.org,2010://1.681</id>

    <published>2010-01-24T11:56:57Z</published>
    <updated>2010-01-24T12:45:33Z</updated>

    <summary> I have been using CouchDB for some time now, mostly as audit storage for PXElator. Audit data stores are most useful for ad-hoc queries (hum, when did I saw that host last time?), and CouchDB map/reduces took half an hour or more. I wrote mall script couchdb2mongodb.pl to migrate my data over to MongoDB (in 26 minutes) and run first query I could write after reading MongoDB documentation about advanced queries. It took only 30 seconds, compared to 30 minutes or more in CouchDB. I was amazed. This was NoSQL database which I can understand and tune. MongoDB has indexes and profiler so tuning query down to three seconds was a simple matter of adding an index. All my RDBMS knowledge was reusable here, so I decided to take a look why is it so much faster than CouchDB for same data... To be honest, MongoDB, High-Performance SQL-Free Database by Dwight Merriman, CEO of 10gen won me over to finally try MongoDB. It was technical enough to make me think about MongoDB arhitecture and benefits. It&apos;s clearly pragmatic, let&apos;s re-think horizontally scalable hash storage with ad-hoc queries model, but with funny twist about close coupling with language types all encoded in BSON format, which is very similar to Google&apos;s protocol buffers. First, let&apos;s have a look at raw side of data on disk. At some level, it will translate to number of IO operations involving rotating platters and usage of buffer cache. root@opr:~# du -hc /var/lib/couchdb/0.9.0/.pxelator* /var/lib/couchdb/0.9.0/pxelator.couch 655M /var/lib/couchdb/0.9.0/.pxelator_design 23M /var/lib/couchdb/0.9.0/.pxelator_temp 7.8G /var/lib/couchdb/0.9.0/pxelator.couch 8.4G total root@opr:~# du -hc /var/lib/mongodb/pxelator.* 65M /var/lib/mongodb/pxelator.0 129M /var/lib/mongodb/pxelator.1 257M /var/lib/mongodb/pxelator.2 513M /var/lib/mongodb/pxelator.3 513M /var/lib/mongodb/pxelator.4 513M /var/lib/mongodb/pxelator.5 17M /var/lib/mongodb/pxelator.ns 2.0G total Here is a first hint about performance: MongoDB&apos;s 2G of data (which are used as mmap memory directly, leaving flushes and caching to OS layer) are almost a perfect fit into 3G of RAM memory I have in this machine. MongoDB has montodump utility which dumps bson for backup and it&apos;s even smaller: root@opr:~# du -hcs dump/pxelator/* 1.1G dump/pxelator/audit.bson 4.0K dump/pxelator/system.indexes.bson 76K dump/pxelator/system.profile.bson 1.1G total So I switched PXElator to use MongoDB as storage. I never pushed anything in production after just one day of testing it, but first query speedup from 30 min to 30 sec, and ability to cut it down to 3 sec if I added index (which took about 13 sec to create) is just something which provides me with powerful analytical tool I didn&apos;t have before....</summary>
    <author>
        <name>Dobrica Pavlinušić</name>
        <uri>http://www.rot13.org/~dpavlin/</uri>
    </author>
    
        <category term="PXElator" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="couchdb" label="CouchDB" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="mongodb" label="MongoDB" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="pxelator" label="PXElator" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://blog.rot13.org/">
        <![CDATA[<p>
I have been using <a href="http://couchdb.apache.org/">CouchDB</a> for some time now, mostly as audit storage for <a href="https://www.ohloh.net/p/PXElator">PXElator</a>.

Audit data stores are most useful for ad-hoc queries (hum, when did I saw that host last time?), and CouchDB  map/reduces took half an hour or more. 

I wrote mall script <a href="http://svn.rot13.org/index.cgi/pxelator/view/bin/couchdb2mongodb.pl">couchdb2mongodb.pl</a> to migrate my data over to MongoDB (in 26 minutes) and run <a href="http://saturn.ffzg.hr/rot13/index.cgi?mongodb" title="MongoDB page on my wiki">first query I could write</a> after reading <a href="http://www.mongodb.org/display/DOCS/Advanced+Queries">MongoDB documentation about advanced queries</a>.

<em>It took only 30 seconds, compared to 30 minutes or more in CouchDB</em>. I was amazed.
</p>
<p>
This was NoSQL database which I can understand and tune. <a href=http://www.mongodb.org/display/DOCS/Indexes"">MongoDB has indexes</a> and <a href="http://www.mongodb.org/display/DOCS/Database+Profiler">profiler</a> so tuning query down to three seconds was a simple matter of adding an index. All my RDBMS knowledge was reusable here, so I decided to take a look why is it so much faster than CouchDB for same data...
</p>
<p>
To be honest, <a href="http://www.leadit.us/hands-on-tech/MongoDB-High-Performance-SQL-Free-Database">MongoDB, High-Performance SQL-Free Database by Dwight Merriman, CEO of 10gen</a> won me over to finally try MongoDB. It was technical enough to make me think about MongoDB arhitecture and benefits. It's clearly pragmatic, let's re-think <a href="http://www.mongodb.org/display/DOCS/Sharding">horizontally scalable</a> hash storage with <a href="http://www.mongodb.org/display/DOCS/Querying">ad-hoc queries</a> model, but with funny twist about close coupling with language types all encoded in <a href="http://www.mongodb.org/display/DOCS/BSON">BSON</a> format, which is very similar to <a href="http://code.google.com/apis/protocolbuffers/">Google's protocol buffers</a>.
</p>
<p>
First, let's have a look at raw side of data on disk. At some level, it will translate to number of IO operations involving rotating platters and usage of buffer cache.
<pre>
root@opr:~# du -hc /var/lib/couchdb/0.9.0/.pxelator* /var/lib/couchdb/0.9.0/pxelator.couch
655M    /var/lib/couchdb/0.9.0/.pxelator_design
23M     /var/lib/couchdb/0.9.0/.pxelator_temp
7.8G    /var/lib/couchdb/0.9.0/pxelator.couch
8.4G    total

root@opr:~# du -hc /var/lib/mongodb/pxelator.*
65M     /var/lib/mongodb/pxelator.0
129M    /var/lib/mongodb/pxelator.1
257M    /var/lib/mongodb/pxelator.2
513M    /var/lib/mongodb/pxelator.3
513M    /var/lib/mongodb/pxelator.4
513M    /var/lib/mongodb/pxelator.5
17M     /var/lib/mongodb/pxelator.ns
2.0G    total
</pre>
Here is a first hint about performance: MongoDB's 2G of data (which are used as mmap memory directly, leaving flushes and caching to OS layer) are almost a perfect fit into 3G of RAM memory I have in this machine.
</p>
<p>
MongoDB has <a href="http://www.mongodb.org/display/DOCS/Import+Export+Tools#ImportExportTools-mongodump">montodump</a> utility which dumps bson for backup and it's even smaller:
<pre>
root@opr:~# du -hcs dump/pxelator/*
1.1G    dump/pxelator/audit.bson
4.0K    dump/pxelator/system.indexes.bson
76K     dump/pxelator/system.profile.bson
1.1G    total
</pre>
</p>
<p>
So I switched PXElator to use MongoDB as storage. I never pushed anything in production after just one day of testing it, but first query speedup from 30 min to 30 sec, and ability to cut it down to 3 sec if I added index (which took about 13 sec to create) is just something which provides me with powerful analytical tool I didn't have before.
</p>]]>
        
    </content>
</entry>

<entry>
    <title>OmniKey CardMan 5321 supported by librfid</title>
    <link rel="alternate" type="text/html" href="http://blog.rot13.org/2010/01/omnikey_cardman_5321_supported_by_librfid.html" />
    <id>tag:blog.rot13.org,2010://1.680</id>

    <published>2010-01-19T15:38:31Z</published>
    <updated>2010-01-19T16:03:22Z</updated>

    <summary> I had OmniKey CardMan 5321 reader sitting on my desk for quite some time. First time I tried it, I had problem with propitiatory binary driver which expected pcscd to be compiled without hal support to make it work. Fortunately, we now have pcsc-omnikey package in Debian which should make usage of this reader much easier. But, I really wanted more low-level implementation, allowing me to muck with cards without need to pass through whole smart card stack (since I&apos;m really only interested in RFID part of this reader). So, I did some searching and found out that librfid - A Free Software RFID stack implements support for this reader, so here is a quick overview of how to get started: # build dependency dpavlin@klin:/rest/cvs/librfid$ sudo apt-get install libusb-dev # checkout source dpavlin@klin:/rest/cvs$ svn co https://svn.gnumonks.org/trunk/librfid/ dpavlin@klin:/rest/cvs$ cd librfid/ dpavlin@klin:/rest/cvs/librfid$ ./autogen.sh # build dpavlin@klin:/rest/cvs/librfid$ ./configure --enable-ccid dpavlin@klin:/rest/cvs/librfid$ make Now we can test if our reader is working: dpavlin@klin:/rest/cvs/librfid$ sudo ./utils/librfid-tool -s lt-librfid-tool - (C) 2005-2008 by Harald Welte This program is Free Software and has ABSOLUTELY NO WARRANTY initializing librfid opening reader handle OpenPCD, CM5x21 No OpenPCD found scanning for RFID token... Layer 2 success (ISO 15693): eb 6e 77 1f 00 01 04 e0 And, that&apos;s not all. We can also read content of our tag: dpavlin@klin:/rest/cvs/librfid$ sudo ./utils/librfid-tool -r -1 lt-librfid-tool - (C) 2005-2008 by Harald Welte This program is Free Software and has ABSOLUTELY NO WARRANTY initializing librfid opening reader handle OpenPCD, CM5x21 No OpenPCD found Layer2 init ok Layer 2 success (ISO 15693)[8]: &apos; eb 6e 77 1f 00 01 04 e0&apos; block[ 0:00]sec:0x8 data(4): 04 11 00 01 block[ 1:01]sec:0x8 data(4): 31 33 30 32 block[ 2:02]sec:0x8 data(4): 30 32 39 37 block[ 3:03]sec:0x8 data(4): 31 30 00 00 block[ 4:04]sec:0x8 data(4): 00 00 00 00 ... block[ 26:1a]sec:0x8 data(4): 00 00 00 00 block[ 27:1b]sec:0x8 data(4): 57 5f 4f 4b no data(read_block(28)&gt;&gt; -1) It&apos;s exactly what I was looking for: ability to do low-level block transfer with RFID card. This is great news since I don&apos;t have to carry bulky 3M reader and antenna with me to conferences to demonstrate RFID. Since I didn&apos;t find librfid first time I searched for software to drive this reader, I hope that this post will be helpful to someone.If you intend to buy RFID reader, take a look at OpenPCD instead of this one :-)...</summary>
    <author>
        <name>Dobrica Pavlinušić</name>
        <uri>http://www.rot13.org/~dpavlin/</uri>
    </author>
    
        <category term="hack-of-the-week" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="rfid" label="RFID" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://blog.rot13.org/">
        <![CDATA[<p>
<a href="http://blog.rot13.org/assets_c/2010/01/CardMan-5321_free-42.html" onclick="window.open('http://blog.rot13.org/assets_c/2010/01/CardMan-5321_free-42.html','popup','width=398,height=326,scrollbars=no,resizable=no,toolbar=no,directories=no,location=no,menubar=no,status=no,left=0,top=0'); return false"><img src="http://blog.rot13.org/assets_c/2010/01/CardMan-5321_free-thumb-160x131-42.jpg" width="160" height="131" alt="CardMan-5321_free.jpg" class="mt-image-right" style="float: right; margin: 0 0 20px 20px;" /></a>

I had <a href="http://www.hidglobal.com/prod_detail.php?prod_id=171">OmniKey CardMan 5321</a> reader sitting on my desk for quite some time. First time I tried it, I had problem with propitiatory binary driver which expected <tt>pcscd</tt> to be compiled without hal support to make it work.
</p>
<p>
Fortunately, we now have <tt>pcsc-omnikey</tt> package in Debian which should make usage of this reader much easier. But, I really wanted more low-level implementation, allowing me to muck with cards without need to pass through whole smart card stack (since I'm really only interested in RFID part of this reader).
</p>
<p>
So, I did some searching and found out that <a href="http://openmrtd.org/projects/librfid/">librfid - A Free Software RFID stack</a> implements support for this reader, so here is a quick overview of how to get started:
<pre>
# build dependency
dpavlin@klin:/rest/cvs/librfid$ sudo apt-get install libusb-dev

# checkout source
dpavlin@klin:/rest/cvs$ svn co https://svn.gnumonks.org/trunk/librfid/
dpavlin@klin:/rest/cvs$ cd librfid/
dpavlin@klin:/rest/cvs/librfid$ ./autogen.sh

# build
dpavlin@klin:/rest/cvs/librfid$ ./configure --enable-ccid
dpavlin@klin:/rest/cvs/librfid$ make
</pre>
Now we can test if our reader is working:
<pre>
dpavlin@klin:/rest/cvs/librfid$ sudo ./utils/librfid-tool -s
lt-librfid-tool - (C) 2005-2008 by Harald Welte
This program is Free Software and has ABSOLUTELY NO WARRANTY

initializing librfid
opening reader handle OpenPCD, CM5x21
No OpenPCD found
scanning for RFID token...
Layer 2 success (ISO 15693):  eb 6e 77 1f 00 01 04 e0
</pre>
And, that's not all. We can also read content of our tag:
<pre>
dpavlin@klin:/rest/cvs/librfid$ sudo ./utils/librfid-tool -r -1
lt-librfid-tool - (C) 2005-2008 by Harald Welte
This program is Free Software and has ABSOLUTELY NO WARRANTY

initializing librfid
opening reader handle OpenPCD, CM5x21
No OpenPCD found
Layer2 init ok
Layer 2 success (ISO 15693)[8]: ' eb 6e 77 1f 00 01 04 e0'
block[  0:00]sec:0x8 data(4):  04 11 00 01
block[  1:01]sec:0x8 data(4):  31 33 30 32
block[  2:02]sec:0x8 data(4):  30 32 39 37
block[  3:03]sec:0x8 data(4):  31 30 00 00
block[  4:04]sec:0x8 data(4):  00 00 00 00
...
block[ 26:1a]sec:0x8 data(4):  00 00 00 00
block[ 27:1b]sec:0x8 data(4):  57 5f 4f 4b
no data(read_block(28)>> -1)
</pre>
It's <em>exactly what I was looking for</em>: ability to do low-level block transfer with RFID card.
</p>
<p>
This is great news since I don't have to carry bulky 3M reader and antenna with me to conferences to demonstrate RFID. Since I didn't find <tt>librfid</tt> first time I searched for software to drive this reader, I hope that this post will be helpful to someone.If you intend to buy RFID reader, take a look at <a href="http://www.openpcd.org/">OpenPCD</a> instead of this one <tt>:-)</tt>
</p>]]>
        
    </content>
</entry>

<entry>
    <title>Agile web development in 2010</title>
    <link rel="alternate" type="text/html" href="http://blog.rot13.org/2010/01/agile_web_development_in_2010.html" />
    <id>tag:blog.rot13.org,2010://1.679</id>

    <published>2010-01-14T22:10:22Z</published>
    <updated>2010-01-14T22:57:06Z</updated>

    <summary> I have been developing web application since 1995, and things have changed a lot since than. Back in the old days, we tried to render good in text-only browsers and machines where much slower back than. Why it that important? I had interesting problem today: write csv file filtering application in an hour. Basically, I had one hour to make semi-formated csv file somehow searchable. It had sub-totals, and you wanted to type some words and search for then within each section (they all have to be in same section to make section visible as result). Since data is really textual report from SQL database, it seemed somehow logical to put it back into database and write complex SQL query to return just parts of it. Or store it in full-text search. In 1990 or so... But, let&apos;s take a look in directory: I have 600K csv file. I decided to write simple cgi wrapper which understands sections (and ignores rest), basically streaming csv converted to html table back to client (which provided nice incremental rendering for bigger result sets). I had simple input-box, submit button, html table application in one hour. And it was used 522 times today, speeding up manual search and retrieve work with papers. Let&apos;s think about this situation again. There is only one simple rule for agile: scale your solution to your problem, not to your technological preferences. Rest of the day, I spent fighting utf-8 encoding (in 2010 still, sigh!), aligning columns and formatting floating numbers (with few style=&quot;color:gray&quot; here and there) and added highlight to lines within section which match search words. At the end of the day, I added a simple summaries on the bottom. Not bad for 1 hour/1 day application....</summary>
    <author>
        <name>Dobrica Pavlinušić</name>
        <uri>http://www.rot13.org/~dpavlin/</uri>
    </author>
    
        <category term="hack-of-the-week" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://blog.rot13.org/">
        <![CDATA[<p>
I have been developing web application since 1995, and things have changed a lot since than. Back in the old days, we tried to render good in text-only browsers and machines where much slower back than. Why it that important? I had interesting problem today: write csv file filtering application in an hour.
</p>
<p>
Basically, I had one hour to make semi-formated csv file somehow searchable. It had sub-totals, and you wanted to type some words and search for then within each section (they all have to be in same section to make section visible as result). Since data is really textual report from SQL database, it seemed somehow logical to put it back into database and write complex SQL query to return just parts of it. Or store it in full-text search. In 1990 or so...
</p>
<p>
But, let's take a look in directory: I have 600K csv file. I decided to write simple cgi wrapper which understands sections (and ignores rest), basically streaming csv converted to html table back to client (which provided nice incremental rendering for bigger result sets). I had simple input-box, submit button, html table application in one hour. And it was used 522 times today, speeding up manual search and retrieve work with papers.
</p>
<p>
Let's think about this situation again. There is only one simple rule for agile: scale your solution to your problem, not to your technological preferences. Rest of the day, I spent fighting utf-8 encoding (in 2010 still, sigh!), aligning columns and formatting floating numbers (with few style="color:gray" here and there) and added highlight to lines within section which match search words.
</p>
<p>
At the end of the day, I added a simple summaries on the bottom. Not bad for 1 hour/1 day application. 
</p>]]>
        
    </content>
</entry>

<entry>
    <title>Protocol analysts of DRAC remote console</title>
    <link rel="alternate" type="text/html" href="http://blog.rot13.org/2010/01/protocol_analysts_of_drac_remote_console.html" />
    <id>tag:blog.rot13.org,2010://1.678</id>

    <published>2010-01-10T19:19:38Z</published>
    <updated>2010-01-10T21:35:26Z</updated>

    <summary> As you know by now, I have been playing with Dell&apos;s remote consoles in hope that I will be able to connect from my Linux to Dell&apos;s RAC reliably. Currently, I have to run Windows XP with Internet Explorer and Java in kvm to have access to my servers, and that&apos;s clearly not reliable combination. DRAC is PCI card which is presented to system as VGA which then transfers screen updates over the network to client. It also allows virtual media, but in a sense, it&apos;s mix-up of http over ssl and few propitiatory protocols: 443 - https interface 3368 - virtual media (proprietary) 5900 - keyboard and mouse (ssl encrypted) 5901 - video redirection (optionally ssl encrypted) It&apos;s very strange that all documentation calls 5900 video redirection port and 5901 keyboard/mouse redirection when all traces of traffic between client and server clearly show that ports are swapped in implementation. Did you notice ssl encrypted keyboard/mouse channel? I first decided to tackle this problem with well known SSL man in the middle approach. I decided to use simpliest possible approach first using something like: apt-get install stunnel openssl req -new -x509 -days 365 -nodes -out cert.pem -keyout cert.pem # https mitm stunnel -p cert.pem -d 443 -r 5443 stunnel -c -d 5443 -r 10.60.0.100:443 # 5900 mitm stunnel -p cert.pem -d 5900 -r 5999 stunnel -c -d 5999 -r 10.60.0.100:5900 and than recoding all output using wireshark: sudo tshark -w /tmp/drac.pcap -i any &apos;port 5999 or port 5901 or port 5443&apos; This allowed me to capture all unencrypted traffic into single pcap file which proved very useful for initial protocol analysis using wireshark. In short, you have to do following: make https connection to https://drac/cgi-bin/webcgi/winvkvm?state=1 and acquire vKvmSessionId console redirection authentication key connect to keyboard/mouse port 5900 forcing SSL_cipher_list to supported RC4-MD5 cipher and send vKvmSessionId connect to video port 5901 Finding supported cipher for communication between us and server was a real problem. They are using openssl-0.9.7f and I had to downgrade all the way to Debian woody to make stunnel work. Same problem is visible with latest firmware update for DRAC where Active X plugin doesn&apos;t have old enough configuration in SSL handshake and doesn&apos;t work any more. Java plugin, on the other hand, provides much more cipher options, so one of them still works. ssldump was very useful for finding such problems. Fortunately, kost was much more persistent than me, and he found out that adding &apos;SSL_cipher_list&apos; =&gt; &apos;RC4-MD5&apos; will force supported cipher. Armed with that new finding, I was able to modify kost&apos;s ssl mitm script up to the point where I can see decrypted key-presses, mouse movements and video settings. Hack, I even wrote drac-vkvm.pl async client which does steps outlined above. All is not well, unfortunately. When sending authentication request, we need vKvmSessionId which we get from web server, but packet which is sent contains also two bytes which change with session. I haven&apos;t been able to figure this part out, and since same two byte sequence is needed to open video channel (to see VGA output) so I&apos;m stuck. Bytes don&apos;t look like crc16, and source code doesn&apos;t provide any hints about secondary 16-bit auth info. It seems that client calculates it somehow, since both connections close when I try to send different values for it. I could write session recorder, but that isn&apos;t terribly useful, because it still forces me to use Windows+Java setup to access my console. I will collect usefull snippets about Dell&apos;s RAC protocol on wiki....</summary>
    <author>
        <name>Dobrica Pavlinušić</name>
        <uri>http://www.rot13.org/~dpavlin/</uri>
    </author>
    
        <category term="hack-of-the-week" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="drac" label="DRAC" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="dell" label="dell" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://blog.rot13.org/">
        <![CDATA[<p>
As you know by now, I have been playing with Dell's remote consoles in hope that I will be able to connect from my Linux to Dell's RAC reliably. Currently, I have to run Windows XP with Internet Explorer and Java in kvm to have access to my servers, and that's clearly not reliable combination.
</p>

<p>
DRAC is PCI card which is presented to system as VGA which then transfers screen updates over the network to client. It also allows virtual media, but in a sense, it's mix-up of http over ssl and few propitiatory protocols:

<ul>
<li>443 - https interface
<li>3368 - virtual media (proprietary)
<li>5900 - keyboard and mouse (ssl encrypted)
<li>5901 - video redirection (optionally ssl encrypted)
</ul>

It's very strange that all documentation calls 5900 video redirection port and 5901 keyboard/mouse redirection when all traces of traffic between client and server clearly show that ports are swapped in implementation.
</p>

<p>
Did you notice ssl encrypted keyboard/mouse channel? I first decided to tackle this problem with well known <a href="http://en.wikipedia.org/wiki/Man-in-the-middle_attack">SSL man in the middle approach</a>. I decided to use simpliest possible approach first using something like:

<pre>
apt-get install stunnel

openssl req -new -x509 -days 365 -nodes -out cert.pem -keyout cert.pem

# https mitm
stunnel -p cert.pem -d 443 -r 5443
stunnel -c -d 5443 -r 10.60.0.100:443

# 5900 mitm
stunnel -p cert.pem -d 5900 -r 5999
stunnel -c -d 5999 -r 10.60.0.100:5900
</pre>

and than recoding all output using wireshark:

<pre>
sudo tshark -w /tmp/drac.pcap -i any 'port 5999 or port 5901 or port 5443'
</pre>

This allowed me to capture all unencrypted traffic into single pcap file which proved very useful for initial protocol analysis using <tt>wireshark</tt>. In short, you have to do following:

<ol>
<li>make https connection to <tt>https://drac/cgi-bin/webcgi/winvkvm?state=1</tt> and acquire vKvmSessionId  <em>console redirection authentication key</em>
<li>connect to keyboard/mouse port 5900 forcing <tt>SSL_cipher_list</tt> to supported <tt>RC4-MD5</tt> cipher and send vKvmSessionId
<li>connect to video port 5901
</ol>

Finding supported cipher for communication between us and server was a real problem. They are <a href="http://linux.dell.com/files/drac5/source/1.45/d5_src_0902101.iso" title="ISO image with source code from Dell">using openssl-0.9.7f</a> and I had to downgrade all the way to Debian woody to make <tt>stunnel</tt> work. Same problem is visible with latest firmware update for DRAC where Active X plugin doesn't have old enough configuration in SSL handshake and doesn't work any more. Java plugin, on the other hand, provides much more cipher options, so one of them still works. <tt>ssldump</tt> was very useful for finding such problems.
</p>

<p>
Fortunately, <a href="http://kost.com.hr/">kost</a> was much more persistent than me, and he found out that adding <tt>'SSL_cipher_list' => 'RC4-MD5'</tt> will force supported cipher. Armed with that new finding, I was able to <a href="http://svn.rot13.org/index.cgi/scripts/view/trunk/mitm-ssl.pl">modify kost's ssl mitm script</a> up to the point where I can see decrypted key-presses, mouse movements and video settings. Hack, I even wrote <a href="http://svn.rot13.org/index.cgi/pxelator/view/bin/drac-vkvm.pl">drac-vkvm.pl</a> async client which does steps outlined above.
</p>

<p>
All is not well, unfortunately. When sending authentication request, we need <tt>vKvmSessionId</tt> which we get from web server, but packet which is sent contains also two bytes which change with session. I haven't been able to figure this part out, and since same two byte sequence is needed to open video channel (to see VGA output) so I'm stuck.
<br>
Bytes <a href="http://stackoverflow.com/questions/401231/determining-crc-algorithm-from-data-crc-embedded-application">don't look like crc16</a>, and source code doesn't provide any hints about secondary 16-bit auth info. It seems that client calculates it somehow, since both connections close when I try to send different values for it.
</p>

<p>
I could write session recorder, but that isn't terribly useful, because it still forces me to use Windows+Java setup to access my console. I will collect <a href="http://saturn.ffzg.hr/rot13/index.cgi?dell_rac">usefull snippets about Dell's RAC protocol on wiki</a>.
</p>
]]>
        
    </content>
</entry>

<entry>
    <title>Dell&apos;s RAC support under Linux == drek</title>
    <link rel="alternate" type="text/html" href="http://blog.rot13.org/2009/12/dells_rac_support_under_linux_drek.html" />
    <id>tag:blog.rot13.org,2009://1.677</id>

    <published>2009-12-30T17:21:12Z</published>
    <updated>2010-01-11T17:27:51Z</updated>

    <summary> Back in 2007 I wrote draft of blog post about semi-working solution for remote console on Dell&apos;s servers. I never finished it, but now I got a few more Dell servers and I&apos;m not impressed. Linux support is even worse. Drek is shit in Croatian, btw. First, update your RAC to latest firmware. It&apos;s a challenging task on Dell&apos;s web (I did it three times allready and still I can&apos;t remember procedure, so I&apos;m documenting it here): search for drac 4 firmware (DRAC 4/I) and select newest version available (due to ranking sorting this can be hard task, select date sort). If you have DRAC 5, searching over Dell&apos;s site isn&apos;t much help. But, you can hop directly to ftp site and select file with name f_drac5*.exe. Now download hard-drive format (it&apos;s self-extracting zip) and extract firmware: dpavlin@t61p:~/Downloads/dell/2800$ unzip f_0603v17en_d4.exe Archive: f_0603v17en_d4.exe inflating: firmimg.dm1 dpavlin@t61p:~/Downloads/dell/2900$ unzip f_drac5v145_A00.exe Archive: f_drac5v145_A00.exe inflating: firmimg.d5 Upload firmimg.* via web interface (if you have really old version of RAC, you might need IE to do this, but recent versions from last year or two work also with Firefox. Firmware update doesn&apos;t work with Google Chrome). This is just the beginning of Internet Explorer dependencies, so get used to it. Good idea is to ping your DRAC while uploading firmware. While flash is programming, you will get interruption in ICMP echo reply, but that&apos;s not a reason for worry. It will come back. After all that, you still won&apos;t get Linux support. At least not with recent Firefox. Lousy work, Dell! How are you accessing your Dell servers from Linux?...</summary>
    <author>
        <name>Dobrica Pavlinušić</name>
        <uri>http://www.rot13.org/~dpavlin/</uri>
    </author>
    
        <category term="howto" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="drac" label="DRAC" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="dell" label="Dell" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://blog.rot13.org/">
        <![CDATA[<p>
Back in 2007 I wrote draft of blog post about semi-working solution for remote console on Dell's servers. I never finished it, but now I got a few more Dell servers and I'm not impressed. Linux support is even worse. <em>Drek</em> is <em>shit</em> in Croatian, btw.
</p>
<p>
First, update your RAC to latest firmware. It's a challenging task on Dell's web (I did it three times allready and still I can't remember procedure, so I'm documenting it here): search for <tt>drac 4 firmware</tt> (<a href="http://search.dell.com/results.aspx?cat=sup&subcat=dyd&c=us&l=en&s=gen&k=drac+4/i+firmware&sort=-date">DRAC 4/I</a>) and select <em>newest</em> version available (due to ranking sorting this can be hard task, select date sort). If you have DRAC 5, searching over Dell's site isn't much help. But, you can hop <a href="ftp://ftp.us.dell.com/sysman/">directly to ftp site</a> and select file with name <tt>f_drac5*.exe</tt>.
</p>
Now download hard-drive format (it's self-extracting zip) and extract firmware:

<pre>
dpavlin@t61p:~/Downloads/dell/2800$ unzip f_0603v17en_d4.exe 
Archive:  f_0603v17en_d4.exe
  inflating: firmimg.dm1             

dpavlin@t61p:~/Downloads/dell/2900$ unzip f_drac5v145_A00.exe 
Archive:  f_drac5v145_A00.exe
  inflating: firmimg.d5              
</pre>

Upload <tt>firmimg.*</tt> via web interface (if you have really old version of RAC, you might need IE to do this, but recent versions from last year or two work also with Firefox. Firmware update <em>doesn't work with Google Chrome</em>). This is just the beginning of Internet Explorer dependencies, so get used to it.
</p>
<p>
Good idea is to ping your DRAC while uploading firmware. While flash is programming, you will get interruption in ICMP echo reply, but that's not a reason for worry. It will come back.
</p>
<p>
After all that, you still won't get Linux support. At least not with recent Firefox. Lousy work, Dell! How are you accessing your Dell servers from Linux?
</p>]]>
        
    </content>
</entry>

<entry>
    <title>Dump streams using mplayer and at</title>
    <link rel="alternate" type="text/html" href="http://blog.rot13.org/2009/12/dump_streams_using_mplayer_and_at.html" />
    <id>tag:blog.rot13.org,2009://1.676</id>

    <published>2009-12-28T17:39:22Z</published>
    <updated>2009-12-29T20:26:53Z</updated>

    <summary> As you probably know, this part of the year is mostly about Chaos Communication Congress with a lot of great lectures, but you might want to record a stream or two. When I want to schedule something at specific time, I usually use at but mplayer is picky, so at the end I used following script: #!/bin/sh -x mplayer http://streaming-26c3-wmv.fem-net.de/saal$1 -noconsolecontrols \ -dumpstream -dumpfile saal$1-`date +%Y%m%dT%H%M%S`.wmv &amp; This will allow mplayer to detach from console, so it will work in backup. Happy hacking! Update: stopping streams manually is not fun, so here is improved script which has three arguments: room number, from time and to time #!/bin/sh -x # usage: record.sh 1 13:45 15:15 room=$1 from=$2 to=$3 url=http://streaming-26c3-wmv.fem-net.de/saal$room file=`date +%Y%m%d`-$from-$to-saal$room echo &quot;Record $from - $to $url -&gt; $file&quot; echo &quot;mplayer $url -noconsolecontrols -dumpstream -dumpfile $file.wmv&quot; | at $from echo &quot;kill \`ps ax | grep $file\`&quot; | at $to If you need to see all jobs scheduled, use atq. However, there is no easy way to correlate which task will execute in which time slot in atq output, so I wrote small atq.pl script which displays commands which will be executed (you will need to run it with root privileges)....</summary>
    <author>
        <name>Dobrica Pavlinušić</name>
        <uri>http://www.rot13.org/~dpavlin/</uri>
    </author>
    
        <category term="hack-of-the-week" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="26c3" label="26c3" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="at" label="at" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="mplayer" label="mplayer" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://blog.rot13.org/">
        <![CDATA[<p>
As you probably know, this part of the year is mostly about <a href="http://events.ccc.de/congress/2009/Fahrplan">Chaos Communication Congress</a> with a lot of great lectures, but you might want to record a <a href="http://events.ccc.de/congress/2009/wiki/Streams">stream</a> or two.
</p>
<p>
When I want to schedule something at specific time, I usually use <tt>at</tt> but <tt>mplayer</tt> is picky, so at the end I used following script:
<pre>
#!/bin/sh -x

mplayer http://streaming-26c3-wmv.fem-net.de/saal$1 -noconsolecontrols \
   -dumpstream -dumpfile saal$1-`date +%Y%m%dT%H%M%S`.wmv &
</pre>
This will allow mplayer to detach from console, so it will work in backup. Happy hacking!
</p>
<p><em>Update</em>: stopping streams manually is not fun, so here is improved script which has three arguments: room number, from time and to time
<pre>
#!/bin/sh -x

# usage: record.sh 1 13:45 15:15

room=$1
from=$2
to=$3

url=http://streaming-26c3-wmv.fem-net.de/saal$room
file=`date +%Y%m%d`-$from-$to-saal$room

echo "Record $from - $to $url -> $file"

echo "mplayer $url -noconsolecontrols -dumpstream -dumpfile $file.wmv" | at $from
echo "kill \`ps ax | grep $file\`" | at $to
</pre>
</p>
<p>
If you need to see all jobs scheduled, use <tt>atq</tt>. However, there is no easy way to correlate which task will execute in which time slot in <tt>atq</tt> output, so I wrote <a href="http://svn.rot13.org/index.cgi/scripts/view/trunk/atq.pl">small atq.pl script which displays commands which will be executed</a> (you will need to run it with <tt>root</tt> privileges).
</p>]]>
        
    </content>
</entry>

<entry>
    <title>LDAP server application integration with virtual LDAP</title>
    <link rel="alternate" type="text/html" href="http://blog.rot13.org/2009/12/ldap_server_application_integration_with_virtual_ldap.html" />
    <id>tag:blog.rot13.org,2009://1.675</id>

    <published>2009-12-13T22:44:38Z</published>
    <updated>2009-12-13T23:09:03Z</updated>

    <summary> You have your new shiny application, and LDAP server on the other side. Easy as pie. What can go wrong? you use e-mail as login, and application assumes that logins don&apos;t have domain in them and allows you embedding of whole login into DN application can import various interesting fields using LDAP, but you have data somewhere else, and it doesn&apos;t really belong into your LDAP you need to provide subset of data in your database as LDAP server to application I had written about my saga with LDAP about augmenting LDAP search responses and exposing RDBMS data as LDAP server. But today, I added rewrite of bind, so now I can use unmodified Koha, and all needed quirks for my AAI@EduHr schema are outside application. This made my attempt to virtualize LDAP almost complete so I created a project page on Ohloh. I will write small updates about status there, so If any of this is interesting to you, hop over there....</summary>
    <author>
        <name>Dobrica Pavlinušić</name>
        <uri>http://www.rot13.org/~dpavlin/</uri>
    </author>
    
        <category term="code" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="ldap" label="ldap" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl" label="perl" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://blog.rot13.org/">
        <![CDATA[<p>
You have your new shiny application, and LDAP server on the other side. Easy as pie. What can go wrong?
<ul>
<li>you use e-mail as login, and application assumes that logins don't have domain in them and allows you embedding of whole login into DN
<li>application can import various interesting fields using LDAP, but you have data somewhere else, and it doesn't really belong into your LDAP
<li>you need to provide subset of data in your database as LDAP server to application
</ul>
</p>
<p>
I had written about my saga with LDAP about <a href="http://blog.rot13.org/2009/03/virtual_ldap_rewrite_or_augment_data_on_the_fly.html">augmenting LDAP search responses</a> and <a href="http://blog.rot13.org/2009/03/integrating_systems_using_netldapserver_and_rdbms.html">exposing RDBMS data as LDAP server</a>. But today, I added rewrite of bind, so now I can use unmodified Koha, and all needed quirks for my <a href="http://www.aaiedu.hr/">AAI@EduHr</a> schema are outside application.
</p>
<p>
This made my attempt to <a href="https://www.ohloh.net/p/virtual-ldap">virtualize LDAP almost complete so I created a project page on Ohloh</a>. I will write small updates about status there, so If any of this is interesting to you, hop over there.
</p>]]>
        
    </content>
</entry>

<entry>
    <title>xxd: hexdump something quickly</title>
    <link rel="alternate" type="text/html" href="http://blog.rot13.org/2009/12/xxd_hexdump_something_quickly.html" />
    <id>tag:blog.rot13.org,2009://1.674</id>

    <published>2009-12-09T18:33:08Z</published>
    <updated>2009-12-09T18:47:45Z</updated>

    <summary> We have all been in this situation: you have two files which are subtly different, and you need to take a quick look in them. Let me point you towards xxd which is part of vim. Users of other editors can stop reading now! :-) dpavlin@t61p:~/t61p/utf-8-accents$ xxd good 0000000: 506f 7669 6a65 736e 6f20 6172 6865 6f6c Povijesno arheol 0000010: 6fc5 a16b 6920 766f 6469 c48d 2070 6f20 o..ki vodi.. po 0000020: 4f73 6f72 750a Osoru. dpavlin@t61p:~/t61p/utf-8-accents$ xxd bad 0000000: 506f 7669 6a65 736e 6f20 6172 6865 6f6c Povijesno arheol 0000010: 6f73 cc8c 6b69 2076 6f64 6963 cc8c 2070 os..ki vodic.. p 0000020: 6f20 4f73 6f72 750a o Osoru. Now, if I could only find peace of perl code which puts accents back to characters......</summary>
    <author>
        <name>Dobrica Pavlinušić</name>
        <uri>http://www.rot13.org/~dpavlin/</uri>
    </author>
    
        <category term="hack-of-the-week" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://blog.rot13.org/">
        <![CDATA[<p>
We have all been in this situation: you have two files which are subtly different, and you need to take a quick look in them. Let me point you towards <tt>xxd</tt> which is part of <a href="http://www.vim.org/">vim</a>. Users of other editors can stop reading now! <tt>:-)</tt>
</p>
<pre>
dpavlin@t61p:~/t61p/utf-8-accents$ xxd good
0000000: 506f 7669 6a65 736e 6f20 6172 6865 6f6c  Povijesno arheol
0000010: 6fc5 a16b 6920 766f 6469 c48d 2070 6f20  o..ki vodi.. po 
0000020: 4f73 6f72 750a                           Osoru.
dpavlin@t61p:~/t61p/utf-8-accents$ xxd bad
0000000: 506f 7669 6a65 736e 6f20 6172 6865 6f6c  Povijesno arheol
0000010: 6f73 cc8c 6b69 2076 6f64 6963 cc8c 2070  os..ki vodic.. p
0000020: 6f20 4f73 6f72 750a                      o Osoru.
</pre>
<p>
Now, if I could only find peace of perl code which puts accents back to characters...
</p>]]>
        
    </content>
</entry>

<entry>
    <title>HTML5TV: video archive with slide sync without plugins</title>
    <link rel="alternate" type="text/html" href="http://blog.rot13.org/2009/12/html5tv_video_archive_with_slide_sync_without_plugins.html" />
    <id>tag:blog.rot13.org,2009://1.673</id>

    <published>2009-12-01T12:22:29Z</published>
    <updated>2009-12-01T12:37:50Z</updated>

    <summary><![CDATA[ Last weekend we had Nothing will happen event and I did small presentation about HTML5TV which is: video annotation interface based on mplayer with slide overview web interface using HTML5 &lt;video&gt; tag and some JavaScript I have collected some of presentations at http://html5tv.rot13.org/, so hop over there and have a look. If you have more interesting presentations, you can easily fork HTML5TV at github, annotate presentation and submit it for inclusion (or make your own archive if you prefer that). Have fun and let me know what you think about it....]]></summary>
    <author>
        <name>Dobrica Pavlinušić</name>
        <uri>http://www.rot13.org/~dpavlin/</uri>
    </author>
    
        <category term="code" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="html5" label="html5" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="mplayer" label="mplayer" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="perl" label="perl" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="video" label="video" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://blog.rot13.org/">
        <![CDATA[<p>
Last weekend we had <a href="http://www.nsnd.org/" title="Ništa se neće dogoditi...">Nothing will happen</a> event and I did small presentation about <a href="http://github.com/dpavlin/HTML5TV">HTML5TV</a> which is:
<ul>
<li>video annotation interface based on mplayer with slide overview
<span class="mt-enclosure mt-enclosure-image" style="display: inline;"><a href="http://blog.rot13.org/assets_c/2009/12/html5tv-editing-34.html" onclick="window.open('http://blog.rot13.org/assets_c/2009/12/html5tv-editing-34.html','popup','width=1274,height=984,scrollbars=no,resizable=no,toolbar=no,directories=no,location=no,menubar=no,status=no,left=0,top=0'); return false"><img src="http://blog.rot13.org/assets_c/2009/12/html5tv-editing-thumb-320x247-34.png" width="320" height="247" alt="html5tv-editing.png" class="mt-image-center" style="text-align: center; display: block; margin: 0 auto 20px;" /></a></span>
<li>web interface using HTML5 &lt;video&gt; tag and some JavaScript
<span class="mt-enclosure mt-enclosure-image" style="display: inline;"><a href="http://blog.rot13.org/assets_c/2009/12/html5tv-web-37.html" onclick="window.open('http://blog.rot13.org/assets_c/2009/12/html5tv-web-37.html','popup','width=1278,height=1003,scrollbars=no,resizable=no,toolbar=no,directories=no,location=no,menubar=no,status=no,left=0,top=0'); return false"><img src="http://blog.rot13.org/assets_c/2009/12/html5tv-web-thumb-320x251-37.png" width="320" height="251" alt="html5tv-web.png" class="mt-image-center" style="text-align: center; display: block; margin: 0 auto 20px;" /></a></span>
</ul>
I have collected some of presentations at <a href="http://html5tv.rot13.org/"><tt>http://html5tv.rot13.org/</tt></a>, so hop over there and have a look. If you have more interesting presentations, you can easily <a href="">fork HTML5TV at github</a>, annotate presentation and submit it for inclusion (or make your own archive if you prefer that). Have fun and let me know what you think about it.
</p>]]>
        
    </content>
</entry>

<entry>
    <title>x2x: share mouse and keyboard over ssh</title>
    <link rel="alternate" type="text/html" href="http://blog.rot13.org/2009/11/x2x_share_mouse_and_keyboard_over_ssh.html" />
    <id>tag:blog.rot13.org,2009://1.672</id>

    <published>2009-11-23T13:05:42Z</published>
    <updated>2009-11-24T13:11:31Z</updated>

    <summary> For quote some time I have been using x2x to have single keyboard and mouse for multiple machines (EeePC or third monitor at work), but I had problem with selection buffers. x2x was written for scenario where all X servers are listening to network connections, so if you had two machines klin and t42 and you wanted to use keyboard and mouse on klin you would have to do something like this: dpavlin@t42:~$ xhost klin dpavlin@klin:~$ x2x -to klin:0 -west However, recent Debian systems are not listening to TCP connections, so you will have to modify xserverrc for this to work: dpavlin@t42:~$ cat /etc/X11/xinit/xserverrc #!/bin/sh exec /usr/bin/X11/X #-nolisten tcp However, it&apos;s much nicer to depend on ssh X11 forwarding to provide encryption using: dpavlin@klin:~$ ssh -X t42 x2x -to :0 -west To finish this post, I have to include small patch which allows to switch copy/paste direction (which I don&apos;t need any more, but it proved useful in at least one case): diff -r 2ce6789a43da x2x.c --- a/x2x.c Tue Mar 18 22:47:34 2008 +0600 +++ b/x2x.c Tue Nov 24 14:08:16 2009 +0100 @@ -1125,7 +1125,7 @@ if (doSel) { // pDpyInfo-&gt;initialClipboardSeen = False; pDpyInfo-&gt;winSelText = NULL; - pDpyInfo-&gt;hwndNextViewer = SetClipboardViewer(pDpyInfo-&gt;edgewindow); + pDpyInfo-&gt;hwndNextViewer = SetClipboardViewer(pDpyInfo-&gt;bigwindow); } pDpyInfo-&gt;onedge = 0;...</summary>
    <author>
        <name>Dobrica Pavlinušić</name>
        <uri>http://www.rot13.org/~dpavlin/</uri>
    </author>
    
    
    <content type="html" xml:lang="en" xml:base="http://blog.rot13.org/">
        <![CDATA[<p>
For quote some time I have been using <a href="http://x2x.dottedmag.net/">x2x</a> to have single keyboard and mouse for multiple machines (EeePC or third monitor at work), but I had problem with selection buffers. <tt>x2x</tt> was written for scenario where all X servers are listening to network connections, so if you had two machines <tt>klin</tt> and <tt>t42</tt> and you wanted to use keyboard and mouse on <tt>klin</tt> you would have to do something like this:
<pre>
dpavlin@t42:~$ xhost klin

dpavlin@klin:~$ x2x -to klin:0 -west
</pre>
However, recent Debian systems are not listening to TCP connections, so you will have to modify <tt>xserverrc</tt> for this to work:
<pre>
dpavlin@t42:~$ cat /etc/X11/xinit/xserverrc 
#!/bin/sh

exec /usr/bin/X11/X #-nolisten tcp
</pre>
However, it's much nicer to depend on ssh X11 forwarding to provide encryption using:
<pre>
dpavlin@klin:~$ ssh -X t42 x2x -to :0 -west
</pre>
To finish this post, I have to include small patch which allows to switch copy/paste direction (which I don't need any more, but it proved useful in at least one case):
<pre>
diff -r 2ce6789a43da x2x.c
--- a/x2x.c     Tue Mar 18 22:47:34 2008 +0600
+++ b/x2x.c     Tue Nov 24 14:08:16 2009 +0100
@@ -1125,7 +1125,7 @@
       if (doSel) {
         // pDpyInfo->initialClipboardSeen = False;
         pDpyInfo->winSelText = NULL;
-        pDpyInfo->hwndNextViewer = SetClipboardViewer(pDpyInfo->edgewindow);
+        pDpyInfo->hwndNextViewer = SetClipboardViewer(pDpyInfo->bigwindow);
       }
 
       pDpyInfo->onedge = 0;
</pre>
</p>]]>
        
    </content>
</entry>

<entry>
    <title>Change gtk font size without userChrome.css</title>
    <link rel="alternate" type="text/html" href="http://blog.rot13.org/2009/11/change_gtk_font_size_without_userchromecss.html" />
    <id>tag:blog.rot13.org,2009://1.671</id>

    <published>2009-11-18T16:38:03Z</published>
    <updated>2009-11-18T16:37:50Z</updated>

    <summary> If you have any objection your X11 setup (especially if you are not running Gnome or KDE) it&apos;s probably: Firefox menu font size is too big! However, that&apos;s really not right complaint. If you create your own userChrome.css and install it in correct location, you will notice that rest of applications still won&apos;t look good. But, Firefox was biggest problem, so you move on... But, solution is really simple: dpavlin@t61p:~$ cat .gtkrc-2.0 gtk-font-name = &quot;Verdana 7&quot; This will change all GTK application&apos;s (including FIrefox, OpenOffice.org and others) to sane font size for huge monitors with high DPI settings. It&apos;s a single line fix to all your problems!, take a look:...</summary>
    <author>
        <name>Dobrica Pavlinušić</name>
        <uri>http://www.rot13.org/~dpavlin/</uri>
    </author>
    
        <category term="howto" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="x11" label="x11" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://blog.rot13.org/">
        <![CDATA[<p>
If you have any objection your X11 setup (especially if you are not running Gnome or KDE) it's probably:
<quote>
Firefox menu font size is too big!
</quote>
However, that's really not right complaint. If you create your own <a href="http://www.mozilla.org/unix/customizing.html">userChrome.css</a> and install it in correct location, you will notice that rest of applications still won't look good. But, Firefox was biggest problem, so you move on...
</p>
<p>
But, solution is really simple:
<pre>
dpavlin@t61p:~$ cat .gtkrc-2.0 
gtk-font-name = "Verdana 7"
</pre>
This will change all GTK application's (including FIrefox, OpenOffice.org and others) to sane font size for huge monitors with high DPI settings. <b>It's a single line fix to all your problems!</b>, take a look:

<span class="mt-enclosure mt-enclosure-image" style="display: inline;"><a href="http://blog.rot13.org/assets_c/2009/11/gtk-font-change-31.html" onclick="window.open('http://blog.rot13.org/assets_c/2009/11/gtk-font-change-31.html','popup','width=958,height=238,scrollbars=no,resizable=no,toolbar=no,directories=no,location=no,menubar=no,status=no,left=0,top=0'); return false"><img src="http://blog.rot13.org/assets_c/2009/11/gtk-font-change-thumb-320x79-31.png" width="320" height="79" alt="gtk-font-change.png" class="mt-image-center" style="text-align: center; display: block; margin: 0 auto 20px;" /></a></span>

</p>]]>
        
    </content>
</entry>

<entry>
    <title>X11 selection, clipboard and how to use them</title>
    <link rel="alternate" type="text/html" href="http://blog.rot13.org/2009/11/x11_selection_clipboard_and_how_to_use_them.html" />
    <id>tag:blog.rot13.org,2009://1.670</id>

    <published>2009-11-15T20:31:47Z</published>
    <updated>2009-11-17T21:14:42Z</updated>

    <summary> One of first differences when you start using X11 is that you can just select any text on screen and press middle mouse button to paste it back. But, after a while you end up in situation where you did ctrl+c in application, and somehow you expect that middle mouse button will paste it back. X11 implementation of copy/paste is much more complicated, as you might read from excellent X Selections, Cut Buffers, and Kill Rings. Most of the time, having two different clipboards is very useful. Think about copy/pasting url and title at the same time from one web page to another (like I do often when writing blog posts like this one). So, how to we manage buffers more efficiently? First, install xclip and try it out: dpavlin@t61p:~$ xclip -h Usage: xclip [OPTION] [FILE]... Access an X server selection for reading or writing. -i, -in read text into X selection from standard input or files (default) -o, -out prints the selection to standard out (generally for piping to a file or program) -l, -loops number of selection requests to wait for before exiting -d, -display X display to connect to (eg localhost:0&quot;) -h, -help usage information -selection selection to access (&quot;primary&quot;, &quot;secondary&quot;, &quot;clipboard&quot; or &quot;buffer-cut&quot;) -noutf8 don&apos;t treat text as utf-8, use old unicode -version version information -silent errors only, run in background (default) -quiet run in foreground, show what&apos;s happening -verbose running commentary Help output is probably a little verbose, but just remember following things: -in is default -out displays content default selection is primary (which is content you marked on screen) -selection clipboard is only other thing you need to rember So, armed with that knowledge, here are couple of examples: # display selected text xclip -out # display clipboard (copy/paste in applications) xclip -out -selection clipbaord # transfer selection into copy/paste buffer xclip -out | xclip -selection clipboard # transfer selection into copy/paste buffer xclip -out -selection clipboard | xclip Last example is useful if you want to paste something back in terminal and it somehow ended up in copy/paste buffer, following is Zotero example: Just let your imagination go wild: what if you have only textarea and you want to do some massive editing for which vi whould be better? You can install excellent It&apos;s All Text! Firefox extension but, you could also write something like this: xclip -out &gt; /tmp/$$.txt &amp;&amp; vi /tmp/$$.txt &amp;&amp; xclip -in -selection clipboard You could bind that to a key in your window manager or start different editor if you wanted to... or I guess live can be simple again if you just install autocutsel Few days after I wrote this blog post, I had interesting problem. I was trying to decrease font size in firefox and I found instructions which included filename and content itself. I copied content with Ctrl+C and selected filename and used this little gem: xclip -sel clipboard -out &gt; `xclip -out`...</summary>
    <author>
        <name>Dobrica Pavlinušić</name>
        <uri>http://www.rot13.org/~dpavlin/</uri>
    </author>
    
        <category term="hack-of-the-week" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="x11" label="x11" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://blog.rot13.org/">
        <![CDATA[<p>
One of first differences when you start using X11 is that you can just select any text on screen and press middle mouse button to paste it back. But, after a while you end up in situation where you did <tt>ctrl+c</tt> in application, and somehow you expect that middle mouse button will paste it back.
</p>
<p>
X11 implementation of copy/paste is much more complicated, as you might read from excellent <a href="http://www.jwz.org/doc/x-cut-and-paste.html">X Selections, Cut Buffers, and Kill Rings.</a>
</p>
<p>
Most of the time, having two different clipboards is very useful. Think about copy/pasting url and title at the same time from one web page to another (like I do often when writing blog posts like this one).
</p>
<p>
So, how to we manage buffers more efficiently? First, install <tt>xclip</tt> and try it out:
<pre>
dpavlin@t61p:~$ xclip -h
Usage: xclip [OPTION] [FILE]...
Access an X server selection for reading or writing.

  -i, -in          read text into X selection from standard input or files
                   (default)
  -o, -out         prints the selection to standard out (generally for
                   piping to a file or program)
  -l, -loops       number of selection requests to wait for before exiting
  -d, -display     X display to connect to (eg localhost:0")
  -h, -help        usage information
      -selection   selection to access ("primary", "secondary", "clipboard" or "buffer-cut")
      -noutf8      don't treat text as utf-8, use old unicode
      -version     version information
      -silent      errors only, run in background (default)
      -quiet       run in foreground, show what's happening
      -verbose     running commentary
</pre>
Help output is probably a little verbose, but just remember following things:
<ul>
<li><b>-in</b> is default 
<li><b>-out</b> displays content
<li>default selection is primary (which is content you marked on screen)
<li><b>-selection clipboard</b> is only other thing you need to rember
</ul>
So, armed with that knowledge, here are couple of examples:
<pre>
# display selected text
xclip -out

# display clipboard (copy/paste in applications)
xclip -out -selection clipbaord

# transfer selection into copy/paste buffer
xclip -out | xclip -selection clipboard

# transfer selection into copy/paste buffer
xclip -out -selection clipboard | xclip
</pre>

Last example is useful if you want to paste something back in terminal and it somehow ended up in copy/paste buffer, following is Zotero example:

<span class="mt-enclosure mt-enclosure-image" style="display: inline;"><a href="http://blog.rot13.org/assets_c/2009/11/zotero-copy-to-clipboard-28.html" onclick="window.open('http://blog.rot13.org/assets_c/2009/11/zotero-copy-to-clipboard-28.html','popup','width=568,height=396,scrollbars=no,resizable=no,toolbar=no,directories=no,location=no,menubar=no,status=no,left=0,top=0'); return false"><img src="http://blog.rot13.org/assets_c/2009/11/zotero-copy-to-clipboard-thumb-320x223-28.png" width="320" height="223" alt="zotero-copy-to-clipboard.png" class="mt-image-center" style="text-align: center; display: block; margin: 0 auto 20px;" /></a></span>

</p>
<p>
Just let your imagination go wild: what if you have only textarea and you want to do some massive editing for which vi whould be better? You can install excellent <a href="https://addons.mozilla.org/en-US/firefox/addon/4125">It's All Text! Firefox extension</a> but, you could also write something like this:
<pre>
xclip -out > /tmp/$$.txt && vi /tmp/$$.txt && xclip -in -selection clipboard < /tmp/$$.txt
</pre>
You could bind that to a key in your window manager or start different editor if you wanted to... or I guess live can be simple again if you just install <a href="http://www.nongnu.org/autocutsel/"><tt>autocutsel</tt></a>
</p>
<p>
Few days after I wrote this blog post, I had interesting problem. I was trying to decrease font size in firefox and I found instructions which included filename and content itself. I copied content with <tt>Ctrl+C</tt> and selected filename and used this little gem:
<pre>
xclip -sel clipboard -out > `xclip -out`
</pre>
</p>]]>
        
    </content>
</entry>

<entry>
    <title>Edit MARC records in your favourite editor</title>
    <link rel="alternate" type="text/html" href="http://blog.rot13.org/2009/11/edit_marc_records_in_your_favourite_editor.html" />
    <id>tag:blog.rot13.org,2009://1.669</id>

    <published>2009-11-07T12:06:59Z</published>
    <updated>2009-11-07T13:43:08Z</updated>

    <summary> MARC is binary structured file format used in libraries and occasionally you need a way to quickly edit records in it. There are quite a few tools available for editing MARC records, but none of them are really easy to use. Few days ago, I overheard conversation in which somebody said you can&apos;t just edit in your editor, because you have to fix leader field afterward. That got me thinking... MARC format is really quite interesting, designed to be easily used on tapes, so it has a bunch of pointers to exact record positions which change if size of field values change. Editing binary MARC directly in editor isn&apos;t really possible because you would have to fix leader (which has size of whole record which allows easy skipping on tape) and all pointers to start of each field manually. I did some of that while writing MARC::Fast, but I wouldn&apos;t recommend that to anyone. MARC::Record already has utility called marcdump which will convert MARC into human readable format: dpavlin@t61p:/srv/webpac2$ marcdump t/data/marc.iso &gt; dump.txt t/data/marc.iso dpavlin@t61p:/srv/webpac2$ head dump.txt LDR 01002nam0 2200289 45 001 800328901 100 _a19800328d1999 y0hrvy0191 ba 101 1 _ahrv 102 _aHR 105 _aa m 000yy 200 1 _aMjerne nesigurnosti rezultata mjerenja odstupanja od oblika i polo`aja _emagistarski rad _fZdravko Bar{i} _gvoditelj Vedran Mudronja I can easily edit this in my favorite editor (which is vim if you really wanted to know) to replace CROASCII characters with utf-8 equivalents of something like that. So, I wrote dump2marc which parse marcdump output and converts it back to MARC file format like this: dpavlin@t61p:/srv/webpac2$ ./bin/dump2marc.pl dump.txt &gt; dump.marc It will also dump parsed records to STDERR which you can redirect to file using 2&gt;dump.txt.parsed. If you dump generated MARC with marcdump you can use diff to view changes: dpavlin@t61p:/srv/webpac2$ ./bin/dump2marc.pl dump.txt &gt; dump.marc \ &amp;&amp; marcdump dump.marc &gt; dump.marc.txt \ &amp;&amp; diff -u dump.txt dump.marc.txt If we wanted to track changes, add dump file (and MARC if needed) to git and using it to produce diffs would be one possible solution. I know that by this point, you are already rolling your eyes thinking: this is command line editing for MARC. Same work-flow could be turned into web application using simple upload button to upload MARC, and then opening textarea with dump which is converted back to MARC ready to download after submit. It would be sane to automatically add every revision to git on server-side and provide some kind of rollback to some last version over git too, maybe over gitweb?...</summary>
    <author>
        <name>Dobrica Pavlinušić</name>
        <uri>http://www.rot13.org/~dpavlin/</uri>
    </author>
    
        <category term="hack-of-the-week" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="marc" label="MARC" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="library" label="library" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://blog.rot13.org/">
        <![CDATA[<p>
<a href="http://en.wikipedia.org/wiki/MARC_standards" title="MAchine-Readable Cataloging">MARC</a> is binary structured file format used in libraries and occasionally you need a way to quickly edit records in it.
</p>

<p>
There are quite a few tools available for editing MARC records, but none of them are really easy to use. Few days ago, I overheard conversation in which somebody said <em>you can't just edit in your editor, because you have to fix leader field afterward</em>.
That got me thinking...
</p>

<p>
MARC format is really quite interesting, designed to be easily used on tapes, so it has a bunch of pointers to exact record positions which change if size of field values change.
</p>
<p>
Editing binary MARC directly in editor isn't really possible because you would have to fix leader (which has size of whole record which allows easy skipping on tape) and all pointers to start of each field manually. I did some of that while writing <a href="http://search.cpan.org/dist/MARC-Fast/">MARC::Fast</a>, but I wouldn't recommend that to anyone.
</p>

<p>
<a href="http://search.cpan.org/dist/MARC-Record">MARC::Record</a> already has utility called <tt>marcdump</tt> which will convert MARC into human readable format:
<pre>
dpavlin@t61p:/srv/webpac2$ marcdump t/data/marc.iso > dump.txt
t/data/marc.iso
dpavlin@t61p:/srv/webpac2$ head dump.txt 
LDR 01002nam0 2200289   45  
001     800328901
100    _a19800328d1999       y0hrvy0191    ba
101 1  _ahrv
102    _aHR
105    _aa   m   000yy
200 1  _aMjerne nesigurnosti rezultata mjerenja odstupanja od oblika i polo`aja
       _emagistarski rad
       _fZdravko Bar{i}
       _gvoditelj Vedran Mudronja
</pre>
<p>
I can easily edit this in my favorite editor (which is <tt>vim</tt> if you really wanted to know) to replace CROASCII characters with utf-8 equivalents of something like that.
</p>
<p>
So, I wrote <a href="http://svn.rot13.org/index.cgi/webpac2/view/trunk/bin/dump2marc.pl">dump2marc which parse marcdump output and converts it back to MARC file format</a> like this:
<pre>
dpavlin@t61p:/srv/webpac2$ ./bin/dump2marc.pl dump.txt > dump.marc
</pre>
It will also dump parsed records to STDERR which you can redirect to file using <tt>2>dump.txt.parsed</tt>.
</p>
<p>
If you dump generated MARC with <tt>marcdump</tt> you can use diff to view changes:
<pre>
dpavlin@t61p:/srv/webpac2$ ./bin/dump2marc.pl dump.txt > dump.marc \
  && marcdump dump.marc > dump.marc.txt \
  && diff -u dump.txt dump.marc.txt
</pre>
</p>
<p>
If we wanted to track changes, add dump file (and MARC if needed) to git and using it to produce diffs would be one possible solution. I know that by this point, you are already rolling your eyes thinking: <em>this is command line editing for MARC</em>.
</p>
<p>
Same work-flow could be turned into web application using simple upload button to upload MARC, and then opening textarea with dump which is converted back to MARC ready to download after submit. It would be sane to automatically add every revision to git on server-side and provide some kind of rollback to some last version over git too, maybe over gitweb?
</p>]]>
        
    </content>
</entry>

</feed>
