Example #1
0
/* Debug code for printing entries in the CFDictionary 'userInfo'. */
static void PrintDictEntry(const void *key, const void *value, void *context) {
  char *tmp = NULL;
  char *buffer = calloc(1, 512);
  
  CFStringGetCString(key, buffer, 512, kCFStringEncodingUTF8);
  LOG_DEBUG("    Key:\n");
  LOG_DEBUG("      \"%s\"", buffer);

  CFStringGetCString(value, buffer, 512, kCFStringEncodingUTF8);
  LOG_DEBUG("    Value:\n");
  LOG_DEBUG("      \"%s\"\n", buffer);
  LOG_DEBUG("    Hex:\n");
  LOG_DEBUG("      ");
  for(tmp = buffer; *tmp != '\0'; ++tmp)
    LOG_DEBUG(" %s%hhX", ((*tmp & 0xFF) < 0x10 ? "0" : ""), *tmp);
  LOG_DEBUG("\n");

  GetCorruptedMacFUSEStringAsUTF8(value, buffer, 512);
  LOG_DEBUG("    Value (de-corrupted):\n");
  LOG_DEBUG("      \"%s\"\n", buffer);
  LOG_DEBUG("    Hex (de-corrupted):\n");
  LOG_DEBUG("      ");
  for(tmp = buffer; *tmp != '\0'; ++tmp)
    LOG_DEBUG(" %s%hhX", ((*tmp & 0xFF) < 0x10 ? "0" : ""), *tmp);
  LOG_DEBUG("\n");

  free(buffer);

/*   FILE *dbgoutput = fopen("valuedump-utf32be.txt", "w"); */
/*   memset(buffer, 0, 512); */
/*   CFStringGetCString(value, buffer, 512, kCFStringEncodingUTF32BE); */
/*   fwrite(buffer, 512, 1, dbgoutput); */
/*   fclose(dbgoutput); */
}
Example #2
0
/* Debug code for printing entries in the CFDictionary 'userInfo'. */
static void PrintDictEntry(const void *key, const void *value, void *context) {
  char buffer[512];
  CFStringGetCString(key, buffer, 512, kCFStringEncodingUTF8);
  DEBUG("    Key: \"%s\"", buffer);
  GetCorruptedMacFUSEStringAsUTF8(value, buffer, 512);
  DEBUG(", Value: \"%s\"\n", buffer);
/*   FILE *dbgoutput = fopen("valuedump-utf32be.txt", "w"); */
/*   memset(buffer, 0, 512); */
/*   CFStringGetCString(value, buffer, 512, kCFStringEncodingUTF32BE); */
/*   fwrite(buffer, 512, 1, dbgoutput); */
/*   fclose(dbgoutput); */
}
Example #3
0
int main(int argc, char** argv) {
  if(argc < 4) {
    PrintUsage(stdout);
    return 0;
  }
  
  /* <argv parsing> */
  
  /* Parse argument: mountpoint (CFString) */
  /*CFStringRef mountpoint = CFStringCreateWithCString(kCFAllocatorDefault, 
    argv[1], kCFStringEncodingUTF8); */
  /* Parse argument: mountpointRaw (char*) */
  char *mountpointRaw = argv[1];
  
  /* Parse argument: timeout (double) */
  double timeout;
  {
    CFStringRef timeoutString = CFStringCreateWithCString(kCFAllocatorDefault, 
							 argv[2], kCFStringEncodingUTF8);
    timeout = CFStringGetDoubleValue(timeoutString);
    CFRelease(timeoutString);
    if(timeout == 0.0) {
      fprintf(stdout, "Invalid argument: timeout (\"%s\"", argv[2]);
      return -1;
    }
  }
  
  /* Parse argument: mount_command */
  const char *mount_command = argv[3];
  
  /* </argv parsing> */
 
  CFNotificationCenterRef centerRef;
  CFStringRef notificationObjectName = CFSTR(FUSE_LISTEN_OBJECT);
  CFStringRef notificationName = CFSTR(FUSE_MOUNT_NOTIFICATION_NAME);
  CFRunLoopRef crl;
  
  if(DEBUGMODE) {
    DEBUG("Testing NotificationCallback...\n");
    NotificationCallback(NULL, NULL, notificationObjectName, NULL, NULL);
    DEBUG("Test completed. Adding observer...\n");
  }
  
  centerRef = CFNotificationCenterGetDistributedCenter();
  crl = CFRunLoopGetCurrent();
  
  /* Think. Will the child process also be an observer? I don't think so... */
  CFNotificationCenterAddObserver(centerRef, NULL, NotificationCallback, notificationName,
				  notificationObjectName, CFNotificationSuspensionBehaviorDrop);
    

  int forkRetval = fork();
  if(forkRetval == -1) {
    fprintf(stderr, "Could not fork!\n");
    return -1;
  }
  else if(forkRetval != 0) {
    // Parent process
    int childProcessPID = forkRetval;

    int waitpid_status = 0;
    DEBUG("Waiting for PID %d...\n", childProcessPID);
    int waitpidres = waitpid(childProcessPID, &waitpid_status, 0);
    if(waitpidres == childProcessPID) {
      if(!WIFEXITED(waitpid_status)) {
	DEBUG("Child process did not exit cleanly! Returning -1.");
	return -1;
      }
      
      int retval = WEXITSTATUS(waitpid_status);
      DEBUG("PID %d returned with exit code: %d Exiting fuse_wait with this exit code...\n", childProcessPID, retval);
      if(retval != 0) {
	DEBUG("Exit value indicates an error while executing mount command. Returning without\n");
	DEBUG("waiting for notification.\n");
	DEBUG("Returning retval: %d\n", retval);
	return retval;
      }
    }
    else {
      DEBUG("Abnormal termination of process %d. :( waitpid returned: %d\n", childProcessPID, waitpidres);
      return -1;
    }
    
    DEBUG("Running run loop a long time...\n");
    CFStringRef mountPathSnapshot = NULL;
    while(mountPathSnapshot == NULL) {
      int crlrimRetval = CFRunLoopRunInMode(kCFRunLoopDefaultMode, timeout, true);
      DEBUG("Exited from run loop. Let's find out why... crlrimRetval: %d (handled: %d)\n", crlrimRetval, kCFRunLoopRunHandledSource);
      mountPathSnapshot = mountPath; // Might have been modified during run loop.
      if(crlrimRetval != kCFRunLoopRunHandledSource) {
	fprintf(stderr, "Did not receive a signal within %f seconds. Exiting...\n", timeout);
	break;
      }
      else if(mountPathSnapshot != NULL) {
	DEBUG("mountPathSnapshot: %X\n", (int)mountPathSnapshot);
	
	int mountPathUTF8Length = CFStringGetLength(mountPath) + 1;  // null terminator
	char *mountPathUTF8 = malloc(mountPathUTF8Length);
	memset(mountPathUTF8, 0, mountPathUTF8Length);
	GetCorruptedMacFUSEStringAsUTF8(mountPath, mountPathUTF8, mountPathUTF8Length);
	
	char *canonicalMountPath = malloc(PATH_MAX);
	char *canonicalMountpoint = malloc(PATH_MAX);
	memset(canonicalMountPath, 0, PATH_MAX);
	memset(canonicalMountpoint, 0, PATH_MAX);
	
	realpath(mountPathUTF8, canonicalMountPath);
	realpath(mountpointRaw, canonicalMountpoint);
	
	int cmpres = strncmp(canonicalMountPath, canonicalMountpoint, PATH_MAX);
	
	if(cmpres != 0) {
	  if(DEBUGMODE) {
	    DEBUG("Strings NOT equal. cmpres=%d\n", cmpres);
	    DEBUG("mountPath (UTF-8): \"%s\"\n", canonicalMountPath);
	    DEBUG("mountpoint (UTF-8): \"%s\"\n", canonicalMountpoint);
	  }
	  mountPathSnapshot = NULL;
	}
	else
	  DEBUG("Mounter has signaled! Great success!\n");
	
	free(mountPathUTF8);
	free(canonicalMountPath);
	free(canonicalMountpoint);
      }
      //CFRunLoopRun();
    }
    DEBUG("Run loop done.\n");
    if(mountPath != NULL)
      CFRelease(mountPath);
    
    return 0; // We have previously checked that the return value from the child process is 0. We can't get here if it isn't.
  }
  else { // forkRetval == 0
    // Child process
    const int childargc = argc-3;
    char *childargv[childargc+1];
    childargv[childargc] = NULL; // Null terminated
    int i;
    for(i = 0; i < childargc; ++i)
      childargv[i] = argv[i+(argc-childargc)];
    
    if(DEBUGMODE) {
      DEBUG("Contents of argv:\n");
      for(i = 0; i < argc; ++i)
	DEBUG("  argv[%i]: \"%s\"\n", i, argv[i]);
      
      DEBUG("Contents of childargv:\n");
      for(i = 0; i < childargc; ++i)
	DEBUG("  childargv[%i]: \"%s\"\n", i, childargv[i]);
    }
    
    execvp(mount_command, childargv);
    fprintf(stderr, "Could not execute %s!\n", argv[3]);
    return -1;
  }
}