Tag Archives: mac

Use a Windows NTFS, or Linux, or other–formatted disk for Apple Time Machine Backups

It is well known that you have to use an Apple formatted disk (HFS+) for Time Machine Backups and you can’t use an NTFS formatted disk, or any of the preferred *nix disk formats with Time Machine.

Except you can.

Gotchas And Caveats

It’s not always a first choice option:

  • If your Windows drive is connected over USB2, it will be much slower than a Mac disk connected over Thunderbolt or FireWire. My first backup of 120GB took about 10 hours, aka all night. But that was still better than no backup whilst waiting for a new drive to arrive in the post.
  • The backup volume will not auto-mount when you plug the drive in. You must manually double-click the <YourMachineName>.sparsebundle in the Finder each time you plug the drive in. After that, Time Machine backups will run as normal.

Instructions

  • Plug in your foreign-formatted disk and get a read/write driver for it
  • Save the the script from tmMakeImage script in, for instance, your Downloads directory.
  • Open a terminal window.
  • If you saved to Downloads, then something like this should make the script executable and show you command line usage:
    cd ~/Downloads
    chmod a+x tmMakeImage
    mv tmMakeImage /usr/local/bin
    tmMakeImage
  • So if your external drive has a Volume called WinDrive, and your Mac drive is about 250GB then this command should initialise it for Time Machine backups:
    tmMakeImage 500GB /Volumes/WinDrive GO
  • Optionally, follow up with an immediate tmutil startbackup

Opening the Time Machine preferences should now show that you have “Time Machine Backups” selected as your backup drive. Don’t forget to double-click the sparsebundle each time you attach the drive, to mount your Backup Volume and allow Time Machine to do its stuff.

Background

Using Sparsebundles to create HFS+ formatted drive on a ‘foreign’ disk format

Apple created, it seems, sparse images and sparse bundles to solve the problem of saving backups on a network drive. Time Machine uses and recognises them. It will even auto-mount the sparsebundle disk image when you re-attach the drive in order to start running a backup.

Local drives and network drives

Most instructions on the web focus on network drives. Good instructions without any command-line stuff is here: http://www.hciguy.com/2010/06/16/using-time-machine-to-backup-your-mac-to-an-ntfs-drive-over-the-network-running-win-7/ For network drives, the sparsebundle name includes your Mac’s MAC address which it doesn’t need to for a locally-connected drive.

Things Under the Hood of Time Machine Disks

  • You can’t create a sparsebundle directly on a network or ‘foreign’ drive so the typical thing is to create it on your machine first, and then copy it to its final destination.
  • Sparsebundles don’t use up empty space. An sparsebundle declared as 500GB but still empty will only take up a few megabytes of real disk space.
  • A sparsebundle used by Time Machine has a com.apple.TimeMachine.MachineID.plist file in the package, which contains the UUID of the physical machine it belongs to. This stops you accidentally using backups on the ‘wrong’ machine. (Time Machine does let you browse and use ‘wrong’ backups though).
  • A Time Machine drive must have “Ignore ownership permissions” Off, whereas by default the Mac mounts external drives with “Ignore ownership permissions” set to On. This setting is not stored on the drive itself; it’s stored on your machine and can be specified each time the drive is mounted (man hdiutil) or specified permanently (man vsdbutil)
  • You can set the Time Machine destination to a sparsebundle on an attached drive by first mounting it then doing tmutil setdestination /Volumes/Volumenameonceitsbeenmounted. You mount the image either by double-clicking it in Finder, or with hdiutil attach /path/to/image.
  • Learn More:
    man tmutil
    man hdiutil
    man vsdbutil
    
  • You can still use your backup disks for other files alongside your Time Machine backups. Just don’t touch the Backups.backupdb folder! The Finder will protect it to some extent; it doesn’t let you modify things in there, but it will let you delete and add things.
  • The Script

    Most of the things in the tmMakeImage script can be found on the net going back to 2007, but you’ll still find recent answers on the internet saying it can’t be done.

Command line concatenate PDFs on OS X

A great post at http://gotofritz.net/blog/howto/joining-pdf-files-in-os-x-from-the-command-line/ which does what it says on the tin.

He explains how to link to a python script included in OS X since some years ago so as to make concatenating PDFs as easy as typing

pdfconcat -o output.pdf *.pdf

The heavy lifting is all done with calls to OS X Quartz.CoreGraphics module so this isn’t going to work on other platforms, but for the curious it demonstrates how easily you can do such stuff on OS X.

#! /usr/bin/python
#
# join
#   Joing pages from a a collection of PDF files into a single PDF file.
#
#   join [--output <file>] [--shuffle] [--verbose]"
#
#   Parameter:
#
#   --shuffle
#	Take a page from each PDF input file in turn before taking another from each file.
#	If this option is not specified then all of the pages from a PDF file are appended
#	to the output PDF file before the next input PDF file is processed.
#
#   --verbose
#   Write information about the doings of this tool to stderr.
#
import sys
import os
import getopt
import tempfile
import shutil
from CoreFoundation import *
from Quartz.CoreGraphics import *

verbose = False

def createPDFDocumentWithPath(path):
	global verbose
	if verbose:
		print "Creating PDF document from file %s" % (path)
	return CGPDFDocumentCreateWithURL(CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, path, len(path), False))

def writePageFromDoc(writeContext, doc, pageNum):

	global verbose
	page = CGPDFDocumentGetPage(doc, pageNum)
	if page:
		mediaBox = CGPDFPageGetBoxRect(page, kCGPDFMediaBox)
		if CGRectIsEmpty(mediaBox):
			mediaBox = None
			
		CGContextBeginPage(writeContext, mediaBox)
		CGContextDrawPDFPage(writeContext, page)
		CGContextEndPage(writeContext)
		if verbose:
			print "Copied page %d from %s" % (pageNum, doc)

def shufflePages(writeContext, docs, maxPages):
	
	for pageNum in xrange(1, maxPages + 1):
		for doc in docs:
			writePageFromDoc(writeContext, doc, pageNum)
				
def append(writeContext, docs, maxPages):

	for doc in docs:
		for pageNum in xrange(1, maxPages + 1) :
			writePageFromDoc(writeContext, doc, pageNum)

def main(argv):

	global verbose

	# The PDF context we will draw into to create a new PDF
	writeContext = None

	# If True then generate more verbose information
	source = None
	shuffle = False
	
	# Parse the command line options
	try:
		options, args = getopt.getopt(argv, "o:sv", ["output=", "shuffle", "verbose"])

	except getopt.GetoptError:
		usage()
		sys.exit(2)

	for option, arg in options:

		if option in ("-o", "--output") :
			if verbose:
				print "Setting %s as the destination." % (arg)
			writeContext = CGPDFContextCreateWithURL(CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, arg, len(arg), False), None, None)

		elif option in ("-s", "--shuffle") :
			if verbose :
				print "Shuffle pages to the output file."
			shuffle = True

		elif option in ("-v", "--verbose") :
			print "Verbose mode enabled."
			verbose = True

		else :
			print "Unknown argument: %s" % (option)
	
	if writeContext:
		# create PDFDocuments for all of the files.
		docs = map(createPDFDocumentWithPath, args)
		
		# find the maximum number of pages.
		maxPages = 0
		for doc in docs:
			if CGPDFDocumentGetNumberOfPages(doc) > maxPages:
				maxPages = CGPDFDocumentGetNumberOfPages(doc)
	
		if shuffle:
			shufflePages(writeContext, docs, maxPages)
		else:
			append(writeContext, docs, maxPages)
		
		CGPDFContextClose(writeContext)
		del writeContext
		#CGContextRelease(writeContext)
    
def usage():
	print "Usage: join [--output <file>] [--shuffle] [--verbose]"

if __name__ == "__main__":
	main(sys.argv[1:])

Compile & Build Mono on Mac OS X

In spite of what you might still read on http://www.mono-project.com/, mono source moved to github.com/mono/mono. To build and compile on the mac however the simplest instructions are still the “One Stop Shop Build Script” at the bottom of http://www.mono-project.com/Compiling_Mono_on_OSX. They worked for me first time although I hit a couple of issues:

  1. Having a space in the path to where I built it broke the build script
  2. Fetching the mono repo from git failed several times. This may – or may not – be related to the OS X 10.9 Mavericks / Versions issue noted at http://www.git-tower.com/blog/make-git-rebase-safe-on-osx/ but I’ve had no further problems since following their instruction to
    git config --global core.trustctime false

Asp.Net MVC 4 on Mono and Windows

Having at last got an Asp.Net Mvc 4 project template working on the Mac/Xamarin/Mono, I came to grief again when deploying it to a Windows hosted server. The problem is that whereas mono works without Microsoft.Web.Infrastructure.dll (and indeed is likely to give errors if you have it), for hosting on Windows you must re-include it.
So my deploy process now includes putting Microsoft.Web.Infrastructure.dll back in the web application bin/ directory; and now I can develop on the Mac and deploy to a Windows Server.

Equivalent of bash / shell aliases for Windows command line

Relief comes from an unexpected quarter if you pine for your unix command line shell aliases and other such:

doskey ls=dir $*

is what you want. you can put it in an autorun setting in your registry by pasting this into notepad and saving it as something.reg

Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\Software\Microsoft\Command Processor]
"AutoRun"="\"C:\\Program Files\\Commands\\CmdAutoRun.cmd\""

If you prefer to do it by hand rather than by double clicking a .reg file, you don’t need the extra quotes and escapes (but keep the outermost quotes):

"C:\Program Files\Commands\CmdAutoRun.cmd"

Note you use $* instead of %*. You can otherwise use $1-$9. Further escape codes are on the technet DosKey page