]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/plugins/fd/bpipe-fd.c
98f93c450e192d18b2070ff6d89d813ada4d95aa
[bacula/bacula] / bacula / src / plugins / fd / bpipe-fd.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2007-2008 Free Software Foundation Europe e.V.
5
6    The main author of Bacula is Kern Sibbald, with contributions from
7    many others, a complete list can be found in the file AUTHORS.
8    This program is Free Software; you can redistribute it and/or
9    modify it under the terms of version two of the GNU General Public
10    License as published by the Free Software Foundation, which is 
11    listed in the file LICENSE.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23    Bacula® is a registered trademark of John Walker.
24    The licensor of Bacula is the Free Software Foundation Europe
25    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26    Switzerland, email:ftf@fsfeurope.org.
27 */
28 /*
29  * A simple pipe plugin for Bacula
30  *
31  *  Kern Sibbald, October 2007
32  *
33  */
34 #include "fd-plugins.h"
35
36 #undef malloc
37 #undef free
38 #undef strdup
39
40 #ifdef __cplusplus
41 extern "C" {
42 #endif
43
44 #define PLUGIN_LICENSE      "GPL"
45 #define PLUGIN_AUTHOR       "Kern Sibbald"
46 #define PLUGIN_DATE         "January 2008"
47 #define PLUGIN_VERSION      "1"
48 #define PLUGIN_DESCRIPTION  "Test File Daemon Plugin"
49
50 /* Forward referenced functions */
51 static bRC newPlugin(bpContext *ctx);
52 static bRC freePlugin(bpContext *ctx);
53 static bRC getPluginValue(bpContext *ctx, pVariable var, void *value);
54 static bRC setPluginValue(bpContext *ctx, pVariable var, void *value);
55 static bRC handlePluginEvent(bpContext *ctx, bEvent *event, void *value);
56 static bRC startBackupFile(bpContext *ctx, struct save_pkt *sp);
57 static bRC endBackupFile(bpContext *ctx);
58 static bRC pluginIO(bpContext *ctx, struct io_pkt *io);
59 static bRC startRestoreFile(bpContext *ctx, const char *cmd);
60 static bRC endRestoreFile(bpContext *ctx);
61 static bRC createFile(bpContext *ctx, struct restore_pkt *rp);
62 static bRC setFileAttributes(bpContext *ctx, struct restore_pkt *rp);
63
64
65 /* Pointers to Bacula functions */
66 static bFuncs *bfuncs = NULL;
67 static bInfo  *binfo = NULL;
68
69 static pInfo pluginInfo = {
70    sizeof(pluginInfo),
71    PLUGIN_INTERFACE_VERSION,
72    PLUGIN_MAGIC,
73    PLUGIN_LICENSE,
74    PLUGIN_AUTHOR,
75    PLUGIN_DATE,
76    PLUGIN_VERSION,
77    PLUGIN_DESCRIPTION,
78 };
79
80 static pFuncs pluginFuncs = {
81    sizeof(pluginFuncs),
82    PLUGIN_INTERFACE_VERSION,
83
84    /* Entry points into plugin */
85    newPlugin,                         /* new plugin instance */
86    freePlugin,                        /* free plugin instance */
87    getPluginValue,
88    setPluginValue,
89    handlePluginEvent,
90    startBackupFile,
91    endBackupFile,
92    startRestoreFile,
93    endRestoreFile,
94    pluginIO,
95    createFile,
96    setFileAttributes
97 };
98
99 struct plugin_ctx {
100    boffset_t offset;
101    FILE *fd;
102    bool backup;
103    char *cmd;
104    char *fname;
105    char *reader;
106    char *writer;
107 };
108
109 bRC loadPlugin(bInfo *lbinfo, bFuncs *lbfuncs, pInfo **pinfo, pFuncs **pfuncs)
110 {
111    bfuncs = lbfuncs;                  /* set Bacula funct pointers */
112    binfo  = lbinfo;
113 // printf("bpipe-fd: Loaded: size=%d version=%d\n", bfuncs->size, bfuncs->version);
114
115    *pinfo  = &pluginInfo;             /* return pointer to our info */
116    *pfuncs = &pluginFuncs;            /* return pointer to our functions */
117
118    return bRC_OK;
119 }
120
121 bRC unloadPlugin() 
122 {
123 // printf("bpipe-fd: Unloaded\n");
124    return bRC_OK;
125 }
126
127 static bRC newPlugin(bpContext *ctx)
128 {
129    struct plugin_ctx *p_ctx = (struct plugin_ctx *)malloc(sizeof(struct plugin_ctx));
130    memset(p_ctx, 0, sizeof(struct plugin_ctx));
131    ctx->pContext = (void *)p_ctx;        /* set our context pointer */
132    return bRC_OK;
133 }
134
135 static bRC freePlugin(bpContext *ctx)
136 {
137    struct plugin_ctx *p_ctx = (struct plugin_ctx *)ctx->pContext;
138    if (p_ctx->cmd) {
139       free(p_ctx->cmd);
140    }
141    free(p_ctx);
142    return bRC_OK;
143 }
144
145 static bRC getPluginValue(bpContext *ctx, pVariable var, void *value) 
146 {
147    return bRC_OK;
148 }
149
150 static bRC setPluginValue(bpContext *ctx, pVariable var, void *value) 
151 {
152    return bRC_OK;
153 }
154
155 static bRC handlePluginEvent(bpContext *ctx, bEvent *event, void *value)
156 {
157    struct plugin_ctx *p_ctx = (struct plugin_ctx *)ctx->pContext;
158 // char *name;
159
160    switch (event->eventType) {
161    case bEventJobStart:
162 //    printf("bpipe-fd: JobStart=%s\n", (char *)value);
163       break;
164    case bEventJobEnd:
165 //    printf("bpipe-fd: JobEnd\n");
166       break;
167    case bEventStartBackupJob:
168 //    printf("bpipe-fd: BackupStart\n");
169       break;
170    case bEventEndBackupJob:
171 //    printf("bpipe-fd: BackupEnd\n");
172       break;
173    case bEventLevel:
174 //    printf("bpipe-fd: JobLevel=%c %d\n", (int)value, (int)value);
175       break;
176    case bEventSince:
177 //    printf("bpipe-fd: since=%d\n", (int)value);
178       break;
179
180    case bEventStartRestoreJob:
181       printf("bpipe-fd: StartRestoreJob\n");
182       break;
183
184    case bEventEndRestoreJob:
185       printf("bpipe-fd: EndRestoreJob\n");
186       break;
187
188    /* Plugin command e.g. plugin = <plugin-name>:<name-space>:read command:write command */
189    case bEventRestoreCommand:
190       printf("bpipe-fd: EventRestoreCommand cmd=%s\n", (char *)value);
191    case bEventBackupCommand:
192       char *p;
193       printf("bpipe-fd: pluginEvent cmd=%s\n", (char *)value);
194       p_ctx->cmd = strdup((char *)value);
195       p = strchr(p_ctx->cmd, ':');
196       if (!p) {
197          bfuncs->JobMessage(ctx, __FILE__, __LINE__, M_FATAL, 0, "Plugin terminator not found: %s\n", (char *)value);
198          return bRC_Error;
199       }
200       *p++ = 0;           /* terminate plugin */
201       p_ctx->fname = p;
202       p = strchr(p, ':');
203       if (!p) {
204          bfuncs->JobMessage(ctx, __FILE__, __LINE__, M_FATAL, 0, "File terminator not found: %s\n", (char *)value);
205          return bRC_Error;
206       }
207       *p++ = 0;           /* terminate file */
208       p_ctx->reader = p;
209       p = strchr(p, ':');
210       if (!p) {
211          bfuncs->JobMessage(ctx, __FILE__, __LINE__, M_FATAL, 0, "Reader terminator not found: %s\n", (char *)value);
212          return bRC_Error;
213       }
214       *p++ = 0;           /* terminate reader string */
215       p_ctx->writer = p;
216       printf("bpipe-fd: plugin=%s fname=%s reader=%s writer=%s\n", 
217          p_ctx->cmd, p_ctx->fname, p_ctx->reader, p_ctx->writer);
218       break;
219
220    default:
221       printf("bpipe-fd: unknown event=%d\n", event->eventType);
222    }
223 // bfuncs->getBaculaValue(ctx, bVarFDName, (void *)&name);
224 // printf("FD Name=%s\n", name);
225 // bfuncs->JobMessage(ctx, __FILE__, __LINE__, 1, 0, "JobMesssage message");
226 // bfuncs->DebugMessage(ctx, __FILE__, __LINE__, 1, "DebugMesssage message");
227    return bRC_OK;
228 }
229
230 static bRC startBackupFile(bpContext *ctx, struct save_pkt *sp)
231 {
232    struct plugin_ctx *p_ctx = (struct plugin_ctx *)ctx->pContext;
233    time_t now = time(NULL);
234    sp->fname = p_ctx->fname;
235    sp->statp.st_mode = 0700 | S_IFREG;
236    sp->statp.st_ctime = now;
237    sp->statp.st_mtime = now;
238    sp->statp.st_atime = now;
239    sp->statp.st_size = -1;
240    sp->statp.st_blksize = 4096;
241    sp->statp.st_blocks = 1;
242    p_ctx->backup = true;
243 // printf("bpipe-fd: startBackupFile\n");
244    return bRC_OK;
245 }
246
247 static bRC endBackupFile(bpContext *ctx)
248 {
249    /*
250     * We would return bRC_More if we wanted startBackupFile to be
251     * called again to backup another file
252     */
253 // printf("bpipe-fd: endBackupFile\n");
254    return bRC_OK;
255 }
256
257 /*
258  * Do actual I/O
259  */
260 static bRC pluginIO(bpContext *ctx, struct io_pkt *io)
261 {
262    struct plugin_ctx *p_ctx = (struct plugin_ctx *)ctx->pContext;
263     
264    io->status = 0;
265    io->io_errno = 0;
266    switch(io->func) {
267    case IO_OPEN:
268       printf("bpipe-fd: IO_OPEN\n");
269       if (io->flags & (O_CREAT | O_WRONLY)) {
270          p_ctx->fd = popen(p_ctx->writer, "w");
271          printf("bpipe-fd: IO_OPEN writer=%s\n", p_ctx->writer);
272          if (!p_ctx->fd) {
273             io->io_errno = errno;
274             bfuncs->JobMessage(ctx, __FILE__, __LINE__, M_FATAL, 0, 
275                "bpipe-fd: writer=%s failed: ERR=%d\n", p_ctx->writer, errno);
276             return bRC_Error;
277          }
278       } else {
279          p_ctx->fd = popen(p_ctx->reader, "r");
280          printf("bpipe-fd: IO_OPEN reader=%s\n", p_ctx->reader);
281          if (!p_ctx->fd) {
282             io->io_errno = errno;
283             bfuncs->JobMessage(ctx, __FILE__, __LINE__, M_FATAL, 0, 
284                "bpipe-fd: reader=%s failed: ERR=%d\n", p_ctx->reader, errno);
285             return bRC_Error;
286          }
287       }
288       sleep(1);                 /* let pipe connect */
289       break;
290
291    case IO_READ:
292       if (!p_ctx->fd) {
293          bfuncs->JobMessage(ctx, __FILE__, __LINE__, M_FATAL, 0, "NULL read FD\n");
294          return bRC_Error;
295       }
296       io->status = fread(io->buf, 1, io->count, p_ctx->fd);
297       printf("bpipe-fd: IO_READ buf=%p len=%d\n", io->buf, io->status);
298       if (io->status == 0 && ferror(p_ctx->fd)) {
299          bfuncs->JobMessage(ctx, __FILE__, __LINE__, M_FATAL, 0, "Pipe read error\n");
300          printf("Error reading pipe\n");
301          return bRC_Error;
302       }
303 //    printf("status=%d\n", io->status);
304       break;
305
306    case IO_WRITE:
307       if (!p_ctx->fd) {
308          bfuncs->JobMessage(ctx, __FILE__, __LINE__, M_FATAL, 0, "NULL write FD\n");
309          return bRC_Error;
310       }
311       printf("bpipe-fd: IO_WRITE fd=%p buf=%p len=%d\n", p_ctx->fd, io->buf, io->count);
312       io->status = fwrite(io->buf, 1, io->count, p_ctx->fd);
313       printf("bpipe-fd: IO_WRITE buf=%p len=%d\n", io->buf, io->status);
314       if (io->status == 0 && ferror(p_ctx->fd)) {
315          bfuncs->JobMessage(ctx, __FILE__, __LINE__, M_FATAL, 0, "Pipe write error\n");
316          printf("Error writing pipe\n");
317          return bRC_Error;
318       }
319 //    printf("status=%d\n", io->status);
320       break;
321
322    case IO_CLOSE:
323       if (!p_ctx->fd) {
324          bfuncs->JobMessage(ctx, __FILE__, __LINE__, M_FATAL, 0, "NULL FD\n");
325          return bRC_Error;
326       }
327       io->status = pclose(p_ctx->fd);
328       printf("bpipe-fd: IO_CLOSE\n");
329       break;
330
331    case IO_SEEK:
332       io->offset = p_ctx->offset;
333       break;
334    }
335    return bRC_OK;
336 }
337
338 static bRC startRestoreFile(bpContext *ctx, const char *cmd)
339 {
340    printf("bpipe-fd: startRestoreFile cmd=%s\n", cmd);
341    return bRC_OK;
342 }
343
344 static bRC endRestoreFile(bpContext *ctx)
345 {
346    printf("bpipe-fd: endRestoreFile\n");
347    return bRC_OK;
348 }
349
350 static bRC createFile(bpContext *ctx, struct restore_pkt *rp)
351 {
352    printf("bpipe-fd: createFile\n");
353    return bRC_OK;
354 }
355
356 static bRC setFileAttributes(bpContext *ctx, struct restore_pkt *rp)
357 {
358    printf("bpipe-fd: setFileAttributes\n");
359    return bRC_OK;
360 }
361
362
363 #ifdef __cplusplus
364 }
365 #endif