EzDevInfo.com

mount interview questions

Top mount frequently asked interview questions

Using FUSE library with Java; trying to replicate hello.c example

I am trying to create bindings to the FUSE library using JNA, but I have hit a snag along the road. I have minimized the code as much as possible to make it digestible here.

The FUSE library comes with a few example filesystems written in C. The simplest of them is hello.c. The following is a minimized version of its code to simply a few prints in the filesystem functions:

hello.c:

/*
  FUSE: Filesystem in Userspace
  Copyright (C) 2001-2007  Miklos Szeredi <miklos@szeredi.hu>

  This program can be distributed under the terms of the GNU GPL.
  See the file COPYING.

  gcc -Wall hello.c -o hello `pkg-config fuse --cflags --libs`
*/
#define FUSE_USE_VERSION 26

#include <fuse.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>

static int hello_getattr(const char *path, struct stat *stbuf)
{
    printf("getattr was called\n");
    return 0;
}

static int hello_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi)
{
    printf("readdir was called\n");
    return 0;
}

static int hello_open(const char *path, struct fuse_file_info *fi)
{
    printf("open was called\n");
    return 0;
}

static int hello_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi)
{
    printf("read was called\n");
    return 0;
}

static struct fuse_operations hello_oper = {
    .getattr    = hello_getattr,
    .readdir    = hello_readdir,
    .open       = hello_open,
    .read       = hello_read,
};

int main(int argc, char *argv[])
{
    return fuse_main_real(argc, argv, &hello_oper, sizeof(hello_oper), NULL);
}

This can be compiled using gcc -Wall hello.c -o hello -D_FILE_OFFSET_BITS=64 -I/usr/include/fuse -pthread -lfuse -lrt -ldl

And invoked with ./hello.c -f /some/mount/point

The -f flag is to make it stay in the foreground so that you can see the printf()'s working.

All of this works well, you can see the printf()'s executing properly. I am trying to replicate the same thing in Java using JNA. Here is what I came up with:

FuseTemp.java:

import com.sun.jna.Callback;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;

public class FuseTemp
{
    public static interface Fuse extends Library
    {
        int fuse_main_real(int argc, String[] argv, StructFuseOperations op, long size, Pointer user_data);
    }

    @SuppressWarnings("unused")
    public static class StructFuseOperations extends Structure
    {
        public static class ByReference extends StructFuseOperations implements Structure.ByReference
        {
        }

        public Callback getattr = new Callback()
        {
            public int callback(final String path, final Pointer stat)
            {
                System.out.println("getattr was called");
                return 0;
            }
        };
        public Callback readlink = null;
        public Callback mknod = null;
        public Callback mkdir = null;
        public Callback unlink = null;
        public Callback rmdir = null;
        public Callback symlink = null;
        public Callback rename = null;
        public Callback link = null;
        public Callback chmod = null;
        public Callback chown = null;
        public Callback truncate = null;
        public Callback utime = null;
        public Callback open = new Callback()
        {
            public int callback(final String path, final Pointer info)
            {
                System.out.println("open was called");
                return 0;
            }
        };
        public Callback read = new Callback()
        {
            public int callback(final String path, final Pointer buffer, final long size, final long offset, final Pointer fi)
            {
                System.out.println("read was called");
                return 0;
            }
        };
        public Callback write = null;
        public Callback statfs = null;
        public Callback flush = null;
        public Callback release = null;
        public Callback fsync = null;
        public Callback setxattr = null;
        public Callback getxattr = null;
        public Callback listxattr = null;
        public Callback removexattr = null;
        public Callback opendir = null;
        public Callback readdir = new Callback()
        {
            public int callback(final String path, final Pointer buffer, final Pointer filler, final long offset,
                    final Pointer fi)
            {
                System.out.println("readdir was called");
                return 0;
            }
        };
        public Callback releasedir = null;
        public Callback fsyncdir = null;
        public Callback init = null;
        public Callback destroy = null;
        public Callback access = null;
        public Callback create = null;
        public Callback ftruncate = null;
        public Callback fgetattr = null;
        public Callback lock = null;
        public Callback utimens = null;
        public Callback bmap = null;
        public int flag_nullpath_ok;
        public int flag_reserved;
        public Callback ioctl = null;
        public Callback poll = null;
    }

    public static void main(final String[] args)
    {
        final String[] actualArgs = { "-f", "/some/mount/point" };
        final Fuse fuse = (Fuse) Native.loadLibrary("fuse", Fuse.class);
        final StructFuseOperations.ByReference operations = new StructFuseOperations.ByReference();
        System.out.println("Mounting");
        final int result = fuse.fuse_main_real(actualArgs.length, actualArgs, operations, operations.size(), null);
        System.out.println("Result: " + result);
        System.out.println("Mounted");
    }
}

The definition of the the fuse_operations struct can be found here.

This can be compiled using: javac -cp path/to/jna.jar FuseTemp.java

And invoked using java -cp path/to/jna.jar:. FuseTemp

jna.jar is available here.

The error that comes up is: fusermount: failed to access mountpoint /some/mount/point: Permission denied.

I am executing both programs as the same user with the same permissions on the same mountpoint folder, and I am in the fuse group. I am using:

  • Linux kernel 3.0.0
  • FUSE 2.8.4
  • OpenJDK 1.6.0_23
  • JNA 3.4.0

So my question is: What exactly is different between these two programs (hello.c and FuseTemp.java), and how to make them do the same thing?

Thanks in advance.

Edit: Here is some additional info.

Initial stat of the mountpoint:

  File: `/some/mount/point'
  Size: 4096            Blocks: 8          IO Block: 4096   directory
Device: 803h/2051d      Inode: 540652      Links: 2
Access: (0777/drwxrwxrwx)  Uid: ( 1000/ myusername)   Gid: ( 1000/ myusername)

Output I get from running the Java program as regular user:

Mounting
fusermount: failed to access mountpoint /some/mount/point: Permission denied
Result: 1
Mounted
(program exits with return code 0)

After this, trying to execute stat gives the following error message:

stat: cannot stat/some/mount/point': Transport endpoint is not connected`

That is because the Java program isn't running anymore, so fuse cannot call its callbacks. To unmount, if I try fusermount -u /some/mount/point, I get:

fusermount: entry for /some/mountpoint not found in /etc/mtab

And if I try sudo fusermount -u /some/mount/point, the mountpoint is successfully unmounted and there is no output from fusermount. /etc/mtab is chmod'd 644 (-rw-r--r--) so my user can read it, but it doesn't contain /some/mount/point. After a successful unmount, the mountpoint is back to its old permissions (777 directory).

Now, running the java program as root:

Mounting
Result: 1
Mounted
(program exits with return code 0)

After that, stating /some/mount/point shows that is has not been modified, i.e. it is still a 777 directory.

I have also rewritten FuseTemp.java to include all Callbacks as Callbacks instead of Pointers. The behavior is the same, however.

I looked at fuse's source code and the error code 1 can be returned at multiple points throughout the execution. I will pinpoint where exactly is it failing on the fuse side and report back here.

Now for hello.c: running it as regular user, starting with the same permissions on /some/mount/point and passing it the arguments -f and /some/mount/point, the program doesn't print any output at first but keeps running. When running stat on the mountpoint, the program prints

getattr was called

like it should. stat returns an error, but that's simply because hello.c's getattr function doesn't give it any information, so no problems there. After executing fusermount -u /some/mount/point as regular user, the program exits with return code 0 and the unmount is successful.

Running it as root, starting with the same permissions on /some/mount/point and passing it the arguments -f and /some/mount/point, the program doesn't print any output at first but keeps running. When running stat on the mountpoint, I get a permission error because I am not root. When running stat on it as root, the program prints

getattr was called

like it should. Executing fusermount -u /some/mount/point as regular user yields

fusermount: entry for /some/mount/point not found in /etc/mtab

Executing fusermount as root, the program exits with return code 0 and the unmount is successful.


Source: (StackOverflow)

how to mount a exFAT partition in Ubuntu 11.04 [closed]

How can I format a partition with exFAT format in Ubuntu 11.04?

When I mount a exFAT partition using command 'mount /dev/sdb1 /mnt', it is said that I need to specify the file system, and then I think it needs to add '-t' option to do that, so I modify the command 'mount -t exfat /dev/sdb1 /mnt', but it is said there is no exfat file system, so I want to know how to mount a exFAT partition in Ubuntu 11.04?


Source: (StackOverflow)

Advertisements

Force unmount of NFS-mounted directory [closed]

I have an NFS-mounted directory on a Linux machine that has hung. I've tried to force an unmount, but it doesn't seem to work:

$ umount -f /mnt/data
$ umount2: Device or resource busy
$ umount: /mnt/data: device is busy

If I type "mount", it appears that the directory is no longer mounted, but it hangs if I do "ls /mnt/data", and if I try to remove the mountpoint, I get:

$ rmdir /mnt/data
rmdir: /mnt/data: Device or resource busy

Is there anything I can do other than reboot the machine?


Source: (StackOverflow)

OS X mount local directory [closed]

Is it possible to mount a local directory into another one? Using Perforce, I want to do something equivalent to symlinking a directory, but in a way that fools it into thinking it's really just another directory in the project.

I would like to do something like:

mount /foo/bar /home/foo/bar

Is this possible, and if so what options do I need to give it?


Source: (StackOverflow)

Manually put files to Android emulator SD card

I'm just having trouble with getting my emulator SD card work... I created a new AVD device with a new SD card.

So how to put data onto it? I found the "correct" file to be mounted on Daemon tools, but is corrupt or simply not readable...

It would be great if you have any idea :)


Source: (StackOverflow)

How to Mount a Linux directory from a different PC to your local Linux PC?

Is there a way to mount a Linux directory from a different PC to your local Linux PC? How?


Source: (StackOverflow)

Transport endpoint is not connected

FUSE is constantly(every 2 - 3 days) giving me this Transport endpoint is not connected error on my mount point and the only thing that seems to fix it is rebooting.

I currently have my mount points setup like this, I'm not sure what other details I should add here so let me know if I missed anything..

/dev/sdc1 /mnt/hdd2 ext4 defaults 0 0
/dev/sdb1 /mnt/hdd1 ext4 defaults 0 0
mhddfs#/mnt/hdd1,/mnt/hdd2 /data fuse defaults,allow_other 0 0

Source: (StackOverflow)

PHP file_exists sometimes returns false for a file on CIFS share

I have a CIFS share from Windows Server 2012 R2 mounted on Ubuntu 14.04.2 LTS (kernel 3.13.0-61-generic) like this

/etc/fstab

//10.1.2.3/Share /Share cifs credentials=/root/.smbcredentials/share_user,user=share_user,dirmode=0770,filemode=0660,uid=4000,gid=5000,forceuid,forcegid,noserverino,cache=none 0 0

The gid=5000 corresponds to group www-data which runs a PHP process.

The files are mounted correctly when I check via the console logged in as the www-data user - they are readable and removable (the operations that are used by the PHP script).

The PHP script is processing about 50-70 000 files per day. The files are created on the host Windows machine and some time later the PHP script running on the Linux machine is notified about a new file, checks if the file exists (file_exists), reads it and deletes. Usually all works fine, but sometimes (a few hundreds to 1-2 000 per day) the PHP script raises an error that the file does not exist. That should never be the case, since it is notified only of actually existing files.

When I manually check those files reported as not existing, they are correctly accessible on the Ubuntu machine and have a creation date from before the PHP script checked their existence.

Then I trigger the PHP script manually to pick up that file and it is picked up without problems.

What I already tried

There are multiple similar questions, but I seem to have exhausted all the advices:

  • I added clearstatcache() before checking file_exists($f)
  • The file and directory permissions are OK (exactly the same file is picked up correctly later on)
  • The path used for checking file_exists($f) is an absolute path with no special characters - the file paths are always of format /Share/11/222/333.zip (with various digits)
  • I used noserverino share mount parameter
  • I used cache=none share mount parameter

/proc/fs/cifs/Stats/ displays as below, but I don't know if there is anything suspicious here. The share in question is 2) \\10.1.2.3\Share

Resources in use
CIFS Session: 1
Share (unique mount targets): 2
SMB Request/Response Buffer: 1 Pool size: 5
SMB Small Req/Resp Buffer: 1 Pool size: 30
Operations (MIDs): 0

6 session 2 share reconnects
Total vfs operations: 133925492 maximum at one time: 11

1) \\10.1.2.3\Share_Archive
SMBs: 53824700 Oplocks breaks: 12
Reads:  699 Bytes: 42507881
Writes: 49175075 Bytes: 801182924574
Flushes: 0
Locks: 12 HardLinks: 0 Symlinks: 0
Opens: 539845 Closes: 539844 Deletes: 156848
Posix Opens: 0 Posix Mkdirs: 0
Mkdirs: 133 Rmdirs: 0
Renames: 0 T2 Renames 0
FindFirst: 21 FNext 28 FClose 0
2) \\10.1.2.3\Share
SMBs: 50466376 Oplocks breaks: 1082284
Reads:  39430299 Bytes: 2255596161939
Writes: 2602 Bytes: 42507782
Flushes: 0
Locks: 1082284 HardLinks: 0 Symlinks: 0
Opens: 2705841 Closes: 2705841 Deletes: 539832
Posix Opens: 0 Posix Mkdirs: 0
Mkdirs: 0 Rmdirs: 0
Renames: 0 T2 Renames 0
FindFirst: 227401 FNext 1422 FClose 0

One pattern I think I see is that the error is raised only if the file in question has been already processed (read and deleted) earlier by the PHP script. There are many files that have been correctly processed and then processed again later, but I have never seen that error for a file that is processed for the first time. The time between re-processing varies from 1 to about 20 days. For re-processing, the file is simply recreated under the same path on the Windows host with updated content.

What can be the problem? How can I investigate better? How can I determine if the problem lies on the PHP or OS side?


Update

I have moved the software that produces the files to a Ubuntu VM that mounts the same shares the same way. This component is coded in Java. I am not seeing any issues when reading/writing to the files.


Update - PHP details

The exact PHP code is:

$strFile = zipPath($intApplicationNumber);

clearstatcache();

if(!file_exists($strFile)){
    return responseInternalError('ZIP file does not exist', $strFile);
}

The intApplicationNumber is a request parameter (eg. 12345678) which is simply transformed to a path by the zipPath() function (eg. \Share\12\345\678.zip - always a full path).

The script may be invoked concurrently with different application numbers, but will not be invoked concurrently with the same application number.

If the script fails (returns the 'ZIP file does not exist' error), it will be called again a minute later. If that fails, it will be permanently marked as failed. Then, usually more than an hour later, I can call the script manually with the same invocation (GET request) that it's done on production and it works fine, the file is found and sent in the response:

public static function ResponseRaw($strFile){
    ob_end_clean();
    self::ReadFileChunked($strFile, false);
    exit;
}

protected static function ReadFileChunked($strFile, $blnReturnBytes=true) {
    $intChunkSize = 1048576; // 1M
    $strBuffer = '';
    $intCount = 0;
    $fh = fopen($strFile, 'rb');

    if($fh === false){
        return false;
    }

    while(!feof($fh)){
        $strBuffer = fread($fh, $intChunkSize);
        echo $strBuffer;
        if($blnReturnBytes){
            $intCount += strlen($strBuffer);
        }
    }

    $blnStatus = fclose($fh);

    if($blnReturnBytes && $blnStatus){
        return $intCount;
    }

    return $blnStatus;
}

After the client receives the file, he notifies the PHP server that the file can be moved to an archive location (by means of copy() and unlink()). That part works fine.


STRACE result

After several days of no errors, the error reappeared. I ran strace and it reports

access("/Share/11/222/333.zip", F_OK) = -1 ENOENT (No such file or directory)

for some files that do exist when I run ls /Share/11/222/333.zip from the command line. Therefore the problem is on the OS level, PHP is not to be blamed.

The errors started appearing when the load on the disk on the host increased (due to other processes), so @risyasin's suggestion below seems most likely - it's a matter of busy resources/timeouts.

I'll try @miguel-svq's advice of skipping the existence test and just going for fopen() right away and handling the error then. I'll see if it changes anything.


Source: (StackOverflow)

How do I specify a label/path with spaces in /etc/fstab? [closed]

I am having trouble trying to get theh permissions for some of my external drives set up.

I believe the probem is due to how I am dealing with spaces in the text such that the commands can be interpreted by the terminal. I have found this, which seems to indicate that I need to configure my etc/fstab file to show the following:

# UNCONFIGURED FSTAB FOR BASE SYSTEM
/host/ubuntu/disks/swap.disk    none    swap    sw  0   0
LABEL='Expansion Drive'  /media/'Expansion Drive'  ntfs-3g  defaults,umask=0022,fmask=0133  0  0
LABEL='Expansion Drive_'  /media/'Expansion Drive_'  ntfs-3g  defaults,umask=0022,fmask=0133  0  0

However, This is showing an error that the drive Drive_' is not ready. I realize that this is due to using ""s or ''s, but I am not sure how else to do this properly. My 2 drives are called Expansion Drive and Expansion Drive_ . Anyone know how to solve this problem?

EDIT: Here is what I can see in the media folder:

chasebrown@ubuntu:/media$ ls -al
total 32
drwxr-xr-x  6 root       root        1024 Mar  9 16:32 .
drwxr-xr-x 24 root       root        1024 Feb 23 23:14 ..
drwx------  1 chasebrown chasebrown  4096 Mar  8 04:21 Expansion Drive
drwx------  1 chasebrown chasebrown  4096 Mar  8 04:21 Expansion Drive_
dr-x------  1 chasebrown chasebrown  2048 May 20  2009 GDRV-25922+VR2
drwx------  1 chasebrown chasebrown 20480 Mar  8 04:21 WD EXTERNAL

Also sudo lsblk -f:

chasebrown@ubuntu:/dev/disk/by-uuid$ sudo lsblk -f
[sudo] password for chasebrown: 
NAME   FSTYPE  LABEL           MOUNTPOINT
sda                            
├─sda1 ntfs    System Reserved 
└─sda2 ntfs                    
sdb                            
└─sdb1 ntfs                    /host
sdc                            
└─sdc1 ntfs    Expansion Drive /media/Expansion Drive_
sdd                            
└─sdd1 ntfs    Expansion Drive /media/Expansion Drive
sde                            
└─sde1 ntfs    WD EXTERNAL     /media/WD EXTERNAL
sr0    iso9660 GDRV-25922+VR2  /media/GDRV-25922+VR2
loop0  ext3                    /

And sudo blkid:

chasebrown@ubuntu:/dev/disk/by-uuid$ sudo blkid
/dev/loop0: UUID="87a15942-982f-4edd-bf44-439dc286fd7c" SEC_TYPE="ext2" TYPE="ext3" 
/dev/sr0: LABEL="GDRV-25922+VR2" TYPE="iso9660" 
/dev/sda1: LABEL="System Reserved" UUID="64CEEA61CEEA2B4E" TYPE="ntfs" 
/dev/sda2: UUID="4CA4EBC0A4EBAAA2" TYPE="ntfs" 
/dev/sdb1: UUID="00064EEE064EE46E" TYPE="ntfs" 
/dev/sdc1: LABEL="Expansion Drive" UUID="C682A8EE82A8E3E1" TYPE="ntfs" 
/dev/sdd1: LABEL="Expansion Drive" UUID="D006D78406D769CC" TYPE="ntfs" 
/dev/sde1: LABEL="WD EXTERNAL" UUID="D65AFC375AFC15C9" TYPE="ntfs" 

Therefore my new fstab file is:

# UNCONFIGURED FSTAB FOR BASE SYSTEM
/host/ubuntu/disks/swap.disk    none    swap    sw  0   0
LABEL=Expansion\040Drive  /media/Expansion\040Drive  ntfs-3g  defaults,umask=0022,fmask=0133  0  0
LABEL=Expansion\040Drive_  /media/Expansion\040Drive_  ntfs-3g  defaults,umask=0022,fmask=0133  0  0

SOLUTION: I ended up changing the LABEL to UUID and it worked for some reason.

Here is the resulting /etc/fstab file was :

# UNCONFIGURED FSTAB FOR BASE SYSTEM
/host/ubuntu/disks/swap.disk    none    swap    sw  0   0
UUID=C682A8EE82A8E3E1  /media/Expansion\040Drive  ntfs-3g  defaults,umask=0022,fmask=0133  0  0
UUID=D006D78406D769CC  /media/Expansion\040Drive_  ntfs-3g  defaults,umask=0022,fmask=0133  0  0

Source: (StackOverflow)

Named routes in mounted rails engine

I'm making a small rails engine which I mount like this:

mount BasicApp::Engine => "/app"

Using this answer I have verified that all the routes in the engine are as the should be:

However - when I (inside the engine) link to a named route (defined inside the engine) I get this error

undefined local variable or method `new_post_path' for #<#<Class:0x000000065e0c08>:0x000000065d71d0>

Running "rake route" clearly verifies that "new_post" should be a named path, so I have no idea why Rails (3.1.0) can't figure it out. Any help is welcome

my config/route.rb (for the engine) look like this

BasicApp::Engine.routes.draw do
  resources :posts, :path => '' do
                resources :post_comments
                resources :post_images
        end
end

I should add that it is and isolated engine. However paths like main_app.root_path works fine - while root_path does not


Source: (StackOverflow)

Where is a file mounted?

Given a path to a file or directory, how can I determine the mount point for that file? For example, if /tmp is mounted as a tmpfs filesystem then given the file name /tmp/foo/bar I want to know that it's stored on a tmpfs rooted at /tmp.

This will be in C++ and I'd like to avoid invoking external commands via system(). The code should be robust--not necessarily against deliberate tampering but definitely in the face of nested mountpoints, symlinks, etc.

I haven't been able to find a simple system call to do this. It looks like I'll have to write the check myself. Here's a rough outline of what I'm planning.

  1. Canonicalize the file name a la the readlink shell command. How?
  2. Read /etc/mtab with getmntent() & co.
  3. Determine the corresponding mount entry for the file. How?

For #1 is there a simple system call or do I need to read each directory component of the path and resolve them with readlink(2) if they are symlinks? And handle . and .. myself? Seems like a pain.

For #3 I've got various ideas on how to do this. Not sure which is best.

  1. open() the file, its parent, its parent's parent, etc. using openat(fd, "..") until I reach one of the /etc/mtab entries. (How do I know when I do? fstat() them and compare the inode numbers?)
  2. Find the longest directory name in the mount table which is a substring of my file name.

I'm leaning towards the first option but before I code it all up I want to make sure I'm not overlooking anything--ideally a built-in function that does this already!


Source: (StackOverflow)

How to register newly mounted drive in git bash?

In my day-to-day work (I'm using MS Windows), I keep my git bash (actually using console2 for this) open for the whole day. It is also very frequent that I mount new drives that I would like to work with git. However I noticed that I need to exit the bash and open it again in order to make it recognize new drive letter.

Is there any command that 'registers' already mounted drive in git bash ? thanks

edit2: I do not have any option to left a comment under my own question (weird ..?), so I post it here:

$ mount -a
sh.exe": mount: command not found

Source: (StackOverflow)

How to register FUSE filesystem type with mount(8) and fstab?

I've written a small FUSE-based filesystem and now the only part's missing is that I want to register it with fstab(5) to auto-mount it on system startup and/or manually mount it with just mount /srv/virtual-db. How can I achieve this?

I know, I can just run /usr/bin/vdbfs.py /srv/virtual-db from some init script, but that's not exactly pretty.

I'm sorry because this may be not exactly a programming question, but it's highly related, as the packaging and deployment is still the programmer's job.


Source: (StackOverflow)

FUSE error: Transport endpoint is not connected

I'm trying to implement the FUSE filesystem. I am receiving this error:

cannot access MountDir: Transport endpoint is not connected

This the relevant parts of the program. There are two directories, MirrorDir and MountDir, that exist withing the same directory as all of the code. I am calling the program like this:

./myFS -o nonempty -o allow_other MirrorDir MountDir

Can anyone see what I am doing wrong?

static struct fuse_operations xmp_oper = {
    .getattr    = xmp_getattr,
    .readdir    = xmp_readdir,
    .open       = xmp_open,
    .read       = xmp_read,
};

int main(int argc, char *argv[]) {
    int fuse_stat;
    char* mirrorDir;

    mirrorDir = malloc(sizeof(strlen(argv[argc-2]+1)));
    if (mirrorDir == NULL) {
        perror("main calloc");
        abort();
    }

    // Pull the rootdir out of the argument list and save it in my internal data
    mirrorDir = realpath(argv[argc-2], NULL);

    argv[argc-2] = argv[argc-1];
    argv[argc-1] = NULL;
    argc--;

    // turn over control to fuse
    fprintf(stderr, "about to call fuse_main\n");   
    fuse_stat = fuse_main(argc, argv, &xmp_oper, mirrorDir);
    fprintf(stderr, "fuse_main returned %d\n", fuse_stat);
    return fuse_stat;
}

Source: (StackOverflow)