Thread: Anyone familiar with linux file APIs?

  1. #1
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733

    Anyone familiar with linux file APIs?

    I'd like to check if a path is from a mounted media, on windows it's fairly easy, just grab the first ':' character and declare anything before it as a drive but on linux I'm struggling to find some similarly simple method of checking if the path is mounted, reason I want to do so is for this function:
    Code:
    int paw_split_path
    (
    	char *src
    	, char **PROTOCOL
    	, char **BASE
    	, char **PORT
    	, char **DIR
    	, char **ENT
    	, char **EXT
    	, char **HASH
    	, char **QRY
    )
    {
    	*QRY = NULL;
    	*HASH = NULL;
    	*PORT = NULL;
    	*PROTOCOL = NULL;
    	
    	*BASE = strstr( src, "://" );
    	if ( *BASE )
    	{
    		*PROTOCOL = src;
    		*BASE = *BASE + 3;
    		*DIR = strstr( *BASE, "/" );
    		
    		for ( char *i = *BASE; i < *BASE_END; ++i )
    		{
    			if ( *i == ':' )
    			{
    				*PORT = i;
    				break;
    			}
    		}
    		
    		*ENT = *DIR + 1;
    		*HASH = strstr( *ENT, "#" );
    		*QRY = strstr( *HASH ? *HASH : *ENT, "?" );
    		
    		if ( *HASH )
    		{
    			for
    			(
    				char *i = strstr( *ENT, "/" )
    				; i && i < *HASH
    				; *ENT = i + 1, i = strstr( i, "/" )
    			);
    		}
    		else if ( *QRY )
    		{
    			for
    			(
    				char *i = strstr( *ENT, "/" )
    				; i && i < *QRY
    				; *ENT = i + 1, i = strstr( i, "/" )
    			);
    		}
    		else
    		{
    			for
    			(
    				char *i = strstr( *ENT, "/" )
    				; i
    				; *ENT = i + 1, i = strstr( i, "/" )
    			);
    		}
    	}
    	else
    	{
    		*ENT = strrchr( src, '\\' );
    		
    		if ( !(*ENT) ) *ENT = strrchr( src, '/' );
    		
    		*DIR = strchr( *ENT, ':' );
    		
    		if ( *DIR )
    		{
    			*DIR = *DIR + 1;
    			*BASE = src;
    		}
    		else
    		{
    		}
    	}
    }

  2. #2
    Registered User
    Join Date
    May 2009
    Posts
    4,183
    "...a computer is a stupid machine with the ability to do incredibly smart things, while computer programmers are smart people with the ability to do incredibly stupid things. They are,in short, a perfect match.." Bill Bryson

  3. #3
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    Quote Originally Posted by stahta01 View Post
    I appreciate the attempt but that's all for the shell & bash, I need a function in the operating system

  4. #4
    Registered User rstanley's Avatar
    Join Date
    Jun 2014
    Location
    New York, NY
    Posts
    1,106
    I would look at man 2 stat for starters.

  5. #5
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    Quote Originally Posted by rstanley View Post
    I would look at man 2 stat for starters.
    I did consider that but the documentation doesn't explain what to look for when seeing if a path it is linked to a device's root, or at least doesn't do a good enough job of it since I can't work it out

  6. #6
    Registered User
    Join Date
    May 2012
    Location
    Arizona, USA
    Posts
    945
    What do you mean by "mounted media"? Every part of the file system (even the root directory) is on mounted media (except for special system directories like /proc and /sys which exist without media backing them).

    Using the stat system call, you can find out the ID of the device that contains the file with the st_dev member of struct stat. I suppose you can do something special if st_dev of a file is different than st_dev for /, for example.

    I'm not sure what that'll gain you since it's not uncommon even today for various directories in the file system (e.g., /usr, /home, /tmp, etc) to be on different media/partitions than /.

  7. #7
    Registered User rstanley's Avatar
    Join Date
    Jun 2014
    Location
    New York, NY
    Posts
    1,106
    There is no concept of Drive Letters in Linux as there is in Windoze. All data storage devices are mounted in some path below the file system root '/'.

    If you pass a "Path" to stat, you will be notified if the "Path" is valid and mounted.

    The /etc/mtab file will show all the mounted data storage devices, the path, file system type, (iso9660, ext4, etc...) and other info.

    The /etc/fstab file will show all the storage devices to be automatically mounted during bootup.

    If this doesn't help, I don't know how to answer your question. Perhaps you need to study a good book on the Linux Operating System.

  8. #8
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    Quote Originally Posted by christop View Post
    What do you mean by "mounted media"? Every part of the file system (even the root directory) is on mounted media (except for special system directories like /proc and /sys which exist without media backing them).

    Using the stat system call, you can find out the ID of the device that contains the file with the st_dev member of struct stat. I suppose you can do something special if st_dev of a file is different than st_dev for /, for example.

    I'm not sure what that'll gain you since it's not uncommon even today for various directories in the file system (e.g., /usr, /home, /tmp, etc) to be on different media/partitions than /.
    That was actually helpful, I'll iterate through each directory in the path until reach the filename or the device is different, btw what I meant was something like the "C:\" you get for system media and alternative medias like CD Drive or SD Card etc in windows

  9. #9
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    Okay, this is what I have, see any problems?

    Code:
    ...
    	else
    	{
    		
    #ifdef PAW_WIN32
    		*ENT = strrchr( src, '\\' );
    		*DIR_SEP = **ENT;
    		*DIR = strchr( src, ':' );
    		*DIR = *DIR + 1;
    		*BASE = src;
    #else
    		struct stat root_st;
    		
    		*ENT = strrchr( src, '/' );
    		*DIR_SEP = **ENT;	
    		*DIR = src;
    		*BASE = src;
    		
    		stat( "/", &root_st );
    		
    		for ( char *i = *DIR; i && i < *ENT; i = strchr( i, *DIR_SEP ) )
    		{
    			struct stat st;
    			
    			*i = '\0';
    			
    			if ( stat( *BASE, &st ) || !S_ISDIR(st.st_mode) )
    				break;
    			
    			*i = *DIR_SEP;
    				
    			if ( st.st_dev != root_st.st_dev )
    			{
    				*DIR = i;
    				break;
    			}
    		}
    #endif
    	}
    }

  10. #10
    Registered User
    Join Date
    Sep 2020
    Posts
    425
    Windows now also supports mount points inside file systems.

    It just isn't used very often....

  11. #11
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    I'll look into that later then, for now a simple method is good enough, I'll just add a TODO comment in there to jog my memory later

  12. #12
    Registered User
    Join Date
    Feb 2019
    Posts
    1,078
    /proc/mounts or /proc/self/mounts

  13. #13
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    Quote Originally Posted by flp1969 View Post
    /proc/mounts or /proc/self/mounts
    Honestly that seems slower than the method I've gone with, it IS good for enumerating them though so ty, I'll eventually make use of that

  14. #14
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    Found something of semi-relevance today:
    NtQueryInformationFile
    Code:
    #ifdef PAW_WIN32
    struct paw_path paw__win32_get_file_user_path( void *ud, HANDLE file )
    {
    	FILE_NAME_INFORMATION fi;
    	IO_STATUS_BLOCK iob;
    	struct paw_path path = {0};
    	char *_path;
    	
    	NtQueryInformationFile
    	(
    		file
    		, &iob
    		, &fi
    		, sizeof(fi)
    		, FileAlternateNameInformation
    	);
    
    	return path;
    }
    #endif
    What I ideally wanted to do was not store path information if I don't have to, this seems like a step in the right direction for windows and haven't checked linux yet but plan to do that later, open to suggestions though (yes I know the function is incomplete but thought I would check here to see if there was anyone familiar with the function that could/would point out any errors in usage or give tips on what to do with the results, particularly that io status block, not something I typically deal with so would like some people to explain their understanding of it.

  15. #15
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    I feel like something is wrong with these, if anyone spots it, mind telling me what it is please
    Code:
    #ifdef PAW_WIN32
    struct paw_path* paw_get_sym_path_by_handle( void *ud, HANDLE file )
    {
    	FILE_NAME_INFORMATION fi;
    	IO_STATUS_BLOCK iob;
    	struct paw_path *path;
    	size_t want;
    	
    	NtQueryInformationFile
    	(
    		file
    		, &iob
    		, &fi
    		, sizeof(fi)
    		, FileAlternateNameInformation
    	);
    	
    	want = fi.FileNameLength + sizeof(struct paw_path) + 1;
    	path = paw.alloc( ud, NULL, 0, want );
    	
    	if ( path )
    	{
    		memset( path, 0, want );
    		path->_size = want;
    		path->used = fi.FileNameLength;
    		path->size = path->used + 1;
    		path->path = (char*)(path + 1);
    		memcpy( path->path, fi.FileName, path->used );
    		paw_split_path( path, path->path );
    		return paw;
    	}
    	
    	return NULL;
    }
    struct paw_path* paw_get_abs_path_by_handle( void *ud, HANDLE file )
    {
    	FILE_NAME_INFORMATION fi;
    	IO_STATUS_BLOCK iob;
    	struct paw_path *path;
    	size_t want;
    	
    	NtQueryInformationFile
    	(
    		file
    		, &iob
    		, &fi
    		, sizeof(fi)
    		, FileNameInformation
    	);
    	
    	want = fi.FileNameLength + sizeof(struct paw_path) + 1;
    	path = paw.alloc( ud, NULL, 0, want );
    	
    	if ( path )
    	{
    		memset( path, 0, want );
    		path->_size = want;
    		path->used = fi.FileNameLength;
    		path->size = path->used + 1;
    		path->path = (char*)(path + 1);
    		memcpy( path->path, fi.FileName, path->used );
    		paw_split_path( path, path->path );
    		return paw;
    	}
    	
    	return NULL;
    }
    #else
    struct paw_path* paw_get_sym_path_by_fd( void *ud, int file )
    {
    	struct paw_path* path = NULL;
    	size_t want = BUFSIZ, size = 0;
    	ssize_t ret;
    	char _path[bitsof(int)];
    	int err;
    	
    	sprintf( _path, "/proc/self/fd/%d", fd );
    	
    	while (1)
    	{
    		void *temp = paw.alloc( ud, path, size, want );
    		
    		if ( !temp )
    		{
    			memset( path, size );
    			paw.alloc( ud, path, size, 0 );
    			return NULL;
    		}
    		
    		path = temp;
    		size = want;
    		
    		memset( path, 0, size );
    		path->_size = size;
    		path->size = size - sizeof(struct paw_path);
    		path->path = (char*)(path + 1);
    		
    		ret = readlink( _path, path->path, path->size );
    		err = errno;
    		
    		if ( ret == -1 )
    		{
    			if ( err == ENAMETOOLONG )
    				continue;
    			
    			paw.alloc( ud, path, size, 0 );
    			return NULL;
    		}
    		
    		break;
    	}
    	
    	paw_split_path( path, path->path );
    	
    	return path;
    }
    
    struct paw_path* paw_get_abs_path_by_fd( void *ud, int file )
    {
    	return paw_get_sym_path_by_fd( ud, file );
    }
    #endif
    Last edited by awsdert; 05-22-2021 at 07:05 AM. Reason: half a woprd got chopped off

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Anyone familiar with Qt?
    By Al3 in forum C++ Programming
    Replies: 4
    Last Post: 03-04-2015, 10:34 AM
  2. Anyone here familiar with FIRST?
    By KingDubya in forum A Brief History of Cprogramming.com
    Replies: 6
    Last Post: 12-02-2005, 02:37 PM
  3. cstring and apis
    By neandrake in forum C++ Programming
    Replies: 2
    Last Post: 03-11-2004, 01:54 AM
  4. APIs
    By Unregistered in forum Windows Programming
    Replies: 1
    Last Post: 06-04-2002, 06:44 PM
  5. Anybody Familiar with A.L.I.C.E. bot?
    By blackwyvern in forum C++ Programming
    Replies: 6
    Last Post: 01-23-2002, 10:53 PM

Tags for this Thread