]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/newvol.c
Merge in all the low-risk changes from the Windows branch.
[bacula/bacula] / bacula / src / dird / newvol.c
1 /*
2  *
3  *   Bacula Director -- newvol.c -- creates new Volumes in
4  *    catalog Media table from the LabelFormat specification.
5  *
6  *     Kern Sibbald, May MMI
7  *
8  *    This routine runs as a thread and must be thread reentrant.
9  *
10  *  Basic tasks done here:
11  *      If possible create a new Media entry
12  *
13  *   Version $Id$
14  */
15 /*
16    Copyright (C) 2000-2006 Kern Sibbald
17
18    This program is free software; you can redistribute it and/or
19    modify it under the terms of the GNU General Public License
20    version 2 as amended with additional clauses defined in the
21    file LICENSE in the main source directory.
22
23    This program is distributed in the hope that it will be useful,
24    but WITHOUT ANY WARRANTY; without even the implied warranty of
25    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
26    the file LICENSE for additional details.
27
28  */
29
30 #include "bacula.h"
31 #include "dird.h"
32
33 /* Forward referenced functions */
34 static bool create_simple_name(JCR *jcr, MEDIA_DBR *mr, POOL_DBR *pr);
35 static bool perform_full_name_substitution(JCR *jcr, MEDIA_DBR *mr, POOL_DBR *pr);
36
37
38 /*
39  * Automatic Volume name creation using the LabelFormat
40  *
41  *  The media record must have the PoolId filled in when
42  *   calling this routine.
43  */
44 bool newVolume(JCR *jcr, MEDIA_DBR *mr)
45 {
46    POOL_DBR pr;
47
48    memset(&pr, 0, sizeof(pr));
49
50    /* See if we can create a new Volume */
51    db_lock(jcr->db);
52    pr.PoolId = mr->PoolId;
53    if (!db_get_pool_record(jcr, jcr->db, &pr)) {
54       goto bail_out;
55    }
56    if (pr.MaxVols == 0 || pr.NumVols < pr.MaxVols) {
57       memset(mr, 0, sizeof(MEDIA_DBR));
58       set_pool_dbr_defaults_in_media_dbr(mr, &pr);
59       jcr->VolumeName[0] = 0;
60       bstrncpy(mr->MediaType, jcr->store->media_type, sizeof(mr->MediaType));
61       if (generate_job_event(jcr, "NewVolume") == 1 && jcr->VolumeName[0] &&
62           is_volume_name_legal(NULL, jcr->VolumeName)) {
63          bstrncpy(mr->VolumeName, jcr->VolumeName, sizeof(mr->VolumeName));
64       /* Check for special characters */
65       } else if (pr.LabelFormat[0] && pr.LabelFormat[0] != '*') {
66          if (is_volume_name_legal(NULL, pr.LabelFormat)) {
67             /* No special characters, so apply simple algorithm */
68             if (!create_simple_name(jcr, mr, &pr)) {
69                goto bail_out;
70             }
71          } else {  /* try full substitution */
72             /* Found special characters, so try substitution */
73             if (!perform_full_name_substitution(jcr, mr, &pr)) {
74                goto bail_out;
75             }
76             if (!is_volume_name_legal(NULL, mr->VolumeName)) {
77                Jmsg(jcr, M_ERROR, 0, _("Illegal character in Volume name \"%s\"\n"),
78                   mr->VolumeName);
79                goto bail_out;
80             }
81          }
82       } else {                                       
83          goto bail_out;
84       }
85       pr.NumVols++;
86       mr->Enabled = 1;
87       if (db_create_media_record(jcr, jcr->db, mr) &&
88          db_update_pool_record(jcr, jcr->db, &pr)) {
89          db_unlock(jcr->db);
90          Jmsg(jcr, M_INFO, 0, _("Created new Volume \"%s\" in catalog.\n"), mr->VolumeName);
91          Dmsg1(90, "Created new Volume=%s\n", mr->VolumeName);
92          return true;
93       } else {
94          Jmsg(jcr, M_ERROR, 0, "%s", db_strerror(jcr->db));
95       }
96    }
97 bail_out:
98    db_unlock(jcr->db);
99    return false;
100 }
101
102 static bool create_simple_name(JCR *jcr, MEDIA_DBR *mr, POOL_DBR *pr)
103 {
104    char name[MAXSTRING];
105    char num[20];
106
107    /* See if volume already exists */
108    mr->VolumeName[0] = 0;
109    bstrncpy(name, pr->LabelFormat, sizeof(name));
110    for (int i=pr->NumVols+1; i<(int)pr->NumVols+11; i++) {
111       MEDIA_DBR tmr;
112       memset(&tmr, 0, sizeof(tmr));
113       sprintf(num, "%04d", i);
114       bstrncpy(tmr.VolumeName, name, sizeof(tmr.VolumeName));
115       bstrncat(tmr.VolumeName, num, sizeof(tmr.VolumeName));
116       if (db_get_media_record(jcr, jcr->db, &tmr)) {
117          Jmsg(jcr, M_WARNING, 0,
118              _("Wanted to create Volume \"%s\", but it already exists. Trying again.\n"),
119              tmr.VolumeName);
120          continue;
121       }
122       bstrncpy(mr->VolumeName, name, sizeof(mr->VolumeName));
123       bstrncat(mr->VolumeName, num, sizeof(mr->VolumeName));
124       break;                    /* Got good name */
125    }
126    if (mr->VolumeName[0] == 0) {
127       Jmsg(jcr, M_ERROR, 0, _("Too many failures. Giving up creating Volume name.\n"));
128       return false;
129    }
130    return true;
131 }
132
133 /*
134  * Perform full substitution on Label
135  */
136 static bool perform_full_name_substitution(JCR *jcr, MEDIA_DBR *mr, POOL_DBR *pr)
137 {
138    bool ok = false;
139    POOLMEM *label = get_pool_memory(PM_FNAME);
140    jcr->NumVols = pr->NumVols;
141    if (variable_expansion(jcr, pr->LabelFormat, &label)) {
142       bstrncpy(mr->VolumeName, label, sizeof(mr->VolumeName));
143       ok = true;
144    }
145    free_pool_memory(label);
146    return ok;
147 }