Recursively remove/delete a directory in PHP using SPL components

File system management is not the most common use case for PHP, but in writing a command line tool today I was surprised to find that PHP doesn’t have a function to recursively remove a directory (I was expecting at least a flag for rmdir or unlick, but no, nothing).

I did a quick Google search, just to be sure, and found numerous other people asking this same question and a few rather long winded recursive functional solutions floating around.

No being much of functional programming (and also because really there is no excuse for it when PHP has had reasonable OOP and some fantastic stuff in the SPL for a long time now) I knocked together a much cleaner SPL based solution for recursively deleting a directory:

function recursiveRmDir($dir)
{
    $iterator = new RecursiveIteratorIterator(new \RecursiveDirectoryIterator($dir, \FilesystemIterator::SKIP_DOTS), \RecursiveIteratorIterator::CHILD_FIRST);
    foreach ($iterator as $filename => $fileInfo) {
        if ($fileInfo->isDir()) {
            rmdir($filename);
        } else {
            unlink($filename);
        }
    }
}

I’ve obviously not added any checks to ensure that rmdir and unlink are successful, but this would be a simple addition and I really wanted to post this as an example of a nice modern way to use PHP rather than relying on old functional components.

Share

Patching VMware Tools to fix multiple installation errors on Ubuntu 13.04

Ubuntu 13.04 has the 3.8.0 kernel which has a few changes that VMware have not got round to fixing in the tools package yet. These patches were written for VMware Workstation 9, but I used them successfully with VMware Fusion 5, so there is little or no difference between the tools package for either product. I also did not write these patches myself but I’m writing this post to consolidate fixes for multiple separate issues when attempting to install tools on an Ubuntu 13.04 guest.

Issue 1 – Cannot find kernel headers

This is something to do with the location of version.h changing in the newer kernel and can be fixed with a simple simlink:

sudo ln -s /usr/src/linux-headers-$(uname -r)/include/generated/uapi/linux/version.h /usr/src/linux-headers-$(uname -r)/include/linux/version.h

Issue 2 – Build of vmci fails

The following errors will be encountered in vmware-config-tools.pl:

Using 2.6.x kernel build system.
make: Entering directory `/tmp/modconfig-9TKqy8/vmci-only'
/usr/bin/make -C /lib/modules/3.8.0-21-generic/build/include/.. SUBDIRS=$PWD SRCROOT=$PWD/. \
      MODULEBUILDDIR= modules
make[1]: Entering directory `/usr/src/linux-headers-3.8.0-21-generic'
  CC [M]  /tmp/modconfig-9TKqy8/vmci-only/linux/driver.o
/tmp/modconfig-9TKqy8/vmci-only/linux/driver.c:127:4: error: implicit declaration of function ‘__devexit_p’ [-Werror=implicit-function-declaration]
/tmp/modconfig-9TKqy8/vmci-only/linux/driver.c:127:4: error: initialiser element is not constant
/tmp/modconfig-9TKqy8/vmci-only/linux/driver.c:127:4: error: (near initialisation for ‘vmci_driver.remove’)
/tmp/modconfig-9TKqy8/vmci-only/linux/driver.c:1754:1: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘vmci_probe_device’
/tmp/modconfig-9TKqy8/vmci-only/linux/driver.c:1982:1: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘vmci_remove_device’
/tmp/modconfig-9TKqy8/vmci-only/linux/driver.c:119:12: warning: ‘vmci_probe_device’ used but never defined [enabled by default]
/tmp/modconfig-9TKqy8/vmci-only/linux/driver.c:121:13: warning: ‘vmci_remove_device’ used but never defined [enabled by default]
/tmp/modconfig-9TKqy8/vmci-only/linux/driver.c:2063:1: warning: ‘vmci_interrupt’ defined but not used [-Wunused-function]
/tmp/modconfig-9TKqy8/vmci-only/linux/driver.c:2137:1: warning: ‘vmci_interrupt_bm’ defined but not used [-Wunused-function]
/tmp/modconfig-9TKqy8/vmci-only/linux/driver.c:1717:1: warning: ‘vmci_enable_msix’ defined but not used [-Wunused-function]
cc1: some warnings being treated as errors
make[2]: *** [/tmp/modconfig-9TKqy8/vmci-only/linux/driver.o] Error 1
make[1]: *** [_module_/tmp/modconfig-9TKqy8/vmci-only] Error 2
make[1]: Leaving directory `/usr/src/linux-headers-3.8.0-21-generic'
make: *** [vmci.ko] Error 2
make: Leaving directory `/tmp/modconfig-9TKqy8/vmci-only'

The communication service is used in addition to the standard communication
between the guest and the host.  The rest of the software provided by VMware
Tools is designed to work independently of this feature.
If you wish to have the VMCI feature, you can install the driver by running
vmware-config-tools.pl again after making sure that gcc, binutils, make and the
kernel sources for your running kernel are installed on your machine. These
packages are available on your distribution's installation CD.
[ Press Enter key to continue ]

The solution to this issue involves patching driver.c to work with the 3.8 kernel:

cd ~
wget http://cdn.philbayfield.com/downloads/vmware-vmci.patch
cd /usr/lib/vmware-tools/modules/source/
sudo tar xf vmci.tar
cd vmci-only/
sudo patch -p1 < ~/vmware-vmci.patch
cd ..
sudo tar cf vmci.tar vmci-only

Issue 3 – Build of vmhgfs fails

The following errors will be encountered in vmware-config-tools.pl:

Using 2.6.x kernel build system.
make: Entering directory `/tmp/modconfig-LxeJ83/vmhgfs-only'
/usr/bin/make -C /lib/modules/3.8.0-21-generic/build/include/.. SUBDIRS=$PWD SRCROOT=$PWD/. \
      MODULEBUILDDIR= modules
make[1]: Entering directory `/usr/src/linux-headers-3.8.0-21-generic'
  CC [M]  /tmp/modconfig-LxeJ83/vmhgfs-only/backdoor.o
  CC [M]  /tmp/modconfig-LxeJ83/vmhgfs-only/backdoorGcc64.o
  CC [M]  /tmp/modconfig-LxeJ83/vmhgfs-only/bdhandler.o
  CC [M]  /tmp/modconfig-LxeJ83/vmhgfs-only/cpName.o
  CC [M]  /tmp/modconfig-LxeJ83/vmhgfs-only/cpNameLinux.o
  CC [M]  /tmp/modconfig-LxeJ83/vmhgfs-only/cpNameLite.o
  CC [M]  /tmp/modconfig-LxeJ83/vmhgfs-only/dentry.o
  CC [M]  /tmp/modconfig-LxeJ83/vmhgfs-only/dir.o
  CC [M]  /tmp/modconfig-LxeJ83/vmhgfs-only/file.o
  CC [M]  /tmp/modconfig-LxeJ83/vmhgfs-only/filesystem.o
  CC [M]  /tmp/modconfig-LxeJ83/vmhgfs-only/fsutil.o
  CC [M]  /tmp/modconfig-LxeJ83/vmhgfs-only/hgfsBd.o
  CC [M]  /tmp/modconfig-LxeJ83/vmhgfs-only/hgfsEscape.o
  CC [M]  /tmp/modconfig-LxeJ83/vmhgfs-only/hgfsUtil.o
  CC [M]  /tmp/modconfig-LxeJ83/vmhgfs-only/inode.o
/tmp/modconfig-LxeJ83/vmhgfs-only/inode.c: In function ‘HgfsTruncatePages’:
/tmp/modconfig-LxeJ83/vmhgfs-only/inode.c:888:4: error: implicit declaration of function ‘vmtruncate’ [-Werror=implicit-function-declaration]
cc1: some warnings being treated as errors
make[2]: *** [/tmp/modconfig-LxeJ83/vmhgfs-only/inode.o] Error 1
make[1]: *** [_module_/tmp/modconfig-LxeJ83/vmhgfs-only] Error 2
make[1]: Leaving directory `/usr/src/linux-headers-3.8.0-21-generic'
make: *** [vmhgfs.ko] Error 2
make: Leaving directory `/tmp/modconfig-LxeJ83/vmhgfs-only'

The filesystem driver (vmhgfs module) is used only for the shared folder
feature. The rest of the software provided by VMware Tools is designed to work
independently of this feature.

If you wish to have the shared folders feature, you can install the driver by
running vmware-config-tools.pl again after making sure that gcc, binutils, make
and the kernel sources for your running kernel are installed on your machine.
These packages are available on your distribution's installation CD.
[ Press Enter key to continue ]

The solution to this issue involves patching compat_mm.h to work with the 3.8 kernel:

cd ~
wget http://cdn.philbayfield.com/downloads/vmware-vmhgfs.patch
cd /usr/lib/vmware-tools/modules/source/
sudo tar xf vmhgfs.tar
cd vmhgfs-only/shared/
sudo patch -p1 < ~/vmware-vmhgfs.patch
cd ../..
sudo tar cf vmhgfs.tar vmhgfs-only

Finally, after adding any (or all) of these patches, just run vmware-config-tools.pl again and all should complete without issue.

Share