aboutsummaryrefslogtreecommitdiff
path: root/src/3rdParty/efsw/platform/posix/FileSystemImpl.cpp
blob: 92eeb4768ead869f995071de3c287b410e290cf1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
#include <efsw/platform/posix/FileSystemImpl.hpp>

#if defined( EFSW_PLATFORM_POSIX )

#include <cstring>
#include <dirent.h>
#include <efsw/FileInfo.hpp>
#include <efsw/FileSystem.hpp>
#include <unistd.h>

#ifndef _DARWIN_FEATURE_64_BIT_INODE
#define _DARWIN_FEATURE_64_BIT_INODE
#endif

#ifndef _FILE_OFFSET_BITS
#define _FILE_OFFSET_BITS 64
#endif

#include <climits>
#include <cstdlib>
#include <sys/stat.h>

#if EFSW_OS == EFSW_OS_LINUX || EFSW_OS == EFSW_OS_SOLARIS || EFSW_OS == EFSW_OS_ANDROID
#include <sys/vfs.h>
#elif EFSW_OS == EFSW_OS_MACOSX || EFSW_OS == EFSW_OS_BSD || EFSW_OS == EFSW_OS_IOS
#include <sys/mount.h>
#include <sys/param.h>
#endif

/** Remote file systems codes */
#define S_MAGIC_AFS 0x5346414F
#define S_MAGIC_AUFS 0x61756673
#define S_MAGIC_CEPH 0x00C36400
#define S_MAGIC_CIFS 0xFF534D42
#define S_MAGIC_CODA 0x73757245
#define S_MAGIC_FHGFS 0x19830326
#define S_MAGIC_FUSEBLK 0x65735546
#define S_MAGIC_FUSECTL 0x65735543
#define S_MAGIC_GFS 0x01161970
#define S_MAGIC_GPFS 0x47504653
#define S_MAGIC_KAFS 0x6B414653
#define S_MAGIC_LUSTRE 0x0BD00BD0
#define S_MAGIC_NCP 0x564C
#define S_MAGIC_NFS 0x6969
#define S_MAGIC_NFSD 0x6E667364
#define S_MAGIC_OCFS2 0x7461636F
#define S_MAGIC_PANFS 0xAAD7AAEA
#define S_MAGIC_PIPEFS 0x50495045
#define S_MAGIC_SMB 0x517B
#define S_MAGIC_SNFS 0xBEEFDEAD
#define S_MAGIC_VMHGFS 0xBACBACBC
#define S_MAGIC_VXFS 0xA501FCF5

#if EFSW_OS == EFSW_OS_LINUX
#include <cstdio>
#include <mntent.h>
#endif

namespace efsw { namespace Platform {

#if EFSW_OS == EFSW_OS_LINUX

std::string findMountPoint( std::string file ) {
	std::string cwd = FileSystem::getCurrentWorkingDirectory();
	struct stat last_stat;
	struct stat file_stat;

	stat( file.c_str(), &file_stat );

	std::string mp;

	if ( efsw::FileSystem::isDirectory( file ) ) {
		last_stat = file_stat;

		if ( !FileSystem::changeWorkingDirectory( file ) )
			return "";
	} else {
		std::string dir = efsw::FileSystem::pathRemoveFileName( file );

		if ( !FileSystem::changeWorkingDirectory( dir ) )
			return "";

		if ( stat( ".", &last_stat ) < 0 )
			return "";
	}

	while ( true ) {
		struct stat st;

		if ( stat( "..", &st ) < 0 )
			goto done;

		if ( st.st_dev != last_stat.st_dev || st.st_ino == last_stat.st_ino )
			break;

		if ( !FileSystem::changeWorkingDirectory( ".." ) ) {
			goto done;
		}

		last_stat = st;
	}

	/* Finally reached a mount point, see what it's called.  */
	mp = FileSystem::getCurrentWorkingDirectory();

done:
	FileSystem::changeWorkingDirectory( cwd );

	return mp;
}

std::string findDevicePath( const std::string& directory ) {
	struct mntent* ent;
	FILE* aFile;

	aFile = setmntent( "/proc/mounts", "r" );

	if ( aFile == NULL )
		return "";

	while ( NULL != ( ent = getmntent( aFile ) ) ) {
		std::string dirName( ent->mnt_dir );

		if ( dirName == directory ) {
			std::string fsName( ent->mnt_fsname );

			endmntent( aFile );

			return fsName;
		}
	}

	endmntent( aFile );

	return "";
}

bool isLocalFUSEDirectory( std::string directory ) {
	efsw::FileSystem::dirRemoveSlashAtEnd( directory );

	directory = findMountPoint( directory );

	if ( !directory.empty() ) {
		std::string devicePath = findDevicePath( directory );

		return !devicePath.empty();
	}

	return false;
}

#endif

bool FileSystem::changeWorkingDirectory( const std::string& path ) {
	return -1 != chdir( path.c_str() );
}

std::string FileSystem::getCurrentWorkingDirectory() {
	char dir[PATH_MAX + 1];
	char* result = getcwd( dir, PATH_MAX + 1 );
	return result != NULL ? std::string( result ) : std::string();
}

FileInfoMap FileSystem::filesInfoFromPath( const std::string& path ) {
	FileInfoMap files;

	DIR* dp;
	struct dirent* dirp;

	if ( ( dp = opendir( path.c_str() ) ) == NULL )
		return files;

	while ( ( dirp = readdir( dp ) ) != NULL ) {
		if ( strcmp( dirp->d_name, ".." ) != 0 && strcmp( dirp->d_name, "." ) != 0 ) {
			std::string name( dirp->d_name );
			std::string fpath( path + name );

			files[name] = FileInfo( fpath );
		}
	}

	closedir( dp );

	return files;
}

char FileSystem::getOSSlash() {
	return '/';
}

bool FileSystem::isDirectory( const std::string& path ) {
	struct stat st;
	int res = stat( path.c_str(), &st );

	if ( 0 == res ) {
		return static_cast<bool>( S_ISDIR( st.st_mode ) );
	}

	return false;
}

bool FileSystem::isRemoteFS( const std::string& directory ) {
#if EFSW_OS == EFSW_OS_LINUX || EFSW_OS == EFSW_OS_MACOSX || EFSW_OS == EFSW_OS_BSD || \
	EFSW_OS == EFSW_OS_SOLARIS || EFSW_OS == EFSW_OS_ANDROID || EFSW_OS == EFSW_OS_IOS
	struct statfs statfsbuf;

	statfs( directory.c_str(), &statfsbuf );

	switch ( statfsbuf.f_type | 0UL ) {
		case S_MAGIC_FUSEBLK: /* 0x65735546 remote */
		{
#if EFSW_OS == EFSW_OS_LINUX
			return !isLocalFUSEDirectory( directory );
#endif
		}
		case S_MAGIC_AFS:	  /* 0x5346414F remote */
		case S_MAGIC_AUFS:	  /* 0x61756673 remote */
		case S_MAGIC_CEPH:	  /* 0x00C36400 remote */
		case S_MAGIC_CIFS:	  /* 0xFF534D42 remote */
		case S_MAGIC_CODA:	  /* 0x73757245 remote */
		case S_MAGIC_FHGFS:	  /* 0x19830326 remote */
		case S_MAGIC_FUSECTL: /* 0x65735543 remote */
		case S_MAGIC_GFS:	  /* 0x01161970 remote */
		case S_MAGIC_GPFS:	  /* 0x47504653 remote */
		case S_MAGIC_KAFS:	  /* 0x6B414653 remote */
		case S_MAGIC_LUSTRE:  /* 0x0BD00BD0 remote */
		case S_MAGIC_NCP:	  /* 0x564C remote */
		case S_MAGIC_NFS:	  /* 0x6969 remote */
		case S_MAGIC_NFSD:	  /* 0x6E667364 remote */
		case S_MAGIC_OCFS2:	  /* 0x7461636F remote */
		case S_MAGIC_PANFS:	  /* 0xAAD7AAEA remote */
		case S_MAGIC_PIPEFS:  /* 0x50495045 remote */
		case S_MAGIC_SMB:	  /* 0x517B remote */
		case S_MAGIC_SNFS:	  /* 0xBEEFDEAD remote */
		case S_MAGIC_VMHGFS:  /* 0xBACBACBC remote */
		case S_MAGIC_VXFS:	  /* 0xA501FCF5 remote */
		{
			return true;
		}
		default: {
			return false;
		}
	}
#endif

	return false;
}

}} // namespace efsw::Platform

#endif