]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/newvol.c
Tweak comment in create_simple_name()
[bacula/bacula] / bacula / src / dird / newvol.c
1 /*
2    Bacula(R) - The Network Backup Solution
3
4    Copyright (C) 2000-2015 Kern Sibbald
5    Copyright (C) 2000-2014 Free Software Foundation Europe e.V.
6
7    The original author of Bacula is Kern Sibbald, with contributions
8    from many others, a complete list can be found in the file AUTHORS.
9
10    You may use this file and others of this release according to the
11    license defined in the LICENSE file, which includes the Affero General
12    Public License, v3.0 ("AGPLv3") and some additional permissions and
13    terms pursuant to its AGPLv3 Section 7.
14
15    This notice must be preserved when any source code is 
16    conveyed and/or propagated.
17
18    Bacula(R) is a registered trademark of Kern Sibbald.
19 */
20 /*
21  *
22  *   Bacula Director -- newvol.c -- creates new Volumes in
23  *    catalog Media table from the LabelFormat specification.
24  *
25  *     Kern Sibbald, May MMI
26  *
27  *    This routine runs as a thread and must be thread reentrant.
28  *
29  *  Basic tasks done here:
30  *      If possible create a new Media entry
31  *
32  */
33
34 #include "bacula.h"
35 #include "dird.h"
36
37 /* Forward referenced functions */
38 static bool create_simple_name(JCR *jcr, MEDIA_DBR *mr, POOL_DBR *pr);
39 static bool perform_full_name_substitution(JCR *jcr, MEDIA_DBR *mr, POOL_DBR *pr);
40
41
42 /*
43  * Automatic Volume name creation using the LabelFormat
44  *
45  *  The media record must have the PoolId filled in when
46  *   calling this routine.
47  */
48 bool newVolume(JCR *jcr, MEDIA_DBR *mr, STORE *store)
49 {
50    POOL_DBR pr;
51
52    memset(&pr, 0, sizeof(pr));
53
54    /* See if we can create a new Volume */
55    db_lock(jcr->db);
56    pr.PoolId = mr->PoolId;
57    if (!db_get_pool_numvols(jcr, jcr->db, &pr)) {
58       goto bail_out;
59    }
60    if (pr.MaxVols == 0 || pr.NumVols < pr.MaxVols) {
61       mr->clear();
62       set_pool_dbr_defaults_in_media_dbr(mr, &pr);
63       jcr->VolumeName[0] = 0;
64       bstrncpy(mr->MediaType, jcr->wstore->media_type, sizeof(mr->MediaType));
65       generate_plugin_event(jcr, bDirEventNewVolume); /* return void... */
66       if (jcr->VolumeName[0] && is_volume_name_legal(NULL, jcr->VolumeName)) {
67          bstrncpy(mr->VolumeName, jcr->VolumeName, sizeof(mr->VolumeName));
68       /* Check for special characters */
69       } else if (pr.LabelFormat[0] && pr.LabelFormat[0] != '*') {
70          if (is_volume_name_legal(NULL, pr.LabelFormat)) {
71             /* No special characters, so apply simple algorithm */
72             if (!create_simple_name(jcr, mr, &pr)) {
73                goto bail_out;
74             }
75          } else {  /* try full substitution */
76             /* Found special characters, so try substitution */
77             if (!perform_full_name_substitution(jcr, mr, &pr)) {
78                goto bail_out;
79             }
80             if (!is_volume_name_legal(NULL, mr->VolumeName)) {
81                Jmsg(jcr, M_ERROR, 0, _("Illegal character in Volume name \"%s\"\n"),
82                   mr->VolumeName);
83                goto bail_out;
84             }
85          }
86       } else {
87          goto bail_out;
88       }
89       pr.NumVols++;
90       mr->Enabled = 1;
91       set_storageid_in_mr(store, mr);
92       if (db_create_media_record(jcr, jcr->db, mr) &&
93          db_update_pool_record(jcr, jcr->db, &pr)) {
94          Jmsg(jcr, M_INFO, 0, _("Created new Volume=\"%s\", Pool=\"%s\", MediaType=\"%s\" in catalog.\n"),
95             mr->VolumeName, pr.Name, mr->MediaType);
96          Dmsg1(90, "Created new Volume=%s\n", mr->VolumeName);
97          db_unlock(jcr->db);
98          return true;
99       } else {
100          Jmsg(jcr, M_ERROR, 0, "%s", db_strerror(jcr->db));
101       }
102    }
103 bail_out:
104    db_unlock(jcr->db);
105    return false;
106 }
107
108 static bool create_simple_name(JCR *jcr, MEDIA_DBR *mr, POOL_DBR *pr)
109 {
110    char name[MAXSTRING];
111    char num[20];
112    db_int64_ctx ctx;
113    POOL_MEM query(PM_MESSAGE);
114    char ed1[50];
115
116    /* See if volume already exists */
117    mr->VolumeName[0] = 0;
118    bstrncpy(name, pr->LabelFormat, sizeof(name));
119    ctx.value = 0;
120    /* TODO: Remove Pool as it is not used in the query */
121    Mmsg(query, "SELECT MAX(MediaId) FROM Media,Pool WHERE Pool.PoolId=%s",
122         edit_int64(pr->PoolId, ed1));
123    if (!db_sql_query(jcr->db, query.c_str(), db_int64_handler, (void *)&ctx)) {
124       Jmsg(jcr, M_WARNING, 0, _("SQL failed, but ignored. ERR=%s\n"), db_strerror(jcr->db));
125       ctx.value = pr->NumVols+1;
126    }
127    for (int i=(int)ctx.value+1; i<(int)ctx.value+100; i++) {
128       MEDIA_DBR tmr;
129       sprintf(num, "%04d", i);
130       bstrncpy(tmr.VolumeName, name, sizeof(tmr.VolumeName));
131       bstrncat(tmr.VolumeName, num, sizeof(tmr.VolumeName));
132       if (db_get_media_record(jcr, jcr->db, &tmr)) {
133          Jmsg(jcr, M_WARNING, 0,
134              _("Wanted to create Volume \"%s\", but it already exists. Trying again.\n"),
135              tmr.VolumeName);
136          continue;
137       }
138       bstrncpy(mr->VolumeName, name, sizeof(mr->VolumeName));
139       bstrncat(mr->VolumeName, num, sizeof(mr->VolumeName));
140       break;                    /* Got good name */
141    }
142    if (mr->VolumeName[0] == 0) {
143       Jmsg(jcr, M_ERROR, 0, _("Too many failures. Giving up creating Volume name.\n"));
144       return false;
145    }
146    return true;
147 }
148
149 /*
150  * Perform full substitution on Label
151  */
152 static bool perform_full_name_substitution(JCR *jcr, MEDIA_DBR *mr, POOL_DBR *pr)
153 {
154    bool ok = false;
155    POOLMEM *label = get_pool_memory(PM_FNAME);
156    jcr->NumVols = pr->NumVols;
157    if (variable_expansion(jcr, pr->LabelFormat, &label)) {
158       bstrncpy(mr->VolumeName, label, sizeof(mr->VolumeName));
159       ok = true;
160    }
161    free_pool_memory(label);
162    return ok;
163 }