chkdsk hangs — but not from Vista

I usually run chkdsk from a bootable CD such as Hiren’s, but today I had a Vista machine with a disk fault, and chkdsk from the CD kept hanging at 1% of phase 4: it got completely stuck, and I had to force the computer to power off.

I thought that the disk must be completely borked, but in fact it did boot into Windows — but very slowly.  And when I set Vista’s chkdsk to run on restart, it worked perfectly: it just found bad sectors in one file.

So, the moral is: don’t dismiss the idea of running chkdsk from the faulty disk, even with Vista.

Using nametrans with offlineimap

(Originally posted on the offlineimap mailing list on 15 Jan 2012)

I’ve finally got offlineimap’s ‘nametrans’ feature to do what I want.

Part of the problem was that I found the documentation and examples to be somewhat ambiguous in terms of which direction the translation would happen.

Anyway, I’ve got it working, so here are my notes which will hopefully be helpful to others.

The ‘nametrans’ configuration option allows conversion between different folder names on the local and remote repositories.

nametrans specifies a Python expression which, given each folder name from the repository in turn, returns the equivalent name on the other repository.

In the configuration of the local repository, the nametrans code receives each local folder name, and returns the name of the equivalent remote folder.

In the remote repository configuration, the nametrans code gets the remote folder names, one at a time, and returns the equivalent local names.

Here’s a real example. My remote repository is on my ISP’s server. The ISP’s spam filter puts spam emails into a folder called ‘Spam’, and deleted emails into ‘Trash’. The local repository, on a Debian server running Dovecot IMAP, is accessed by users via Outlook, which likes to use the folder name ‘Junk E-mail’ for spam and ‘Deleted Items’ for deleted emails.

So to avoid confusion, I’ve set up name translations:

<code>[Repository LocalIMAP]
type = IMAP
remotehost = localhost
...
nametrans = lambda foldername: re.sub ('^Junk E-mail$', 'Spam',
re.sub ('^Deleted Items$', 'Trash',
foldername))

[Repository RemoteIMAP]
type = IMAP
remotehost = isp.example.com
...
nametrans = lambda foldername: re.sub ('^Spam$', 'Junk E-mail',
re.sub ('^Trash$', 'Deleted Items',
foldername))</code>

I won’t explain Python lambdas and regular expressions here. But beginners should note

  1. the variable name after the word ‘lambda’ can be anything you like, but must be the same as is used in the expression after the ‘:’; it makes sense to call it ‘foldername’, or just ‘f’ if you don’t like typing.
  2. the re.sub function takes three arguments:
    1. regular expression to match against the third argument
    2. the string to return if there’s a match
    3. the value to match against — here the folder name.
  3. the use of ^ and $ to mark the beginning and end of the match, i.e. to make sure the whole folder name is matched.
  4. if there is no match, re.sub() returns the folder name unchanged.
  5. re.sub() can be nested to allow more than one translation.

With this configuration, offlineimap will synchronise the local ‘Junk E-mail’ folder with the remote ‘Spam’ folder, and local ‘Deleted Items’ with remote ‘Trash’ in both directions.

Problems will occur if the ‘foreign’ name exists as a folder. For example, if ‘Trash’ exists on the local repository, you’ll get this error message:

<code>ERROR: INFINITE FOLDER CREATION DETECTED! Folder 'Trash' (repository
'LocalIMAP') would be created as folder 'Trash' (repository
'RemoteIMAP'). The latter becomes 'Deleted Items' in return, leading to
infinite folder creation cycles.
SOLUTION: 1) Do set your nametrans rules on both repositories so they
lead to identical names if applied back and forth. 2) Use folderfilter
settings on a repository to prevent some folders from being created on
the other side.</code>

I found that message only partially helpful: does it mean use both solutions 1) and 2), or either?

Solution 3) would be “Remove folder ‘Trash’ from the local repository”, but if you don’t want to do that, then solution 2) is required: add a folderfilter to stop the local ‘Trash’ from being copied to the remote side, like this (in the local repository configuration):

<code>folderfilter = lambda foldername: foldername not in ['Trash']</code>

That folderfilter is only required, in this example, if ‘Trash’ already exists locally, or if there is any danger of it being created in the future. It’s always possible that a translated folder name could be created by the user, so it’s safest to add folderfilters for any translated folder names. To complete my real-world example from above, I need:

<code>[Repository LocalIMAP]
# Has folders: Inbox, Junk E-mail, Deleted Items, etc.
type = IMAP
remotehost = localhost
...
nametrans = lambda foldername: re.sub ('^Junk E-mail$', 'Spam',
                                re.sub ('^Deleted Items$', 'Trash',
                                foldername))
folderfilter = lambda foldername: foldername not in ['Spam', 'Trash']

[Repository RemoteIMAP]
# Has folders: Inbox, Spam, Trash, etc.
type = IMAP
remotehost = isp.example.com
...
nametrans = lambda foldername: re.sub ('^Spam$', 'Junk E-mail',
                                re.sub ('^Trash$', 'Deleted Items',
                                foldername))
folderfilter = lambda foldername: foldername not in ['Junk E-mail',
                                                     'Deleted Items']
</code>

I hope that’s clear, and that it’s helpful to people. Perhaps some of it could be included in the offlineimap documentation.

GnuCash on Arch Linux

The version of GnuCash in Arch Linux, although up-to-date, is not compiled to use the webkit library, so formatting of reports such the tax invoice is very basic: it doesn't use the fonts that can be selected in the report options.

It's easily fixed though:

  1. sudo pacman -S abs webkitgtk2
  2. sudo abs
  3. copy /var/abs/extra/gnucash to a suitable place, such as ~/abs/
  4. cd ~/abs/gnucash
  5. add the option '–with-html-engine=webkit' to the PKGBUILD file after the line beginning with './configure'.  Or apply this patch:
    — PKGBUILD~    2012-11-20 16:49:51.048534626 +0000
    +++ PKGBUILD    2012-11-20 16:49:54.015211392 +0000
    @@ -1,4 +1,4 @@
    -# $Id: PKGBUILD,v 1.1 2012/11/20 05:03:00 chris Exp chris $
    +# $Id: PKGBUILD 165143 2012-08-11 18:49:18Z eric $
     # Maintainer: Aaron Griffin <aaron@archlinux.org>
     # Contributor: Mark Schneider <queueRAM@gmail.com>
     
    @@ -22,6 +22,7 @@
     build() {
       cd "${srcdir}/${pkgname}-${pkgver}"
       ./configure –prefix=/usr –mandir=/usr/share/man –sysconfdir=/etc \
    +    –with-html-engine=webkit \
         –libexecdir=/usr/lib –disable-schemas-install –enable-ofx –enable-aqbanking
       make
     }
  6. makepkg
  7. sudo pacman -U *.xz

Changing the location of the Users directory on Windows 7

I've just set up a Windows 7 PC, and it helpfully asked if I wanted to create one big partition on the (1TB) disk, or to create a separate partition for 'data'.  It offered a default size of 50GB for the 'system', but I chose 100GB, with all the rest for 'data'.  And then it completely failed to put the users' 'My Documents' etc. onto the data partition.  In my experience, very few ordinary Windows users make use of space that isn't in the default location, i.e. My Documents, My Music, or My Videos.

So there must be an easy way to get Windows to put My Documents somewhere else mustn't there?  Well, sort of.  Right-click on My Documents, select Properties, and change the location.  Fine.  But you have to do it for each category, and each user.  And it still doesn't move the application data, registry stuff, or the temporary files etc.

On the other hand, with Windows 7 it's also possible to include arbirtrary directories into the 'library', so that could work for you.

I found a good set of instructions on SevenForums that actually does what I want.  It's a bit fiddly, and I found those instructions incomplete.

So this is my solution.  Ideally do this when setting up the computer from new — otherwise, there will be a lot of registry editing at least, and quite possibly some applications that lose track of their files. 

Notes:

  • Obviously, I take no responsibility for the correctness or suitability of these notes: use them at your own risk. 
  • This is not a step-by-step idiot's guide: the instructions require you to understand the process and make decisions of your own.
  • This is for a home computer — not one that's connected to a domain.

The approach is to use an administrator account to move each of the other accounts (which may themselves be administrators).  If you've got two admin accounts, they can move each other.  Or you can create a temporary administrator account just for this manouevre.  It should also be possible to do this from a bootable CD such as Hiren's, although I haven't tried that yet.

  1. Backup the whole system, because this could all go horribly wrong.
  2. And create a restore point, just in case.
  3. Choose or create an administrator account, which I'll call 'admin'. 
  4. Change the folder settings to make all files (including system ones) visible.
  5. Create a folder on the destination disk/partition — I'll call it X:\Users.
  6. For each other user (referred to here as 'user'):
    1. Make sure user is logged off.
    2. Log on as admin.
    3. In Explorer (or by whatever means you choose) Copy and Paste C:\Users\User into X:\Users\, clicking 'Continue' or whatever to allow it to proceed.
    4. Using regedit (or your favourite registry editor), navigate to HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList and find the S-1-5-long-number entry with the ProfileImagePath that matches user.  Change it from C:\Users\User to X:\Users\User.
    5. Log on as user and take ownership of X:\Users\User.  
    6. If that worked, you can now delete C:\Users\User.
  7. If you want to keep user admin, you'll need to log on as a different administrator, and perform the steps above, treating admin as user.
  8. Then do the same thing for C:\Users\Public and C:\Users\Default.  In these cases, the registry entries to change are HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\Public and HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\Default respectively: change them to X:\Users\Public and X:\Users\Default.
  9. Now to change the default location for new users created in the future by changing HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\ProfilesDirectory to X:\Users.
  10. That's most of it done.  Except that there are probably lots of hard-coded references to C:\Users scattered throughout the registry.  Use a registry editor that does bulk search-and-replace, such RegAlyzer, to find and change every C:\Users\… to X:\Users\…  And then do a similar edit to change %System%\Users\… to X:\Users…
  11. Then reboot and check that it all works.
  12. If you created the admin just for this maneouvre, you can delete it now.

How to Resolve “mount error(12): Cannot allocate memory” on a Windows Share

[Copied from http://jlcoady.net/windows/how-to-resolve-mount-error12-cannot-allocate-memory-windows-share because it's so useful.]

If you mount a Windows 7 share using Samba/CIFS you may run into “mount error(12): Cannot allocate memory” if you are using very large files on the Windows machine. Looks like in certain situations Windows needs to be told to run as a file server and to expect large files. You can read more details at Large Files are locking up Windows 7 32 bit and 64 bit, but the solution is to make two registry edits and then restart a service:

  1. Set “HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management\LargeSystemCache” to “1″.
  2. Set “HKLM\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters\Size” to “3″.
  3. Restart the “server” service.

Once you have done that you should be able to mount the share using a command like “sudo mount -a” or just reboot the Linux machine.

Agere DSP / Martian modem on Ubuntu 10.10

Dial-up modems have always been a pain on Linux.  I got this one working though.

System: old PC running Ubuntu 10.10 (yes, still).

Modem: PCI card with Agere DSP chipset — i.e. a 'winmodem'.

Scanmodem reveals that it will work with the 'martian' driver, which is available on Ubuntu as packages 'martian' and 'martian-source'.

Having installed the packages, there is still some work to do which has to be repeated every time the Linux kernel gets updated:

  1. Make sure that you've got the linux-headers-xx package that matches your current kernel.
  2. As root:
    cd /usr/src/modules/martian-modem/source
    make
    make install
    depmod -a
    modprobe martian-dev

  3. Now you can run 'martian-modem –daemon' which sets up the modem as /dev/ttySM0
  4. I found that, after rebooting, it all Just Worked — /dev/ttySM0 was there and accessible.
  5. So I could set up Gnome PPP to use /dev/ttySM0
  6. Sorted.

(Those instructions are fairly minimal, but you should get the idea.)

Arch Linux, XFCE, and UK Keyboards

I know Arch Linux doesn't hold your hand like other distros do, but I think it could make setting the keyboard layout easier.

Firstly, set the locale in rc.conf:

    ...
    KEYMAP=&quot;uk&quot;
    LOCALE=&quot;en_GB.UTF-8&quot;
    ...

and then reboot.  Reboot?  Surely there's a better way, but I don't know what it is.

Edit /etc/locale.gen to uncomment the ones you want to use — en_GB.UTF-8 and en_GB in my case.

Then you can run

    # locale &gt; /etc/locale.conf

For 'normal' sorting of ls listings etc., edit /etc/locale.conf and set

    LC_COLLATE=&quot;C&quot;

That should sort things out on the console.

For XFCE, it's tricky because the Applications Menu / Settings / Keyboard seems to be ignored.  So refer to https://wiki.archlinux.org/index.php/Xorg#Setting_Keyboard_Layout_With_Hot-Plugging and add this to /etc/X11/xorg.conf:

    Section &quot;InputClass&quot;
        Identifier             &quot;Keyboard Defaults&quot;
        MatchIsKeyboard        &quot;yes&quot;
        Option                 &quot;XkbLayout&quot; &quot;gb&quot;
    EndSection

and restart X.