/* Copyright (C) 2019 MariaDB Corporation 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; version 2 of the License. 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ // Defines stuff client code will use to construct messages to StorageManager. #pragma once #include #include #include namespace storagemanager { #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-variable" #pragma pack(push, 1) struct sm_msg_header { uint32_t type; // SM_MSG_{START,CONT,END} uint32_t payloadLen; // refers to the length of what follows the header uint8_t flags; // see below for valid values }; // current values for the flags field in sm_msg_header static const uint8_t CONT = 0x1; // this means another message will follow as part of this request or response struct sm_request { sm_msg_header header; uint8_t payload[]; }; struct sm_response { sm_msg_header header; ssize_t returnCode; // if < 0 it indicates an error, and payload contains a 4-byte errno value uint8_t payload[]; }; // all msgs to and from StorageManager begin with this magic and a payload length static const uint32_t SM_MSG_START = 0xbf65a7e1; // for read/write/append, which may break a message into chunks, messages not the // beginning or end of the larger message will preface a chunk with this magic static const uint32_t SM_MSG_CONT = 0xfa371bd2; // for read/write/append, the last chunk of a message should begin with this magic static const uint32_t SM_MSG_END = 0x9d5bc31b; static const uint32_t SM_HEADER_LEN = sizeof(sm_msg_header); // the unix socket StorageManager is listening on __attribute__((unused)) static const char* socket_name = "\0storagemanager"; #pragma GCC diagnostic pop // opcodes understood by StorageManager. Cast these to // a uint8_t to use them. enum Opcodes { OPEN, READ, WRITE, STAT, UNLINK, APPEND, TRUNCATE, LIST_DIRECTORY, PING, COPY, SYNC, LIST_IOTASKS, TERMINATE_IOTASK }; /* All commands sent to and from StorageManager begin with SM_MSG_START, and a uint32_t for the length of the payload. In the payload, all responses from StorageManager begin with a return code, which is the same as the corresponding syscall. If the return code is an error (usually < 0), then a 4-byte value for errno follows. On success, no errno is sent. On success, what follows is any output parameters from the call. Note: filenames and pathnames in the following parameters should be absolute rather than relative. */ /* OPEN ---- command format: 1-byte opcode|4-byte openmode|4-byte filename length|filename response format: struct stat */ struct open_cmd { uint8_t opcode; // == OPEN int32_t openmode; uint32_t flen; char filename[]; }; struct open_resp { struct stat statbuf; }; /* READ ---- command format: 1-byte opcode|size_t count|off_t offset|4-byte filename length|filename response format: data (size is stored in the return code) */ struct read_cmd { uint8_t opcode; // == READ size_t count; off_t offset; uint32_t flen; char filename[]; }; typedef uint8_t read_resp; /* WRITE ----- command format: 1-byte opcode|size_t count|off_t offset|4-byte filename length|filename|data response format: */ struct write_cmd { uint8_t opcode; // == WRITE ssize_t count; off_t offset; uint32_t flen; char filename[]; // after this is the data to be written, ie at &filename[flen] }; /* APPEND ------ command format: 1-byte opcode|size_t count|4-byte filename length|filename|data response format: */ struct append_cmd { uint8_t opcode; // == APPEND ssize_t count; uint32_t flen; char filename[]; // after this is the data to be written, ie at &filename[flen] }; /* UNLINK ------ command format: 1-byte opcode|4-byte filename length|filename response format: */ struct unlink_cmd { uint8_t opcode; // == UNLINK uint32_t flen; char filename[]; }; /* STAT ---- command format: 1-byte opcode|4-byte filename length|filename response format: struct stat */ struct stat_cmd { uint8_t opcode; // == STAT uint32_t flen; char filename[]; }; struct stat_resp { struct stat statbuf; }; /* TRUNCATE -------- command format: 1-byte opcode|off_t length|4-byte filename length|filename response format: */ struct truncate_cmd { uint8_t opcode; // == TRUNCATE off_t length; uint32_t flen; char filename[]; }; /* LIST_DIRECTORY -------------- command format: 1-byte opcode|4-byte path length|pathname response format: 4-byte num elements| (4-byte filename length|filename) * num elements */ struct listdir_cmd { uint8_t opcode; // == LIST_DIRECTORY uint32_t plen; char path[]; }; struct listdir_resp_entry { uint32_t flen; char filename[]; }; struct listdir_resp { uint32_t elements; listdir_resp_entry entries[]; // followed by (elements * listdir_resp_entry) }; /* PING ---- command format: 1-byte opcode response format: nothing yet */ struct ping_cmd { uint8_t opcode; }; /* COPY ---- command format: 1-byte opcode|4-byte filename1 length|filename2|4-byte filename2 length|filename2 response format: */ struct f_name { uint32_t flen; char filename[]; }; struct copy_cmd { uint8_t opcode; f_name file1; // use f_name as an overlay at the end of file1 to get file2. }; /* LIST_IOTASKS ------------ command format: 1-byte opcode response format: 4-byte num elements|(8-byte id|double runningTime) * num elements */ struct list_iotask_cmd { uint8_t opcode; }; struct list_iotask_resp_entry { uint64_t id; double runningTime; }; struct list_iotask_resp { uint32_t elements; list_iotask_resp_entry entries[]; }; /* TERMINATE_IOTASK ---------------- command format: 1-byte opcode|8-byte id response format: */ struct terminate_iotask_cmd { uint8_t opcode; uint64_t id; }; #pragma pack(pop) } // namespace storagemanager