-<p>For noen dager siden ble jeg tipset om en ny norsk webtjeneste for
-å holde styr på ens tegneseriesamling. Har så smått begynt å
-teste den og lagt inn noen hundre oppføringer, og det ser ut til å
-fungere fint. Utvikleren, Trond Hallstensen, er selv ivrig samler og
-har laget systemet i første omgang for seg selv, men altså gjort det
-mulig også for andre å bidra. Tjenesten har potensiale til å bli
-en komplett og verdifull tegneserieindeks over norske serier. Da jeg
-oppdaget tjenesten var det endel mangler som gjorde meg skeptisk til
-å registrere min samling der. Det var nemlig ingen måte å hente ut
-en maskinlesbar oversikt over det jeg registrerte, slik at mine data
-ville være innelåst i tjenesten. Siden den gang har Trond lagt til
-en eksportfunksjon til CSV-format, slik at i hvert fall noen av
-feltene i databasen kan hentes ut for mine serier. Pr. i dag er det
-serie, seriegruppe, år, nr og tittel_på_forside.</p>
-
-<p>Prinsipielt ønsker jeg å kunne hente ut alle feltene om en
-tegneserie, for å unngå repetisjon av det som skjedde med IMDB og
-CDDB på 90-tallet. Begge begynte som fellesskapsprosjekter der
-brukerne bidro på like vilkår, og ble lukket inne da
-initiativtageren og innehaveren av maskinen der tjenesten kjørte
-hadde fått nok innhold til at de ikke lenger følte at de trengte å
-behandle brukerne som likemenn. Trond har skrevet til meg at flere
-felter vil bli lagt inn i eksporten (blant annet strekkode), men
-uttrykt skepsis til å gjøre all informasjonen tilgjengelig (han
-ønsker slik jeg forsto han å kontrollere tjenesten og ikke gjøre
-det mulig å lage konkurrerende tjeneste). Holdningen gjør meg ennå
-mer skeptisk, men tjenesten fungerer fint, så jeg har bestemt meg for
-å ta den i bruk, men begrense meg til å registrere informasjon som
-er tilgjengelig i eksporten.</p>
-
-<p>Har ennå ikke begynt masseregistrering, da jeg venter på støtte for
-strekkoder i tjenesten. Har strekkodeleser, og vil spare litt tid i
-registreringen når jeg går løs på mine esker. Foreløbig har jeg
-registrert litt tilfeldige serier som ligger rundt om i huset, men for
-å få et komplett arkiv må nok noen tusen tegneserier registreres.</p>
-
-<p>Løsningen er i følge utvikleren laget med et Oracle-spesifikt
-verktøy for å lage webtjenester, og ikke fri programvare.
-Utvikleren tar imot innspill men det hørtes ikke ut som om utvikling
-av systemet var enkelt å dele mellom flere, slik at det må via
-ham.</p>
-
-<p>Høres dette interessant ut, besøk
-<a href="http://www.mineserier.no/">mineserier.no</a> og ta en
-titt.</p>
+<p>A few years ago, I was involved in a project planning to use
+Windows file servers as home directory servers for Debian
+Edu/Skolelinux machines. This was thought to be no problem, as the
+access would be through the SMB network file system protocol, and we
+knew other sites used SMB with unix and samba as the file server to
+mount home directories without any problems. But, after months of
+struggling, we had to conclude that our goal was impossible.</p>
+
+<p>The reason is simply that while SMB can be used for home
+directories when the file server is Samba running on Unix, this only
+work because of Samba have some extensions and the fact that the
+underlying file system is a unix file system. When using a Windows
+file server, the underlying file system do not have POSIX semantics,
+and several programs will fail if the users home directory where they
+want to store their configuration lack POSIX semantics.</p>
+
+<p>As part of this work, I wrote a small C program I want to share
+with you all, to replicate a few of the problematic applications (like
+OpenOffice.org and GCompris) and see if the file system was working as
+it should. If you find yourself in spooky file system land, it might
+help you find your way out again. This is the fs-test.c source:</p>
+
+<pre>
+/*
+ * Some tests to check the file system sematics. Used to verify that
+ * CIFS from a windows server do not work properly as a linux home
+ * directory.
+ * License: GPL v2 or later
+ *
+ * needs libsqlite3-dev and build-essential installed
+ * compile with: gcc -Wall -lsqlite3 -DTEST_SQLITE fs-test.c -o fs-test
+*/
+
+#define _FILE_OFFSET_BITS 64
+#define _LARGEFILE_SOURCE 1
+#define _LARGEFILE64_SOURCE 1
+
+#define _GNU_SOURCE /* for asprintf() */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#ifdef TEST_SQLITE
+/*
+ * Test sqlite open, as done by gcompris require the libsqlite3-dev
+ * package and linking with -lsqlite3. A more low level test is
+ * below.
+ * See also <URL: http://www.sqlite.org./faq.html#q5 >.
+ */
+#include <sqlite3.h>
+#define CREATE_TABLE_USERS \
+ "CREATE TABLE users (user_id INT UNIQUE, login TEXT, lastname TEXT, firstname TEXT, birthdate TEXT, class_id INT ); "
+int test_sqlite_open(void) {
+ char *zErrMsg;
+ char *name = "testsqlite.db";
+ sqlite3 *db=NULL;
+ unlink(name);
+ int rc = sqlite3_open(name, &db);
+ if( rc ){
+ printf("error: sqlite open of %s failed: %s\n", name, sqlite3_errmsg(db));
+ sqlite3_close(db);
+ return -1;
+ }
+
+ /* create tables */
+ rc = sqlite3_exec(db,CREATE_TABLE_USERS, NULL, 0, &zErrMsg);
+ if( rc != SQLITE_OK ){
+ printf("error: sqlite table create failed: %s\n", zErrMsg);
+ sqlite3_close(db);
+ return -1;
+ }
+ printf("info: sqlite worked\n");
+ sqlite3_close(db);
+ return 0;
+}
+#endif /* TEST_SQLITE */
+
+/*
+ * Demonstrate locking issue found in gcompris using sqlite3. This
+ * work with ext3, but not with cifs server on Windows 2003. This is
+ * done in the sqlite3 library.
+ * See also
+ * <URL:http://www.cygwin.com/ml/cygwin/2001-08/msg00854.html> and the
+ * POSIX specification
+ * <URL:http://www.opengroup.org/onlinepubs/009695399/functions/fcntl.html>.
+ */
+int test_gcompris_locking(void) {
+ struct flock fl;
+ char *name = "testsqlite.db";
+ unlink(name);
+ int fd = open(name, O_RDWR|O_CREAT|O_LARGEFILE, 0644);
+ printf("info: testing fcntl locking\n");
+
+ fl.l_whence = SEEK_SET;
+ fl.l_pid = getpid();
+ printf(" Read-locking 1 byte from 1073741824");
+ fl.l_start = 1073741824;
+ fl.l_len = 1;
+ fl.l_type = F_RDLCK;
+ if (0 != fcntl(fd, F_SETLK, &fl) ) printf(" - error!\n"); else printf("\n");
+
+ printf(" Read-locking 510 byte from 1073741826");
+ fl.l_start = 1073741826;
+ fl.l_len = 510;
+ fl.l_type = F_RDLCK;
+ if (0 != fcntl(fd, F_SETLK, &fl) ) printf(" - error!\n"); else printf("\n");
+
+ printf(" Unlocking 1 byte from 1073741824");
+ fl.l_start = 1073741824;
+ fl.l_len = 1;
+ fl.l_type = F_UNLCK;
+ if (0 != fcntl(fd, F_SETLK, &fl) ) printf(" - error!\n"); else printf("\n");
+
+ printf(" Write-locking 1 byte from 1073741824");
+ fl.l_start = 1073741824;
+ fl.l_len = 1;
+ fl.l_type = F_WRLCK;
+ if (0 != fcntl(fd, F_SETLK, &fl) ) printf(" - error!\n"); else printf("\n");
+
+ printf(" Write-locking 510 byte from 1073741826");
+ fl.l_start = 1073741826;
+ fl.l_len = 510;
+ if (0 != fcntl(fd, F_SETLK, &fl) ) printf(" - error!\n"); else printf("\n");
+
+ printf(" Unlocking 2 byte from 1073741824");
+ fl.l_start = 1073741824;
+ fl.l_len = 2;
+ fl.l_type = F_UNLCK;
+ if (0 != fcntl(fd, F_SETLK, &fl) ) printf(" - error!\n"); else printf("\n");
+
+ close(fd);
+ return 0;
+}
+
+/*
+ * Test if permissions of freshly created directories allow entries
+ * below them. This was a problem with OpenOffice.org and gcompris.
+ * Mounting with option 'sync' seem to solve this problem while
+ * slowing down file operations.
+ */
+int test_subdirectory_creation(void) {
+#define LEVELS 5
+ char *path = strdup("test");
+ char *dirs[LEVELS];
+ int level;
+ printf("info: testing subdirectory creation\n");
+ for (level = 0; level < LEVELS; level++) {
+ char *newpath = NULL;
+ if (-1 == mkdir(path, 0777)) {
+ printf(" error: Unable to create directory '%s': %s\n",
+ path, strerror(errno));
+ break;
+ }
+ asprintf(&newpath, "%s/%s", path, "test");
+ free(path);
+ path = newpath;
+ }
+ return 0;
+}
+
+/*
+ * Test if symlinks can be created. This was a problem detected with
+ * KDE.
+ */
+int test_symlinks(void) {
+ printf("info: testing symlink creation\n");
+ unlink("symlink");
+ if (-1 == symlink("file", "symlink"))
+ printf(" error: Unable to create symlink\n");
+ return 0;
+}
+
+int main(int argc, char **argv) {
+ printf("Testing POSIX/Unix sematics on file system\n");
+ test_symlinks();
+ test_subdirectory_creation();
+#ifdef TEST_SQLITE
+ test_sqlite_open();
+#endif /* TEST_SQLITE */
+ test_gcompris_locking();
+ return 0;
+}
+</pre>
+
+<p>When everything is working, it should print something like
+this:</p>
+
+<pre>
+Testing POSIX/Unix sematics on file system
+info: testing symlink creation
+info: testing subdirectory creation
+info: sqlite worked
+info: testing fcntl locking
+ Read-locking 1 byte from 1073741824
+ Read-locking 510 byte from 1073741826
+ Unlocking 1 byte from 1073741824
+ Write-locking 1 byte from 1073741824
+ Write-locking 510 byte from 1073741826
+ Unlocking 2 byte from 1073741824
+</pre>
+
+<p>I do not remember the exact details of the problems we saw, but one
+of them was with locking, where if I remember correctly, POSIX allow a
+read-only lock to be upgraded to a read-write lock without unlocking
+the read-only lock (while Windows do not). Another was a bug in the
+CIFS/SMB client implementation in the Linux kernel where directory
+meta information would be wrong for a fraction of a second, making
+OpenOffice.org fail to create its deep directory tree because it was
+not allowed to create files in its freshly created directory.</p>
+
+<p>Anyway, here is a nice tool for your tool box, might you never need
+it. :)</p>