cp_dir_watcher: C++ Linux library for monitoring files in a directory

I’ve posted C++ code that I wrote a while ago to monitor files in a directory:
https://github.com/rebrik/cp_dir_watcher

Below is the  README:
cp_dir_watcher is a C++ Linux library designed to monitor changes to files in a directory. It is released under Boost Software License: http://www.boost.org/LICENSE_1_0.txt

Possible usage scenario: a server is writing logs to a dir, and you want to make sure that the logs are constantly updated. So you write an app (using this project) which receives and processes a timeout event that is generated when nothing happens to a file or a dir for a certain time. Another scenario is to use provided classes to build a real-time parser which processes new data in the log files as soon as they are written to.

The library consists of two classes: dir_watcher_t and file_watcher_t. Users should derive their own classes from these two classes and provide necessary functionality in the virtual callback functions defined in the base classes.

Library comes with an example application: test00. It contains classes dir_watcher_tst_t and file_watcher_tst_t which inherit from dir_watcher_t and file_watcher_t. The test is watching the dir “./delme/” and 3 files in it: f1.txt, f2.txt, f3.txt and reports events to stdout.  Try creating, editing, deleting, renaming these files and see the reported events. You can delete or rename the dir itself while the program is running, but the dir must be present when the program starts.

Two system libraries are used: libev and inotify: libev is used to implement the main loop and inotify reports filesystem events. These events are received by the main loop and then dispatched to the appropriate callbacks.

To build the project open a terminal in the “test00” dir and run a command:

make CONF=Release

You can also use “make CONF=Debug”, “make CONF=Release clean” or just open the project in NetBeans

 

Xubuntu + Xfce: setting shell environment

System: Ubuntu 12.04 (precise)
Desktop Environment: Xfce 4.10, distributed by Xubuntu

As it often happens, an update or install messes up your system and in the process of fixing it you start researching and learning something new. Which is a good thing. Bad thing is that you sure have other plans when you are forced to work on the fix.

This time it was installation of Ruby enVironment Manager (rvm). Everything went smoothly at the time, but later I’ve noticed that my ~/.bashrc is no longer sourced. It turns out that rvm installed .bash_profile  in my home dir (I did not have it before). Also the instructions suggested to run terminal in the login mode to make sure rvm is working. Now I know what happened and why, but it took me some time to figure it out. Below is what I learned and how I fixed and organized my shell environment in the process.

A bit of theory first. Your shell can be: login/non-login and interactive/non-interactive. These options make 4 possible combinations. Login shell is used when the user is required to login, e.g. via ssh – usually it is also an interactive shell. In desktop environment terminal is normally started as an interactive non-login shell, but it is possible to configure the terminal to start as a login shell (despite the name it does not ask for user/password when it starts). In Xfce: open a terminal and set the option using this path:  Menu -> Edit -> Preferences -> General Tab -> “Run command as login shell”

Here is how bash deals with the 3 files which can be present in the home dir (derived from “man bash”). Interactive login shell searches files in this order (only the first found is executed):

~/.bash_profile
~/.bash_login
~/.profile

Interactive non-login shell uses only this one:
~/.bashrc

To avoid surprises I’ve put all custom settings into ~/.bashrc
and sourced it from ~/.bash_profile
Something like that:

# if running bash
if [ -n "$BASH_VERSION" ]; then
    # include .bashrc if it exists
    if [ -f "$HOME/.bashrc" ]; then
    . "$HOME/.bashrc"
    fi
fi

This way I get the same environment in both login and non-login shells.

After having done this I decided that I also want to have custom environment for the programs launched from the desktop environment (GUI). When Xfce session starts (right after you are authenticated in the initial login screen), Xfce tries to run the script from ~/.config/xfce4/xinitrc, if it is not found, it runs the script located in /etc/xdg/xfce4/xinitrc. Below is the sequence of calls when the user’s script is found:
root: /sbin/init
root: lightdm
root: lightdm –session-child 12 97
user:  /bin/sh/ /home/user/.config/xfce4//xinitrc — /etc/X11/xinit/xserverrc
user: xfce4-session
The last process launches everything related to the desktop environment, and its children inherit the settings provided in xinitrc. To customize the GUI environment you are supposed to copy the system file to your home dir and modify it:

cp /etc/xdg/xfce4/xinitrc ~/.config/xfce4/xinitrc

Here is a part of the modified file:

# run xfce4-session if installed
if which xfce4-session >/dev/null 2>&1; then

  # check if we start xfce4-session with ck-launch-session. this is only
  # required for starting from a console, not a login manager
  if test "x$XFCE4_SESSION_WITH_CK" = "x1"; then
    if which ck-launch-session >/dev/null 2>&1; then
      ck-launch-session xfce4-session
    else
      echo
      echo "You have tried to start Xfce with consolekit support, but"
      echo "ck-launch-session is not installed."
      echo "Aborted startup..."
      echo

      exit 1
    fi
  else
    # set gui environment
    if [ -f "$HOME/.xfcebashrc" ]; then
        source "$HOME/.xfcebashrc"
    fi
    # start xfce4-session normally
    xfce4-session
  fi

  exit 0
fi

The snippet above is almost identical to the original system file, I’ve only inserted these lines:

     # set gui environment
     if [ -f "$HOME/.xfcebashrc" ]; then
         . "$HOME/.xfcebashrc"
     fi

Note that the script is run under sh, not bash, so bash-specific commands like source would not work. In the code above ~/.xfcebashrc is sourced, and I can configure my GUI environment by making it look like this:

# Local Java installation path
PATH=$HOME/bin/jdk1.6.0_31/bin:$PATH
export JAVA_HOME=$HOME/bin/jdk1.6.0_31

# Android tools path
PATH=$PATH:$HOME/bin/android-sdk-linux/tools:\
$HOME/bin/android-sdk-linux/platform-tools
# Android NDK path
PATH=$PATH:$HOME/bin/android-ndk

# Add RVM to PATH for scripting
PATH=$PATH:$HOME/.rvm/bin 

export PATH

Now I have to take care of two files when I want to change shell environment:
~/.xfcebashrc    – for GUI – launched programs and
~/.bashrc          – for the terminal
Having two files I can set these environments independently. Note that the GUI environment will change on the next GUI login.

And in the end some useful commands and resources found on the net.
To see which path (or other environment) is being used by your GUI programs, start “Run Program” from the System menu and run this (it will produce a message containing the GUI path):

xmessage $PATH

To check if the shell is login or non-login:

shopt login_shell

To check environment of a running process with a known PID (replace PID with a number):

xargs --null --max-args=1 echo < /proc/PID/environ

Useful resources:
http://wiki.debian.org/EnvironmentVariables
http://wiki.debian.org/DotFiles

 

VLC could not open the file and the MRL

I started to get this error on my Video PC Win XP SP3:

File reading failed:
VLC could not open the file
"C:\Profiles\user\Temp\PLUGTM~2\PLUGIN~2.ASH". (Bad file descriptor)
Your input can't be opened:
VLC is unable to open the MRL 
'file:///C:/Profiles/user/Temp/PLUGTM~2/PLUGIN~2.ASH'. 
Check the log for details.

This only happens if VLC is not running when a web page requests VLC to start streaming the video. If VLC is running, the stream is opened without a problem. Looks like some sort of timing issue at the VLC startup. I could not find a solution on the web, fixing VLC is not an option, so I decided to make sure that VLC is always running. Added a shortcut to the Startup dir in Windows, it starts VLC in the minimized mode (tray icon):

"C:\Program Files\VideoLAN\VLC\vlc" --qt-start-minimized

There is a positive side-effect: the first start of a VLC stream is noticeably faster. Unfortunately, killing all instances of VLC will bring back the problem.

There is an option to start VLC as a service, but I have not tried this yet:

 vlc -I ntservice --ntservice-extraintf=http --ntservice-install

Web control interface is at http://127.0.0.1:8080/

Restoring boot sector on Windows XP notebook

I had another disk/partition adventure recently. My notebook stopped booting after I updated XUbuntu on the second partition of the HD. Apparently the update screwed-up boot sector on Win XP partition (the first one). So I got a USB flash drive with WinXP SP3 setup and booted from it hoping to use Windows recovery tools: fixboot and fixmbr. Unfortunately the recovery was not able to find any Windows installations; in fact it did not see the disk at all. The notebook uses Intel ICH9 controller and its drivers are not available on the setup disk. Apparently I could not use a floppy to add an extra driver in the boot process, so I needed to add these drivers to the installation. There are instructions on how to do this using nLite, but it looked like it can take a long time. And then I realized that I can disable AHCI mode of the SATA controller. One change in the BIOS settings, and the setup disk could find Windows partition and I fixed boot sector using fixboot. After fixing the boot sector I changed SATA controller mode back to AHCI and everything worked fine.

On other motherboards/notebooks these compatibility modes can be called differently (ATA, IDE, something else?), AHCI is sometimes called “native” mode.

Moving bootable NTFS partition to a new drive

My old video PC started acting up – it was losing BIOS settings randomly. So I’ve replaced the motherboard, installed Windows XP, software, … Everything worked fine but the ancient IDE disk from Maxtor turned out to be very noisy. So I’ve ordered an SSD – the cheapest and hence the smallest I could get. Just enough to install the OS: all videos and music are located on a Samba server. When the new disk arrived, I decided to copy Windows XP partition to the new disk – installing XP again is no fun.

Starting state and notation:

  • Maxtor 160GB disk with 80GB NTFS boot partition – I’ll call it HD
  • OSZ 32GB disk – I’ll call it SSD
  • Windows XP PC – I’ll call it XP
  • Ubuntu PC – I’ll call it Ubuntu

Here is what I did. It is not a step-by-step instruction, just a description of what actually worked (I tried other options). Use at your own risk.

Connected SSD and HD to my Ubuntu, the disks were labeled as:
sdg – SSD (destination)
sdf – HD (source)
Check these labels every time you connect a disk to Ubuntu.

Since I already “played” with the SSD, I needed to clean-up the config area. The command below will delete all partitions, MBR,  EVERYTHING. Be very careful not to use it on a wrong drive:

sudo dd if=/dev/zero of=/dev/sdg count=1024

Plug SSD into XP. Go to the Disk Manager, initialize the disk, create full-disk NTFS partition (32GB), mark this partition as active. Try to boot XP from this disk – it should produce an error “NTLDR not found” It means that MBR is OK and the partition is bootable.

We need to shrink 80GB partition on HD –  SSD is only 32GB. New size will be 24GB:

sudo ntfsresize -s 24G  /dev/sdf1

At this point we have a 24GB NTFS volume on a 80GB partition. Yes, NTFS volumes can be smaller than the partition they are in.

Plug HD into XP and boot from it. The system will check the disk before booting.

Plug SSD and HD into Ubuntu. Clone the 24GB NTFS volume from HD to the 32GB partition on SSD. Flag -O means overwrite existing file (disk partition in our case):

sudo ntfsclone -O /dev/sdg1 /dev/sdf1

Run this command to find the exact size of the partition on SSD:

sudo ntfsresize -i /dev/sdg1

The output should look like this:

ntfsresize v2012.1.15AR.1 (libntfs-3g)
Device name        : /dev/sdg1
NTFS volume version: 3.1
Cluster size       : 4096 bytes
Current volume size: 23999996416 bytes (24000 MB)
Current device size: 32012757504 bytes (32013 MB)
Checking filesystem consistency ...
100.00 percent completed
Accounting clusters ...
Space in use       : 12343 MB (51.4%)
Collecting resizing constraints ...
You might resize at 12342161408 bytes or 12343 MB (freeing 11657 MB).
Please make a test run using both the -n and -s options before real resizing!

We need to resize NTFS volume to fill the partition. In the info above we see that the device size is 32012757504 bytes, so we set new volume size to 32012757 kilobytes:

sudo ntfsresize --size 32012757k  /dev/sdg1

This is it. Plug SSD into XP. The system will check the disk on first boot.

If new partition is bigger than the old one there is no need to shrink the old NTFS volume. Just clone and resize.