/* * Copyright (c) Likewise Software. All rights Reserved. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the license, or (at * your option) any later version. * * This library 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 Lesser * General Public License for more details. You should have received a copy * of the GNU Lesser General Public License along with this program. If * not, see . * * LIKEWISE SOFTWARE MAKES THIS SOFTWARE AVAILABLE UNDER OTHER LICENSING * TERMS AS WELL. IF YOU HAVE ENTERED INTO A SEPARATE LICENSE AGREEMENT * WITH LIKEWISE SOFTWARE, THEN YOU MAY ELECT TO USE THE SOFTWARE UNDER THE * TERMS OF THAT SOFTWARE LICENSE AGREEMENT INSTEAD OF THE TERMS OF THE GNU * LESSER GENERAL PUBLIC LICENSE, NOTWITHSTANDING THE ABOVE NOTICE. IF YOU * HAVE QUESTIONS, OR WISH TO REQUEST A COPY OF THE ALTERNATE LICENSING * TERMS OFFERED BY LIKEWISE SOFTWARE, PLEASE CONTACT LIKEWISE SOFTWARE AT * license@likewisesoftware.com */ /* * Module Name: * * archive.c * * Abstract: * * Archive API * Primary entry points * * Authors: Brian Koropoff (bkoropoff@likewisesoftware.com) * */ #include "archive-private.h" #include "util-private.h" #include #include #include #include static LWMsgStatus lwmsg_archive_construct( LWMsgAssoc* assoc ) { LWMsgStatus status = LWMSG_STATUS_SUCCESS; LWMsgArchive* archive = ARCHIVE_PRIVATE(assoc); archive->fd = -1; archive->mode = 0; archive->disp = 0; archive->byte_order = LWMSG_BIG_ENDIAN; BAIL_ON_ERROR(status = lwmsg_data_context_new(&assoc->context, &archive->data_context)); error: return status; } static void lwmsg_archive_destruct( LWMsgAssoc* assoc ) { LWMsgArchive* archive = ARCHIVE_PRIVATE(assoc); if (archive->fd != -1) { close(archive->fd); } if (archive->file) { free(archive->file); } if (archive->data_context) { lwmsg_data_context_delete(archive->data_context); } } static LWMsgStatus lwmsg_archive_close_assoc( LWMsgAssoc* assoc ) { LWMsgArchive* archive = ARCHIVE_PRIVATE(assoc); return lwmsg_archive_close(archive); } static LWMsgStatus lwmsg_archive_reset( LWMsgAssoc* assoc ) { LWMsgStatus status = LWMSG_STATUS_SUCCESS; BAIL_ON_ERROR(status = LWMSG_STATUS_UNSUPPORTED); error: return status; } static LWMsgStatus lwmsg_archive_send_msg( LWMsgAssoc* assoc, LWMsgMessage* message ) { LWMsgArchive* archive = ARCHIVE_PRIVATE(assoc); return lwmsg_archive_write_message(archive, message); } static LWMsgStatus lwmsg_archive_recv_msg( LWMsgAssoc* assoc, LWMsgMessage* message ) { LWMsgArchive* archive = ARCHIVE_PRIVATE(assoc); return lwmsg_archive_read_message(archive, message); } static LWMsgStatus lwmsg_archive_finish( LWMsgAssoc* assoc, LWMsgMessage** message ) { LWMsgStatus status = LWMSG_STATUS_SUCCESS; *message = NULL; return status; } static LWMsgStatus lwmsg_archive_set_nonblock( LWMsgAssoc* assoc, LWMsgBool nonblock ) { LWMsgStatus status = LWMSG_STATUS_SUCCESS; BAIL_ON_ERROR(status = LWMSG_STATUS_UNSUPPORTED); error: return status; } static LWMsgStatus lwmsg_archive_get_peer_security_token( LWMsgAssoc* assoc, LWMsgSecurityToken** out_token ) { LWMsgStatus status = LWMSG_STATUS_SUCCESS; BAIL_ON_ERROR(status = LWMSG_STATUS_UNSUPPORTED); error: *out_token = NULL; return status; } static LWMsgStatus lwmsg_archive_get_session( LWMsgAssoc* assoc, LWMsgSession** session ) { LWMsgStatus status = LWMSG_STATUS_SUCCESS; BAIL_ON_ERROR(status = LWMSG_STATUS_UNSUPPORTED); error: return status; } static LWMsgAssocState lwmsg_archive_get_state( LWMsgAssoc* assoc ) { LWMsgArchive* archive = ARCHIVE_PRIVATE(assoc); if (archive->fd != -1) { return LWMSG_ASSOC_STATE_IDLE; } else { return LWMSG_ASSOC_STATE_NOT_ESTABLISHED; } } static LWMsgStatus lwmsg_archive_set_timeout( LWMsgAssoc* assoc, LWMsgTimeout type, LWMsgTime* value ) { LWMsgStatus status = LWMSG_STATUS_SUCCESS; BAIL_ON_ERROR(status = LWMSG_STATUS_UNSUPPORTED); error: return status; } static LWMsgStatus lwmsg_archive_open_fd( LWMsgArchive* archive ) { LWMsgStatus status = LWMSG_STATUS_SUCCESS; if (archive->fd == -1) { if (archive->file) { archive->fd = open( archive->file, (archive->disp == LWMSG_ARCHIVE_READ ? O_RDONLY : (O_WRONLY | O_CREAT)), archive->mode); if (archive->fd < 0) { BAIL_ON_ERROR(status = lwmsg_error_raise_errno(&archive->base.context.error, errno)); } } else { ASSOC_RAISE_ERROR(&archive->base, status = LWMSG_STATUS_INVALID_STATE, "No fd or filename specified"); } } error: return status; } static LWMsgStatus lwmsg_archive_establish( LWMsgAssoc* assoc, LWMsgSessionConstructFunction construct, LWMsgSessionDestructFunction destruct, void* data ) { LWMsgArchive* archive = ARCHIVE_PRIVATE(assoc); return lwmsg_archive_open(archive); } static LWMsgAssocClass archive_class = { .construct = lwmsg_archive_construct, .destruct = lwmsg_archive_destruct, .send_msg = lwmsg_archive_send_msg, .recv_msg = lwmsg_archive_recv_msg, .close = lwmsg_archive_close_assoc, .reset = lwmsg_archive_reset, .get_peer_security_token = lwmsg_archive_get_peer_security_token, .get_session = lwmsg_archive_get_session, .get_state = lwmsg_archive_get_state, .set_timeout = lwmsg_archive_set_timeout, .establish = lwmsg_archive_establish, .set_nonblock = lwmsg_archive_set_nonblock, .finish = lwmsg_archive_finish }; LWMsgStatus lwmsg_archive_new( const LWMsgContext* context, LWMsgProtocol* prot, LWMsgArchive** archive ) { LWMsgStatus status = LWMSG_STATUS_SUCCESS; LWMsgAssoc* assoc = NULL; BAIL_ON_ERROR(status = lwmsg_assoc_new(context, prot, &archive_class, sizeof(LWMsgArchive), &assoc)); *archive = ARCHIVE_PRIVATE(assoc); done: return status; error: goto done; } LWMsgStatus lwmsg_archive_set_fd( LWMsgArchive* archive, int fd, LWMsgArchiveDisposition disp ) { LWMsgStatus status = LWMSG_STATUS_SUCCESS; if (fd < 0) { ASSOC_RAISE_ERROR(&archive->base, status = LWMSG_STATUS_INVALID_PARAMETER, "Invalid file descriptor"); } if (archive->file) { free(archive->file); archive->file = NULL; } if (archive->fd >= 0) { close(archive->fd); archive->fd = -1; } archive->fd = fd; archive->disp = disp; error: return status; } LWMsgStatus lwmsg_archive_set_file( LWMsgArchive* archive, const char* file, LWMsgArchiveDisposition disp, mode_t mode ) { LWMsgStatus status = LWMSG_STATUS_SUCCESS; if (archive->file) { free(archive->file); archive->file = NULL; } if (archive->fd >= 0) { close(archive->fd); archive->fd = -1; } archive->file = strdup(file); if (!archive->file) { BAIL_ON_ERROR(status = LWMSG_STATUS_MEMORY); } archive->disp = disp; archive->mode = mode; error: return status; } LWMsgStatus lwmsg_archive_set_byte_order( LWMsgArchive* archive, LWMsgByteOrder order ) { LWMsgStatus status = LWMSG_STATUS_SUCCESS; archive->byte_order = order; lwmsg_data_context_set_byte_order(archive->data_context, order); return status; } LWMsgAssoc* lwmsg_archive_as_assoc( LWMsgArchive* archive ) { return &archive->base; } void lwmsg_archive_delete( LWMsgArchive* archive ) { lwmsg_assoc_delete(&archive->base); } LWMsgStatus lwmsg_archive_open( LWMsgArchive* archive ) { LWMsgStatus status = LWMSG_STATUS_SUCCESS; if (archive->fd >= 0) { ARCHIVE_RAISE_ERROR(archive, status = LWMSG_STATUS_INVALID_STATE, "Archive is already open"); } switch (archive->disp) { case LWMSG_ARCHIVE_READ: BAIL_ON_ERROR(status = lwmsg_archive_open_fd(archive)); BAIL_ON_ERROR(status = lwmsg_archive_read_header_fd(archive)); break; case LWMSG_ARCHIVE_WRITE: BAIL_ON_ERROR(status = lwmsg_archive_open_fd(archive)); BAIL_ON_ERROR(status = lwmsg_archive_write_header_fd(archive)); break; } error: return status; } LWMsgStatus lwmsg_archive_close( LWMsgArchive* archive ) { LWMsgStatus status = LWMSG_STATUS_SUCCESS; if (archive->fd != -1) { close(archive->fd); archive->fd = -1; } return status; } LWMsgStatus lwmsg_archive_write_message( LWMsgArchive* archive, LWMsgMessage* message ) { LWMsgStatus status = LWMSG_STATUS_SUCCESS; if (!(archive->disp & LWMSG_ARCHIVE_WRITE)) { ARCHIVE_RAISE_ERROR(archive, status = LWMSG_STATUS_INVALID_STATE, "Archive not open for writing"); } BAIL_ON_ERROR(status = lwmsg_archive_write_message_fd(archive, message)); error: return status; } LWMsgStatus lwmsg_archive_read_message( LWMsgArchive* archive, LWMsgMessage* message ) { LWMsgStatus status = LWMSG_STATUS_SUCCESS; if (!archive->disp & LWMSG_ARCHIVE_READ) { ARCHIVE_RAISE_ERROR(archive, status = LWMSG_STATUS_INVALID_STATE, "Archive not open for reading"); } BAIL_ON_ERROR(status = lwmsg_archive_read_message_fd(archive, message)); error: return status; } LWMsgStatus lwmsg_archive_destroy_message( LWMsgArchive* archive, LWMsgMessage* message ) { LWMsgStatus status = LWMSG_STATUS_SUCCESS; LWMsgTypeSpec* type = NULL; if (message->tag >= 0) { BAIL_ON_ERROR(status = lwmsg_protocol_get_message_type(archive->base.prot, message->tag, &type)); if (type != NULL) { BAIL_ON_ERROR(status = lwmsg_data_free_graph(archive->data_context, type, message->data)); } message->tag = -1; message->data = NULL; } error: return status; }