1 /* 2 * Copyright 2008, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 #ifndef UNIX_ADDRESS_H 6 #define UNIX_ADDRESS_H 7 8 #include <sys/un.h> 9 10 #include <SupportDefs.h> 11 12 13 // NOTE: We support the standard FS address space as well as the alternative 14 // internal address space Linux features (sun_path[0] is 0, followed by 5 hex 15 // digits, without null-termination). The latter one is nice to have, because 16 // the address lookup is quick (hash table lookup, instead of asking the VFS to 17 // resolve the path), and we don't have to pollute the FS when auto-binding 18 // sockets (e.g. on connect()). 19 20 21 #define INTERNAL_UNIX_ADDRESS_LEN (2 + 1 + 5) 22 // sun_len + sun_family + null byte + 5 hex digits 23 24 25 struct vnode; 26 27 28 class UnixAddress { 29 public: UnixAddress()30 UnixAddress() 31 { 32 Unset(); 33 } 34 UnixAddress(const UnixAddress & other)35 UnixAddress(const UnixAddress& other) 36 { 37 *this = other; 38 } 39 UnixAddress(int32 internalID)40 UnixAddress(int32 internalID) 41 { 42 SetTo(internalID); 43 } 44 UnixAddress(dev_t volumeID,ino_t nodeID,struct vnode * vnode)45 UnixAddress(dev_t volumeID, ino_t nodeID, struct vnode* vnode) 46 { 47 SetTo(volumeID, nodeID, vnode); 48 } 49 SetTo(int32 internalID)50 void SetTo(int32 internalID) 51 { 52 fInternalID = internalID; 53 fVolumeID = -1; 54 fNodeID = -1; 55 fVnode = NULL; 56 } 57 SetTo(dev_t volumeID,ino_t nodeID,struct vnode * vnode)58 void SetTo(dev_t volumeID, ino_t nodeID, struct vnode* vnode) 59 { 60 fInternalID = -1; 61 fVolumeID = volumeID; 62 fNodeID = nodeID; 63 fVnode = vnode; 64 } 65 Unset()66 void Unset() 67 { 68 fInternalID = -1; 69 fVolumeID = -1; 70 fNodeID = -1; 71 fVnode = NULL; 72 } 73 IsValid()74 bool IsValid() const 75 { 76 return fInternalID >= 0 || fVolumeID >= 0; 77 } 78 IsInternalAddress()79 bool IsInternalAddress() const 80 { 81 return fInternalID >= 0; 82 } 83 InternalID()84 int32 InternalID() const 85 { 86 return fInternalID; 87 } 88 VolumeID()89 int32 VolumeID() const 90 { 91 return fVolumeID; 92 } 93 NodeID()94 int32 NodeID() const 95 { 96 return fNodeID; 97 } 98 Vnode()99 struct vnode* Vnode() const 100 { 101 return fVnode; 102 } 103 HashCode()104 uint32 HashCode() const 105 { 106 return fInternalID >= 0 107 ? fInternalID 108 : uint32(fVolumeID) ^ uint32(fNodeID); 109 } 110 111 char* ToString(char *buffer, size_t bufferSize) const; 112 113 UnixAddress& operator=(const UnixAddress& other) 114 { 115 fInternalID = other.fInternalID; 116 fVolumeID = other.fVolumeID; 117 fNodeID = other.fNodeID; 118 fVnode = other.fVnode; 119 return *this; 120 } 121 122 bool operator==(const UnixAddress& other) const 123 { 124 return fInternalID >= 0 125 ? fInternalID == other.fInternalID 126 : fVolumeID == other.fVolumeID 127 && fNodeID == other.fNodeID; 128 } 129 130 bool operator!=(const UnixAddress& other) const 131 { 132 return !(*this == other); 133 } 134 IsEmptyAddress(const sockaddr_un & address)135 static bool IsEmptyAddress(const sockaddr_un& address) 136 { 137 return address.sun_len == sizeof(sockaddr) 138 && address.sun_path[0] == '\0' && address.sun_path[1] == '\0'; 139 } 140 InternalID(const sockaddr_un & address)141 static int32 InternalID(const sockaddr_un& address) 142 { 143 if (address.sun_len < INTERNAL_UNIX_ADDRESS_LEN 144 || address.sun_path[0] != '\0') { 145 return B_BAD_VALUE; 146 } 147 148 // parse the ID 149 int32 id = 0; 150 151 for (int32 i = 0; i < 5; i++) { 152 char c = address.sun_path[i + 1]; 153 if (c >= '0' && c <= '9') 154 id = (id << 4) + (c - '0'); 155 else if (c >= 'a' && c <= 'f') 156 id = (id << 4) + 10 + (c - 'a'); 157 else 158 return B_BAD_VALUE; 159 } 160 161 return id; 162 } 163 164 private: 165 // fat interface: If fInternalID is >= 0, it's an address in the internal 166 // namespace, otherwise a FS address. 167 int32 fInternalID; 168 dev_t fVolumeID; 169 ino_t fNodeID; 170 struct vnode* fVnode; 171 }; 172 173 174 #endif // UNIX_ADDRESS_H 175