Reputation: 2291
I am using the following code as reference to get the list of volumes from a Solaris 11.2 machine:
#include <time.h>
#include <sys/mntent.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/vfs.h>
#include <errno.h>
struct mntent
{
char *mnt_fsname; /* Device or server for filesystem. */
char *mnt_dir; /* Directory mounted on. */
char *mnt_type; /* Type of filesystem: ufs, nfs, etc. */
char *mnt_opts; /* Comma-separated options for fs. */
int mnt_freq; /* Dump frequency (in days). */
int mnt_passno; /* Pass number for `fsck'. */
};
char ** getVolumeList(int * size)
{
char ** volList = NULL;
int listLen = 0;
char tmp[1024];
struct mntent* vp ;
FILE *fp=fopen("/etc/mnttab", "r");
int result;
printf("in getVolumeList\n");
printf("coming here 1\n");
volList = (char **) malloc(sizeof(char*) * (*size));
printf("coming here \n");
vp = getmntent(fp);
if (vp == NULL)
printf("vp is null");
result = getmntent(fp,vp);
if(result == -1)
{
printf ("getmntent returned:%d. Hence breaking from loop\n", result);
}
/*
ignore all entries for which mount options is set to ignore
these don't show up in dk -k also although dk -a shows them
*/
if(vp->mnt_dir != NULL)
{
strcpy(tmp,vp->mnt_dir);
volList[listLen] = (char*) malloc(sizeof(char) * (strlen(tmp)+1));
strcpy(volList[listLen], tmp);
listLen++;
}
else
{
printf("\nmountp is NULL \n");
}
printf("freeing vp\n");
if (vp != NULL)
{
free(vp);
}
if (fp != NULL)
{
fclose(fp);
}
*size = listLen;
printf("returning from getVolumeList\n");
return volList;
}
but this seems to be throwing the following seg fault :
#0 0xfe663923 in getmntent_compat () from /lib/libc.so.1
I am guessing this is due to the fact the mntent.h on solaris 11.2 does not have a struct mntent defined or the following method signatures in the header file: getmntent(); getmntent(fp,vp)
Is there any other equivalent way to determine the volumes that are mounted on a solaris machine or better yet a OS independent method to determine the volumes that are currently mounted ?
P.S. I am novice with C.
Upvotes: 1
Views: 449
Reputation: 1698
There are a few different errors in the code. Something along these lines might work:
#include <stdio.h>
#include <mntent.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
/* Return a NULL-terminated list of filesystem mountpoints, or NULL on error.
* The individual strings in the result need to be freed,
* as does the result array.
*/
char **getVolumeList(void)
{
char **res = NULL;
int allocated = 1;
int size = 0;
struct mntent *ent;
FILE *fp = setmntent("/etc/mnttab", "r");
if( !fp ) return NULL;
while( (ent=getmntent(fp)) )
{
if(allocated <= size+1)
{
allocated *= 2;
res = realloc(res, sizeof(char*)*allocated );
if( !res ) return NULL;
}
res[size++] = strdup( ent->mnt_dir );
res[size] = NULL;
}
endmntent(fp);
return res;
}
This function returns a dynamically sized null terminated array, which at least removes a hardcoded limit from the code.
The actual reason for your crash is probably that you are not using the correct method to open the file, getmntent() needs some additional storage in order to do it's work (unlike getmntent_r, where you are responsible for creating the storage)
Also, you should not free the storage returned by getmntent since it is documented as being static.
The function above would be used along these lines:
int main(int argc, char **argv)
{
int i;
char ** list = getVolumeList();
if(!list)
{
fprintf(stderr, "failed to get list\n");
return 1;
}
for(int i=0; list[i]; i++ )
{
fprintf( stdout, "%d: %s\n", i, list[i]; );
free( list[i] );
}
free( list );
}
Upvotes: 2