1 //---
2 //
3 // License: MIT
4 //
5 // Description: This class provides manipulation of filenames.
6 //
7 //---
8 // $Id$
9
10 #include <ossim/ossimConfig.h> /* to pick up platform defines */
11
12 #include <ossim/base/ossimFilename.h>
13 #include <ossim/base/ossimFileInfoInterface.h>
14 #include <ossim/base/ossimCommon.h>
15 #include <ossim/base/ossimConstants.h>
16 #include <ossim/base/ossimDirectory.h>
17 #include <ossim/base/ossimDate.h>
18 #include <ossim/base/ossimEnvironmentUtility.h>
19 #include <ossim/base/ossimNotify.h>
20 #include <ossim/base/ossimRegExp.h>
21 #include <ossim/base/ossimStreamFactoryRegistry.h>
22
23
24 #include <cstdio>
25 #include <cstdlib>
26 #include <cstring>
27 #include <cerrno>
28 #include <iostream>
29 #include <fstream>
30 using namespace std;
31
32 #if defined(_WIN32)
33 # include <io.h>
34 # include <direct.h>
35 # include <sys/utime.h>
36 # include <windows.h>
37 #else
38 # include <sys/types.h>
39 # include <utime.h>
40 # include <sys/stat.h>
41 # include <unistd.h>
42 # include <dirent.h>
43 # include <fcntl.h>
44 #endif
45
46 #include <sys/stat.h>
47
48 #ifdef __BORLANDC__
49 # include <dir.h>
50 # include <direct.h>
51 # include <stdlib.h>
52 # include <io.h>
53 #endif
54
55 #if defined(_WIN32)
56 const char ossimFilename::OSSIM_NATIVE_PATH_SEPARATOR = '\\';
57 #else
58 const char ossimFilename::OSSIM_NATIVE_PATH_SEPARATOR = '/';
59 #endif
60
61 // Internal ossimFilename separator.
62 const char ossimFilename::OSSIM_FILENAME_PATH_SEPARATOR = '/';
63
64
65 /**
66 * This was taken from Wx widgets for performing touch and access date stamps.
67 */
68 #if defined(_WIN32)
69 typedef WIN32_FIND_DATA FIND_STRUCT;
70 typedef HANDLE FIND_DATA;
71 typedef DWORD FIND_ATTR;
72
73 class ossimFileHandle
74 {
75 public:
76 enum OpenMode
77 {
78 Read,
79 Write
80 };
81
ossimFileHandle(const ossimString & filename,OpenMode mode)82 ossimFileHandle(const ossimString& filename, OpenMode mode)
83 {
84 m_hFile = ::CreateFile(
85 filename.c_str(), // name
86 mode == Read ? GENERIC_READ // access mask
87 : GENERIC_WRITE,
88 FILE_SHARE_READ | // sharing mode
89 FILE_SHARE_WRITE, // (allow everything)
90 NULL, // no secutity attr
91 OPEN_EXISTING, // creation disposition
92 0, // no flags
93 NULL // no template file
94 );
95
96 if ( m_hFile == INVALID_HANDLE_VALUE )
97 {
98 // wxLogSysError(_("Failed to open '%s' for %s"),
99 // filename.c_str(),
100 // mode == Read ? _("reading") : _("writing"));
101 }
102 }
103
~ossimFileHandle()104 ~ossimFileHandle()
105 {
106 if ( m_hFile != INVALID_HANDLE_VALUE )
107 {
108 if ( !::CloseHandle(m_hFile) )
109 {
110 // wxLogSysError(_("Failed to close file handle"));
111 }
112 }
113 }
114
115 // return true only if the file could be opened successfully
isOk() const116 bool isOk() const { return m_hFile != INVALID_HANDLE_VALUE; }
117
118 // get the handle
operator HANDLE() const119 operator HANDLE() const { return m_hFile; }
120
121 private:
122 HANDLE m_hFile;
123 };
124
convertOssimToFileTime(FILETIME * ft,const ossimDate & dt)125 static void convertOssimToFileTime(FILETIME *ft, const ossimDate& dt)
126 {
127 SYSTEMTIME st;
128 st.wDay = dt.getDay();
129 st.wMonth = (WORD)(dt.getMonth());
130 st.wYear = (WORD)dt.getYear();
131 st.wHour = dt.getHour();
132 st.wMinute = dt.getMin();
133 st.wSecond = dt.getSec();
134 // st.wMilliseconds = dt.GetMillisecond();
135
136 FILETIME ftLocal;
137 if ( !::SystemTimeToFileTime(&st, &ftLocal) )
138 {
139 // wxLogLastError(_T("SystemTimeToFileTime"));
140 }
141
142 if ( !::LocalFileTimeToFileTime(&ftLocal, ft) )
143 {
144 // wxLogLastError(_T("LocalFileTimeToFileTime"));
145 }
146 }
147
convertFileTimeToOssim(ossimLocalTm & dt,const FILETIME & ft)148 static void convertFileTimeToOssim(ossimLocalTm &dt, const FILETIME &ft)
149 {
150 FILETIME ftcopy = ft;
151 FILETIME ftLocal;
152 if ( !::FileTimeToLocalFileTime(&ftcopy, &ftLocal) )
153 {
154 // wxLogLastError(_T("FileTimeToLocalFileTime"));
155 }
156
157 SYSTEMTIME st;
158 if ( !::FileTimeToSystemTime(&ftLocal, &st) )
159 {
160 // wxLogLastError(_T("FileTimeToSystemTime"));
161 }
162
163 dt.setDay(st.wDay);
164 dt.setMonth(st.wMonth);
165 dt.setYear(st.wYear);
166 dt.setHour(st.wHour);
167 dt.setMin(st.wMinute);
168 dt.setSec(st.wSecond);
169
170 // dt->Set(st.wDay, wxDateTime::Month(st.wMonth - 1), st.wYear,
171 // st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
172 }
173
IsFindDataOk(FIND_DATA fd)174 static inline bool IsFindDataOk(FIND_DATA fd)
175 {
176 return fd != INVALID_HANDLE_VALUE;
177 }
178
FindFirst(const ossimString & spec,FIND_STRUCT * finddata)179 static inline FIND_DATA FindFirst(const ossimString& spec,
180 FIND_STRUCT *finddata)
181 {
182 return ::FindFirstFile(spec.c_str(), finddata);
183 }
184
ossimGetDirectoryTimes(const ossimString & dirname,FILETIME * ftAccess,FILETIME * ftCreate,FILETIME * ftMod)185 static bool ossimGetDirectoryTimes(const ossimString& dirname,
186 FILETIME *ftAccess,
187 FILETIME *ftCreate,
188 FILETIME *ftMod)
189 {
190
191 FIND_STRUCT fs;
192 FIND_DATA fd = FindFirst(dirname, &fs);
193 if ( !IsFindDataOk(fd) )
194 {
195 return false;
196 }
197
198 *ftAccess = fs.ftLastAccessTime;
199 *ftCreate = fs.ftCreationTime;
200 *ftMod = fs.ftLastWriteTime;
201
202 FindClose(fd);
203
204 return true;
205 }
206 #endif
207
208 const ossimFilename ossimFilename::NIL=("");
209
ossimFilename()210 ossimFilename::ossimFilename()
211 : ossimString()
212 {}
213
ossimFilename(const ossimFilename & src)214 ossimFilename::ossimFilename(const ossimFilename& src)
215 : ossimString(src)
216 {
217 }
218
ossimFilename(const ossimString & src)219 ossimFilename::ossimFilename(const ossimString& src)
220 : ossimString(src)
221 {
222 if ( m_str.size() )
223 {
224 converPathSeparator();
225 // convertToNative();
226 }
227 }
228
ossimFilename(const std::string & src)229 ossimFilename::ossimFilename(const std::string& src)
230 : ossimString(src)
231 {
232 if ( m_str.size() )
233 {
234 converPathSeparator();
235 // convertToNative();
236 }
237 }
238
ossimFilename(const char * src)239 ossimFilename::ossimFilename(const char* src)
240 : ossimString(src)
241 {
242 if ( m_str.size() )
243 {
244 converPathSeparator();
245 // convertToNative();
246 }
247 }
248
operator =(const ossimFilename & f)249 const ossimFilename& ossimFilename::operator=(const ossimFilename& f)
250 {
251 if ( this != &f )
252 {
253 m_str = f.m_str;
254 }
255 return *this;
256 }
257
ossimFilename(Iter s,Iter e)258 template <class Iter> ossimFilename::ossimFilename(Iter s, Iter e)
259 : ossimString(s, e)
260 {
261 if ( m_str.size() )
262 {
263 converPathSeparator();
264 // convertToNative();
265 }
266 }
267
operator ==(const ossimFilename & rhs) const268 bool ossimFilename::operator == (const ossimFilename& rhs)const
269 {
270 return ossimString::operator==(rhs);
271 }
272
operator ==(const ossimString & rhs) const273 bool ossimFilename::operator == (const ossimString& rhs)const
274 {
275 return ossimString::operator==(rhs);
276 }
277
operator ==(const char * rhs) const278 bool ossimFilename::operator == (const char* rhs)const
279 {
280 return ossimString::operator ==(rhs);
281 }
282
283 #if 0
284 void ossimFilename::convertBackToForwardSlashes()
285 {
286 std::string::iterator currentChar = this->begin();
287
288 while(currentChar != this->end())
289 {
290 if(*currentChar == '\\')
291 {
292 *currentChar = '/';
293 }
294 ++currentChar;
295 }
296 }
297
298 void ossimFilename::convertForwardToBackSlashes()
299 {
300 std::string::iterator currentChar = this->begin();
301
302 while(currentChar != this->end())
303 {
304 if(*currentChar == '/')
305 {
306 *currentChar = '\\';
307 }
308 ++currentChar;
309 }
310 m_pathSeparator = '\\';
311 }
312 #endif
313
setTimes(ossimLocalTm * accessTime,ossimLocalTm * modTime,ossimLocalTm * createTime) const314 bool ossimFilename::setTimes(ossimLocalTm* accessTime,
315 ossimLocalTm* modTime,
316 #if defined(_WIN32)
317 ossimLocalTm* createTime)const
318 #else
319 ossimLocalTm* /* createTime */ )const
320 #endif
321 {
322 #if defined(_WIN32)
323 if(isDir())
324 {
325 // need to implement this later
326 return false;
327 }
328 else
329 {
330 ossimFileHandle fh(this->expand(), ossimFileHandle::Write);
331 if(fh.isOk())
332 {
333 FILETIME ftAccess, ftCreate, ftWrite;
334
335 if ( createTime )
336 {
337 convertOssimToFileTime(&ftCreate, *createTime);
338 }
339 if ( accessTime )
340 {
341 convertOssimToFileTime(&ftAccess, *accessTime);
342 }
343 if ( modTime )
344 {
345 convertOssimToFileTime(&ftWrite, *modTime);
346 }
347 if ( ::SetFileTime(fh,
348 createTime ? &ftCreate : NULL,
349 accessTime ? &ftAccess : NULL,
350 modTime ? &ftWrite : NULL) )
351 {
352 return true;
353 }
354 }
355 }
356 #else
357 if ( !accessTime && !modTime )
358 {
359 // can't modify the creation time anyhow, don't try
360 return true;
361 }
362 utimbuf utm;
363 utm.actime = accessTime ? accessTime->getTicks() : modTime->getTicks();
364 utm.modtime = modTime ? modTime->getTicks() : accessTime->getTicks();
365 if ( utime(expand().c_str(), &utm) == 0 )
366 {
367 return true;
368 }
369
370 #endif
371
372 return false;
373 }
374
getTimes(ossimLocalTm * accessTime,ossimLocalTm * modTime,ossimLocalTm * createTime) const375 bool ossimFilename::getTimes(ossimLocalTm *accessTime,
376 ossimLocalTm *modTime,
377 ossimLocalTm *createTime) const
378 {
379 if(!expand().exists()) return false;
380
381 #if defined(_WIN32)
382 // we must use different methods for the files and directories under
383 // Windows as CreateFile(GENERIC_READ) doesn't work for the directories and
384 // CreateFile(FILE_FLAG_BACKUP_SEMANTICS) works -- but only under NT and
385 // not 9x
386 bool ok;
387 FILETIME ftAccess, ftCreate, ftWrite;
388 if ( isDir() )
389 {
390 ok = ossimGetDirectoryTimes(expand().c_str(),
391 &ftAccess, &ftCreate, &ftWrite);
392 ok = false;
393 }
394 else // file
395 {
396 ossimFileHandle fh(expand().c_str(), ossimFileHandle::Read);
397 if ( fh.isOk() )
398 {
399 ok = ::GetFileTime(fh,
400 createTime ? &ftCreate : NULL,
401 accessTime ? &ftAccess : NULL,
402 modTime ? &ftWrite : NULL) != 0;
403 }
404 else
405 {
406 ok = false;
407 }
408 }
409
410 if ( ok )
411 {
412 if ( createTime )
413 {
414 convertFileTimeToOssim(*createTime, ftCreate);
415 }
416 if ( accessTime )
417 {
418 convertFileTimeToOssim(*accessTime, ftAccess);
419 }
420 if ( modTime )
421 {
422 convertFileTimeToOssim(*modTime, ftWrite);
423 }
424
425 return true;
426 }
427 #else
428 struct stat sbuf;
429 stat(c_str(), &sbuf);
430 if ( stat( expand().c_str(), &sbuf) == 0 )
431 {
432 if ( accessTime )
433 {
434 *accessTime = ossimLocalTm(sbuf.st_atime);
435 }
436 if ( modTime )
437 {
438 *modTime = ossimLocalTm(sbuf.st_mtime);
439 }
440 if ( createTime )
441 {
442 *createTime = ossimLocalTm(sbuf.st_ctime);
443 }
444 return true;
445 }
446 #endif // platforms
447
448
449 return false;
450 }
451
452 // Time in seconds since last accessed.
lastAccessed() const453 ossim_int64 ossimFilename::lastAccessed() const
454 {
455 ossim_int64 result = -1;
456
457 if( expand().exists() )
458 {
459 ossim_int64 currentTime = ossim::getTime();
460
461 #if defined(_WIN32)
462 cerr << "ossimFilename::lastAccessed() not implemented for windows!" << endl;
463 #else
464 struct stat sbuf;
465 stat(c_str(), &sbuf);
466 if ( stat( expand().c_str(), &sbuf) == 0 )
467 {
468 time_t atime = sbuf.st_atime; // This cast to seconds(time_t).
469 result = currentTime - (ossim_int64)atime;
470 }
471 #endif // platforms
472 }
473
474 return result;
475 }
476
touch() const477 bool ossimFilename::touch()const
478 {
479 #if defined( _WIN32 )
480 ossimDate now;
481
482 return setTimes(&now, &now, 0);
483
484 #else
485 if ( utime(expand().c_str(), NULL) == 0 )
486 {
487 return true;
488 }
489
490 return false;
491 #endif
492 }
493
expand() const494 ossimFilename ossimFilename::expand() const
495 {
496 //---
497 // Note: ossimEnvironmentUtility::getCurrentWorkingDir() is returning
498 // a blank string on windows with vs9. This was resulting in seg faults
499 // in this method so added checks were added for size of returned result.
500 // (drb 20100113)
501 //---
502 ossimFilename result = "";
503 if ( size() )
504 {
505 result = *this;
506
507 if ( needsExpansion() )
508 {
509
510 //#if defined(_WIN32)
511 // result.convertBackToForwardSlashes();
512 //#endif
513
514 bool addCwd = false;
515
516 if ( (size() > 1) && (*(begin()) == '~') && (*(begin()+1) == OSSIM_FILENAME_PATH_SEPARATOR) )
517 {
518 ossimFilename homeDir =
519 ossimEnvironmentUtility::instance()->getUserDir();
520
521 ossimFilename s( (result.begin()+2) , result.end());
522 result = homeDir.dirCat(s);
523 }
524 else if( (size() > 1) &&
525 (*(begin()) == '.') && (*(begin()+1) == OSSIM_FILENAME_PATH_SEPARATOR) )
526 {
527 // dot slash i.e. ./foo
528 addCwd = true;
529 }
530 else if ( (size() > 2) && (*(begin()) == '.')
531 && (*(begin()+1) == '.') && (*(begin()+2) == OSSIM_FILENAME_PATH_SEPARATOR) )
532 {
533 // ../foo
534 addCwd = true;
535 }
536 else if (result == ".")
537 {
538 result = ossimEnvironmentUtility::instance()->
539 getCurrentWorkingDir();
540 }
541
542 if (addCwd)
543 {
544 ossimFilename cwd = ossimEnvironmentUtility::instance()->
545 getCurrentWorkingDir();
546 result = cwd.dirCat(result);
547 }
548 else if ( result.isRelative() )
549 {
550 if ( result.size() && ((*(result.begin())) != '$') )
551 {
552 ossimFilename cwd = ossimEnvironmentUtility::instance()->
553 getCurrentWorkingDir();
554 result = cwd.dirCat(result);
555 }
556 }
557
558 // Check result to see if we're finished.
559 if ( result.needsExpansion() )
560 {
561 // now expand any environment variable substitutions
562
563 ossimFilename finalResult;
564 const char* tempPtr = result.c_str();
565 ossim_int32 startIdx = -1;
566 ossim_int32 resultSize = (ossim_uint32)result.size();
567 ossim_int32 scanIdx = 0;
568 while(scanIdx < resultSize)
569 {
570 // look for start of substitution pattern
571 if(tempPtr[scanIdx] == '$')
572 {
573 if(tempPtr[scanIdx+1] == '(')
574 {
575 scanIdx += 2;
576 startIdx = scanIdx;
577 }
578 else
579 {
580 //---
581 // Infinite loop fix with below file on window:
582 // "\\kiosk\x$\SourceImagery\foo.ntf" (drb 21 Nov. 2016)
583 //---
584 finalResult += tempPtr[scanIdx];
585 ++scanIdx;
586 }
587 }
588 // look for an end pattern and apply if we found a start pattern
589 else if(tempPtr[scanIdx] == ')')
590 {
591 if(startIdx != -1)
592 {
593 ossimFilename value(
594 ossimEnvironmentUtility::instance()->
595 getEnvironmentVariable(ossimString(tempPtr+startIdx,
596 tempPtr+scanIdx)));
597 #if defined(_WIN32) // do windows style replacment
598 // value.convertBackToForwardSlashes();
599 #endif
600 finalResult += value;
601 // reset start idx indicator to not set so we are ready for next pattern
602 //
603 startIdx = -1;
604 }
605 else // if no start then tack on the )
606 {
607 finalResult += tempPtr[scanIdx];
608 }
609 ++scanIdx;
610 }
611 else if(startIdx == -1)
612 {
613 finalResult += tempPtr[scanIdx];
614 ++scanIdx;
615 }
616 else
617 {
618 ++scanIdx;
619 }
620 }
621 #if defined(_WIN32)
622
623 #else
624 finalResult.gsub("//", "/", true);
625 #endif
626 result = finalResult;
627
628 } // matches: if ( result.needsExpansion() )
629
630 #if defined(_WIN32)
631 // result.convertForwardToBackSlashes();
632 #endif
633
634 } // matches: if ( needsExpansion() )
635
636 //---
637 // If we had a size before "expand()" and now we don't something went
638 // wrong...
639 //---
640 if (!result.size())
641 {
642 result = *this;
643 }
644
645 } // matches: if ( size() )
646
647 return result;
648 }
649
exists() const650 bool ossimFilename::exists() const
651 {
652 bool result = false;
653 if ( isUrl() == false )
654 {
655 #if defined(_WIN32)
656 result = (_access(c_str(), ossimFilename::OSSIM_EXIST) == 0);
657 #else
658 result = ((access(c_str(), ossimFilename::OSSIM_EXIST)) == 0);
659 #endif
660 }
661 else
662 {
663 result = ossim::StreamFactoryRegistry::instance()->exists( this->string() );
664 }
665 return result;
666 }
667
isFile() const668 bool ossimFilename::isFile() const
669 {
670 #if defined(_WIN32)
671 struct _stat sbuf;
672 if ( _stat(c_str(), &sbuf ) == -1)
673 return false;
674 return (_S_IFMT & sbuf.st_mode ? true : false);
675 #else
676 struct stat sbuf;
677
678 stat(c_str(), &sbuf);
679 return ((sbuf.st_mode & S_IFMT) == S_IFREG);
680 #endif
681 }
682
isDir() const683 bool ossimFilename::isDir() const
684 {
685 if ( empty() )
686 {
687 return false;
688 }
689
690 ossimFilename temp = c_str();
691 const char& lastChar = temp[temp.size()-1];
692 if ( lastChar == '/' || lastChar == '\\' )
693 {
694 temp = temp.beforePos(temp.size() - 1);
695 }
696
697 #if defined(_WIN32)
698
699 struct _stat sbuf;
700 if ( _stat(temp.c_str(), &sbuf ) == -1)
701 return false;
702 return (_S_IFDIR & sbuf.st_mode ? true : false);
703 #else
704 struct stat sbuf;
705 if (stat(temp.c_str(), &sbuf) == -1)
706 return false;
707 return (S_ISDIR(sbuf.st_mode));
708 #endif
709 }
710
isReadable() const711 bool ossimFilename::isReadable() const
712 {
713 #if defined(_WIN32)
714
715 struct _stat sbuf;
716 if ( _stat(c_str(), &sbuf ) == -1)
717 return false;
718 return (_S_IREAD & sbuf.st_mode ? true : false);
719 #else
720 return (access(c_str(), ossimFilename::OSSIM_READ) == 0);
721 #endif
722 }
723
isUrl() const724 bool ossimFilename::isUrl() const
725 {
726 bool result = false;
727 if ( m_str.size() )
728 {
729 //---
730 // Must have at least room for a protocol and "://", e.g.
731 // "s3://my_bucket/data1/foo.tif
732 //---
733 std::size_t found = m_str.find( std::string("://") );
734 if ( ( found != std::string::npos ) && ( found > 1 ) )
735 {
736 result = true;
737 }
738 }
739 return result;
740 }
741
isWriteable() const742 bool ossimFilename::isWriteable() const
743 {
744 #if defined(_WIN32)
745
746 struct _stat sbuf;
747 if ( _stat(c_str(), &sbuf ) == -1)
748 return false;
749 return (_S_IWRITE & sbuf.st_mode ? true : false);
750 #else
751 return (access(c_str(), ossimFilename::OSSIM_WRITE) == 0);
752 #endif
753 }
754
isExecutable() const755 bool ossimFilename::isExecutable() const
756 {
757 #if defined(_WIN32)
758
759 struct _stat sbuf;
760 if ( _stat(c_str(), &sbuf ) == -1)
761 return false;
762 return (_S_IEXEC & sbuf.st_mode ? true : false);
763 #else
764 return (access(c_str(), ossimFilename::OSSIM_EXE) == 0);
765 #endif
766 }
767
ext() const768 ossimString ossimFilename::ext() const
769 {
770 std::string::size_type pos = m_str.rfind('.');
771 if (pos == std::string::npos)
772 {
773 return ossimFilename::NIL;
774 }
775
776 return ossimFilename(m_str.substr(pos+1));
777 }
778
file() const779 ossimFilename ossimFilename::file() const
780 {
781 std::string::size_type pos = m_str.rfind(OSSIM_FILENAME_PATH_SEPARATOR);
782 if (pos == std::string::npos)
783 return *this;
784 else
785 return ossimFilename(m_str.substr(pos+1));
786 }
787
path() const788 ossimFilename ossimFilename::path() const
789 {
790 // finds the last occurrence of the given string; in this case '/';
791 std::string::size_type pos = m_str.rfind(OSSIM_FILENAME_PATH_SEPARATOR);
792
793 if (pos == 0)
794 return ossimFilename(ossimFilename(OSSIM_FILENAME_PATH_SEPARATOR));
795 if (pos == std::string::npos)
796 {
797 // We got to the end of the file and did not find a path separator.
798 return ossimFilename::NIL;
799 }
800
801 return ossimFilename(m_str.substr(0, pos));
802 }
803
drive() const804 ossimFilename ossimFilename::drive()const
805 {
806 ossimFilename result;
807 ossimRegExp regEx("^([a-z|A-Z])+:");
808 if(regEx.find( m_str.c_str() ) )
809 {
810 result = ossimFilename(ossimString(this->begin() + regEx.start(),
811 this->begin() + regEx.end()));
812 }
813 else
814 {
815 result = "";
816 }
817
818 return result;
819 }
820
fileNoExtension() const821 ossimFilename ossimFilename::fileNoExtension()const
822 {
823 std::string::size_type dot_pos = m_str.rfind('.');
824 std::string::size_type slash_pos = m_str.rfind(OSSIM_FILENAME_PATH_SEPARATOR);
825
826 if(dot_pos == std::string::npos)
827 {
828 if(slash_pos == std::string::npos)
829 {
830 return *this;
831 }
832 else
833 {
834 return ossimFilename(this->begin()+slash_pos+1,
835 this->end());
836 }
837 }
838 else if(slash_pos == std::string::npos)
839 {
840 return ossimFilename(this->begin(), this->begin()+dot_pos);
841 }
842 else if(slash_pos < dot_pos)
843 {
844 return ossimFilename(this->begin()+slash_pos+1,
845 this->begin() + dot_pos);
846 }
847
848 return ossimFilename(this->begin()+slash_pos+1,
849 this->end());
850
851 }
noExtension() const852 ossimFilename ossimFilename::noExtension()const
853 {
854 ossimString drivePart;
855 ossimString pathPart;
856 ossimString filePart;
857 ossimString extPart;
858
859 split(drivePart, pathPart, filePart, extPart);
860
861 extPart.clear();
862
863 ossimFilename result;
864
865 result.merge(drivePart, pathPart, filePart, extPart);
866
867 return result;
868 }
869
setExtension(const ossimString & e)870 ossimFilename& ossimFilename::setExtension(const ossimString& e)
871 {
872 ossimString newExtPart = e;
873
874 //---
875 // If e has a dot "." in the front of it strip it off...
876 //---
877 if ( (e.begin() != e.end()) && ((*(e.begin())) == '.') )
878 {
879 newExtPart = ossimString(e.begin() + 1, e.end());
880 }
881
882 ossimString drivePart;
883 ossimString pathPart;
884 ossimString filePart;
885 ossimString extPart;
886
887 split(drivePart,
888 pathPart,
889 filePart,
890 extPart);
891
892 merge(drivePart,
893 pathPart,
894 filePart,
895 newExtPart);
896
897 return *this;
898 }
899
setDrive(const ossimString & d)900 ossimFilename& ossimFilename::setDrive(const ossimString& d)
901 {
902 ossimString drivePart;
903 ossimString pathPart;
904 ossimString filePart;
905 ossimString extPart;
906
907 split(drivePart,
908 pathPart,
909 filePart,
910 extPart);
911
912 merge(d,
913 pathPart,
914 filePart,
915 extPart);
916
917 return *this;
918 }
919
setPath(const ossimString & p)920 ossimFilename& ossimFilename::setPath(const ossimString& p)
921 {
922 ossimString drivePart;
923 ossimString pathPart;
924 ossimString filePart;
925 ossimString extPart;
926
927 split(drivePart,
928 pathPart,
929 filePart,
930 extPart);
931
932 merge(drivePart,
933 p,
934 filePart,
935 extPart);
936
937 return *this;
938 }
939
setFile(const ossimString & f)940 ossimFilename& ossimFilename::setFile(const ossimString& f)
941 {
942 ossimString drivePart;
943 ossimString pathPart;
944 ossimString filePart;
945 ossimString extPart;
946
947 split(drivePart,
948 pathPart,
949 filePart,
950 extPart);
951
952 merge(drivePart,
953 pathPart,
954 f,
955 extPart);
956
957 return *this;
958 }
959
960
split(ossimString & drivePart,ossimString & pathPart,ossimString & filePart,ossimString & extPart) const961 void ossimFilename::split(ossimString& drivePart,
962 ossimString& pathPart,
963 ossimString& filePart,
964 ossimString& extPart)const
965 {
966 drivePart = drive();
967 pathPart = path();
968 if(drivePart != "")
969 {
970 pathPart = pathPart.substitute(drivePart, "");
971 }
972 filePart = fileNoExtension();
973 extPart = ext();
974 }
975
merge(const ossimString & drivePart,const ossimString & pathPart,const ossimString & filePart,const ossimString & extPart)976 void ossimFilename::merge(const ossimString& drivePart,
977 const ossimString& pathPart,
978 const ossimString& filePart,
979 const ossimString& extPart)
980 {
981 ossimFilename result = drivePart;
982
983 if(pathPart != "")
984 {
985 result = result.dirCat(ossimFilename(pathPart));
986 }
987
988 if(filePart!="")
989 {
990 result = result.dirCat(ossimFilename(filePart));
991 }
992
993 if(extPart != "")
994 {
995 result += ".";
996 result += extPart;
997 }
998
999 *this = result;
1000 }
1001
dirCat(const ossimFilename & file) const1002 ossimFilename ossimFilename::dirCat(const ossimFilename& file) const
1003 {
1004 // If this string is empty simply return the input file.
1005 if (empty()) return file;
1006 if (file.empty()) return *this;
1007
1008 ossimFilename dir = *this;
1009 ossimFilename tempFile = file;
1010
1011 // Check the end and see if it already has a "/".
1012 string::const_iterator i = dir.end();
1013
1014 --i; // decrement past the trailing null.
1015
1016 if ( (*i) != OSSIM_FILENAME_PATH_SEPARATOR)
1017 {
1018 dir += ossimString(OSSIM_FILENAME_PATH_SEPARATOR);
1019 }
1020
1021 // check for dot slash or just slash: ./foo or /foo
1022 std::string::iterator iter = tempFile.begin();
1023 if (iter != tempFile.end())
1024 {
1025 if ((*iter) == OSSIM_FILENAME_PATH_SEPARATOR)
1026 {
1027 ++iter; // skip slash
1028 }
1029 else if (tempFile.size() > 1)
1030 {
1031 if ( ((*iter) == '.') && ( *(iter + 1) == OSSIM_FILENAME_PATH_SEPARATOR) )
1032 {
1033 iter = iter + 2; // skip dot slash
1034 }
1035 }
1036 }
1037
1038 dir += std::string(iter, tempFile.end());
1039
1040 return dir;
1041 }
1042
fileSize() const1043 ossim_int64 ossimFilename::fileSize() const
1044 {
1045 ossim_int64 size = 0;
1046
1047 if ( isUrl() == false )
1048 {
1049 struct stat sbuf;
1050 if ( stat( this->c_str(), &sbuf ) == 0 )
1051 {
1052 size = (ossim_int64)sbuf.st_size;
1053 }
1054 else
1055 {
1056 ifstream in(c_str());
1057 if(in)
1058 {
1059 in.seekg(0, std::ios_base::end);
1060 size = (ossim_int64)in.tellg();
1061 }
1062 }
1063 }
1064 else
1065 {
1066 std::shared_ptr<ossim::istream> in = ossim::StreamFactoryRegistry::instance()->
1067 createIstream( this->string() );
1068 if ( in )
1069 {
1070 ossimFileInfoInterface* intf = dynamic_cast<ossimFileInfoInterface*>( in.get() );
1071 if ( intf )
1072 {
1073 size = intf->getFileSize();
1074 }
1075 else
1076 {
1077 in->seekg(0, std::ios_base::end);
1078 size = (ossim_int64)in->tellg();
1079 }
1080 }
1081 }
1082
1083 return size;
1084 }
1085
createDirectory(bool recurseFlag,int perm) const1086 bool ossimFilename::createDirectory( bool recurseFlag,
1087 int perm ) const
1088 {
1089 if(exists()) return true;
1090
1091 if ( empty() ) return false;
1092
1093 if(recurseFlag)
1094 {
1095 ossimString tempString = this->expand().c_str();
1096
1097 vector<ossimString> result;
1098 tempString.split(result,OSSIM_FILENAME_PATH_SEPARATOR);
1099
1100 if(result.size())
1101 {
1102 ossimString current = result[0];
1103
1104 // Reconstruct UNC paths under Windows.
1105 #if defined(_WIN32)
1106 bool bGotUNC = false;
1107 if ( current.length() == 0 && tempString.length() > 2 )
1108 {
1109 const char* fstr = tempString.c_str();
1110 const char fstar0 = fstr[0];
1111 const char fstar1 = fstr[1];
1112 if ( fstar0=='\\' && fstar1=='\\' )
1113 {
1114 bGotUNC = true;
1115 current = OSSIM_FILENAME_PATH_SEPARATOR;
1116 }
1117 }
1118 #endif
1119
1120 for(ossim_uint32 i = 1; i < result.size(); ++i)
1121 {
1122 current += (OSSIM_FILENAME_PATH_SEPARATOR+result[i]);
1123
1124 #if defined(_WIN32)
1125 if ( bGotUNC == true && i==1 )
1126 {
1127 // The root of the UNC path is assumed to exist.
1128 continue;
1129 }
1130 #endif
1131
1132 if(current != OSSIM_FILENAME_PATH_SEPARATOR)
1133 {
1134 if(!ossimFilename(current).exists())
1135 {
1136 #if defined(__BORLANDC__)
1137 if ( _mkdir(current.c_str()) != 0 )
1138 #elif defined(_WIN32)
1139 if ( _mkdir(current.c_str()) != 0 )
1140 #else
1141 if ( mkdir(current.c_str(), perm) != 0 )
1142 #endif
1143 {
1144 return false;
1145 }
1146 }
1147 }
1148 }
1149 }
1150 }
1151 else
1152 {
1153 #if defined (__BORLANDC__)
1154 if ( _mkdir(c_str()) != 0 )
1155 #elif defined(_WIN32)
1156 if ( _mkdir(c_str()) != 0 )
1157 #else
1158 if ( mkdir(c_str(), perm) != 0 )
1159 #endif
1160 {
1161 return false;
1162 }
1163 else
1164 {
1165 return true;
1166 }
1167 }
1168 return true;
1169 }
1170
remove(const ossimFilename & pathname)1171 bool ossimFilename::remove(const ossimFilename& pathname)
1172 {
1173 bool result = true;
1174
1175 #if defined(__VISUALC__) || defined(__BORLANDC__) || defined(__WATCOMC__) || \
1176 defined(__GNUWIN32__) || defined(_MSC_VER)
1177
1178 // Note: not sure if these work on all of the above flavors. drb - 14 Sep. 2011.
1179 if(pathname.isDir())
1180 {
1181 // Note this only removes empty directories.
1182 result = ( RemoveDirectory( pathname.c_str() ) != 0 );
1183 }
1184 else
1185 {
1186 result = ( DeleteFile( pathname.c_str() ) != 0 );
1187 }
1188 #else /* Unix flavor from unistd.h. */
1189 if(pathname.isDir())
1190 {
1191 result = ( rmdir( pathname.c_str() ) == 0 );
1192 }
1193 else
1194 {
1195 result = ( unlink( pathname.c_str() ) == 0 );
1196 }
1197 #endif
1198
1199 return result;
1200 }
1201
wildcardRemove(const ossimFilename & pathname)1202 bool ossimFilename::wildcardRemove(const ossimFilename& pathname)
1203 {
1204 std::vector<ossimFilename> fileListToRemove;
1205 ossimFilename tempPathname = pathname;
1206
1207 if(!tempPathname.isDir())
1208 {
1209 ossimFilename file = tempPathname.file();
1210 ossimFilename path = tempPathname.path();
1211 if(path == "")
1212 {
1213 path = ".";
1214 }
1215 ossimDirectory dir;
1216 if(dir.open(path))
1217 {
1218 dir.findAllFilesThatMatch(fileListToRemove,
1219 file.c_str());
1220 }
1221 else
1222 {
1223 }
1224 }
1225 else
1226 {
1227 fileListToRemove.push_back(ossimFilename(pathname));
1228 }
1229 ossim_uint32 idx = 0;
1230 bool result = true;
1231 for(idx = 0; idx < fileListToRemove.size(); ++idx)
1232 {
1233 #if defined(__VISUALC__) || defined(__BORLANDC__) || defined(__WATCOMC__) || \
1234 defined(__GNUWIN32__) || defined(_MSC_VER)
1235
1236 if(remove(fileListToRemove[idx].c_str()) != 0)
1237 {
1238 result = false;
1239 }
1240 #else
1241 if (unlink(fileListToRemove[idx]) == -1)
1242 {
1243 result = false;
1244 }
1245 #endif /* HAVE_UNISTD_H */
1246 }
1247 return result;
1248 }
1249
rename(const ossimFilename & destFile,bool overwriteDestinationFlag) const1250 bool ossimFilename::rename(const ossimFilename& destFile, bool overwriteDestinationFlag)const
1251 {
1252 bool result = true;
1253 if ( this->string() != destFile.string() )
1254 {
1255 if ( overwriteDestinationFlag && destFile.exists() )
1256 {
1257 destFile.remove();
1258 }
1259
1260 if ( destFile.exists() == false )
1261 {
1262 // std::rename from cstdio returns 0 on success.
1263 if ( std::rename(this->c_str(), destFile.c_str()) != 0 )
1264 {
1265 result = false;
1266 }
1267 }
1268 else
1269 {
1270 ossimNotify(ossimNotifyLevel_WARN)
1271 << "ossimFilenam::rename WARNING:"
1272 << "\nDestination File Exists: " << destFile << std::endl;
1273 result = false;
1274 }
1275 }
1276 return result;
1277 }
1278
remove() const1279 bool ossimFilename::remove()const
1280 {
1281 return ossimFilename::remove(*this);
1282 }
1283
wildcardRemove() const1284 bool ossimFilename::wildcardRemove()const
1285 {
1286 return ossimFilename::wildcardRemove(*this);
1287 }
1288
copyFileTo(const ossimFilename & outputFile) const1289 bool ossimFilename::copyFileTo(const ossimFilename& outputFile) const
1290 {
1291 bool result = false;
1292
1293 std::ifstream is(this->c_str(), std::ios::in|std::ios::binary);
1294 if ( is.good() )
1295 {
1296 ossimFilename f = outputFile;
1297 if ( f.isDir() )
1298 {
1299 f = f.dirCat( this->file() );
1300 }
1301
1302 if ( f != *this )
1303 {
1304 std::ofstream os( f.c_str(), std::ios::out|std::ios::binary );
1305 if ( os.good() )
1306 {
1307 // Copy the file:
1308 char c;
1309 while(is.get(c))
1310 {
1311 os.put(c);
1312 }
1313
1314 if ( is.eof() && !os.fail())
1315 {
1316 result = true;
1317 }
1318 else
1319 {
1320 ossimNotify(ossimNotifyLevel_WARN)
1321 << "WARNING: "
1322 << "ossimFilename::copyFileTo WARNING:"
1323 << "\nError detected writing from file "
1324 << this->c_str() << " to file " << f.c_str() << std::endl;
1325 }
1326 }
1327 else
1328 {
1329 ossimNotify(ossimNotifyLevel_WARN)
1330 << "WARNING: "
1331 << "ossimFilename::copyFileTo WARNING:"
1332 << "\nCannot open: " << f.c_str() << std::endl;
1333 }
1334 } // if ( f != *this )
1335 else
1336 {
1337 ossimNotify(ossimNotifyLevel_WARN)
1338 << "WARNING: "
1339 << "ossimFilename::copyFileTo WARNING:"
1340 << "\nFiles the same!" << std::endl;
1341 }
1342
1343 } // if ( is.good() )
1344 else
1345 {
1346 ossimNotify(ossimNotifyLevel_WARN)
1347 << "WARNING: "
1348 << "ossimFilename::copyFileTo WARNING:"
1349 << "\nCannot open: " << this->c_str() << std::endl;
1350 }
1351
1352 return result;
1353 }
1354
1355 //---
1356 // We will only return false if we are absolutely sure absolutely sure we
1357 // are not relative. No pun intended:)
1358 //---
isRelative() const1359 bool ossimFilename::isRelative() const
1360 {
1361 bool result = true;
1362 if (size())
1363 {
1364 //---
1365 // Look for unix "/"...
1366 // ESH: Look for Windows "\" (with prepending escape character \)
1367 //---
1368 if ( (*(begin()) == '/') || (*(begin()) == '\\') )
1369 {
1370 result = false;
1371 }
1372 else
1373 {
1374 // Look for windows drive
1375 ossimRegExp regEx("^([a-z|A-Z])+:");
1376 if ( regEx.find(c_str()) == true)
1377 {
1378 result = false;
1379 }
1380 }
1381 }
1382 return result;
1383 }
1384
needsExpansion() const1385 bool ossimFilename::needsExpansion() const
1386 {
1387 bool result = false;
1388 if ( m_str.size() )
1389 {
1390 // Do not expand URLs.
1391 if ( isUrl() == false )
1392 {
1393 result = isRelative();
1394 if (result == false)
1395 {
1396 // Check for '$'
1397 std::string::size_type pos = m_str.find('$', 0);
1398 {
1399 if (pos != std::string::npos)
1400 {
1401 // found '$'
1402 result = true;
1403 }
1404 }
1405
1406 }
1407 }
1408 }
1409 return result;
1410 }
1411
getPathSeparator() const1412 char ossimFilename::getPathSeparator() const
1413 {
1414 return OSSIM_FILENAME_PATH_SEPARATOR;
1415 }
1416
appendTimestamp()1417 ossimFilename& ossimFilename::appendTimestamp()
1418 {
1419 const std::string format = "%Y%m%d-%H%Mh%Ss";
1420 std::string timestamp;
1421 ossim::getFormattedTime(format, true, timestamp);
1422
1423 return append(timestamp);
1424 }
1425
append(const ossimString & append_this)1426 ossimFilename& ossimFilename::append(const ossimString& append_this)
1427 {
1428 ossimString drivePart;
1429 ossimString pathPart;
1430 ossimString filePart;
1431 ossimString extPart;
1432
1433 split(drivePart, pathPart, filePart, extPart);
1434 filePart += append_this;
1435 merge(drivePart, pathPart, filePart, extPart);
1436
1437 return *this;
1438 }
1439
converPathSeparator()1440 void ossimFilename::converPathSeparator()
1441 {
1442 if ( m_str.size() )
1443 {
1444 std::replace( m_str.begin(), m_str.end(), '\\', OSSIM_FILENAME_PATH_SEPARATOR );
1445 }
1446 }
1447
native() const1448 std::string ossimFilename::native() const
1449 {
1450 #if defined(_WIN32)
1451 std::string s = m_str;
1452 std::replace( s.begin(), s.end(),OSSIM_FILENAME_PATH_SEPARATOR, OSSIM_NATIVE_PATH_SEPARATOR );
1453 return s;
1454 #else
1455 return m_str;
1456 #endif
1457 }
1458
1459 #if 0
1460 void ossimFilename::convertToNative()
1461 {
1462 #if defined(_WIN32)
1463 if ( isUrl() == false )
1464 {
1465 convertForwardToBackSlashes();
1466 }
1467 #else
1468 convertBackToForwardSlashes();
1469
1470 #endif
1471 }
1472 #endif
1473