Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[patch] automatic device finding on Mac and Linux #27

Open
RJVB opened this issue Sep 16, 2018 · 1 comment
Open

[patch] automatic device finding on Mac and Linux #27

RJVB opened this issue Sep 16, 2018 · 1 comment

Comments

@RJVB
Copy link

RJVB commented Sep 16, 2018

Currently hfsinspect will find the device a file is on automatically only on BSD. The author seems to have missed the fact that Apple's Darwin is a BSD variant, and indeed the code works just fine there (on 10.9 at least). Fortunately, because for me the manual specification didn't work.

Linux doesn't have a single syscall that returns the required information, but one can parse the output from df -h.

Here's a patch (corrected):

diff --git a/src/hfsinspect.c b/src/hfsinspect.c
index fb380bf..019724a 100644
--- a/src/hfsinspect.c
+++ b/src/hfsinspect.c
@@ -14,6 +14,9 @@
 #if defined(BSD)
     #include <sys/mount.h>     //statfs
 #endif
+#ifdef __linux__
+    #include <ctype.h>
+#endif
 
 #include "logging/logging.h"   // console printing routines
 #include "volumes/volumes.h"
@@ -69,13 +72,13 @@ char* deviceAtPath(char* path)
 
 bool resolveDeviceAndPath(char* path_in, char* device_out, char* path_out)
 {
-#if defined(__BSD__)
     char* path = realpath(path_in, NULL);
     if (path == NULL) {
         die(1, path_in);
         return false;
     }
 
+#if defined(__BSD__) || defined(__APPLE__)
     struct statfs stats;
     int           result = statfs(path_in, &stats);
     if (result < 0) {
@@ -110,6 +113,60 @@ bool resolveDeviceAndPath(char* path_in, char* device_out, char* path_out)
     debug("Path out: %s", path_out);
 
     return true;
+#elif defined(__linux__)
+    bool ret = false;
+    char *command = NULL;
+    int comlen = asprintf(&command, "df -h \"%s\" | tail --lines=1", path_in);
+    FILE *fp = comlen > 0 ? popen(command, "r") : NULL;
+    if (fp) {
+        char buf[PATH_MAX * 3], *s = buf;
+        if (fgets(buf, sizeof(buf), fp) == buf) {
+            char *d = device_out;
+            s = buf;
+            while (*s && !isspace(*s)) {
+                *d++ = *s++;
+            }
+            if (isspace(*s)) {
+                *d = '\0';
+            } else {
+                warning("%s: failure reading mount device from \"%s\"", __FUNCTION__, buf);
+                device_out[0] = '\0';
+            }
+            s = strstr(buf, "% /");
+            if (s) {
+                char* mountPoint = &s[2];
+                size_t len = strlen(mountPoint);
+                if (len > 0 && mountPoint[len-1] == '\n') {
+                    mountPoint[len-1] = '\0';
+                    len -= 1;
+                }
+                if (strncmp(mountPoint, "/", PATH_MAX) != 0) {
+                    // Remove mount point from path name (rather blindly, yes)
+                    d = &path[len];
+                    (void)strlcpy(path_out, &path[len], PATH_MAX);
+                } else {
+                    (void)strlcpy(path_out, path, PATH_MAX);
+                }
+                free(path);
+                ret = true;
+            } else {
+                warning("%s: failure reading mountPoint from \"%s\"", __FUNCTION__, buf);
+                path_out[0] = '\0';
+            }
+        } else {
+            perror(command);
+        }
+        pclose(fp);
+        debug("Path in: %s", path_in);
+        debug("Device out: %s", device_out);
+        debug("Path out: %s", path_out);
+    } else {
+        perror(command ? command : path_in);
+    }
+    if (comlen) {
+        free(command);
+    }
+    return ret;
 #else
     warning("%s: not supported on this platform", __FUNCTION__);
     return false;
@RJVB
Copy link
Author

RJVB commented Sep 16, 2018

my bad, I had read the code too quickly. Patch fixed.

Here's the output on a decmpfs (HFS) compressed file mounted under linux (where its size shows up as 0 because all content is in the resource fork):

# HFSX Volume Format (v5)
  volume name            = VMs
  case sensitivity       = case sensitive
  bootable               = no

# Record ID 0 (1/22) (length: 304) (Node 45171)
  Catalog Key
  +-----------------------------------------------------------------------------------+
  | length | parentID   | length | nodeName                                           |
  | 54     | 1605764    | 24     | qdockarealayout.cpp.orig                           |
  +-----------------------------------------------------------------------------------+

  recordType             = kHFSPlusFileRecord
  flags                  = 000000001000011
  record->flags          = kHFSThreadExistsMask (2)
  record->flags          = kHFSHasAttributesMask (4)
  record->flags          = kHFSHasDateAddedMask (128)
  reserved1              = 0
  fileID                 = 18239046
  createDate             = Mon 13 Aug 2018 21:43:41 GMT
  contentModDate         = Mon 13 Aug 2018 21:43:41 GMT
  attributeModDate       = Mon 13 Aug 2018 22:09:19 GMT
  accessDate             = Fri 07 Sep 2018 21:15:40 GMT
  backupDate             = Thu 01 Jan 1970 00:00:00 GMT
  ownerID                = 505
  groupID                = 80
  adminFlags             = 0000000 (0)
  ownerFlags             = 0000040 (32)
                         . 00040 compressed
  fileMode               = -rw-r--r--
  fileMode               = 0100644 (33188)
  mode & S_IFMT          = 0100000 (S_IFREG)
  mode                   = 0000400 (S_IRUSR)
  mode                   = 0000200 (S_IWUSR)
  mode                   = 0000040 (S_IRGRP)
  mode                   = 0000004 (S_IROTH)
  special.linkCount      = 1
  
  # Finder Info
    fdType                 = 0x00000000 ()
    fdCreator              = 0x00000000 ()
    fdFlags                = 000000000000000
    fdLocation             = (0, 0)
    opaque                 = 0
  textEncoding           = 0
  reserved2              = 0
  
  # Data Fork
    fork                   = data
    logicalSize            = (empty)
  
  # Resource Fork
    fork                   = resource
    logicalSize            = 19.25 KiB (19716 bytes)
    clumpSize              = 0.00 bytes
    totalBlocks            = 20.00 KiB (5 blocks)
    extents                =   startBlock   blockCount    % of file
                           =     13833415            5       100.00
                           = --------------------------------------
                           =    1 extents            5       100.00
                           = 5.00 blocks per extent on average.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant