Skip navigation

Monthly Archives: February 2012

The task:

I wanted to make a copy of a DCIM folder, copying it from my Kaylee, my desktop machine to Inara, my HTPC. While it’s not the fastest approach, SSH is reasonably quick, unattended, especially if you tune a few parameters in sshd_config, such as prioritizing block ciphers, and in ~/.ssh/config, such as disabling compression when you know the data’s going to be moving across a local gigabit network.

Now, I rather like Midnight Commander. If you grew up on DOS appreciating Norton Commander, you’d probably like it, too. Midnight Commander supports file transfer and browsing over SSH, complete with progress meters and the like. That makes it a generally handy tool for this kind of thing.

The error:

So I ssh’d to my desktop box from a screen session on my HTPC, launched mc, and told it to connect to Kaylee. Then I selected a relatively small folder, DCIM. This particular DCIM directory was only two gigabytes or so.  This was after an earlier aborted attempt to copy some files over; I had to run a quick errand. So when it prompted me whether or not I wanted to overwrite, I told it, All.

I wasn’t happy with my transfer rate, so I aborted, deleted my target directory, and went to try again.

Did you see what I did wrong there?

I connected to Kaylee, launched mc, told mc to connect to Kaylee, and then told it to copy a folder to itself, via SSH link. So I was, file by file, overwriting every file in that DCIM folder. And then I aborted halfway through a transfer. And then I compounded the error by deleting the file. So I deleted 2GB of photos.

The recovery:

A quick search on DuckDuckGo for ext4 undelete turned up extundelete, which turns out to be exactly the tool I needed. One minor rub: the tool requires the filesystem to be unmounted.

So, after killing all the processes using files on the filesystem my home directories happen to sit on, I ran

mount -t ext4 -o remount,ro /dev/device-node /path/to/mount/point

to remount the filesystem read-only. Then I ran the tool. It worked flawlessly, and I got my photos back.

So I have a scenario where this guy’s question might apply. He’s looking to pack resources in with a .lib file, but that simply won’t work, as the file format doesn’t allow for it.

Thing is, my .lib is compiled in the same build sequence as the application it’s supposed to be pulled into, so perhaps I have a little more leeway. A couple things I’ve discovered:

  • It doesn’t matter if you completely hose the syntax inside of one of a .rc file’s TEXTINCLUDE sections. Failures in there will not propagate out and indicate a build failure; your app will compile fine, but you won’t have any resources.
  • Similarly, if you mess up the path to a .rc file you’d like to include, again, build errors won’t propagate out; you’ll just be missing the resources from that file.

Both of these mean that Roger Lipscombe’s 3rd solution, and jeff_t’s elucidation of that approach are very error prone. Even if you get it to work, it’ll likely take you a while to get it right, and you won’t know until you inspect the contents of of your resulting .DLL or .EXE module to see if the resources you’re looking for made it in. Maybe you can do that in a post-build step, but now we’re layering on more complexity, so we look somewhere else.

To take a different tact, you could add the path to your .res file to your main project’s linker options’ additional include directories, and then add your .res file to your inputs for that linker instance. In the past, I’ve found that approach to be error prone; if you have a bunch of project configurations, you need to make sure that that’s applied across all of them. That’s an additional step, which is an additional opportunity for error, and that particular error has bit me many times in the past. So we look somewhere else.

Another approach might be to try using #pragma comment(lib, “library.res”) and #pragma comment(linker, “/INCLUDE:path/to/library/”), surrounded by an IFDEF guard, in one of the headers that gets pulled into your main project. Except while the above approach works great with your .lib file, and while you can put .lib and .res files next to each other under inputs in your project’s linker settings, the above approach won’t work with your .res file. You get another silent error.

There’s really no good solution to pulling in .res files; they don’t have semantic parity with the same features and mechanisms that can pull in .lib files, despite some superficial similarities in their linking semantics. And everything that doesn’t work is a silent failure, until your program fails to find a resource at run time.