blocxx
PosixFile.cpp
Go to the documentation of this file.
1 /*******************************************************************************
2 * Copyright (C) 2005, Vintela, Inc. All rights reserved.
3 * Copyright (C) 2006, Novell, Inc. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * * Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * * Neither the name of
14 * Vintela, Inc.,
15 * nor Novell, Inc.,
16 * nor the names of its contributors or employees may be used to
17 * endorse or promote products derived from this software without
18 * specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 *******************************************************************************/
32 
33 
39 #include "blocxx/BLOCXX_config.h"
40 #include "blocxx/File.hpp"
41 #include "blocxx/Logger.hpp"
42 #include "blocxx/Format.hpp"
43 
44 #ifdef BLOCXX_WIN32
45  #include <io.h>
46  #include <stdlib.h>
47  #include <stdio.h>
48  #include <memory.h>
49 #else
50  #include <fcntl.h>
51  #ifdef BLOCXX_HAVE_UNISTD_H
52  #include <unistd.h>
53  #endif
54 #endif
55 
56 
57 namespace BLOCXX_NAMESPACE
58 {
59 #ifdef BLOCXX_WIN32
60 namespace
61 {
63 // implementation of lock functions
64 int
65 doLock(HANDLE hFile, bool doWait, DWORD lockType)
66 {
67  if (hFile == INVALID_HANDLE_VALUE)
68  {
69  return -1;
70  }
71 
72  DWORD flags = lockType;
73  if (!doWait)
74  {
75  flags |= LOCKFILE_FAIL_IMMEDIATELY;
76  }
77 
78  OVERLAPPED ov;
79  memset(&ov, 0, sizeof(ov));
80  if (!LockFileEx(hFile, flags, 0, 0xffffffff,
81  0xffffffff, &ov))
82  {
83  return -1;
84  }
85 
86  return 0;
87 }
88 
89 } // end unnamed namespace
90 
92 File::File(const File& x) : m_hdl(BLOCXX_INVALID_FILEHANDLE)
93 {
94  if( x.m_hdl != BLOCXX_INVALID_FILEHANDLE )
95  {
96  DuplicateHandle(GetCurrentProcess(), x.m_hdl, GetCurrentProcess(),
97  &m_hdl , 0, FALSE, DUPLICATE_SAME_ACCESS);
98  }
99 }
101 int
102 File::getLock(ELockType type)
103 {
104  return doLock(m_hdl, true, type == E_WRITE_LOCK ?
105  LOCKFILE_EXCLUSIVE_LOCK : 0);
106 }
108 int
109 File::tryLock(ELockType type)
110 {
111  return doLock(m_hdl, false, type == E_WRITE_LOCK ?
112  LOCKFILE_EXCLUSIVE_LOCK : 0);
113 }
115 int
116 File::unlock()
117 {
118  if (m_hdl == INVALID_HANDLE_VALUE)
119  {
120  return -1;
121  }
122 
123  OVERLAPPED ov;
124  memset(&ov, 0, sizeof(ov));
125  if (!UnlockFileEx(m_hdl, 0, 0xffffffff, 0xffffffff, &ov))
126  {
127  return -1;
128  }
129 
130  return 0;
131 }
132 
133 #else // NOT WIN32
134 
136 File::File(const File& x)
137  : m_hdl(x.m_hdl != BLOCXX_INVALID_FILEHANDLE ?
138  dup(x.m_hdl) : BLOCXX_INVALID_FILEHANDLE)
139 {
140 }
141 
142 namespace {
144 // implementation of lock functions
145 int
146 doLock(int hdl, int cmd, short int type)
147 {
148  struct flock lck;
149  ::memset (&lck, '\0', sizeof (lck));
150  lck.l_type = type; // type of lock
151  lck.l_whence = 0; // 0 offset for l_start
152  lck.l_start = 0L; // lock starts at BOF
153  lck.l_len = 0L; // extent is entire file
154  return ::fcntl(hdl, cmd, &lck);
155 }
156 } // end unnamed namespace
158 int
160 {
161  return doLock(m_hdl, F_SETLKW, type == E_WRITE_LOCK ?
162  F_WRLCK : F_RDLCK);
163 }
165 int
167 {
168  return doLock(m_hdl, F_SETLK, type == E_WRITE_LOCK ?
169  F_WRLCK : F_RDLCK);
170 }
172 int
174 {
175  return doLock(m_hdl, F_SETLK, F_UNLCK);
176 }
177 #endif
178 
181 {
182  if (close() == -1)
183  {
184  int lerrno = errno;
185  Logger lgr("blocxx.common");
186  BLOCXX_LOG_ERROR(lgr,
187  Format("Closing file handle %1 failed: %2",
188  m_hdl, lerrno)
189  );
190  errno = lerrno;
191  }
192 }
193 
194 } // end namespace BLOCXX_NAMESPACE
195