Recovering Deleted Files

| No Comments

Recently, I had one particular file that I’d been working on that got corrupted somehow. Unfortunately, I’d let my Time Machine backup lapse somewhat and so I didn’t have a backup.

Anyway, the file wasn’t very big but it would have taken me a little while to write it again so I tried another way of getting the file back. I knew that Xcode uses atomic saves (it writes a new file and then uses a rename) so I figured, so long as I don’t write too much to the disk, there should be an old copy somewhere on the disk. Searching the entire disk would have been tedious though, so I wrote a quick program that creates a file on a volume that uses up all the free space. If you do this by conventional means, you’ll end up with a file full of zeros, but thankfully, OS X comes with the F_SETSIZE fcntl which allows you to set the size of a file without setting the contents. Here’s the code:

#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <stdint.h>
#include <err.h>

int main (int argc, char *argv[])
{
  int fd = open (argv[1], O_CREAT | O_RDWR, 0666);

  uint64_t size = 4096;

  for (;;) {
    if (fcntl (fd, F_SETSIZE, &size)) {
      if (errno == ENOSPC)
        break;
      else
        err (1, "fcntl failed\n");
    }
    size *= 2;
  }

  uint64_t high = size;
  uint64_t low = size / 2;

  while (high > low + 1) {
    size = low + (high - low) / 2;
    if (fcntl (fd, F_SETSIZE, &size)) {
      if (errno != ENOSPC)
        err (1, "fcntl failed");
      high = size;
    } else
      low = size;
  }

  printf ("done: %llu\n", size);

  return 0;
}

Obviously, you want to run this whilst booted from another volume and you have to run it as root.

So then it was a simple case of firing up HexFiend which I happen to know has pretty fast search and I managed to find my file.

Amazon's Silk Browser

| No Comments

From Amazon’s FAQ:

What about handling secure (https) connections?

We will establish a secure connection from the cloud to the site owner on your behalf for page requests of sites using SSL (e.g. https://siteaddress.com). 

Amazon Silk will facilitate a direct connection between your device and that site.  Any security provided by these particular sites to their users would still exist

This sounds a bit ambiguous. Are they or are they not acting as middle men? They might not be as it looks like they’re not using HTTP.

If this is true, I think there’s going to be a huge backlash against this. People simply won’t tolerate them being able to see your private traffic. What happens when a law enforcement agency asks for access? My money is on them changing this before they ship.

errno

| 1 Comment

errno is a macro on OS X and expands to this:

#define errno (*__error())

The reason for this is for thread safety. That means that in the debugger, if you want to see what the current value of errno is, you can type:

p *(int *)__error()

It’s important to remember that if you’re using errno, any system call can reset it. The following code is broken:

NSLog (@"errno: %d", errno);
if (errno == EIO)
  ...

The call to NSLog can, and probably will, reset errno. On 10.6 calls to the free library function (which NSLog can call) will usually reset errno to 2 (ENOENT), so bear this in mind if you’re seeing an errno value of 2 when you wouldn’t expect it.

As a consequence of this, you cannot single step through code in Xcode when you have “Use Data Formatters” checked, and expect errno to be preserved. You will find in many cases errno is reset to 2. In fact, I would recommend turning off “Use Data Formatters”—they cause many problems. Hopefully lldb will bring a non-invasive method of inspecting variables.

Was this post born from bitter experience? Yes it was.

Compile Time Checks

| 1 Comment

Here’s a handy macro you can use to do compile time checks:

#define CHECK__(line, x) typedef char check_##line##_[(x) ? 1 : -1];
#define CHECK_(line, x) CHECK__(line, x)
#define CHECK(x) CHECK_(__LINE__, (x))

You’ll get a compiler error if the check is false. Obviously the condition needs to be something the compiler can figure out at compile time. You might use it like this:

#pragma pack(push, 1)
struct x {
  uint8_t  a;
  uint32_t b;
};
#pragma pack(pop)

CHECK (sizeof (struct x) == 5)

I use it to check sizes of structures that have to match a protocol or format, for example, on disk structures that you know are supposed to be 512 bytes in size.

Static Analyser Invariants

| No Comments

If you’re not using the Static Analyser, you should be. However, sometimes you need to give it a helping hand in order to avoid false positives. Mostly you can use assert to tell the analyser that a certain path is impossible. The problem with that is that it will usually add code to your built product. You could avoid this by defining the NDEBUG macro in your release build but I don’t like to do that (and it isn’t by default); I prefer to leave assertions in my release build. Anyway, here’s some code you can use to do the same thing as assert but won’t add any extra code to your built product. You’d use this instead of assert when it might affect performance and is also obviously always true.

#if __clang__

static void inline static_analyser_no_return (void) 
  __attribute__ ((analyzer_noreturn));

static void inline static_analyser_no_return (void) {}

/* Use this to shut the analyser up without actually adding any code. */

#define static_analyser_invariant(cond) \
  do { if (!cond) static_analyser_no_return (); } while (0)

#else

#define static_analyser_invariant(cond) ((void)0)

#endif

Unsupported iPhone Applications

| No Comments

Mike Ash just posted a list of applications he can’t have on his iPhone. I think that most of his examples are cases where a suitable API doesn’t exist, rather than it being expressly forbidden by Apple. I’m sure there are some applications that are not currently possible on OS X due to lack of a suitable API. I remember that Disk Arbitration (a framework we use for our products) wasn’t made public until 10.4. Another example is Flash Player 10 on OS X; it’s my understanding that the performance improvements are because of an API being made available that wasn’t before.

The iPhone is still relatively new and I’m guessing that they’re fairly busy over at Apple HQ so something has to give. I can’t think of a reason why Apple wouldn’t eventually want to add the APIs to make all his applications possible.

Don’t get me wrong, I don’t particularly like the restrictive nature of the App Store. I actually think it would be nice if there was a mode you could put your iPhone into that disabled many of the restrictions—in this mode you could do whatever you like, e.g. load non-Apple sanctioned applications on your phone, but obviously, in this mode you’d be on your own if something went wrong.

NSURLConnection & Using HEAD Method

| No Comments

If you want to use the HEAD method with NSURLConnection, it’s simple, you use -[NSMutableURLRequest setHTTPMethod:].

However, you need to be careful with redirects. Redirections will revert to using the GET method which usually isn’t what you want, so you need something like:

- (NSURLRequest *)connection:(NSURLConnection *)connection
             willSendRequest:(NSURLRequest *)request
            redirectResponse:(NSURLResponse *)redirectResponse
{
    if ([[request HTTPMethod] isEqualTo:@"HEAD"])
        return request;

    NSMutableURLRequest *newRequest = [request mutableCopy];
    [newRequest setHTTPMethod:@"HEAD"];

    return [newRequest autorelease];
}

I suspect that this bug report is invalid: http://openradar.appspot.com/7019347.

x86_64 Assembler

| No Comments

I’m OK at deciphering PowerPC assembler and i386 assembler but now it’s all x86_64. If you’re having a look at the internals of AppKit in x86_64, you need to print out page 21 of this: http://www.x86-64.org/documentation/abi.pdf and stick it on your wall next to your C operator precedence table.

Now wherever you see objc_msgSend (or something similar), the selector gets passed in $rsi. To find out what it is, type:

p (char *)sel_getName($rsi)

x86_64 comes with instruction pointer relative addressing so you might notice that gdb helpfully displays what the target address is wherever it’s used. So if you’re looking at some assembler that looks like this:

0x00007fff811f33fc <-[NSTableView reloadData]+115>: mov -0x10f16b8b(%rip),%rsi # 0x7fff702dc878
0x00007fff811f3403 <-[NSTableView reloadData]+122>: mov %rbx,%rdi
0x00007fff811f3406 <-[NSTableView reloadData]+125>: callq 0x7fff8184278e <dyld_stub_objc_msgSend>

You can figure out what the call is by typing:

p (char *)sel_getName(*(void **)0x7fff702dc878)

And you’ll see something like:

$2 = 0x7fff8187bb68 "_endMyEditing"

Attempt to Pop an Unknown Autorelease Pool

| No Comments

If you see:

*** attempt to pop an unknown autorelease pool (0x12345678)

You can debug it by setting a breakpoint in the _CFAutoreleasePoolPop function. To find out exactly where, disassemble the _CFAutoreleasePoolPop function, and look for the first call to CFLog. On the i386 architecture it’s at _CFAutoreleasePoolPop+84.

_Block_dump

| No Comments

If you’re playing with blocks you can get debug information by using:

char *_Block_dump (block_t block);

It’s not in any public header so you’ll have to declare it yourself. It returns a debug string you can log and will give you the retain count of the block, whether it’s a global, stack or heap block and other information.