1 //////////////////////////////////////////////////////////////////////////////
2 //
3 // (C) Copyright Ion Gaztanaga 2005-2012. Distributed under the Boost
4 // Software License, Version 1.0. (See accompanying file
5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // See http://www.boost.org/libs/interprocess for documentation.
8 //
9 //////////////////////////////////////////////////////////////////////////////
10 
11 #ifndef BOOST_INTERPROCESS_DETAIL_OS_FILE_FUNCTIONS_HPP
12 #define BOOST_INTERPROCESS_DETAIL_OS_FILE_FUNCTIONS_HPP
13 
14 #ifndef BOOST_CONFIG_HPP
15 #  include <boost/config.hpp>
16 #endif
17 #
18 #if defined(BOOST_HAS_PRAGMA_ONCE)
19 #  pragma once
20 #endif
21 
22 #include <boost/interprocess/detail/config_begin.hpp>
23 #include <boost/interprocess/detail/workaround.hpp>
24 #include <boost/interprocess/errors.hpp>
25 #include <boost/interprocess/permissions.hpp>
26 
27 #include <string>
28 #include <limits>
29 #include <climits>
30 #include <boost/move/detail/type_traits.hpp> //make_unsigned
31 
32 #if defined (BOOST_INTERPROCESS_WINDOWS)
33 #  include <boost/interprocess/detail/win32_api.hpp>
34 #else
35 #  ifdef BOOST_HAS_UNISTD_H
36 #     include <fcntl.h>
37 #     include <unistd.h>
38 #     include <sys/types.h>
39 #     include <sys/stat.h>
40 #     include <errno.h>
41 #     include <cstdio>
42 #     include <dirent.h>
43 #     if 0
44 #        include <sys/file.h>
45 #     endif
46 #  else
47 #    error Unknown platform
48 #  endif
49 #endif
50 
51 #include <cstring>
52 #include <cstdlib>
53 
54 namespace boost {
55 namespace interprocess {
56 
57 #if defined (BOOST_INTERPROCESS_WINDOWS)
58 
59 typedef void *                   file_handle_t;
60 typedef __int64  offset_t;
61 typedef struct mapping_handle_impl_t{
62    void *   handle;
63    bool     is_shm;
64 }  mapping_handle_t;
65 
66 typedef enum { read_only      = winapi::generic_read
67              , read_write     = winapi::generic_read | winapi::generic_write
68              , copy_on_write
69              , read_private
70              , invalid_mode   = 0xffff
71              } mode_t;
72 
73 typedef enum { file_begin     = winapi::file_begin
74              , file_end       = winapi::file_end
75              , file_current   = winapi::file_current
76              } file_pos_t;
77 
78 typedef unsigned long      map_options_t;
79 static const map_options_t default_map_options = map_options_t(-1);
80 
81 namespace ipcdetail{
82 
mapping_handle_from_file_handle(file_handle_t hnd)83 inline mapping_handle_t mapping_handle_from_file_handle(file_handle_t hnd)
84 {
85    mapping_handle_t ret;
86    ret.handle = hnd;
87    ret.is_shm = false;
88    return ret;
89 }
90 
mapping_handle_from_shm_handle(file_handle_t hnd)91 inline mapping_handle_t mapping_handle_from_shm_handle(file_handle_t hnd)
92 {
93    mapping_handle_t ret;
94    ret.handle = hnd;
95    ret.is_shm = true;
96    return ret;
97 }
98 
file_handle_from_mapping_handle(mapping_handle_t hnd)99 inline file_handle_t file_handle_from_mapping_handle(mapping_handle_t hnd)
100 {  return hnd.handle; }
101 
create_directory(const char * path)102 inline bool create_directory(const char *path)
103 {  return winapi::create_directory(path); }
104 
remove_directory(const char * path)105 inline bool remove_directory(const char *path)
106 {  return winapi::remove_directory(path); }
107 
get_temporary_path(char * buffer,std::size_t buf_len,std::size_t & required_len)108 inline bool get_temporary_path(char *buffer, std::size_t buf_len, std::size_t &required_len)
109 {
110    required_len = 0;
111    //std::size_t is always bigger or equal than unsigned long in Windows systems
112    //In case std::size_t is bigger than unsigned long
113    unsigned long buf = buf_len;
114    if(buf_len != buf){   //maybe overflowed
115       return false;
116    }
117    required_len = winapi::get_temp_path(buf_len, buffer);
118    const bool ret = !(buf_len < required_len);
119    if(ret && buffer[required_len-1] == '\\'){
120       buffer[required_len-1] = 0;
121    }
122    return ret;
123 }
124 
create_new_file(const char * name,mode_t mode,const permissions & perm=permissions (),bool temporary=false)125 inline file_handle_t create_new_file
126    (const char *name, mode_t mode, const permissions & perm = permissions(), bool temporary = false)
127 {
128    unsigned long attr = temporary ? winapi::file_attribute_temporary : 0;
129    return winapi::create_file
130       ( name, (unsigned int)mode, winapi::create_new, attr
131       , (winapi::interprocess_security_attributes*)perm.get_permissions());
132 }
133 
create_or_open_file(const char * name,mode_t mode,const permissions & perm=permissions (),bool temporary=false)134 inline file_handle_t create_or_open_file
135    (const char *name, mode_t mode, const permissions & perm = permissions(), bool temporary = false)
136 {
137    unsigned long attr = temporary ? winapi::file_attribute_temporary : 0;
138    return winapi::create_file
139       ( name, (unsigned int)mode, winapi::open_always, attr
140       , (winapi::interprocess_security_attributes*)perm.get_permissions());
141 }
142 
open_existing_file(const char * name,mode_t mode,bool temporary=false)143 inline file_handle_t open_existing_file
144    (const char *name, mode_t mode, bool temporary = false)
145 {
146    unsigned long attr = temporary ? winapi::file_attribute_temporary : 0;
147    return winapi::create_file
148       (name, (unsigned int)mode, winapi::open_existing, attr, 0);
149 }
150 
delete_file(const char * name)151 inline bool delete_file(const char *name)
152 {  return winapi::unlink_file(name);   }
153 
truncate_file(file_handle_t hnd,std::size_t size)154 inline bool truncate_file (file_handle_t hnd, std::size_t size)
155 {
156    offset_t filesize;
157    if(!winapi::get_file_size(hnd, filesize))
158       return false;
159 
160    typedef ::boost::move_detail::make_unsigned<offset_t>::type uoffset_t;
161    const uoffset_t max_filesize = uoffset_t((std::numeric_limits<offset_t>::max)());
162    const uoffset_t uoff_size = uoffset_t(size);
163    //Avoid unused variable warnings in 32 bit systems
164    if(uoff_size > max_filesize){
165       winapi::set_last_error(winapi::error_file_too_large);
166       return false;
167    }
168 
169    if(offset_t(size) > filesize){
170       if(!winapi::set_file_pointer_ex(hnd, filesize, 0, winapi::file_begin)){
171          return false;
172       }
173       //We will write zeros in the end of the file
174       //since set_end_of_file does not guarantee this
175       for(std::size_t remaining = size - filesize, write_size = 0
176          ;remaining > 0
177          ;remaining -= write_size){
178          const std::size_t DataSize = 512;
179          static char data [DataSize];
180          write_size = DataSize < remaining ? DataSize : remaining;
181          unsigned long written;
182          winapi::write_file(hnd, data, (unsigned long)write_size, &written, 0);
183          if(written != write_size){
184             return false;
185          }
186       }
187    }
188    else{
189       if(!winapi::set_file_pointer_ex(hnd, size, 0, winapi::file_begin)){
190          return false;
191       }
192       if(!winapi::set_end_of_file(hnd)){
193          return false;
194       }
195    }
196    return true;
197 }
198 
get_file_size(file_handle_t hnd,offset_t & size)199 inline bool get_file_size(file_handle_t hnd, offset_t &size)
200 {  return winapi::get_file_size(hnd, size);  }
201 
set_file_pointer(file_handle_t hnd,offset_t off,file_pos_t pos)202 inline bool set_file_pointer(file_handle_t hnd, offset_t off, file_pos_t pos)
203 {  return winapi::set_file_pointer_ex(hnd, off, 0, (unsigned long) pos); }
204 
get_file_pointer(file_handle_t hnd,offset_t & off)205 inline bool get_file_pointer(file_handle_t hnd, offset_t &off)
206 {  return winapi::set_file_pointer_ex(hnd, 0, &off, winapi::file_current); }
207 
write_file(file_handle_t hnd,const void * data,std::size_t numdata)208 inline bool write_file(file_handle_t hnd, const void *data, std::size_t numdata)
209 {
210    unsigned long written;
211    return 0 != winapi::write_file(hnd, data, (unsigned long)numdata, &written, 0);
212 }
213 
invalid_file()214 inline file_handle_t invalid_file()
215 {  return winapi::invalid_handle_value;  }
216 
close_file(file_handle_t hnd)217 inline bool close_file(file_handle_t hnd)
218 {  return 0 != winapi::close_handle(hnd);   }
219 
acquire_file_lock(file_handle_t hnd)220 inline bool acquire_file_lock(file_handle_t hnd)
221 {
222    static winapi::interprocess_overlapped overlapped;
223    const unsigned long len = ((unsigned long)-1);
224 //   winapi::interprocess_overlapped overlapped;
225 //   std::memset(&overlapped, 0, sizeof(overlapped));
226    return winapi::lock_file_ex
227       (hnd, winapi::lockfile_exclusive_lock, 0, len, len, &overlapped);
228 }
229 
try_acquire_file_lock(file_handle_t hnd,bool & acquired)230 inline bool try_acquire_file_lock(file_handle_t hnd, bool &acquired)
231 {
232    const unsigned long len = ((unsigned long)-1);
233    winapi::interprocess_overlapped overlapped;
234    std::memset(&overlapped, 0, sizeof(overlapped));
235    if(!winapi::lock_file_ex
236       (hnd, winapi::lockfile_exclusive_lock | winapi::lockfile_fail_immediately,
237        0, len, len, &overlapped)){
238       return winapi::get_last_error() == winapi::error_lock_violation ?
239                acquired = false, true : false;
240 
241    }
242    return (acquired = true);
243 }
244 
release_file_lock(file_handle_t hnd)245 inline bool release_file_lock(file_handle_t hnd)
246 {
247    const unsigned long len = ((unsigned long)-1);
248    winapi::interprocess_overlapped overlapped;
249    std::memset(&overlapped, 0, sizeof(overlapped));
250    return winapi::unlock_file_ex(hnd, 0, len, len, &overlapped);
251 }
252 
acquire_file_lock_sharable(file_handle_t hnd)253 inline bool acquire_file_lock_sharable(file_handle_t hnd)
254 {
255    const unsigned long len = ((unsigned long)-1);
256    winapi::interprocess_overlapped overlapped;
257    std::memset(&overlapped, 0, sizeof(overlapped));
258    return winapi::lock_file_ex(hnd, 0, 0, len, len, &overlapped);
259 }
260 
try_acquire_file_lock_sharable(file_handle_t hnd,bool & acquired)261 inline bool try_acquire_file_lock_sharable(file_handle_t hnd, bool &acquired)
262 {
263    const unsigned long len = ((unsigned long)-1);
264    winapi::interprocess_overlapped overlapped;
265    std::memset(&overlapped, 0, sizeof(overlapped));
266    if(!winapi::lock_file_ex
267       (hnd, winapi::lockfile_fail_immediately, 0, len, len, &overlapped)){
268       return winapi::get_last_error() == winapi::error_lock_violation ?
269                acquired = false, true : false;
270    }
271    return (acquired = true);
272 }
273 
release_file_lock_sharable(file_handle_t hnd)274 inline bool release_file_lock_sharable(file_handle_t hnd)
275 {  return release_file_lock(hnd);   }
276 
delete_subdirectories_recursive(const std::string & refcstrRootDirectory,const char * dont_delete_this,unsigned int count)277 inline bool delete_subdirectories_recursive
278    (const std::string &refcstrRootDirectory, const char *dont_delete_this, unsigned int count)
279 {
280    bool               bSubdirectory = false;       // Flag, indicating whether
281                                                    // subdirectories have been found
282    void *             hFile;                       // Handle to directory
283    std::string        strFilePath;                 // Filepath
284    std::string        strPattern;                  // Pattern
285    winapi::win32_find_data  FileInformation;     // File information
286 
287    //Find all files and directories
288    strPattern = refcstrRootDirectory + "\\*.*";
289    hFile = winapi::find_first_file(strPattern.c_str(), &FileInformation);
290    if(hFile != winapi::invalid_handle_value){
291       do{
292          //If it's not "." or ".." or the pointed root_level dont_delete_this erase it
293          if(FileInformation.cFileName[0] != '.' &&
294             !(dont_delete_this && count == 0 && std::strcmp(dont_delete_this, FileInformation.cFileName) == 0)){
295             strFilePath.erase();
296             strFilePath = refcstrRootDirectory + "\\" + FileInformation.cFileName;
297 
298             //If it's a directory, go recursive
299             if(FileInformation.dwFileAttributes & winapi::file_attribute_directory){
300                // Delete subdirectory
301                if(!delete_subdirectories_recursive(strFilePath, dont_delete_this, count+1)){
302                   winapi::find_close(hFile);
303                   return false;
304                }
305             }
306             //If it's a file, just delete it
307             else{
308                // Set file attributes
309                //if(::SetFileAttributes(strFilePath.c_str(), winapi::file_attribute_normal) == 0)
310                //return winapi::get_last_error();
311                // Delete file
312                winapi::unlink_file(strFilePath.c_str());
313             }
314          }
315       //Go to the next file
316       } while(winapi::find_next_file(hFile, &FileInformation) == 1);
317 
318       // Close handle
319       winapi::find_close(hFile);
320 
321       //See if the loop has ended with an error or just because we've traversed all the files
322       if(winapi::get_last_error() != winapi::error_no_more_files){
323          return false;
324       }
325       else
326       {
327          //Erase empty subdirectories or original refcstrRootDirectory
328          if(!bSubdirectory && count)
329          {
330             // Set directory attributes
331             //if(::SetFileAttributes(refcstrRootDirectory.c_str(), FILE_ATTRIBUTE_NORMAL) == 0)
332                //return ::GetLastError();
333             // Delete directory
334             if(winapi::remove_directory(refcstrRootDirectory.c_str()) == 0)
335                return false;
336          }
337       }
338    }
339    return true;
340 }
341 
342 //This function erases all the subdirectories of a directory except the one pointed by "dont_delete_this"
delete_subdirectories(const std::string & refcstrRootDirectory,const char * dont_delete_this)343 inline bool delete_subdirectories(const std::string &refcstrRootDirectory, const char *dont_delete_this)
344 {
345    return delete_subdirectories_recursive(refcstrRootDirectory, dont_delete_this, 0u);
346 }
347 
348 
349 template<class Function>
for_each_file_in_dir(const char * dir,Function f)350 inline bool for_each_file_in_dir(const char *dir, Function f)
351 {
352    void *             hFile;                       // Handle to directory
353    winapi::win32_find_data  FileInformation;     // File information
354 
355    //Get base directory
356    std::string str(dir);
357    const std::size_t base_root_dir_len = str.size();
358 
359    //Find all files and directories
360    str  +=  "\\*.*";
361    hFile = winapi::find_first_file(str.c_str(), &FileInformation);
362    if(hFile != winapi::invalid_handle_value){
363       do{   //Now loop every file
364          str.erase(base_root_dir_len);
365          //If it's not "." or ".." skip it
366          if(FileInformation.cFileName[0] != '.'){
367             str += "\\";   str += FileInformation.cFileName;
368             //If it's a file, apply erase logic
369             if(!(FileInformation.dwFileAttributes & winapi::file_attribute_directory)){
370                f(str.c_str(), FileInformation.cFileName);
371             }
372          }
373       //Go to the next file
374       } while(winapi::find_next_file(hFile, &FileInformation) == 1);
375 
376       // Close handle and see if the loop has ended with an error
377       winapi::find_close(hFile);
378       if(winapi::get_last_error() != winapi::error_no_more_files){
379          return false;
380       }
381    }
382    return true;
383 }
384 
385 
386 #else    //#if defined (BOOST_INTERPROCESS_WINDOWS)
387 
388 typedef int       file_handle_t;
389 typedef off_t     offset_t;
390 
391 typedef struct mapping_handle_impl_t
392 {
393    file_handle_t  handle;
394    bool           is_xsi;
395 }  mapping_handle_t;
396 
397 typedef enum { read_only      = O_RDONLY
398              , read_write     = O_RDWR
399              , copy_on_write
400              , read_private
401              , invalid_mode   = 0xffff
402              } mode_t;
403 
404 typedef enum { file_begin     = SEEK_SET
405              , file_end       = SEEK_END
406              , file_current   = SEEK_CUR
407              } file_pos_t;
408 
409 typedef int map_options_t;
410 static const map_options_t default_map_options = map_options_t(-1);
411 
412 namespace ipcdetail{
413 
414 inline mapping_handle_t mapping_handle_from_file_handle(file_handle_t hnd)
415 {
416    mapping_handle_t ret;
417    ret.handle = hnd;
418    ret.is_xsi = false;
419    return ret;
420 }
421 
422 inline file_handle_t file_handle_from_mapping_handle(mapping_handle_t hnd)
423 {  return hnd.handle; }
424 
425 inline bool create_directory(const char *path)
426 {  return ::mkdir(path, 0777) == 0 && ::chmod(path, 0777) == 0; }
427 
428 inline bool remove_directory(const char *path)
429 {  return ::rmdir(path) == 0; }
430 
431 inline bool get_temporary_path(char *buffer, std::size_t buf_len, std::size_t &required_len)
432 {
433    required_len = 5u;
434    if(buf_len < required_len)
435       return false;
436    else{
437       std::strcpy(buffer, "/tmp");
438    }
439    return true;
440 }
441 
442 inline file_handle_t create_new_file
443    (const char *name, mode_t mode, const permissions & perm = permissions(), bool temporary = false)
444 {
445    (void)temporary;
446    int ret = ::open(name, ((int)mode) | O_EXCL | O_CREAT, perm.get_permissions());
447    if(ret >= 0){
448       ::fchmod(ret, perm.get_permissions());
449    }
450    return ret;
451 }
452 
453 inline file_handle_t create_or_open_file
454    (const char *name, mode_t mode, const permissions & perm = permissions(), bool temporary = false)
455 {
456    (void)temporary;
457    int ret = -1;
458    //We need a loop to change permissions correctly using fchmod, since
459    //with "O_CREAT only" ::open we don't know if we've created or opened the file.
460    while(1){
461       ret = ::open(name, ((int)mode) | O_EXCL | O_CREAT, perm.get_permissions());
462       if(ret >= 0){
463          ::fchmod(ret, perm.get_permissions());
464          break;
465       }
466       else if(errno == EEXIST){
467          if((ret = ::open(name, (int)mode)) >= 0 || errno != ENOENT){
468             break;
469          }
470       }
471       else{
472          break;
473       }
474    }
475    return ret;
476 }
477 
478 inline file_handle_t open_existing_file
479    (const char *name, mode_t mode, bool temporary = false)
480 {
481    (void)temporary;
482    return ::open(name, (int)mode);
483 }
484 
485 inline bool delete_file(const char *name)
486 {  return ::unlink(name) == 0;   }
487 
488 inline bool truncate_file (file_handle_t hnd, std::size_t size)
489 {
490    typedef boost::move_detail::make_unsigned<off_t>::type uoff_t;
491    if(uoff_t((std::numeric_limits<off_t>::max)()) < size){
492       errno = EINVAL;
493       return false;
494    }
495    return 0 == ::ftruncate(hnd, off_t(size));
496 }
497 
498 inline bool get_file_size(file_handle_t hnd, offset_t &size)
499 {
500    struct stat data;
501    bool ret = 0 == ::fstat(hnd, &data);
502    if(ret){
503       size = data.st_size;
504    }
505    return ret;
506 }
507 
508 inline bool set_file_pointer(file_handle_t hnd, offset_t off, file_pos_t pos)
509 {  return ((off_t)(-1)) != ::lseek(hnd, off, (int)pos); }
510 
511 inline bool get_file_pointer(file_handle_t hnd, offset_t &off)
512 {
513    off = ::lseek(hnd, 0, SEEK_CUR);
514    return off != ((off_t)-1);
515 }
516 
517 inline bool write_file(file_handle_t hnd, const void *data, std::size_t numdata)
518 {  return (ssize_t(numdata)) == ::write(hnd, data, numdata);  }
519 
520 inline file_handle_t invalid_file()
521 {  return -1;  }
522 
523 inline bool close_file(file_handle_t hnd)
524 {  return ::close(hnd) == 0;   }
525 
526 inline bool acquire_file_lock(file_handle_t hnd)
527 {
528    struct ::flock lock;
529    lock.l_type    = F_WRLCK;
530    lock.l_whence  = SEEK_SET;
531    lock.l_start   = 0;
532    lock.l_len     = 0;
533    return -1 != ::fcntl(hnd, F_SETLKW, &lock);
534 }
535 
536 inline bool try_acquire_file_lock(file_handle_t hnd, bool &acquired)
537 {
538    struct ::flock lock;
539    lock.l_type    = F_WRLCK;
540    lock.l_whence  = SEEK_SET;
541    lock.l_start   = 0;
542    lock.l_len     = 0;
543    int ret = ::fcntl(hnd, F_SETLK, &lock);
544    if(ret == -1){
545       return (errno == EAGAIN || errno == EACCES) ?
546                acquired = false, true : false;
547    }
548    return (acquired = true);
549 }
550 
551 inline bool release_file_lock(file_handle_t hnd)
552 {
553    struct ::flock lock;
554    lock.l_type    = F_UNLCK;
555    lock.l_whence  = SEEK_SET;
556    lock.l_start   = 0;
557    lock.l_len     = 0;
558    return -1 != ::fcntl(hnd, F_SETLK, &lock);
559 }
560 
561 inline bool acquire_file_lock_sharable(file_handle_t hnd)
562 {
563    struct ::flock lock;
564    lock.l_type    = F_RDLCK;
565    lock.l_whence  = SEEK_SET;
566    lock.l_start   = 0;
567    lock.l_len     = 0;
568    return -1 != ::fcntl(hnd, F_SETLKW, &lock);
569 }
570 
571 inline bool try_acquire_file_lock_sharable(file_handle_t hnd, bool &acquired)
572 {
573    struct flock lock;
574    lock.l_type    = F_RDLCK;
575    lock.l_whence  = SEEK_SET;
576    lock.l_start   = 0;
577    lock.l_len     = 0;
578    int ret = ::fcntl(hnd, F_SETLK, &lock);
579    if(ret == -1){
580       return (errno == EAGAIN || errno == EACCES) ?
581                acquired = false, true : false;
582    }
583    return (acquired = true);
584 }
585 
586 inline bool release_file_lock_sharable(file_handle_t hnd)
587 {  return release_file_lock(hnd);   }
588 
589 #if 0
590 inline bool acquire_file_lock(file_handle_t hnd)
591 {  return 0 == ::flock(hnd, LOCK_EX); }
592 
593 inline bool try_acquire_file_lock(file_handle_t hnd, bool &acquired)
594 {
595    int ret = ::flock(hnd, LOCK_EX | LOCK_NB);
596    acquired = ret == 0;
597    return (acquired || errno == EWOULDBLOCK);
598 }
599 
600 inline bool release_file_lock(file_handle_t hnd)
601 {  return 0 == ::flock(hnd, LOCK_UN); }
602 
603 inline bool acquire_file_lock_sharable(file_handle_t hnd)
604 {  return 0 == ::flock(hnd, LOCK_SH); }
605 
606 inline bool try_acquire_file_lock_sharable(file_handle_t hnd, bool &acquired)
607 {
608    int ret = ::flock(hnd, LOCK_SH | LOCK_NB);
609    acquired = ret == 0;
610    return (acquired || errno == EWOULDBLOCK);
611 }
612 
613 inline bool release_file_lock_sharable(file_handle_t hnd)
614 {  return 0 == ::flock(hnd, LOCK_UN); }
615 #endif
616 
617 inline bool delete_subdirectories_recursive
618    (const std::string &refcstrRootDirectory, const char *dont_delete_this)
619 {
620    DIR *d = opendir(refcstrRootDirectory.c_str());
621    if(!d) {
622       return false;
623    }
624 
625    struct dir_close
626    {
627       DIR *d_;
628       dir_close(DIR *d) : d_(d) {}
629       ~dir_close() { ::closedir(d_); }
630    } dc(d); (void)dc;
631 
632    struct ::dirent *de;
633    struct ::stat st;
634    std::string fn;
635 
636    while((de=::readdir(d))) {
637       if( de->d_name[0] == '.' && ( de->d_name[1] == '\0'
638             || (de->d_name[1] == '.' && de->d_name[2] == '\0' )) ){
639          continue;
640       }
641       if(dont_delete_this && std::strcmp(dont_delete_this, de->d_name) == 0){
642          continue;
643       }
644       fn = refcstrRootDirectory;
645       fn += '/';
646       fn += de->d_name;
647 
648       if(std::remove(fn.c_str())) {
649          if(::stat(fn.c_str(), & st)) {
650             return false;
651          }
652          if(S_ISDIR(st.st_mode)) {
653             if(!delete_subdirectories_recursive(fn, 0) ){
654                return false;
655             }
656          } else {
657             return false;
658          }
659       }
660    }
661    return std::remove(refcstrRootDirectory.c_str()) ? false : true;
662 }
663 
664 template<class Function>
665 inline bool for_each_file_in_dir(const char *dir, Function f)
666 {
667    std::string refcstrRootDirectory(dir);
668 
669    DIR *d = opendir(refcstrRootDirectory.c_str());
670    if(!d) {
671       return false;
672    }
673 
674    struct dir_close
675    {
676       DIR *d_;
677       dir_close(DIR *d) : d_(d) {}
678       ~dir_close() { ::closedir(d_); }
679    } dc(d); (void)dc;
680 
681    struct ::dirent *de;
682    struct ::stat st;
683    std::string fn;
684 
685    while((de=::readdir(d))) {
686       if( de->d_name[0] == '.' && ( de->d_name[1] == '\0'
687             || (de->d_name[1] == '.' && de->d_name[2] == '\0' )) ){
688          continue;
689       }
690       fn = refcstrRootDirectory;
691       fn += '/';
692       fn += de->d_name;
693 
694       if(::stat(fn.c_str(), & st)) {
695          return false;
696       }
697       //If it's a file, apply erase logic
698       if(!S_ISDIR(st.st_mode)) {
699          f(fn.c_str(), de->d_name);
700       }
701    }
702    return true;
703 }
704 
705 
706 //This function erases all the subdirectories of a directory except the one pointed by "dont_delete_this"
707 inline bool delete_subdirectories(const std::string &refcstrRootDirectory, const char *dont_delete_this)
708 {
709    return delete_subdirectories_recursive(refcstrRootDirectory, dont_delete_this );
710 }
711 
712 #endif   //#if defined (BOOST_INTERPROCESS_WINDOWS)
713 
open_or_create_directory(const char * dir_name)714 inline bool open_or_create_directory(const char *dir_name)
715 {
716    //If fails, check that it's because it already exists
717    if(!create_directory(dir_name)){
718       error_info info(system_error_code());
719       if(info.get_error_code() != already_exists_error){
720          return false;
721       }
722    }
723    return true;
724 }
725 
get_temporary_path()726 inline std::string get_temporary_path()
727 {
728    std::size_t required_len = 0;
729    get_temporary_path(0, 0, required_len);
730    std::string ret_str(required_len, char(0));
731    get_temporary_path(&ret_str[0], ret_str.size(), required_len);
732    while(!ret_str.empty() && !ret_str[ret_str.size()-1]){
733       ret_str.erase(ret_str.size()-1);
734    }
735 
736    return ret_str;
737 }
738 
739 }  //namespace ipcdetail{
740 }  //namespace interprocess {
741 }  //namespace boost {
742 
743 #include <boost/interprocess/detail/config_end.hpp>
744 
745 #endif   //BOOST_INTERPROCESS_DETAIL_OS_FILE_FUNCTIONS_HPP
746