How to mount lost partitions from a disk image without repairing

I came across a hard disk with a corrupted MBR. In other words, I found a hard disk that lost all of its partitions but files and folders are still there. Tool of my choice in this kind of cases is TestDisk.

Instead of repairing the disk directly, I took an image of the whole disk using “dd” because backup is important.

$ sudo dd if=/dev/sdb of=/data/sdb.img
$ sudo chmod -w /data/sdb.img

TestDisk’s quick analysis indicated two partitions, but deep analysis indicated more. This is what led me to experiment with the disk image first before repairing it. I wanted to try read-only mounting these lost partitions without repairing the disk or image. I chose not to repair so I could reuse the same image over and over for experimentation.

As I learned from various sources, here’s how to mount a single partition from a disk image.

$ sudo fdisk -lu /data/sdb.img    # find sector size and partition start boundaries
$ sudo mount -o loop,ro,offset=n /data/sdb.img /mnt    # where n = sector size * start boundary

This works for healthy disks. But when there’s no partitioning information? fdisk utility has nothing to show.

Well, we can get that information from TestDisk. But you’ll need to do some math because TestDisk uses CHS notation to show partition boundaries instead of sectors.

Here’s an example ‘testdisk-detected’ partition table (interesting information in bold text):

Disk /data/sdb.img - 320 GB / 298 GiB
 CHS 38914 255 63 - sector size=512
Disk /data/sdb.img - 320 GB / 298 GiB - CHS 38914 255 63
     Partition               Start        End    Size in sectors
>D HPFS - NTFS              0   1  1  6373 254 63  102398247
 D HPFS - NTFS           6373 166  1 19121 224 63  204800337
 L HPFS - NTFS          19121 226  1 38911 254 63  317928177

I learned that we need to convert CHS to LBA using the formula explained here.

(C * TH * TS) + (H * TS) + (S - 1) = LBA
where TH = Total heads, and TS = Total Sectors

With that, let’s simplify the formula specifically for our case…

(C * 255 * 63) + (H * 63) + (S - 1) = LBA
16065 * C + 63 * H + S - 1 = LBA
Since S = 1 for all partitions,

16065 * C + 63 * H = LBA

Let’s try mounting the third partition:

Start sector LBA    = 16065 * 19121 + 226 * 63
                    = 307178865 + 14238
                    = 307193103
Offset in bytes (n) = 307193103 * 512
                    = 157282868736

Here we go… 3…… 2….. 1……

$ sudo mount -o loop,ro,offset=157282868736 /data/sdb.img /mnt

That worked! 🙂 I’m sure this post will be useful for anyone who’s learning digital forensics.


[JIRA] Behaviours: Restricting an initializer by workflow

I had this problem when I was writing an initializer script for one of the custom fields in my JIRA instance.

This initializer is expected to work on projects of a certain JIRA workflow. It is also expected to work for all workflow actions including “Create”. Because this behaviour is expected to run at issue creation as well, finding the workflow object through ‘underlyingIssue’ object (which is null at the time of issue creation) wasn’t helpful.

Here’s the pseudo-code:

if (currentWorkflow = "My new workflow") {
    // execute the behaviour

Why? Custom field contexts isn’t helpful when working with over hundreds of projects. Every time a project is onboarded to my new workflow, it’s a hassle to configure appropriate custom field context for the project too.

So here’s the workaround I found:

import com.atlassian.jira.component.ComponentAccessor

if (! ( getAction() in ComponentAccessor.workflowManager.getWorkflow("My new workflow").allActions )) return
// if current action doesn't belong to my new workflow, then return and do nothing

I hope if Adaptavist could bundle a ‘getWorkflow()’ function to retrieve workflow information other than action and step details when using initializers.

[JIRA] Dev – Where are OSWorkflow Transition Screens?

Found a piece that isn’t well documented. But as usual, I’m explaining my steps and then the solution. It’s no real big deal anyway. 🙂

Here’s the background:
Mission was to write a Groovy script that returns all the transition screens used across all workflows of a given JIRA workflow scheme (for documentation purposes). This looked pretty easier, until a collection of ‘com.opensymphony.workflow.loader.ActionDescriptor’ came up without any linked JavaDocs. That looked like a dead end.

Then, with a little bit of googling I came across ActionDescriptor source code, which wasn’t helpful either. getView() method looked promising because ‘Transition View’ is a synonym used in JIRA UI for ‘Transition Screen’. But disappointingly it was just returning string ‘fieldscreen’ for every transition. Aw.. snap! 😦

Next attempt is called the ‘Bruteforce method’ (not java.lang.reflect.Method of course 😉 ).

Since I was too lazy to read across the ActionDescriptor’s source code:

// workflow is type of com.atlassian.jira.workflow.JiraWorkflow
// I'm not explaining all my code here
workflow.getAllActions().each {
  it.class.getDeclaredMethods().grep { "^get.*" )
  }.each {
    log.debug ( )

It didn’t took much of time. With a bit of guessing I made my first attempt with getter method ‘getMetaAttributes()’. And it had the eye-catching piece I was looking for!

workflow.getAllActions().each {
  log.debug ( it.getMetaAttributes().toString() )
[opsbar-sequence:10, jira.description:,]
[opsbar-sequence:20, jira.description:,]
[opsbar-sequence:40, jira.description:,]
[opsbar-sequence:60, jira.description:,]

getMetaAttributes() returns a HashMap. So, finally…

def screens = [:]
workflow.getAllActions().each {
  def screenId = it.getMetaAttributes()[""]
  if ( screenId != "" ) {
    def workflowAction = + " - " +
    def workflowActions = []
    if ( screens[screenId] ) workflowActions = screens[screenId]
    workflowActions.add ( workflowAction )
    screens[screenId] = workflowActions
for ( e in screens ) {
  log.debug ( "Transition Screen: " + e.key )
  e.value.each {
    log.debug ( "  Workflow action: " + it )

Nice! This HashMap (‘screens’) is all what I wanted. 🙂 Each transition screen, and then where it has been used.

So one last thing… I also wanted to have a one last peek into ActionDescriptor’s source code on GitHub. Only the writeXML() method gave an indication that metaAttributes is actually a HashMap. There was absolutely no indication that screen association information is kept as a ‘meta attribute‘.

Bottom line(s):

  1. If you are a JIRA developer and whenever you want to find screens associated to a workflow, don’t use getView(). Use getMetaAttributes() and then look for the attribute with key “”. In other words, transition screen is stored as a meta attribute in each transition. Screen is referred by its numeric ID as a string.
  2. Since OpenSymphony doesn’t seem to go away from JIRA, and some already claim that OpenSymphony is dead, it would be worthwhile if Atlassian maintains their own repository of OSWorkflow docs and special remarks.

පුහු මිම්ම

මේක කැම්පස් එකේ දෙක වසර කාලෙ විනාඩි දෙකතුනක ඉතාම සුළු සිද්ධියක්. හැබැයි ඒ පාඩම ජීවිත කාලෙටම මතක තියෙයි.

දවසක් මම බවනේ ලැප්ටොප් එකත් දිග ඇරන් වඩයක් කකා ඉන්නකොට, කැෂුවල් ෂර්ට් එකක් කලිසමට යට නොකර ඇඳලා සැන්ඩ්ල්ස් දෙකකුත් දාගෙන ආපු මනුස්සයෙක් එනවා මං වාඩිවෙලා හිටි මේසෙටම. එන්නේ අලියා බීම බෝතලේකුත් අතේ තියාගෙන. පෙනුමින්, මොකක් හරි පොඩි අවශ්‍යතාවයකට කැම්පස් එකට ආපු කෙනෙක් වගේ තමයි පෙනුණේ – අපේ බැචෙකුගෙ හරි ජුන්නෙකුගෙ හරි තාත්ත කෙනෙක්වත්ද? අපි අතර වචන කීපයයි හුවමාරු වුණේ,

“Mind if I sit here?”

“Sure, no problem.”

මම ඒ මනුස්සයා දිහා නොබල මගේ වැඩේ කරගත්තා, ඒ මනුස්සයා බීම එක බීල යන්න ගියා. ඊට පස්සෙ තමයි සින්නෙක් කිට්ටු කලේ මා ගාවට.

“මල්ලි උඹ දන්නවද අර බීම එක බීල ගිය මනුස්සය කවුද කියල?”

“නෑ, මොකක්ද special?”

“යකෝ ඒ ඇමරිකාවෙ යුනි එකක ප්‍රොෆෙසර් කෙනෙක්. සති දෙකකට ලංකාවට ඇවිත් මෙහේ ලෙක්චර්ස් වලට. හිතන්න පුළුවන්ද දැක්කම?”

පොඩි වෙලාවකට තුෂ්ණිම්භූත වුණු මම, යටිහිතින් කල්පනා කළා… “හොඳ වෙලාවට මගේ හැසිරීමෙන් වරදක් වුණේ නැහැ”. ඒ මනුස්සයගෙ ආචාරශීලී ගතියෙන්වත් මට යමක් නොදැනුණු හැටි!

මේ පුංචි කතාව මට මතක් වුණේ මෑතකදි මම ගැන වැඩිහිටි දෙපාර්ශ්වයක් අතර වෙච්ච පුංචි කතා බහක් මට ආරංචි වුණු නිසා.

“ඒ ළමය සොෆ්ට්වෙයාර් ඉංජිනියර් කෙනෙක්”

“වෙන්න බෑ බලන්නකො තට්ටෙයි රැවුලෙයි හැටි තම්බියෙක් වගේ.”

“ඒ ළමයට කාර් එකක්වත් නැහැනෙ.”

වේලිච්ච ඉරටු නවන්න බැරිව ඇති. හැබැයි “ටිපිකල් ශ්‍රී ලංකන්” පටු සිතිවිලි වලින් අපිවත් මිදෙමු.

[Linux] Tip for heavy users of Ctrl + R

After a lengthy JIRA tip, I’m about to blog a Keyboard Ninja tip for users who do a lot of Ctrl + R thingy to navigate Bash history.

This came up when I didn’t want to use a session manager like PAC but rely on Bash history. I have a server IP address and SSH access.

So, instead of doing just ssh -v thing, I do this:

ssh -v #jirauat

Those who are familiar with scripting know this: Whatever you type after the hash sign won’t effect, because Bash interprets that as a comment. However, Bash history records the complete line.

Later, I don’t have to remember the IP address, but, when I type Ctrl + R followed by jirauat, it comes up quickly. Just hit Enter!

(reverse-i-search)`jiraua': ssh -v #jirauat

And that’s how you easily save few keystrokes plus an additional minute without having to recall numbers.