Ticket #10761: os_file_functions.hpp

File os_file_functions.hpp, 21.6 KB (added by variganji.suresh@…, 8 years ago)

code changes with multiple definition error

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