{"id":44,"date":"2008-02-02T00:33:21","date_gmt":"2008-02-01T22:33:21","guid":{"rendered":"http:\/\/www.thomaskeller.biz\/blog\/2008\/02\/02\/a-linux-tale\/"},"modified":"2008-03-13T03:05:12","modified_gmt":"2008-03-13T01:05:12","slug":"a-linux-tale","status":"publish","type":"post","link":"https:\/\/www.thomaskeller.biz\/blog\/2008\/02\/02\/a-linux-tale\/","title":{"rendered":"A Linux tale&#8230; [updated]"},"content":{"rendered":"<p>My wife and I seem to share a lot of activities recently. We finally gathered a few friends around here with which we do regularily stuff like playing card games and she even got me to take <a href=\"http:\/\/www.salsa-leipzig.de\" target=\"_blank\">Salsa dancing lessons<\/a> with her. Beside that my political interests and meetings are quite regular as well, so it was just natural to think about a event planning solution which would allow us to view, add and edit events. I decided we need a calendar server!<\/p>\n<p>So I started looking around for calendar server solutions. I already had a rather hacky webdav-alike setup on my Virtual Private Server (VPS) which consisted of a single ICS file, secured by a simple HTTP authentication and made writable through a PHP script, but this doesn&#8217;t seem to be the right solution for me. I wanted something better, something stable, something <i>nice<\/i> &#8211; and I apparently found it: Apple released its <a href=\"http:\/\/www.calendarserver.org\" target=\"_blank\">Darwin Calendar Server<\/a>, which is the base of their commercial calendar server solution on Mac OS X Server, as Open Source under the Apache Software License 2.0 some time ago. &#8220;This will replace the old hackish setup on my VServer!&#8221;, I thought&#8230;<\/p>\n<p>I logged into the server and quickly downloaded the project&#8217;s sources from the public SVN repository. The README file stated that it should apparently be enough to start the `run` script in the base directory which would take care of everything, i.e. download and install all dependencies which would be needed for the software to run. This even worked flawlessly (with only one little modification). Up to that point I was very cheerful &#8211; until I actually tried to start the server:<\/p>\n<pre>IOError: [Errno 95] Operation not supported: \\\r\n'\/opt\/calendarserver\/CalendarServer\/twistedcaldav\/test\/data'<\/pre>\n<p>Uh? Ah well, there was something in the README I overlooked:<\/p>\n<pre>WEBDAV PROPERTY STORAGE\r\n-----------------------\r\n\r\nFor starters, twisted.web2.dav requires Bob Ippolito's xattr\r\nlibrary to access file system extended attributes, which are\r\nused to store WebDAV properties.  File system extended \r\nattributes are available on all file systems in Mac OS X, and\r\non some file systems on Linux and FreeBSD.  Another \r\nalternative is to implement a new property store class which\r\ndoes not use extended attributes. The Apache HTTP Server, for\r\nexample, uses a database to keep track of properties on files,\r\nand this method works on many more platforms and file systems.<\/pre>\n<p>xattr? Hrm&#8230; I never heard of that before &#8211; but Google shed light into my darkness: As <a href=\"http:\/\/en.wikipedia.org\/wiki\/Xattr\" target=\"_blank\">Wikipedia<\/a> amongst others states, they are &#8220;[&#8230;] a file system feature that enables users to associate computer files with metadata not interpreted by the filesystem [&#8230;]&#8221;, basically simple key-value pairs of arbitrary size and content. A quick grep over the config file of the currently running kernel showed me that at least support was already compiled into it:<\/p>\n<pre>$ cat \/boot\/config-2.6.11.4-20a-smp | grep XATTR\r\nCONFIG_EXT2_FS_XATTR=y\r\nCONFIG_EXT3_FS_XATTR=y\r\nCONFIG_REISERFS_FS_XATTR=y\r\nCONFIG_DEVPTS_FS_XATTR=y\r\nCONFIG_TMPFS_XATTR=y\r\nCONFIG_CIFS_XATTR=y<\/pre>\n<p>Cool! I read somewhere that in this case one would just have to add the mount option `user_xattr` to \/etc\/fstab and remount the filesystem in question and everything would be fine&#8230; Well, it would be fine if my \/etc\/fstab would actually contain an entry for `\/`! Being on a virtual server started to get a little annoying.<\/p>\n<p>But I didn&#8217;t capitulated, not yet. &#8220;Wasn&#8217;t there a way to create and mount a filesystem from a disk image?&#8221; I wondered. I used this technique a couple of times to mount ISO images and browse their contents back in my old Linux days. I read a bit further on this topic and found <a href=\"http:\/\/edseek.com\/~jasonb\/articles\/linux_loopback.html\" target=\"_blank\">many<\/a> <a href=\"http:\/\/www.linuxquestions.org\/linux\/answers\/Applications_GUI_Multimedia\/Virtual_Filesystem_Building_a_Linux_Filesystem_from_an_Ordinary_File\" target=\"_blank\">helpful<\/a> <a href=\"https:\/\/linuxlink.timesys.com\/docs\/losetup\" target=\"_blank\">ressources<\/a> on this topic. At first I needed to create an image file and format that with a filesystem:<\/p>\n<pre># 128 blocks of 1MByte size\r\n$ dd if=\/dev\/zero of=caldavdata.image bs=1M count=128\r\n128+0 records in\r\n128+0 records out\r\n134217728 bytes (134 MB) copied, 0.506394 seconds, 265 MB\/s\r\n$ mkfs.ext3 -v caldavdata.image\r\nmke2fs 1.36 (05-Feb-2005)\r\ncaldavdata.image is not a block special device.\r\nProceed anyway? (y,n) y\r\nFilesystem label=\r\nOS type: Linux\r\nBlock size=1024 (log=0)\r\nFragment size=1024 (log=0)\r\n32768 inodes, 131072 blocks\r\n6553 blocks (5.00%) reserved for the super user\r\nFirst data block=1\r\n16 block groups\r\n8192 blocks per group, 8192 fragments per group\r\n2048 inodes per group\r\nSuperblock backups stored on blocks: \r\n        8193, 24577, 40961, 57345, 73729\r\n\r\nWriting inode tables: done                            \r\nCreating journal (4096 blocks): done\r\nWriting superblocks and filesystem accounting information: done\r\n\r\nThis filesystem will be automatically checked every 28 mounts\r\nor 180 days, whichever comes first.\r\nUse tune2fs -c or -i to override.<\/pre>\n<p>&#8220;Great! Now I only need to mount that baby!&#8221; I thought:<\/p>\n<pre>$ mount caldavdata.image \/opt\/caldavdata -t ext3 -o loop\r\nmount: could not find any device \/dev\/loop#<\/pre>\n<p>Indeed, there was not one single block device in \/dev starting with `loop` &#8211; in fact the only two block devices I found there at all were related to the virtual server&#8217;s own file system. In my naive thinking I continued: &#8220;Hey, if this block device is not existent, I&#8217;m pretty much sure that I can create it with mknod!&#8221;. Indeed, mknod can create any kind of char or block devices. <a href=\"http:\/\/www.faqs.org\/docs\/linux_admin\/x822.html\" target=\"_blank\">This site<\/a> pointed me to the correct needed major and minor numbers for such a device:<\/p>\n<pre>$ mknod \/dev\/loop0 b 7 0 # 'b' stands for block device\r\n$ ls -lah \/dev\/loop0 \r\nbrw-r--r--  1 root root 7, 0 Feb  1 21:25 \/dev\/loop0<\/pre>\n<p>&#8220;Success!&#8221; I thought and tried the mount command again:<\/p>\n<pre>$ mount caldavdata.image \/opt\/caldavdata -t ext3 -o loop\r\nmount: Could not find any loop device. Maybe this kernel does\r\n       not know about the loop device?\r\n       (If so, recompile or `modprobe loop'.)<\/pre>\n<p>&#8220;Yeah, apparently it does not know about device&#8221; and ran the proposed `modprobe loop`:<\/p>\n<pre>$ modprobe loop\r\nFATAL: Module loop not found.<\/pre>\n<p>Hrm&#8230; could it be that loop wasn&#8217;t compiled as module? Grepping the config told me yes:<\/p>\n<pre>$ cat \/boot\/config-2.6.11.4-20a-smp | grep LOOP\r\nCONFIG_CC_ALIGN_LOOPS=0\r\nCONFIG_BLK_DEV_LOOP=y\r\nCONFIG_BLK_DEV_CRYPTOLOOP=m<\/pre>\n<p>So, the last thing I could think of (as an ignorant Linux user) was to reboot the server and hope that it would <i>somehow<\/i> recognize the loopback file. <\/p>\n<p>Of course, this did not work out.<\/p>\n<p>I&#8217;m now in the sad process to get used to <a href=\"http:\/\/www.google.com\/calendar\" target=\"_blank\">Google Calendar<\/a>&#8230;<\/p>\n<p>[<strong>Update:<\/strong> Actually the only bad things about Google Calendar until today are<\/p>\n<p>a) I don&#8217;t have full control of the server-side storage \/ backup<\/p>\n<p>b) I can&#8217;t publish events to Google via iCal &#8211; well, at least I could not until today. <\/p>\n<p>Apparently Google offers an RSS-alike API to access calendar data and <a href=\"http:\/\/gcaldaemon.sourceforge.net\/\">somebody<\/a> wrote a small Java server which &#8220;translates&#8221; between this custom RSS format and the standard ical format. It allows file-based synchronization (i.e. particularily useful for iCal which can&#8217;t just embed and write CalDAV ressources) and even contains a small web server to do the translation live and in place &#8211; how neat is that?!<\/p>\n<p>You can download <a href=\"http:\/\/gcaldaemon.sourceforge.net\/\">GCalDaemon here<\/a>.]<\/p>\n","protected":false},"excerpt":{"rendered":"<p>My wife and I seem to share a lot of activities recently. We finally gathered a few friends around here with which we do regularily stuff like playing card games and she even got me to take Salsa dancing lessons with her. Beside that my political interests and meetings are quite regular as well, so &hellip; <a href=\"https:\/\/www.thomaskeller.biz\/blog\/2008\/02\/02\/a-linux-tale\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">A Linux tale&#8230; [updated]<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[13,10],"tags":[],"class_list":["post-44","post","type-post","status-publish","format-standard","hentry","category-free-software","category-life"],"_links":{"self":[{"href":"https:\/\/www.thomaskeller.biz\/blog\/wp-json\/wp\/v2\/posts\/44","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.thomaskeller.biz\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.thomaskeller.biz\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.thomaskeller.biz\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.thomaskeller.biz\/blog\/wp-json\/wp\/v2\/comments?post=44"}],"version-history":[{"count":0,"href":"https:\/\/www.thomaskeller.biz\/blog\/wp-json\/wp\/v2\/posts\/44\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.thomaskeller.biz\/blog\/wp-json\/wp\/v2\/media?parent=44"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.thomaskeller.biz\/blog\/wp-json\/wp\/v2\/categories?post=44"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.thomaskeller.biz\/blog\/wp-json\/wp\/v2\/tags?post=44"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}