From 438a7ccdb684864070f033370af5fb3716e44410 Mon Sep 17 00:00:00 2001
From: Eric Cano <Eric.Cano@cern.ch>
Date: Fri, 15 Jan 2016 16:51:21 +0100
Subject: [PATCH] Completed the removal of dependancies to castor packages for
 the main CTA binaries. Added more legacy messages implementations that were
 needed, and the SmartCap class. Fixed bug in re-written part of io.cpp
 (detected by unit test).

---
 tapeserver/castor/io/io.cpp                   |   2 +-
 tapeserver/castor/legacymsg/CMakeLists.txt    |  15 +-
 tapeserver/castor/legacymsg/CommonMarshal.cpp |  88 ++++
 .../legacymsg/GenericErrorReplyMsgBody.cpp    |  33 ++
 .../castor/legacymsg/GenericMarshal_1.hpp     | 139 ------
 .../castor/legacymsg/GenericReplyMsgBody.cpp  |  34 ++
 .../castor/legacymsg/RmcMountMsgBody.cpp      |  38 ++
 tapeserver/castor/legacymsg/RmcProxy.cpp      |  30 ++
 tapeserver/castor/legacymsg/RmcProxyDummy.cpp |  50 ++
 .../castor/legacymsg/RmcUnmountMsgBody.cpp    |  38 ++
 .../legacymsg/TapeConfigRequestMsgBody.cpp    |  36 ++
 tapeserver/castor/legacymsg/TapeMarshal.cpp   | 453 ++++++++++++++++++
 .../castor/legacymsg/TapeStatDriveEntry.cpp   |  45 ++
 .../castor/legacymsg/TapeStatReplyMsgBody.cpp |  33 ++
 .../legacymsg/TapeStatRequestMsgBody.cpp      |  29 ++
 tapeserver/castor/legacymsg/legacymsg.cpp     |  90 ++++
 tapeserver/castor/server/CMakeLists.txt       |   3 +
 tapeserver/castor/server/SmartCap.cpp         |  97 ++++
 18 files changed, 1112 insertions(+), 141 deletions(-)
 create mode 100644 tapeserver/castor/legacymsg/CommonMarshal.cpp
 create mode 100644 tapeserver/castor/legacymsg/GenericErrorReplyMsgBody.cpp
 delete mode 100644 tapeserver/castor/legacymsg/GenericMarshal_1.hpp
 create mode 100644 tapeserver/castor/legacymsg/GenericReplyMsgBody.cpp
 create mode 100644 tapeserver/castor/legacymsg/RmcMountMsgBody.cpp
 create mode 100644 tapeserver/castor/legacymsg/RmcProxy.cpp
 create mode 100644 tapeserver/castor/legacymsg/RmcProxyDummy.cpp
 create mode 100644 tapeserver/castor/legacymsg/RmcUnmountMsgBody.cpp
 create mode 100644 tapeserver/castor/legacymsg/TapeConfigRequestMsgBody.cpp
 create mode 100644 tapeserver/castor/legacymsg/TapeMarshal.cpp
 create mode 100644 tapeserver/castor/legacymsg/TapeStatDriveEntry.cpp
 create mode 100644 tapeserver/castor/legacymsg/TapeStatReplyMsgBody.cpp
 create mode 100644 tapeserver/castor/legacymsg/TapeStatRequestMsgBody.cpp
 create mode 100644 tapeserver/castor/legacymsg/legacymsg.cpp
 create mode 100644 tapeserver/castor/server/SmartCap.cpp

diff --git a/tapeserver/castor/io/io.cpp b/tapeserver/castor/io/io.cpp
index e2eaba8fe6..1f407b1067 100644
--- a/tapeserver/castor/io/io.cpp
+++ b/tapeserver/castor/io/io.cpp
@@ -735,7 +735,7 @@ void castor::io::writeBytes(
       }
     }
     {
-      int sendRet = recv(socketFd, writePtr, bytesRemaining, 0);
+      int sendRet = send(socketFd, writePtr, bytesRemaining, 0);
       cta::exception::Errnum::throwOnMinusOne(sendRet, "In io::writeBytes: failed to send data: ");
       if (sendRet > 0) {
         // We did read more data...
diff --git a/tapeserver/castor/legacymsg/CMakeLists.txt b/tapeserver/castor/legacymsg/CMakeLists.txt
index 4d96f0ad85..017cde5bd0 100644
--- a/tapeserver/castor/legacymsg/CMakeLists.txt
+++ b/tapeserver/castor/legacymsg/CMakeLists.txt
@@ -8,7 +8,20 @@ add_library (ctalegacymsg
   RmcProxyTcpIp.cpp
   RmcMarshal.cpp
   GenericMarshal.cpp
-  MessageHeader.cpp)
+  MessageHeader.cpp
+  legacymsg.cpp
+  TapeConfigRequestMsgBody.cpp
+  TapeMarshal.cpp
+  CommonMarshal.cpp
+  TapeStatReplyMsgBody.cpp
+  TapeStatRequestMsgBody.cpp
+  GenericErrorReplyMsgBody.cpp
+  GenericReplyMsgBody.cpp
+  TapeStatDriveEntry.cpp
+  RmcProxy.cpp
+  RmcMountMsgBody.cpp
+  RmcUnmountMsgBody.cpp
+  RmcProxyDummy.cpp)
 
 add_library (ctalegacymsgunittests SHARED
   CommonMarshalTest.cpp
diff --git a/tapeserver/castor/legacymsg/CommonMarshal.cpp b/tapeserver/castor/legacymsg/CommonMarshal.cpp
new file mode 100644
index 0000000000..5151064291
--- /dev/null
+++ b/tapeserver/castor/legacymsg/CommonMarshal.cpp
@@ -0,0 +1,88 @@
+/******************************************************************************
+ *
+ * This file is part of the Castor project.
+ * See http://castor.web.cern.ch/castor
+ *
+ * Copyright (C) 2003  CERN
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ *
+ *
+ * @author Castor Dev team, castor-dev@cern.ch
+ *****************************************************************************/
+
+#include "castor/io/io.hpp"
+#include "castor/legacymsg/CommonMarshal.hpp"
+
+#include <errno.h>
+#include <iostream>
+#include <string.h>
+
+
+//-----------------------------------------------------------------------------
+// marshal
+//-----------------------------------------------------------------------------
+size_t castor::legacymsg::marshal(char *const dst, const size_t dstLen,
+  const MessageHeader &src)  {
+
+  if(dst == NULL) {
+    castor::exception::Exception ex;
+    ex.getMessage() << "Failed to marshal MessageHeader"
+      << ": Pointer to destination buffer is NULL";
+    throw ex;
+  }
+
+  // Calculate the length of the message header
+  const uint32_t totalLen = 3 * sizeof(uint32_t);  // magic + reqType + len
+
+  // Check that the message header buffer is big enough
+  if(totalLen > dstLen) {
+    castor::exception::Exception ex;
+    ex.getMessage() << "Failed to marshal MessageHeader"
+      ": Buffer too small : required=" << totalLen << " actual=" << dstLen;
+    throw ex;
+  }
+
+  // Marshal the message header
+  char *p = dst;
+  io::marshalUint32(src.magic      , p);
+  io::marshalUint32(src.reqType    , p);
+  io::marshalUint32(src.lenOrStatus, p);
+
+  // Calculate the number of bytes actually marshalled
+  const size_t nbBytesMarshalled = p - dst;
+
+  // Check that the number of bytes marshalled was what was expected
+  if(totalLen != nbBytesMarshalled) {
+    castor::exception::Exception ex;
+    ex.getMessage() << "Failed to marshal MessageHeader"
+      ": Mismatch between expected total length and actual"
+      ": expected=" << totalLen << " actual=" << nbBytesMarshalled;
+    throw ex;
+  }
+
+  return totalLen;
+}
+
+
+//-----------------------------------------------------------------------------
+// unmarshal
+//-----------------------------------------------------------------------------
+void castor::legacymsg::unmarshal(const char * &src, size_t &srcLen,
+  MessageHeader &dst)  {
+
+  io::unmarshalUint32(src, srcLen, dst.magic);
+  io::unmarshalUint32(src, srcLen, dst.reqType);
+  io::unmarshalUint32(src, srcLen, dst.lenOrStatus);
+}
diff --git a/tapeserver/castor/legacymsg/GenericErrorReplyMsgBody.cpp b/tapeserver/castor/legacymsg/GenericErrorReplyMsgBody.cpp
new file mode 100644
index 0000000000..035ae056a3
--- /dev/null
+++ b/tapeserver/castor/legacymsg/GenericErrorReplyMsgBody.cpp
@@ -0,0 +1,33 @@
+/******************************************************************************
+ *
+ * This file is part of the Castor project.
+ * See http://castor.web.cern.ch/castor
+ *
+ * Copyright (C) 2003  CERN
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * 
+ * @author Castor Dev team, castor-dev@cern.ch
+ *****************************************************************************/
+
+#include "castor/legacymsg/GenericErrorReplyMsgBody.hpp"
+
+#include <string.h>
+
+//-----------------------------------------------------------------------------
+// constructor
+//-----------------------------------------------------------------------------
+castor::legacymsg::GenericErrorReplyMsgBody::GenericErrorReplyMsgBody() throw() {
+  memset(errorMessage, '\0', sizeof(errorMessage));
+}
diff --git a/tapeserver/castor/legacymsg/GenericMarshal_1.hpp b/tapeserver/castor/legacymsg/GenericMarshal_1.hpp
deleted file mode 100644
index c8ca236992..0000000000
--- a/tapeserver/castor/legacymsg/GenericMarshal_1.hpp
+++ /dev/null
@@ -1,139 +0,0 @@
-/******************************************************************************
- *
- * This file is part of the Castor project.
- * See http://castor.web.cern.ch/castor
- *
- * Copyright (C) 2003  CERN
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- *
- *
- *
- * @author Castor Dev team, castor-dev@cern.ch
- *****************************************************************************/
-
-#pragma once
-
-#include "castor/exception/Exception.hpp"
-#include "castor/legacymsg/GenericReplyMsgBody.hpp"
-#include "castor/legacymsg/GenericErrorReplyMsgBody.hpp"
-
-#include <stdint.h>
-
-namespace castor {
-namespace legacymsg {
-
-/**
- * Marshals the specified source message into the specified destination buffer.
- *
- * Please note that this method marshals the length of the message body as the
- * third field of the message header (message header = magic + reqType + len).
- *
- * @param dst        The destination message buffer.
- * @param dstLen     The length of the destination buffer.
- * @param srcMagic   The magic number of the source message.
- * @param srcReqType The request type of the source message.
- * @param srcBody    The body of the source message.
- *
- * @return         The total length of the message (header + body).
- */
-size_t marshal(char *const dst, const size_t dstLen, const uint32_t srcMagic,
-  const uint32_t srcReqType, const GenericReplyMsgBody &srcBody)
-  ;
-
-/**
- * Marshals the specified source message into the specified destination buffer.
- *
- * Please note that this method marshals the length of the message body as the
- * third field of the message header (message header = magic + reqType + len).
- *
- * @param dst        The destination message buffer.
- * @param srcMagic   The magic number of the source message.
- * @param srcReqType The request type of the source message.
- * @param srcBody    The body of the source message.
- * @return           The total length of the message (header + body).
- */
-template<int n> size_t marshal(char (&dst)[n], const uint32_t srcMagic,
-  const uint32_t srcReqType, const GenericReplyMsgBody &srcBody)
-   {
-  return marshal(dst, n, srcMagic, srcReqType, srcBody);
-}
-
-/**
- * Unmarshals a message body with the specified destination structure type
- * from the specified source buffer.
- *
- * @param src In/out parameter, before invocation points to the source
- * buffer where the message body should be unmarshalled from and on return
- * points to the byte in the source buffer immediately after the
- * unmarshalled message body.
- * @param srcLen In/out parameter, before invocation is the length of the
- * source buffer from where the message body should be unmarshalled and on
- * return is the number of bytes remaining in the source buffer.
- * @param dst The destination message body structure.
- */
-void unmarshal(const char * &src, size_t &srcLen, GenericReplyMsgBody &dst) ;
-
-/**
- * Marshals the specified source message into the specified destination buffer.
- *
- * Please note that this method marshals the length of the message body as the
- * third field of the message header (message header = magic + reqType + len).
- *
- * @param dst        The destination message buffer.
- * @param dstLen     The length of the destination buffer.
- * @param srcMagic   The magic number of the source message.
- * @param srcReqType The request type of the source message.
- * @param srcBody    The body of the source message.
- *
- * @return         The total length of the message (header + body).
- */
-size_t marshal(char *const dst, const size_t dstLen, const uint32_t srcMagic,
-  const uint32_t srcReqType, const GenericErrorReplyMsgBody &srcBody)
-  ;
-
-/**
- * Marshals the specified source message into the specified destination buffer.
- *
- * Please note that this method marshals the length of the message body as the
- * third field of the message header (message header = magic + reqType + len).
- *
- * @param dst        The destination message buffer.
- * @param srcMagic   The magic number of the source message.
- * @param srcReqType The request type of the source message.
- * @param srcBody    The body of the source message.
- * @return           The total length of the message (header + body).
- */
-template<int n> size_t marshal(char (&dst)[n], const uint32_t srcMagic,
-  const uint32_t srcReqType, const GenericErrorReplyMsgBody &srcBody)
-   {
-  return marshal(dst, n, srcMagic, srcReqType, srcBody);
-}
-
-/**
- * Unmarshals a message body with the specified destination structure type
- * from the specified source buffer.
- *
- * @param src In/out parameter, before invocation points to the source
- * buffer where the message body should be unmarshalled from and on return
- * points to the byte in the source buffer immediately after the
- * unmarshalled message body.
- * @param srcLen In/out parameter, before invocation is the length of the
- * source buffer from where the message body should be unmarshalled and on
- * return is the number of bytes remaining in the source buffer.
- * @param dst The destination message body structure.
- */
-void unmarshal(const char * &src, size_t &srcLen, GenericErrorReplyMsgBody &dst) ;
-
-} // namespace legacymsg
-} // namespace castor
diff --git a/tapeserver/castor/legacymsg/GenericReplyMsgBody.cpp b/tapeserver/castor/legacymsg/GenericReplyMsgBody.cpp
new file mode 100644
index 0000000000..141688fb1f
--- /dev/null
+++ b/tapeserver/castor/legacymsg/GenericReplyMsgBody.cpp
@@ -0,0 +1,34 @@
+/******************************************************************************
+ *
+ * This file is part of the Castor project.
+ * See http://castor.web.cern.ch/castor
+ *
+ * Copyright (C) 2003  CERN
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * 
+ * @author Castor Dev team, castor-dev@cern.ch
+ *****************************************************************************/
+
+#include "castor/legacymsg/GenericReplyMsgBody.hpp"
+
+#include <string.h>
+
+//-----------------------------------------------------------------------------
+// constructor
+//-----------------------------------------------------------------------------
+castor::legacymsg::GenericReplyMsgBody::GenericReplyMsgBody() throw():
+  status(0) {
+  memset(errorMessage, '\0', sizeof(errorMessage));
+}
diff --git a/tapeserver/castor/legacymsg/RmcMountMsgBody.cpp b/tapeserver/castor/legacymsg/RmcMountMsgBody.cpp
new file mode 100644
index 0000000000..44be575cb0
--- /dev/null
+++ b/tapeserver/castor/legacymsg/RmcMountMsgBody.cpp
@@ -0,0 +1,38 @@
+/******************************************************************************
+ *
+ * This file is part of the Castor project.
+ * See http://castor.web.cern.ch/castor
+ *
+ * Copyright (C) 2003  CERN
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * 
+ * @author Castor Dev team, castor-dev@cern.ch
+ *****************************************************************************/
+
+#include "castor/legacymsg/RmcMountMsgBody.hpp"
+
+#include <string.h>
+
+//------------------------------------------------------------------------------
+// constructor
+//------------------------------------------------------------------------------
+castor::legacymsg::RmcMountMsgBody::RmcMountMsgBody() throw():
+  uid(0),
+  gid(0),
+  side(0),
+  drvOrd(0) {
+  memset(unusedLoader, '\0', sizeof(unusedLoader));
+  memset(vid, '\0', sizeof(vid));
+}
diff --git a/tapeserver/castor/legacymsg/RmcProxy.cpp b/tapeserver/castor/legacymsg/RmcProxy.cpp
new file mode 100644
index 0000000000..6103e369a1
--- /dev/null
+++ b/tapeserver/castor/legacymsg/RmcProxy.cpp
@@ -0,0 +1,30 @@
+/******************************************************************************
+ *
+ * This file is part of the Castor project.
+ * See http://castor.web.cern.ch/castor
+ *
+ * Copyright (C) 2003  CERN
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ *
+ * @author Castor Dev team, castor-dev@cern.ch
+ *****************************************************************************/
+
+#include "castor/legacymsg/RmcProxy.hpp"
+
+//-----------------------------------------------------------------------------
+// destructor
+//-----------------------------------------------------------------------------
+castor::legacymsg::RmcProxy::~RmcProxy() throw() {
+}
diff --git a/tapeserver/castor/legacymsg/RmcProxyDummy.cpp b/tapeserver/castor/legacymsg/RmcProxyDummy.cpp
new file mode 100644
index 0000000000..342dceb609
--- /dev/null
+++ b/tapeserver/castor/legacymsg/RmcProxyDummy.cpp
@@ -0,0 +1,50 @@
+/******************************************************************************
+ *
+ * This file is part of the Castor project.
+ * See http://castor.web.cern.ch/castor
+ *
+ * Copyright (C) 2003  CERN
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * @author Castor Dev team, castor-dev@cern.ch
+ *****************************************************************************/
+
+#include "castor/legacymsg/RmcProxyDummy.hpp"
+
+//------------------------------------------------------------------------------
+// mountTapeReadOnly
+//------------------------------------------------------------------------------
+void castor::legacymsg::RmcProxyDummy::mountTapeReadOnly(const std::string &vid,
+  const mediachanger::ScsiLibrarySlot &librarySlot) {
+}
+
+//------------------------------------------------------------------------------
+// mountTapeReadWrite
+//------------------------------------------------------------------------------
+void castor::legacymsg::RmcProxyDummy::mountTapeReadWrite(const std::string &vid,
+  const mediachanger::ScsiLibrarySlot &librarySlot) {
+}
+
+//------------------------------------------------------------------------------
+// dismountTape
+//------------------------------------------------------------------------------
+void castor::legacymsg::RmcProxyDummy::dismountTape(const std::string &vid,
+  const mediachanger::ScsiLibrarySlot &librarySlot) {
+}
+
+//------------------------------------------------------------------------------
+// forceDismountTape
+//------------------------------------------------------------------------------
+void castor::legacymsg::RmcProxyDummy::forceDismountTape(const std::string &vid,
+  const mediachanger::ScsiLibrarySlot &librarySlot) {
+}
diff --git a/tapeserver/castor/legacymsg/RmcUnmountMsgBody.cpp b/tapeserver/castor/legacymsg/RmcUnmountMsgBody.cpp
new file mode 100644
index 0000000000..41d3538a64
--- /dev/null
+++ b/tapeserver/castor/legacymsg/RmcUnmountMsgBody.cpp
@@ -0,0 +1,38 @@
+/******************************************************************************
+ *
+ * This file is part of the Castor project.
+ * See http://castor.web.cern.ch/castor
+ *
+ * Copyright (C) 2003  CERN
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * 
+ * @author Castor Dev team, castor-dev@cern.ch
+ *****************************************************************************/
+
+#include "castor/legacymsg/RmcUnmountMsgBody.hpp"
+
+#include <string.h>
+
+//------------------------------------------------------------------------------
+// constructor
+//------------------------------------------------------------------------------
+castor::legacymsg::RmcUnmountMsgBody::RmcUnmountMsgBody() throw():
+  uid(0),
+  gid(0),
+  drvOrd(0),
+  force(0) {
+  memset(unusedLoader, '\0', sizeof(unusedLoader));
+  memset(vid, '\0', sizeof(vid));
+}
diff --git a/tapeserver/castor/legacymsg/TapeConfigRequestMsgBody.cpp b/tapeserver/castor/legacymsg/TapeConfigRequestMsgBody.cpp
new file mode 100644
index 0000000000..9c019cc7b8
--- /dev/null
+++ b/tapeserver/castor/legacymsg/TapeConfigRequestMsgBody.cpp
@@ -0,0 +1,36 @@
+/******************************************************************************
+ *
+ * This file is part of the Castor project.
+ * See http://castor.web.cern.ch/castor
+ *
+ * Copyright (C) 2003  CERN
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * 
+ * @author Castor Dev team, castor-dev@cern.ch
+ *****************************************************************************/
+
+#include "castor/legacymsg/TapeConfigRequestMsgBody.hpp"
+
+#include <string.h>
+
+//------------------------------------------------------------------------------
+// constructor
+//------------------------------------------------------------------------------
+castor::legacymsg::TapeConfigRequestMsgBody::TapeConfigRequestMsgBody() throw():
+  uid(0),
+  gid(0),
+  status(0) {
+  memset(drive, '\0', sizeof(drive));
+}
diff --git a/tapeserver/castor/legacymsg/TapeMarshal.cpp b/tapeserver/castor/legacymsg/TapeMarshal.cpp
new file mode 100644
index 0000000000..4a9ad4c339
--- /dev/null
+++ b/tapeserver/castor/legacymsg/TapeMarshal.cpp
@@ -0,0 +1,453 @@
+/******************************************************************************
+ *
+ * This file is part of the Castor project.
+ * See http://castor.web.cern.ch/castor
+ *
+ * Copyright (C) 2003  CERN
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ *
+ *
+ * @author Castor Dev team, castor-dev@cern.ch
+ *****************************************************************************/
+
+#include "castor/io/io.hpp"
+#include "castor/legacymsg/CommonMarshal.hpp"
+#include "castor/legacymsg/TapeMarshal.hpp"
+#include "rtcp_constants.h"
+#include "Ctape.h"
+
+#include <errno.h>
+#include <string.h>
+
+//-----------------------------------------------------------------------------
+// marshal
+//-----------------------------------------------------------------------------
+size_t castor::legacymsg::marshal(char *const dst, const size_t dstLen,
+  const TapeStatRequestMsgBody &src)  {
+  const char *const task = "marshal TapeStatRequestMsgBody";
+
+  if(dst == NULL) {
+    castor::exception::Exception ex;
+    ex.getMessage() << "Failed to " << task <<
+      ": Pointer to destination buffer is NULL";
+    throw ex;
+  }
+
+  // Calculate the length of the message body
+  const size_t bodyLen =
+    sizeof(src.uid) +
+    sizeof(src.gid);
+
+  // Calculate the total length of the message (header + body)
+  const uint32_t totalLen =
+    sizeof(uint32_t) + // Magic number
+    sizeof(uint32_t) + // Request type
+    sizeof(uint32_t) + // Length of message body
+    bodyLen;
+
+  // Check that the message buffer is big enough
+  if(totalLen > dstLen) {
+    castor::exception::Exception ex;
+    ex.getMessage() << "Failed to " << task <<
+      ": Buffer too small: required=" << totalLen << " actual=" << dstLen;
+    throw ex;
+  }
+
+  // Marshall message header
+  char *p = dst;
+  try {
+    const uint32_t magic = TPMAGIC;
+    const uint32_t reqType = TPSTAT;
+    io::marshalUint32(magic , p);
+    io::marshalUint32(reqType, p);
+    io::marshalUint32(totalLen, p);
+  } catch(castor::exception::Exception &ne) {
+    castor::exception::Exception ex;
+    ex.getMessage() << "Failed to " << task << ": Failed to marshal header: "
+      << ne.getMessage().str();
+    throw ex;
+  }
+
+  // Marshal message body
+  try {
+    io::marshalUint32(src.uid, p);
+    io::marshalUint32(src.gid, p);
+  } catch(castor::exception::Exception &ne) {
+    castor::exception::Exception ex; 
+    ex.getMessage() << "Failed to " << task << ": Failed to marshal body: "
+      << ne.getMessage().str();
+    throw ex;
+  }
+
+  // Calculate the number of bytes actually marshalled
+  const size_t nbBytesMarshalled = p - dst;
+
+  // Check that the number of bytes marshalled was what was expected
+  if(totalLen != nbBytesMarshalled) {
+    castor::exception::Exception ex;
+    ex.getMessage() << "Failed to " << task <<
+      ": Mismatch between expected total length and actual"
+      ": expected=" << totalLen << " actual=" << nbBytesMarshalled;
+    throw ex;
+  }
+
+  return totalLen;
+}
+
+//-----------------------------------------------------------------------------
+// marshal
+//-----------------------------------------------------------------------------
+size_t castor::legacymsg::marshal(char *const dst, const size_t dstLen,
+  const TapeStatReplyMsgBody &body)  {
+  const char *const task = "marshall TapeStatReplyMsgBody";
+
+  if(dst == NULL) {
+    castor::exception::Exception ex;
+    ex.getMessage() << "Failed to " << task <<
+      ": Pointer to destination buffer is NULL";
+    throw ex;
+  }
+
+  // Calculate the length of the message body
+  uint32_t bodyLen = sizeof(body.number_of_drives);
+  for(uint16_t i = 0; i<body.number_of_drives; i++) {
+    bodyLen +=
+      sizeof(body.drives[i].uid)         +
+      sizeof(body.drives[i].jid)         +
+      strlen(body.drives[i].logicalLibrary) + 1     +
+      sizeof(body.drives[i].up)          +
+      sizeof(body.drives[i].asn)         +
+      sizeof(body.drives[i].asn_time)    +
+      strlen(body.drives[i].drive) + 1   +
+      sizeof(body.drives[i].mode)        +
+      strlen(body.drives[i].lblcode) + 1 +
+      sizeof(body.drives[i].tobemounted) +
+      strlen(body.drives[i].vid) + 1     +
+      strlen(body.drives[i].vsn) + 1     +
+      sizeof(body.drives[i].cfseq);
+  }
+
+  // Calculate the total length of the message (header + body)
+  const uint32_t totalLen =
+    sizeof(uint32_t) + // Magic number
+    sizeof(uint32_t) + // Request type
+    sizeof(uint32_t) + // Length of message body
+    bodyLen;
+
+  // Check that the message header buffer is big enough
+  if(totalLen > dstLen) {
+    castor::exception::Exception ex;
+    ex.getMessage() << "Failed to " << task <<
+      ": Buffer too small: required=" << totalLen << " actual=" << dstLen;
+    throw ex;
+  }
+
+  // Marshal message header
+  char *p = dst;
+  try {
+    const uint32_t magic = TPMAGIC;
+    const uint32_t reqType = MSG_DATA;
+    io::marshalUint32(magic, p);
+    io::marshalUint32(reqType, p);
+    io::marshalUint32(bodyLen, p);
+  } catch(castor::exception::Exception &ne) {
+    castor::exception::Exception ex;
+    ex.getMessage() << "Failed to " << task << ": Failed to marshal header: "
+      << ne.getMessage().str();
+    throw ex;
+  }
+
+  // Marshal message body
+  try {
+    io::marshalUint16(body.number_of_drives, p);
+
+    for(int i=0; i<body.number_of_drives; i++) {
+      io::marshalUint32(body.drives[i].uid, p);
+      io::marshalUint32(body.drives[i].jid, p);
+      io::marshalString(body.drives[i].logicalLibrary, p);
+      io::marshalUint16(body.drives[i].up, p);
+      io::marshalUint16(body.drives[i].asn, p);
+      io::marshalUint32(body.drives[i].asn_time, p);
+      io::marshalString(body.drives[i].drive, p);
+      io::marshalUint16(body.drives[i].mode, p);
+      io::marshalString(body.drives[i].lblcode, p);
+      io::marshalUint16(body.drives[i].tobemounted, p);
+      io::marshalString(body.drives[i].vid, p);
+      io::marshalString(body.drives[i].vsn, p);
+      io::marshalUint32(body.drives[i].cfseq, p);
+    }
+  } catch(castor::exception::Exception &ne) {
+    castor::exception::Exception ex;
+    ex.getMessage() << "Failed to " << task << ": Failed to marshal body: "
+      << ne.getMessage().str();
+    throw ex;
+  }
+
+  // Calculate the number of bytes actually marshalled
+  const size_t nbBytesMarshalled = p - dst;
+
+  // Check that the number of bytes marshalled was what was expected
+  if(totalLen != nbBytesMarshalled) {
+    castor::exception::Exception ex;
+    ex.getMessage() << "Failed to marshal TapeStatReplyMsgBody"
+      ": Mismatch between expected total length and actual"
+      ": expected=" << totalLen << " actual=" << nbBytesMarshalled;
+    throw ex;
+  }
+
+  return totalLen;
+}
+
+//-----------------------------------------------------------------------------
+// marshal
+//-----------------------------------------------------------------------------
+size_t castor::legacymsg::marshal(char *const dst, const size_t dstLen,
+  const TapeConfigRequestMsgBody &src)  {
+  const char *const task = "marshal TapeConfigRequestMsgBody";
+
+  if(dst == NULL) {
+    castor::exception::Exception ex;
+    ex.getMessage() << "Failed to " << task <<
+      ": Pointer to destination buffer is NULL";
+    throw ex;
+  }
+
+  // Calculate the length of the message body
+  const uint32_t bodyLen =
+    sizeof(src.uid) +
+    sizeof(src.gid) +
+    strlen(src.drive) + 1 +
+    sizeof(src.status);
+
+  // Calculate the total length of the message (header + body)
+  const uint32_t totalLen =
+    sizeof(uint32_t) + // magic
+    sizeof(uint32_t) + // reqType
+    sizeof(uint32_t) + // len
+    bodyLen;
+
+  // Check that the message buffer is big enough
+  if(totalLen > dstLen) {
+    castor::exception::Exception ex;
+    ex.getMessage() << "Failed to " << task <<
+      ": Buffer too small: required=" << totalLen << " actual=" << dstLen;
+    throw ex;
+  }
+
+  // Marshal message header
+  char *p = dst;
+  try {
+    const uint32_t magic = TPMAGIC;
+    const uint32_t reqType = TPCONF;
+    io::marshalUint32(magic , p);
+    io::marshalUint32(reqType, p);
+    io::marshalUint32(totalLen, p);
+  } catch(castor::exception::Exception &ne) {
+    castor::exception::Exception ex;
+    ex.getMessage() << "Failed to " << task << ": Failed to marshal header: "
+      << ne.getMessage().str();
+    throw ex;
+  } 
+
+  // Marshal message body
+  try {
+    io::marshalUint32(src.uid, p);
+    io::marshalUint32(src.gid, p);
+    io::marshalString(src.drive, p);
+    io::marshalUint16(src.status, p);
+  } catch(castor::exception::Exception &ne) {
+    castor::exception::Exception ex;
+    ex.getMessage() << "Failed to " << task << ": Failed to marshal body: "
+      << ne.getMessage().str();
+    throw ex;
+  }
+
+  // Calculate the number of bytes actually marshalled
+  const size_t nbBytesMarshalled = p - dst;
+
+  // Check that the number of bytes marshalled was what was expected
+  if(totalLen != nbBytesMarshalled) {
+    castor::exception::Exception ex;
+    ex.getMessage() << "Failed to " << task <<
+      ": Mismatch between expected total length and actual"
+      ": expected=" << totalLen << " actual=" << nbBytesMarshalled;
+    throw ex;
+  }
+
+  return totalLen;
+}
+
+//-----------------------------------------------------------------------------
+// marshal
+//-----------------------------------------------------------------------------
+size_t castor::legacymsg::marshal(char *const dst, const size_t dstLen,
+  const TapeLabelRqstMsgBody &src)  {
+  const char *const task = "marshal TapeLabelRqstMsgBody";
+
+  if(dst == NULL) {
+    castor::exception::Exception ex;
+    ex.getMessage() << "Failed to " << task <<
+      ": Pointer to destination buffer is NULL";
+    throw ex;
+  }
+
+  // Calculate the length of the message body
+  const uint32_t bodyLen =
+    sizeof(src.force) + // force
+    sizeof(src.uid) + // uid
+    sizeof(src.gid) + // gid
+    strlen(src.vid) + 1 + // vid
+    strlen(src.drive) + 1 + // drive
+    strlen(src.logicalLibrary) + 1; // dgn
+
+  // Calculate the total length of the message (header + body)
+  const uint32_t totalLen =
+    sizeof(uint32_t) + // magic
+    sizeof(uint32_t) + // reqType
+    sizeof(uint32_t) + // len
+    bodyLen;
+
+  // Check that the message buffer is big enough
+  if(totalLen > dstLen) {
+    castor::exception::Exception ex;
+    ex.getMessage() << "Failed to " << task <<
+      ": Buffer too small: required=" << totalLen << " actual=" << dstLen;
+    throw ex;
+  }
+
+  // Marshal message header
+  char *p = dst;
+  try {
+    const uint32_t magic = TPMAGIC;
+    const uint32_t reqType = TPLABEL;
+    io::marshalUint32(magic , p);
+    io::marshalUint32(reqType, p);
+    io::marshalUint32(totalLen, p);
+  } catch(castor::exception::Exception &ne) {
+    castor::exception::Exception ex;
+    ex.getMessage() << "Failed to " << task << ": Failed to marshal header: "
+      << ne.getMessage().str();
+    throw ex;
+  }
+
+  // Marshal message body
+  try {
+    io::marshalUint16(src.force, p);
+    io::marshalUint32(src.uid, p);
+    io::marshalUint32(src.gid, p);
+    io::marshalString(src.vid, p);
+    io::marshalString(src.drive, p);
+    io::marshalString(src.logicalLibrary, p);
+  } catch(castor::exception::Exception &ne) {
+    castor::exception::Exception ex;
+    ex.getMessage() << "Failed to " << task << ": Failed to marshal body: "
+      << ne.getMessage().str();
+    throw ex;
+  }
+
+  // Calculate the number of bytes actually marshalled
+  const size_t nbBytesMarshalled = p - dst;
+
+  // Check that the number of bytes marshalled was what was expected
+  if(totalLen != nbBytesMarshalled) {
+    castor::exception::Exception ex;
+    ex.getMessage() << "Failed to " << task <<
+      ": Mismatch between expected total length and actual"
+      ": expected=" << totalLen << " actual=" << nbBytesMarshalled;
+    throw ex;
+  }
+
+  return totalLen;
+}
+
+//-----------------------------------------------------------------------------
+// unmarshal
+//-----------------------------------------------------------------------------
+void castor::legacymsg::unmarshal(const char * &src, size_t &srcLen, TapeStatReplyMsgBody &dst)  {
+  try {
+    io::unmarshalUint16(src, srcLen, dst.number_of_drives);
+    for(int i=0; i<dst.number_of_drives; i++) {
+      io::unmarshalUint32(src, srcLen, dst.drives[i].uid);
+      io::unmarshalUint32(src, srcLen, dst.drives[i].jid);
+      io::unmarshalString(src, srcLen, dst.drives[i].logicalLibrary);
+      io::unmarshalUint16(src, srcLen, dst.drives[i].up);
+      io::unmarshalUint16(src, srcLen, dst.drives[i].asn);
+      io::unmarshalUint32(src, srcLen, dst.drives[i].asn_time);
+      io::unmarshalString(src, srcLen, dst.drives[i].drive);
+      io::unmarshalUint16(src, srcLen, dst.drives[i].mode);
+      io::unmarshalString(src, srcLen, dst.drives[i].lblcode);
+      io::unmarshalUint16(src, srcLen, dst.drives[i].tobemounted);
+      io::unmarshalString(src, srcLen, dst.drives[i].vid);
+      io::unmarshalString(src, srcLen, dst.drives[i].vsn);
+      io::unmarshalUint32(src, srcLen, dst.drives[i].cfseq);
+    }
+  } catch(castor::exception::Exception &ne) {
+    castor::exception::Exception ex;
+    ex.getMessage() << "Failed to unmarshal TapeStatReplyMsgBody: " <<
+      ne.getMessage().str();
+    throw ex;
+  }
+}
+
+//-----------------------------------------------------------------------------
+// unmarshal
+//-----------------------------------------------------------------------------
+void castor::legacymsg::unmarshal(const char * &src, size_t &srcLen, TapeConfigRequestMsgBody &dst)  {
+  try {
+    io::unmarshalUint32(src, srcLen, dst.uid);
+    io::unmarshalUint32(src, srcLen, dst.gid);
+    io::unmarshalString(src, srcLen, dst.drive);
+    io::unmarshalInt16(src, srcLen, dst.status);
+  } catch(castor::exception::Exception &ne) {
+    castor::exception::Exception ex;
+    ex.getMessage() << "Failed to unmarshal TapeConfigRequestMsgBody: " <<
+      ne.getMessage().str();
+    throw ex;
+  }
+}
+
+//-----------------------------------------------------------------------------
+// unmarshal
+//-----------------------------------------------------------------------------
+void castor::legacymsg::unmarshal(const char * &src, size_t &srcLen, TapeLabelRqstMsgBody &dst)  {
+  try {
+    io::unmarshalUint16(src, srcLen, dst.force);
+    io::unmarshalUint32(src, srcLen, dst.uid);
+    io::unmarshalUint32(src, srcLen, dst.gid);
+    io::unmarshalString(src, srcLen, dst.vid);
+    io::unmarshalString(src, srcLen, dst.drive);
+    io::unmarshalString(src, srcLen, dst.logicalLibrary);
+  } catch(castor::exception::Exception &ne) {
+    castor::exception::Exception ex;
+    ex.getMessage() << "Failed to unmarshal TapeLabelRqstMsgBody: " <<
+      ne.getMessage().str();
+    throw ex;
+  }
+}
+
+//-----------------------------------------------------------------------------
+// unmarshal
+//-----------------------------------------------------------------------------
+void castor::legacymsg::unmarshal(const char * &src, size_t &srcLen, TapeStatRequestMsgBody &dst)  {
+  try {
+    io::unmarshalUint32(src, srcLen, dst.uid);
+    io::unmarshalUint32(src, srcLen, dst.gid);
+  } catch(castor::exception::Exception &ne) {
+    castor::exception::Exception ex;
+    ex.getMessage() << "Failed to unmarshal TapeStatRequestMsgBody: " <<
+      ne.getMessage().str();
+    throw ex;
+  }
+}
diff --git a/tapeserver/castor/legacymsg/TapeStatDriveEntry.cpp b/tapeserver/castor/legacymsg/TapeStatDriveEntry.cpp
new file mode 100644
index 0000000000..a527d78fb1
--- /dev/null
+++ b/tapeserver/castor/legacymsg/TapeStatDriveEntry.cpp
@@ -0,0 +1,45 @@
+/******************************************************************************
+ *
+ * This file is part of the Castor project.
+ * See http://castor.web.cern.ch/castor
+ *
+ * Copyright (C) 2003  CERN
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * 
+ * @author Castor Dev team, castor-dev@cern.ch
+ *****************************************************************************/
+
+#include "castor/legacymsg/TapeStatDriveEntry.hpp"
+
+#include <string.h>
+
+//------------------------------------------------------------------------------
+// constructor
+//------------------------------------------------------------------------------
+castor::legacymsg::TapeStatDriveEntry::TapeStatDriveEntry() throw():
+  uid(0),
+  jid(0),
+  up(0),
+  asn(0),
+  asn_time(0),
+  mode(0),
+  tobemounted(0),
+  cfseq(0) {
+  memset(logicalLibrary, '\0', sizeof(logicalLibrary));
+  memset(drive, '\0', sizeof(drive));
+  memset(lblcode, '\0', sizeof(lblcode));
+  memset(vid, '\0', sizeof(vid));
+  memset(vsn, '\0', sizeof(vsn));
+}  
diff --git a/tapeserver/castor/legacymsg/TapeStatReplyMsgBody.cpp b/tapeserver/castor/legacymsg/TapeStatReplyMsgBody.cpp
new file mode 100644
index 0000000000..6b35dae6e3
--- /dev/null
+++ b/tapeserver/castor/legacymsg/TapeStatReplyMsgBody.cpp
@@ -0,0 +1,33 @@
+/******************************************************************************
+ *
+ * This file is part of the Castor project.
+ * See http://castor.web.cern.ch/castor
+ *
+ * Copyright (C) 2003  CERN
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * 
+ * @author Castor Dev team, castor-dev@cern.ch
+ *****************************************************************************/
+
+#include "castor/legacymsg/TapeStatReplyMsgBody.hpp"
+
+#include <string.h>
+
+//------------------------------------------------------------------------------
+// constructor
+//------------------------------------------------------------------------------
+castor::legacymsg::TapeStatReplyMsgBody::TapeStatReplyMsgBody() throw():
+  number_of_drives(0) {
+}
diff --git a/tapeserver/castor/legacymsg/TapeStatRequestMsgBody.cpp b/tapeserver/castor/legacymsg/TapeStatRequestMsgBody.cpp
new file mode 100644
index 0000000000..bca5477a41
--- /dev/null
+++ b/tapeserver/castor/legacymsg/TapeStatRequestMsgBody.cpp
@@ -0,0 +1,29 @@
+/******************************************************************************
+ *
+ * This file is part of the Castor project.
+ * See http://castor.web.cern.ch/castor
+ *
+ * Copyright (C) 2003  CERN
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ * 
+ * @author Castor Dev team, castor-dev@cern.ch
+ *****************************************************************************/
+
+#include "castor/legacymsg/TapeStatRequestMsgBody.hpp"
+#include <string.h>
+
+castor::legacymsg::TapeStatRequestMsgBody::TapeStatRequestMsgBody() throw():
+  uid(0),
+  gid(0) {}
diff --git a/tapeserver/castor/legacymsg/legacymsg.cpp b/tapeserver/castor/legacymsg/legacymsg.cpp
new file mode 100644
index 0000000000..268ac89d7d
--- /dev/null
+++ b/tapeserver/castor/legacymsg/legacymsg.cpp
@@ -0,0 +1,90 @@
+/******************************************************************************
+ *
+ * This file is part of the Castor project.
+ * See http://castor.web.cern.ch/castor
+ *
+ * Copyright (C) 2003  CERN
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * 
+ *
+ * @author Castor Dev team, castor-dev@cern.ch
+ *****************************************************************************/
+
+#include "castor/io/io.hpp"
+#include "castor/legacymsg/CommonMarshal.hpp"
+#include "castor/legacymsg/legacymsg.hpp"
+#include "castor/legacymsg/MessageHeader.hpp"
+#include "castor/legacymsg/GenericReplyMsgBody.hpp"
+#include "Ctape.h"
+#include "castor/utils/utils.hpp"
+#include "GenericMarshal.hpp"
+
+//------------------------------------------------------------------------------
+// writeTapeRcReplyMsg
+//------------------------------------------------------------------------------
+void castor::legacymsg::writeTapeRcReplyMsg(const int timeout, const int fd, const int rc) {
+  try {
+    char dst[12];
+    legacymsg::MessageHeader src;
+    src.magic = TPMAGIC;
+    src.reqType = TAPERC;
+    src.lenOrStatus = rc;
+    const size_t len = legacymsg::marshal(dst, src);
+    castor::io::writeBytes(fd, timeout, len, dst);
+  } catch(castor::exception::Exception &ne) {
+    castor::exception::Exception ex;
+    ex.getMessage() << "Failed to write tape reply message: "
+      << ne.getMessage().str();
+    throw ex;
+  }
+}
+
+//------------------------------------------------------------------------------
+// writeTapeReplyMsg
+//------------------------------------------------------------------------------
+void castor::legacymsg::writeTapeReplyMsg(const int timeout, const int fd, const int rc, const std::string &message) {
+  try {    
+    const int dstlen = 12+4+CA_MAXLINELEN+1; // 12 bytes of header + 4 bytes of return code + max length of error message
+    char dst[dstlen];
+    castor::legacymsg::GenericReplyMsgBody src;    
+    src.status=rc;
+    castor::utils::copyString(src.errorMessage, message);
+    const size_t len = castor::legacymsg::marshal(dst, dstlen, TPMAGIC, MSG_DATA, src);    
+    castor::io::writeBytes(fd, timeout, len, dst);
+  } catch(castor::exception::Exception &ne) {
+    castor::exception::Exception ex;
+    ex.getMessage() << "Failed to write tape reply message: " <<
+      ne.getMessage().str();
+    throw ex;
+  }
+}
+
+//------------------------------------------------------------------------------
+// writeTapeReplyErrorMsg
+//------------------------------------------------------------------------------
+void castor::legacymsg::writeTapeReplyErrorMsg(const int timeout, const int fd, const std::string &message) {
+  try {    
+    const int dstlen = 12 + CA_MAXLINELEN+1; // 12 bytes of header + max length of error message
+    char dst[dstlen];
+    castor::legacymsg::GenericErrorReplyMsgBody src;
+    castor::utils::copyString(src.errorMessage, message);
+    const size_t len = castor::legacymsg::marshal(dst, dstlen, TPMAGIC, MSG_ERR, src);    
+    castor::io::writeBytes(fd, timeout, len, dst);
+  } catch(castor::exception::Exception &ne) {
+    castor::exception::Exception ex;
+    ex.getMessage() << "Failed to write error reply message with and error message=\"" << message << "\". "
+      << ne.getMessage().str();
+    throw ex;
+  }
+}
diff --git a/tapeserver/castor/server/CMakeLists.txt b/tapeserver/castor/server/CMakeLists.txt
index bab11e39ff..0bf14272d7 100644
--- a/tapeserver/castor/server/CMakeLists.txt
+++ b/tapeserver/castor/server/CMakeLists.txt
@@ -9,8 +9,11 @@ add_library (ctaserverutils SHARED
   Mutex.cpp
   Threading.cpp
   ProcessCap.cpp
+  SmartCap.cpp
   Daemon.cpp)
 
+target_link_libraries(ctaserverutils cap)
+
 add_library (ctaserverunittests SHARED
   AtomicCounterTest.cpp
   DaemonTest.cpp
diff --git a/tapeserver/castor/server/SmartCap.cpp b/tapeserver/castor/server/SmartCap.cpp
new file mode 100644
index 0000000000..9d6569eb09
--- /dev/null
+++ b/tapeserver/castor/server/SmartCap.cpp
@@ -0,0 +1,97 @@
+/******************************************************************************
+ *
+ * This file is part of the Castor project.
+ * See http://castor.web.cern.ch/castor
+ *
+ * Copyright (C) 2003  CERN
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ *
+ * @author Castor Dev team, castor-dev@cern.ch
+ *****************************************************************************/
+
+#include "castor/exception/Exception.hpp"
+#include "castor/server/SmartCap.hpp"
+
+//------------------------------------------------------------------------------
+// constructor
+//------------------------------------------------------------------------------
+castor::server::SmartCap::SmartCap() throw():
+  m_cap(NULL) {
+}
+
+//------------------------------------------------------------------------------
+// constructor
+//------------------------------------------------------------------------------
+castor::server::SmartCap::SmartCap(cap_t cap) throw():
+  m_cap(cap) {
+}
+
+//------------------------------------------------------------------------------
+// reset
+//------------------------------------------------------------------------------
+void castor::server::SmartCap::reset(cap_t cap) throw() {
+  // If the new capability state is not the one already owned
+  if(cap != m_cap) {
+
+    // If this smart pointer still owns a capability state then free it using
+    // cap_free()
+    if(NULL != m_cap) {
+      cap_free(m_cap);
+    }
+
+    // Take ownership of the new capability state
+    m_cap = cap;
+  }
+}
+
+//------------------------------------------------------------------------------
+// operator=
+//------------------------------------------------------------------------------
+castor::server::SmartCap &castor::server::SmartCap::operator=(SmartCap& obj) {
+  reset(obj.release());
+  return *this;
+}
+
+//------------------------------------------------------------------------------
+// destructor
+//------------------------------------------------------------------------------
+castor::server::SmartCap::~SmartCap() throw() {
+  reset();
+}
+
+//------------------------------------------------------------------------------
+// get
+//------------------------------------------------------------------------------
+cap_t castor::server::SmartCap::get() const throw() {
+  return m_cap;
+}
+
+//------------------------------------------------------------------------------
+// release
+//------------------------------------------------------------------------------
+cap_t castor::server::SmartCap::release() {
+  // If this smart pointer does not own a capbility state
+  if(NULL == m_cap) {
+    castor::exception::Exception ex;
+    ex.getMessage() << "Smart pointer does not own a capbility state";
+    throw(ex);
+  }
+
+  // Assigning NULL to m_cap indicates this smart pointer does not own a
+  // capability state
+  cap_t tmpCap = m_cap;
+  m_cap = NULL;
+  return tmpCap;
+}
-- 
GitLab