startBackupFile(bpContext *ctx, struct save_pkt *sp)

This entry point is called only if your plugin is a command plugin, and it is called when Bacula encounters the “Plugin = ” directive in the Include section of the FileSet. Called when beginning the backup of a file. Here Bacula provides you with a pointer to the save_pkt structure and you must fill in this packet with the “attribute” data of the file.

struct save_pkt {
   int32_t pkt_size;                  /* size of this packet */
   char *fname;                       /* Full path and filename */
   char *link;                        /* Link name if any */
   struct stat statp;                 /* System stat() packet for file */
   int32_t type;                      /* FT_xx for this file */
   uint32_t flags;                    /* Bacula internal flags */
   bool portable;                     /* set if data format is portable */
   char *cmd;                         /* command */
   struct restore_object restore_obj; /* Info about restore object */
   struct plugin_object plugin_obj;   /* Plugin Object */
   const plugin_metadata *plug_meta;  /* Metadata packet provided by plugin */
   uint32_t delta_seq;                /* Delta sequence number */
   char *object_name;                 /* Object name to create */
   char *object;                      /* restore object data to save */
   int32_t object_len;                /* restore object length */
   int32_t index;                     /* restore object index */
   int32_t pkt_end;                   /* end packet sentinel */
};

The second argument is a pointer to the save_pkt structure for the file to be backed up. The plugin is responsible for filling in all the fields of the save_pkt. If you are backing up a real file, then generally, the statp structure can be filled in by doing a stat system call on the file.

If you are backing up a database or something that is more complex, you might want to create a virtual file. That is a file that does not actually exist on the filesystem, but represents say an object that you are backing up. In that case, you need to ensure that the fname string that you pass back is unique so that it does not conflict with a real file on the system, and you need to artifically create values in the statp packet.

Example programs such as bpipe-fd.c show how to set these fields. You must take care not to store pointers the stack in the pointer fields such as fname and link, because when you return from your function, your stack entries will be destroyed. The solution in that case is to malloc() and return the pointer to it. In order to not have memory leaks, you should store a pointer to all memory allocated in your pContext structure so that in subsequent calls or at termination, you can release it back to the system.

Once the backup has begun, Bacula will call your plugin at the pluginIO entry point to “read” the data to be backed up. Please see the bpipe-fd.c plugin for how to do I/O.

Example of filling in the save_pkt as used in bpipe-fd.c:

struct plugin_ctx *p_ctx = (struct plugin_ctx *)ctx->pContext;
time_t now = time(NULL);
sp->fname = p_ctx->fname;
sp->statp.st_mode = 0700 | S_IFREG;
sp->statp.st_ctime = now;
sp->statp.st_mtime = now;
sp->statp.st_atime = now;
sp->statp.st_size = -1;
sp->statp.st_blksize = 4096;
sp->statp.st_blocks = 1;
p_ctx->backup = true;
return bRC_OK;

Note: the filename to be created has already been created from the command string previously sent to the plugin and is in the plugin context (p_ctxfname) and is a malloc()ed string. This example creates a regular file (S_IFREG), with various fields being created.

In general, the sequence of commands issued from Bacula to the plugin to do a backup while processing the “Plugin = ” directive are:

  1. generate a bEventBackupCommand event to the specified plugin and pass it the command string.

  2. make a startPluginBackup call to the plugin, which fills in the data needed in save_pkt to save as the file attributes and to put on the Volume and in the catalog.

  3. call Bacula’s internal save_file() subroutine to save the specified file. The plugin will then be called at pluginIO() to “open” the file, and then to read the file data. Note, if you are dealing with a virtual file, the “open” operation is something the plugin does internally and it doesn’t necessarily mean opening a file on the filesystem. For example in the case of the bpipe-fd.c program, it initiates a pipe to the requested program. Finally when the plugin signals to Bacula that all the data was read, Bacula will call the plugin with the “close” pluginIO() function.

Possible Next Steps

Go back to Plugin EntryPoints.

Go back to Bacula FD Plugin API.

Go back to Developer Guide.