Skip to content

Instantly share code, notes, and snippets.

@lobeck
Last active March 10, 2016 02:07
Show Gist options
  • Save lobeck/033040abd74e44cce9c4 to your computer and use it in GitHub Desktop.
Save lobeck/033040abd74e44cce9c4 to your computer and use it in GitHub Desktop.
how to lock a TimeMachine sparsebundle on a linux host eg. when using netatalk
this is the actual syscall made by netatalk:
fcntl(7, F_SETLK, {type=F_WRLCK, whence=SEEK_SET, start=9223372036854775799, len=1} ) = 0
// the same in golang (shortened version)
fileHandle, err := os.OpenFile(msg.Filename, os.O_RDWR, 0)
if err != nil {
panic(err)
}
// F_SETLKW => blocking
// F_SETLK => non blocking
err = syscall.FcntlFlock(fileHandle.Fd(), syscall.F_SETLKW, &syscall.Flock_t{Start: 9223372036854775799, Len: 1, Type: syscall.F_WRLCK, Whence: int16(os.SEEK_SET)})
if err != nil {
log.Println(err)
}
fmt.Println("File locked")
# -*- coding: utf-8 -*-
import os, sys
import pprint
import fcntl
# open and get a FD for the file
fd = os.open( "{}/token".format(sys.argv[1]), os.O_RDWR)
# set a exclusive lock - do this nonblocking (LOCK_NB) to either get the lock or fail hard
# if the sparsebundle is mounted at this time, a exception will be thrown
# the start position is taken from the actual netatalk syscall in this case, an explanation for this might be 8 * 1024^6 => 8 EB => HFS+ file size limit
# fcntl.lockf(fd, fcntl.LOCK_EX | fcntl.LOCK_NB, 1, 9223372036854775799, 0)
fcntl.lockf(fd, fcntl.LOCK_EX, 1, 9223372036854775799, 0)
# note: this kind of lock will keep TimeMachine in a endless? loop, it's retrying the backup every 60 seconds until it can get the lock
# this isn't the way TimeMachine does it's internal locking but at least it prevents it from doing anything
# if you now try to mount the sparsebundle, you'll get the "Resource unavailable" message
print raw_input("Press Enter to release the lock")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment