Line data Source code
1 : /*
2 : * Descriptor.cxx
3 : * OksSystem
4 : *
5 : * Created by Matthias Wiesmann on 08.02.05.
6 : * Copyright 2005 CERN. All rights reserved.
7 : *
8 : */
9 :
10 : #include <sys/types.h>
11 : #include <sys/stat.h>
12 : #include <fcntl.h>
13 : #include <unistd.h>
14 :
15 : #include "okssystem/File.hpp"
16 : #include "okssystem/Descriptor.hpp"
17 : #include "okssystem/exceptions.hpp"
18 :
19 : #include "ers/ers.hpp"
20 :
21 0 : int OksSystem::Descriptor::flags(bool read_mode, bool write_mode) {
22 0 : if (read_mode && write_mode) {
23 : return O_RDWR | O_CREAT;
24 : }
25 0 : if (read_mode) {
26 : return O_RDONLY;
27 : }
28 0 : if (write_mode) {
29 0 : return O_WRONLY | O_CREAT;
30 : }
31 : return 0;
32 : } // flags
33 :
34 :
35 0 : OksSystem::Descriptor::Descriptor(const File * file, int i_flags, mode_t perm) {
36 0 : ERS_ASSERT( file )
37 0 : open(file,i_flags,perm);
38 0 : } // Descriptor
39 :
40 0 : OksSystem::Descriptor::~Descriptor() {
41 0 : if (m_fd>=0) {
42 0 : close_safe();
43 : }
44 0 : } // ~Descriptor
45 :
46 0 : OksSystem::Descriptor::operator int() const throw() {
47 0 : return m_fd;
48 : } // operator int()
49 :
50 :
51 : /** Opens the descriptor
52 : * \param file pointer to the file to open
53 : * \param flags open flags
54 : * \param perm the permissions
55 : */
56 :
57 0 : void OksSystem::Descriptor::open(const File * file, int i_flags, mode_t perm) {
58 0 : ERS_ASSERT( file )
59 0 : bool alreadyExists = file->exists();
60 0 : m_fd = ::open(*file,i_flags,perm);
61 0 : m_name = file->full_name();
62 0 : if (m_fd<0) throw OksSystem::OpenFileIssue( ERS_HERE, errno, m_name.c_str() );
63 0 : if((alreadyExists == false) && ((i_flags & O_CREAT) != 0)) {
64 0 : ::fchmod(m_fd, perm);
65 : }
66 0 : } // open
67 :
68 : /** Closes the descriptor
69 : * \param file optional pointer to the file that we close (used for pretty printing potential exceptions).
70 : * \exception OksSystem::CloseFail if there is problem in the \c close okssystem call
71 : */
72 :
73 0 : void OksSystem::Descriptor::close() {
74 0 : const int status = ::close(m_fd);
75 0 : if (status<0) {
76 0 : throw OksSystem::CloseFileIssue( ERS_HERE, errno, m_name.c_str() );
77 : } //
78 0 : m_fd = -1 ;
79 0 : } // close
80 :
81 :
82 : /** Closes a descriptor safely, i.e without throwing exceptions
83 : * If there is a proble, the information is sent to the warning stream
84 : */
85 :
86 0 : void OksSystem::Descriptor::close_safe() throw() {
87 0 : const int status = ::close(m_fd);
88 0 : if (status<0) {
89 0 : ers::warning( OksSystem::CloseFileIssue( ERS_HERE, errno, m_name.c_str() ) );
90 : } // if
91 0 : } // close_safe
92 :
93 0 : int OksSystem::Descriptor::read(void* buffer, size_t number) const {
94 0 : ssize_t status = ::read(m_fd,buffer,number);
95 0 : if (status<0) throw OksSystem::ReadIssue( ERS_HERE, errno, m_name.c_str() );
96 0 : return status;
97 : } // read
98 :
99 :
100 0 : int OksSystem::Descriptor::write(const void* buffer, size_t number) const {
101 0 : ssize_t status = ::write(m_fd,buffer,number);
102 0 : if (status<0) throw OksSystem::WriteIssue( ERS_HERE, errno, m_name.c_str() );
103 0 : return status;
104 : } // write
105 :
106 0 : int OksSystem::Descriptor::fd() const throw() {
107 0 : return m_fd;
108 : }
109 :
110 : /**
111 : * \brief It flags the file descriptor to be closed after any call to the exec okssystem function.
112 : */
113 :
114 0 : void OksSystem::Descriptor::closeOnExec() {
115 :
116 0 : bool success = false;
117 0 : int storeErrno = 0;
118 :
119 0 : int oldFlags = ::fcntl(m_fd, F_GETFD);
120 0 : if(oldFlags != -1) {
121 0 : int newFlags = ::fcntl(m_fd, F_SETFD, oldFlags|FD_CLOEXEC);
122 0 : if(newFlags == -1) {
123 0 : storeErrno = errno;
124 : } else {
125 : success = true;
126 : }
127 : } else {
128 0 : storeErrno = errno;
129 : }
130 :
131 0 : if(!success) {
132 0 : std::string eMsg = "File descriptor for file " + m_name +
133 0 : " will not be closed after exec. Reason: " + std::string(::strerror(storeErrno));
134 0 : throw OksSystem::OksSystemCallIssue(ERS_HERE, storeErrno, "fcntl", eMsg.c_str());
135 0 : }
136 :
137 0 : }
|