]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/cats/sql_create.c
1265d78a057e83bb785b157759a4f35ec2bcbd2c
[bacula/bacula] / bacula / src / cats / sql_create.c
1 /*
2  * Bacula Catalog Database Create record interface routines
3  *
4  *    Kern Sibbald, March 2000
5  *
6  *    Version $Id$
7  */
8
9 /*
10    Copyright (C) 2000-2005 Kern Sibbald
11
12    This program is free software; you can redistribute it and/or
13    modify it under the terms of the GNU General Public License as
14    published by the Free Software Foundation; either version 2 of
15    the License, or (at your option) any later version.
16
17    This program is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20    General Public License for more details.
21
22    You should have received a copy of the GNU General Public
23    License along with this program; if not, write to the Free
24    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
25    MA 02111-1307, USA.
26
27  */
28
29 /* The following is necessary so that we do not include
30  * the dummy external definition of DB.
31  */
32 #define __SQL_C                       /* indicate that this is sql.c */
33
34 #include "bacula.h"
35 #include "cats.h"
36
37 #if    HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL
38
39 /* -----------------------------------------------------------------------
40  *
41  *   Generic Routines (or almost generic)
42  *
43  * -----------------------------------------------------------------------
44  */
45
46 /* Forward referenced subroutines */
47 static int db_create_file_record(JCR *jcr, B_DB *mdb, ATTR_DBR *ar);
48 static int db_create_filename_record(JCR *jcr, B_DB *mdb, ATTR_DBR *ar);
49 static int db_create_path_record(JCR *jcr, B_DB *mdb, ATTR_DBR *ar);
50
51
52 /* Imported subroutines */
53 extern void print_dashes(B_DB *mdb);
54 extern void print_result(B_DB *mdb);
55 extern int QueryDB(const char *file, int line, JCR *jcr, B_DB *db, char *select_cmd);
56 extern int InsertDB(const char *file, int line, JCR *jcr, B_DB *db, char *select_cmd);
57 extern int UpdateDB(const char *file, int line, JCR *jcr, B_DB *db, char *update_cmd);
58 extern void split_path_and_file(JCR *jcr, B_DB *mdb, const char *fname);
59
60
61 /* Create a new record for the Job
62  * Returns: 0 on failure
63  *          1 on success
64  */
65 int
66 db_create_job_record(JCR *jcr, B_DB *mdb, JOB_DBR *jr)
67 {
68    char dt[MAX_TIME_LENGTH];
69    time_t stime;
70    struct tm tm;
71    int stat;
72    utime_t JobTDate;
73    char ed1[30];
74
75    db_lock(mdb);
76
77    stime = jr->SchedTime;
78    ASSERT(stime != 0);
79
80    localtime_r(&stime, &tm);
81    strftime(dt, sizeof(dt), "%Y-%m-%d %T", &tm);
82    JobTDate = (utime_t)stime;
83
84    /* Must create it */
85    Mmsg(mdb->cmd,
86 "INSERT INTO Job (Job,Name,Type,Level,JobStatus,SchedTime,JobTDate) VALUES "
87 "('%s','%s','%c','%c','%c','%s',%s)",
88            jr->Job, jr->Name, (char)(jr->JobType), (char)(jr->JobLevel),
89            (char)(jr->JobStatus), dt, edit_uint64(JobTDate, ed1));
90
91    if (!INSERT_DB(jcr, mdb, mdb->cmd)) {
92       Mmsg2(&mdb->errmsg, _("Create DB Job record %s failed. ERR=%s\n"),
93             mdb->cmd, sql_strerror(mdb));
94       jr->JobId = 0;
95       stat = 0;
96    } else {
97       jr->JobId = sql_insert_id(mdb, _("Job"));
98       stat = 1;
99    }
100    db_unlock(mdb);
101    return stat;
102 }
103
104 /* Create a JobMedia record for medium used this job
105  * Returns: false on failure
106  *          true  on success
107  */
108 bool
109 db_create_jobmedia_record(JCR *jcr, B_DB *mdb, JOBMEDIA_DBR *jm)
110 {
111    bool ok = true;;
112    int count;
113
114    db_lock(mdb);
115
116    /* Now get count for VolIndex */
117    Mmsg(mdb->cmd, "SELECT count(*) from JobMedia");
118    count = get_sql_record_max(jcr, mdb);
119    if (count < 0) {
120       count = 0;
121    }
122    count++;
123
124    Mmsg(mdb->cmd,
125         "INSERT INTO JobMedia (JobId,MediaId,FirstIndex,LastIndex,"
126         "StartFile,EndFile,StartBlock,EndBlock,VolIndex) "
127         "VALUES (%u,%u,%u,%u,%u,%u,%u,%u,%u)",
128         jm->JobId, jm->MediaId, jm->FirstIndex, jm->LastIndex,
129         jm->StartFile, jm->EndFile, jm->StartBlock, jm->EndBlock,count);
130
131    Dmsg0(300, mdb->cmd);
132    if (!INSERT_DB(jcr, mdb, mdb->cmd)) {
133       Mmsg2(&mdb->errmsg, _("Create JobMedia record %s failed: ERR=%s\n"), mdb->cmd,
134          sql_strerror(mdb));
135       ok = false;
136    } else {
137       /* Worked, now update the Media record with the EndFile and EndBlock */
138       Mmsg(mdb->cmd,
139            "UPDATE Media SET EndFile=%u, EndBlock=%u WHERE MediaId=%u",
140            jm->EndFile, jm->EndBlock, jm->MediaId);
141       if (!UPDATE_DB(jcr, mdb, mdb->cmd)) {
142          Mmsg2(&mdb->errmsg, _("Update Media record %s failed: ERR=%s\n"), mdb->cmd,
143               sql_strerror(mdb));
144          ok = false;
145       }
146    }
147    db_unlock(mdb);
148    Dmsg0(300, "Return from JobMedia\n");
149    return ok;
150 }
151
152
153
154 /* Create Unique Pool record
155  * Returns: false on failure
156  *          true  on success
157  */
158 bool
159 db_create_pool_record(JCR *jcr, B_DB *mdb, POOL_DBR *pr)
160 {
161    bool stat;        
162    char ed1[30], ed2[30], ed3[50];
163
164    Dmsg0(200, "In create pool\n");
165    db_lock(mdb);
166    Mmsg(mdb->cmd, "SELECT PoolId,Name FROM Pool WHERE Name='%s'", pr->Name);
167    Dmsg1(200, "selectpool: %s\n", mdb->cmd);
168
169    if (QUERY_DB(jcr, mdb, mdb->cmd)) {
170       mdb->num_rows = sql_num_rows(mdb);
171       if (mdb->num_rows > 0) {
172          Mmsg1(&mdb->errmsg, _("pool record %s already exists\n"), pr->Name);
173          sql_free_result(mdb);
174          db_unlock(mdb);
175          return false;
176       }
177       sql_free_result(mdb);
178    }
179
180    /* Must create it */
181    Mmsg(mdb->cmd,
182 "INSERT INTO Pool (Name,NumVols,MaxVols,UseOnce,UseCatalog,"
183 "AcceptAnyVolume,AutoPrune,Recycle,VolRetention,VolUseDuration,"
184 "MaxVolJobs,MaxVolFiles,MaxVolBytes,PoolType,LabelType,LabelFormat) "
185 "VALUES ('%s',%u,%u,%d,%d,%d,%d,%d,%s,%s,%u,%u,%s,'%s',%d,'%s')",
186                   pr->Name,
187                   pr->NumVols, pr->MaxVols,
188                   pr->UseOnce, pr->UseCatalog,
189                   pr->AcceptAnyVolume,
190                   pr->AutoPrune, pr->Recycle,
191                   edit_uint64(pr->VolRetention, ed1),
192                   edit_uint64(pr->VolUseDuration, ed2),
193                   pr->MaxVolJobs, pr->MaxVolFiles,
194                   edit_uint64(pr->MaxVolBytes, ed3),
195                   pr->PoolType, pr->LabelType, pr->LabelFormat);
196    Dmsg1(200, "Create Pool: %s\n", mdb->cmd);
197    if (!INSERT_DB(jcr, mdb, mdb->cmd)) {
198       Mmsg2(&mdb->errmsg, _("Create db Pool record %s failed: ERR=%s\n"),
199             mdb->cmd, sql_strerror(mdb));
200       pr->PoolId = 0;
201       stat = false;
202    } else {
203       pr->PoolId = sql_insert_id(mdb, _("Pool"));
204       stat = true;
205    }
206    db_unlock(mdb);
207    return stat;
208 }
209
210 /*
211  * Create Unique Device record
212  * Returns: false on failure
213  *          true  on success
214  */
215 bool
216 db_create_device_record(JCR *jcr, B_DB *mdb, DEVICE_DBR *dr)
217 {
218    bool stat;        
219    char ed1[30], ed2[30];
220
221    Dmsg0(200, "In create Device\n");
222    db_lock(mdb);
223    Mmsg(mdb->cmd, "SELECT DeviceId,Name FROM Device WHERE Name='%s'", dr->Name);
224    Dmsg1(200, "selectdevice: %s\n", mdb->cmd);
225
226    if (QUERY_DB(jcr, mdb, mdb->cmd)) {
227       mdb->num_rows = sql_num_rows(mdb);
228       if (mdb->num_rows > 0) {
229          Mmsg1(&mdb->errmsg, _("Device record %s already exists\n"), dr->Name);
230          sql_free_result(mdb);
231          db_unlock(mdb);
232          return false;
233       }
234       sql_free_result(mdb);
235    }
236
237    /* Must create it */
238    Mmsg(mdb->cmd,
239 "INSERT INTO Device (Name,MediaTypeId,StorageId) "
240 "VALUES ('%s',%s,%s)",
241                   dr->Name,
242                   edit_uint64(dr->MediaTypeId, ed1),
243                   edit_uint64(dr->StorageId, ed2));
244    Dmsg1(200, "Create Device: %s\n", mdb->cmd);
245    if (!INSERT_DB(jcr, mdb, mdb->cmd)) {
246       Mmsg2(&mdb->errmsg, _("Create db Device record %s failed: ERR=%s\n"),
247             mdb->cmd, sql_strerror(mdb));
248       dr->DeviceId = 0;
249       stat = false;
250    } else {
251       dr->DeviceId = sql_insert_id(mdb, _("Device"));
252       stat = true;
253    }
254    db_unlock(mdb);
255    return stat;
256 }
257
258 /*
259  * Create Unique storage record
260  * Returns: false on failure
261  *          true  on success
262  */
263 bool
264 db_create_storage_record(JCR *jcr, B_DB *mdb, STORAGE_DBR *sr)
265 {
266    bool stat;        
267
268    Dmsg0(200, "In create storage\n");
269    db_lock(mdb);
270    Mmsg(mdb->cmd, "SELECT StorageId,Name FROM Storage WHERE Name='%s'", sr->Name);
271    Dmsg1(200, "selectstorage: %s\n", mdb->cmd);
272
273    if (QUERY_DB(jcr, mdb, mdb->cmd)) {
274       mdb->num_rows = sql_num_rows(mdb);
275       if (mdb->num_rows > 0) {
276          Mmsg1(&mdb->errmsg, _("Storage record %s already exists\n"), sr->Name);
277          sql_free_result(mdb);
278          db_unlock(mdb);
279          return false;
280       }
281       sql_free_result(mdb);
282    }
283
284    /* Must create it */
285    Mmsg(mdb->cmd,
286 "INSERT INTO Storage (Name,AutoChanger) "
287 "VALUES ('%s',%d)",
288                   sr->Name,
289                   sr->AutoChanger);
290    Dmsg1(200, "Create storage: %s\n", mdb->cmd);
291    if (!INSERT_DB(jcr, mdb, mdb->cmd)) {
292       Mmsg2(&mdb->errmsg, _("Create db storage record %s failed: ERR=%s\n"),
293             mdb->cmd, sql_strerror(mdb));
294       sr->StorageId = 0;
295       stat = false;
296    } else {
297       sr->StorageId = sql_insert_id(mdb, _("Storage"));
298       stat = true;
299    }
300    db_unlock(mdb);
301    return stat;
302 }
303
304
305 /*
306  * Create Unique MediaType record
307  * Returns: false on failure
308  *          true  on success
309  */
310 bool
311 db_create_mediatype_record(JCR *jcr, B_DB *mdb, MEDIATYPE_DBR *mr)
312 {
313    bool stat;        
314
315    Dmsg0(200, "In create mediatype\n");
316    db_lock(mdb);
317    Mmsg(mdb->cmd, "SELECT MediaTypeId,MediaType FROM MediaType WHERE MediaType='%s'", mr->MediaType);
318    Dmsg1(200, "selectmediatype: %s\n", mdb->cmd);
319
320    if (QUERY_DB(jcr, mdb, mdb->cmd)) {
321       mdb->num_rows = sql_num_rows(mdb);
322       if (mdb->num_rows > 0) {
323          Mmsg1(&mdb->errmsg, _("mediatype record %s already exists\n"), mr->MediaType);
324          sql_free_result(mdb);
325          db_unlock(mdb);
326          return false;
327       }
328       sql_free_result(mdb);
329    }
330
331    /* Must create it */
332    Mmsg(mdb->cmd,
333 "INSERT INTO MediaType (MediaType,ReadOnly) "
334 "VALUES ('%s',%d)",
335                   mr->MediaType,
336                   mr->ReadOnly);
337    Dmsg1(200, "Create mediatype: %s\n", mdb->cmd);
338    if (!INSERT_DB(jcr, mdb, mdb->cmd)) {
339       Mmsg2(&mdb->errmsg, _("Create db mediatype record %s failed: ERR=%s\n"),
340             mdb->cmd, sql_strerror(mdb));
341       mr->MediaTypeId = 0;
342       stat = false;
343    } else {
344       mr->MediaTypeId = sql_insert_id(mdb, _("MediaType"));
345       stat = true;
346    }
347    db_unlock(mdb);
348    return stat;
349 }
350
351
352
353
354 /*
355  * Create Media record. VolumeName and non-zero Slot must be unique
356  *
357  * Returns: 0 on failure
358  *          1 on success
359  */
360 int
361 db_create_media_record(JCR *jcr, B_DB *mdb, MEDIA_DBR *mr)
362 {
363    int stat;
364    char ed1[30], ed2[30], ed3[30], ed4[30], ed5[30], ed6[50], ed7[50];
365    struct tm tm;
366
367    db_lock(mdb);
368    Mmsg(mdb->cmd, "SELECT MediaId FROM Media WHERE VolumeName='%s'",
369            mr->VolumeName);
370    Dmsg1(300, "selectpool: %s\n", mdb->cmd);
371
372    if (QUERY_DB(jcr, mdb, mdb->cmd)) {
373       mdb->num_rows = sql_num_rows(mdb);
374       if (mdb->num_rows > 0) {
375          Mmsg1(&mdb->errmsg, _("Volume \"%s\" already exists.\n"), mr->VolumeName);
376          sql_free_result(mdb);
377          db_unlock(mdb);
378          return 0;
379       }
380       sql_free_result(mdb);
381    }
382
383    /* Must create it */
384    Mmsg(mdb->cmd,
385 "INSERT INTO Media (VolumeName,MediaType,PoolId,MaxVolBytes,VolCapacityBytes,"
386 "Recycle,VolRetention,VolUseDuration,MaxVolJobs,MaxVolFiles,"
387 "VolStatus,Slot,VolBytes,InChanger,VolReadTime,VolWriteTime,VolParts,"
388 "EndFile,EndBlock,LabelType) "
389 "VALUES ('%s','%s',%u,%s,%s,%d,%s,%s,%u,%u,'%s',%d,%s,%d,%s,%s,%d,0,0,%d)",
390                   mr->VolumeName,
391                   mr->MediaType, mr->PoolId,
392                   edit_uint64(mr->MaxVolBytes,ed1),
393                   edit_uint64(mr->VolCapacityBytes, ed2),
394                   mr->Recycle,
395                   edit_uint64(mr->VolRetention, ed3),
396                   edit_uint64(mr->VolUseDuration, ed4),
397                   mr->MaxVolJobs,
398                   mr->MaxVolFiles,
399                   mr->VolStatus,
400                   mr->Slot,
401                   edit_uint64(mr->VolBytes, ed5),
402                   mr->InChanger,
403                   edit_uint64(mr->VolReadTime, ed6),
404                   edit_uint64(mr->VolWriteTime, ed7),
405                   mr->VolParts,
406                   mr->LabelType
407                   );
408
409
410    Dmsg1(500, "Create Volume: %s\n", mdb->cmd);
411    if (!INSERT_DB(jcr, mdb, mdb->cmd)) {
412       Mmsg2(&mdb->errmsg, _("Create DB Media record %s failed. ERR=%s\n"),
413             mdb->cmd, sql_strerror(mdb));
414       stat = 0;
415    } else {
416       mr->MediaId = sql_insert_id(mdb, _("Media"));
417       stat = 1;
418       if (mr->set_label_date) {
419          char dt[MAX_TIME_LENGTH];
420          if (mr->LabelDate == 0) {
421             mr->LabelDate = time(NULL);
422          }
423          localtime_r(&mr->LabelDate, &tm);
424          strftime(dt, sizeof(dt), "%Y-%m-%d %T", &tm);
425          Mmsg(mdb->cmd, "UPDATE Media SET LabelDate='%s' "
426               "WHERE MediaId=%d", dt, mr->MediaId);
427          stat = UPDATE_DB(jcr, mdb, mdb->cmd);
428       }
429    }
430
431    /*
432     * Make sure that if InChanger is non-zero any other identical slot
433     *   has InChanger zero.
434     */
435    db_make_inchanger_unique(jcr, mdb, mr);
436
437    db_unlock(mdb);
438    return stat;
439 }
440
441
442
443 /*
444  * Create a Unique record for the client -- no duplicates
445  * Returns: 0 on failure
446  *          1 on success with id in cr->ClientId
447  */
448 int db_create_client_record(JCR *jcr, B_DB *mdb, CLIENT_DBR *cr)
449 {
450    SQL_ROW row;
451    int stat;
452    char ed1[50], ed2[50];
453
454    db_lock(mdb);
455    Mmsg(mdb->cmd, "SELECT ClientId,Uname FROM Client WHERE Name='%s'", cr->Name);
456
457    cr->ClientId = 0;
458    if (QUERY_DB(jcr, mdb, mdb->cmd)) {
459       mdb->num_rows = sql_num_rows(mdb);
460       /* If more than one, report error, but return first row */
461       if (mdb->num_rows > 1) {
462          Mmsg1(&mdb->errmsg, _("More than one Client!: %d\n"), (int)(mdb->num_rows));
463          Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
464       }
465       if (mdb->num_rows >= 1) {
466          if ((row = sql_fetch_row(mdb)) == NULL) {
467             Mmsg1(&mdb->errmsg, _("error fetching Client row: %s\n"), sql_strerror(mdb));
468             Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
469             sql_free_result(mdb);
470             db_unlock(mdb);
471             return 0;
472          }
473          cr->ClientId = str_to_int64(row[0]);
474          if (row[1]) {
475             bstrncpy(cr->Uname, row[1], sizeof(cr->Uname));
476          } else {
477             cr->Uname[0] = 0;         /* no name */
478          }
479          sql_free_result(mdb);
480          db_unlock(mdb);
481          return 1;
482       }
483       sql_free_result(mdb);
484    }
485
486    /* Must create it */
487    Mmsg(mdb->cmd, "INSERT INTO Client (Name,Uname,AutoPrune,"
488 "FileRetention,JobRetention) VALUES "
489 "('%s','%s',%d,%s,%s)", cr->Name, cr->Uname, cr->AutoPrune,
490       edit_uint64(cr->FileRetention, ed1),
491       edit_uint64(cr->JobRetention, ed2));
492
493    if (!INSERT_DB(jcr, mdb, mdb->cmd)) {
494       Mmsg2(&mdb->errmsg, _("Create DB Client record %s failed. ERR=%s\n"),
495             mdb->cmd, sql_strerror(mdb));
496       Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
497       cr->ClientId = 0;
498       stat = 0;
499    } else {
500       cr->ClientId = sql_insert_id(mdb, _("Client"));
501       stat = 1;
502    }
503    db_unlock(mdb);
504    return stat;
505 }
506
507
508 /*
509  * Create a Unique record for the counter -- no duplicates
510  * Returns: 0 on failure
511  *          1 on success with counter filled in
512  */
513 int db_create_counter_record(JCR *jcr, B_DB *mdb, COUNTER_DBR *cr)
514 {
515    COUNTER_DBR mcr;
516    int stat;
517
518    db_lock(mdb);
519    memset(&mcr, 0, sizeof(mcr));
520    bstrncpy(mcr.Counter, cr->Counter, sizeof(mcr.Counter));
521    if (db_get_counter_record(jcr, mdb, &mcr)) {
522       memcpy(cr, &mcr, sizeof(COUNTER_DBR));
523       db_unlock(mdb);
524       return 1;
525    }
526
527    /* Must create it */
528    Mmsg(mdb->cmd, "INSERT INTO Counters (Counter,MinValue,MaxValue,CurrentValue,"
529       "WrapCounter) VALUES ('%s','%d','%d','%d','%s')",
530       cr->Counter, cr->MinValue, cr->MaxValue, cr->CurrentValue,
531       cr->WrapCounter);
532
533    if (!INSERT_DB(jcr, mdb, mdb->cmd)) {
534       Mmsg2(&mdb->errmsg, _("Create DB Counters record %s failed. ERR=%s\n"),
535             mdb->cmd, sql_strerror(mdb));
536       Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
537       stat = 0;
538    } else {
539       stat = 1;
540    }
541    db_unlock(mdb);
542    return stat;
543 }
544
545
546 /*
547  * Create a FileSet record. This record is unique in the
548  *  name and the MD5 signature of the include/exclude sets.
549  *  Returns: 0 on failure
550  *           1 on success with FileSetId in record
551  */
552 bool db_create_fileset_record(JCR *jcr, B_DB *mdb, FILESET_DBR *fsr)
553 {
554    SQL_ROW row;
555    bool stat;
556    struct tm tm;
557
558    db_lock(mdb);
559    fsr->created = false;
560    Mmsg(mdb->cmd, "SELECT FileSetId,CreateTime FROM FileSet WHERE "
561 "FileSet='%s' AND MD5='%s'", fsr->FileSet, fsr->MD5);
562
563    fsr->FileSetId = 0;
564    if (QUERY_DB(jcr, mdb, mdb->cmd)) {
565       mdb->num_rows = sql_num_rows(mdb);
566       if (mdb->num_rows > 1) {
567          Mmsg1(&mdb->errmsg, _("More than one FileSet!: %d\n"), (int)(mdb->num_rows));
568          Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
569       }
570       if (mdb->num_rows >= 1) {
571          if ((row = sql_fetch_row(mdb)) == NULL) {
572             Mmsg1(&mdb->errmsg, _("error fetching FileSet row: ERR=%s\n"), sql_strerror(mdb));
573             Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
574             sql_free_result(mdb);
575             db_unlock(mdb);
576             return false;
577          }
578          fsr->FileSetId = str_to_int64(row[0]);
579          if (row[1] == NULL) {
580             fsr->cCreateTime[0] = 0;
581          } else {
582             bstrncpy(fsr->cCreateTime, row[1], sizeof(fsr->cCreateTime));
583          }
584          sql_free_result(mdb);
585          db_unlock(mdb);
586          return true;
587       }
588       sql_free_result(mdb);
589    }
590
591    if (fsr->CreateTime == 0 && fsr->cCreateTime[0] == 0) {
592       fsr->CreateTime = time(NULL);
593    }
594    localtime_r(&fsr->CreateTime, &tm);
595    strftime(fsr->cCreateTime, sizeof(fsr->cCreateTime), "%Y-%m-%d %T", &tm);
596
597    /* Must create it */
598       Mmsg(mdb->cmd, "INSERT INTO FileSet (FileSet,MD5,CreateTime) "
599 "VALUES ('%s','%s','%s')", fsr->FileSet, fsr->MD5, fsr->cCreateTime);
600
601    if (!INSERT_DB(jcr, mdb, mdb->cmd)) {
602       Mmsg2(&mdb->errmsg, _("Create DB FileSet record %s failed. ERR=%s\n"),
603             mdb->cmd, sql_strerror(mdb));
604       Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
605       fsr->FileSetId = 0;
606       stat = false;
607    } else {
608       fsr->FileSetId = sql_insert_id(mdb, _("FileSet"));
609       fsr->created = true;
610       stat = true;
611    }
612
613    db_unlock(mdb);
614    return stat;
615 }
616
617
618 /*
619  *  struct stat
620  *  {
621  *      dev_t         st_dev;       * device *
622  *      ino_t         st_ino;       * inode *
623  *      mode_t        st_mode;      * protection *
624  *      nlink_t       st_nlink;     * number of hard links *
625  *      uid_t         st_uid;       * user ID of owner *
626  *      gid_t         st_gid;       * group ID of owner *
627  *      dev_t         st_rdev;      * device type (if inode device) *
628  *      off_t         st_size;      * total size, in bytes *
629  *      unsigned long st_blksize;   * blocksize for filesystem I/O *
630  *      unsigned long st_blocks;    * number of blocks allocated *
631  *      time_t        st_atime;     * time of last access *
632  *      time_t        st_mtime;     * time of last modification *
633  *      time_t        st_ctime;     * time of last inode change *
634  *  };
635  */
636
637
638
639 /*
640  * Create File record in B_DB
641  *
642  *  In order to reduce database size, we store the File attributes,
643  *  the FileName, and the Path separately.  In principle, there
644  *  is a single FileName record and a single Path record, no matter
645  *  how many times it occurs.  This is this subroutine, we separate
646  *  the file and the path and create three database records.
647  */
648 int db_create_file_attributes_record(JCR *jcr, B_DB *mdb, ATTR_DBR *ar)
649 {
650
651    db_lock(mdb);
652    Dmsg1(300, "Fname=%s\n", ar->fname);
653    Dmsg0(500, "put_file_into_catalog\n");
654    /*
655     * Make sure we have an acceptable attributes record.
656     */
657    if (!(ar->Stream == STREAM_UNIX_ATTRIBUTES ||
658          ar->Stream == STREAM_UNIX_ATTRIBUTES_EX)) {
659       Mmsg0(&mdb->errmsg, _("Attempt to put non-attributes into catalog\n"));
660       Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
661       goto bail_out;
662    }
663
664
665    split_path_and_file(jcr, mdb, ar->fname);
666
667    if (!db_create_filename_record(jcr, mdb, ar)) {
668       goto bail_out;
669    }
670    Dmsg1(500, "db_create_filename_record: %s\n", mdb->esc_name);
671
672
673    if (!db_create_path_record(jcr, mdb, ar)) {
674       goto bail_out;
675    }
676    Dmsg1(500, "db_create_path_record: %s\n", mdb->esc_name);
677
678    /* Now create master File record */
679    if (!db_create_file_record(jcr, mdb, ar)) {
680       goto bail_out;
681    }
682    Dmsg0(500, "db_create_file_record OK\n");
683
684    Dmsg3(300, "CreateAttributes Path=%s File=%s FilenameId=%d\n", mdb->path, mdb->fname, ar->FilenameId);
685    db_unlock(mdb);
686    return 1;
687
688 bail_out:
689    db_unlock(mdb);
690    return 0;
691 }
692
693 /*
694  * This is the master File entry containing the attributes.
695  *  The filename and path records have already been created.
696  */
697 static int db_create_file_record(JCR *jcr, B_DB *mdb, ATTR_DBR *ar)
698 {
699    int stat;
700
701    ASSERT(ar->JobId);
702    ASSERT(ar->PathId);
703    ASSERT(ar->FilenameId);
704
705    /* Must create it */
706    Mmsg(mdb->cmd,
707         "INSERT INTO File (FileIndex,JobId,PathId,FilenameId,"
708         "LStat,MD5) VALUES (%u,%u,%u,%u,'%s','0')",
709         ar->FileIndex, ar->JobId, ar->PathId, ar->FilenameId,
710         ar->attr);
711
712    if (!INSERT_DB(jcr, mdb, mdb->cmd)) {
713       Mmsg2(&mdb->errmsg, _("Create db File record %s failed. ERR=%s"),
714          mdb->cmd, sql_strerror(mdb));
715       Jmsg(jcr, M_FATAL, 0, "%s", mdb->errmsg);
716       ar->FileId = 0;
717       stat = 0;
718    } else {
719       ar->FileId = sql_insert_id(mdb, _("File"));
720       stat = 1;
721    }
722    return stat;
723 }
724
725 /* Create a Unique record for the Path -- no duplicates */
726 static int db_create_path_record(JCR *jcr, B_DB *mdb, ATTR_DBR *ar)
727 {
728    SQL_ROW row;
729    int stat;
730
731    mdb->esc_name = check_pool_memory_size(mdb->esc_name, 2*mdb->pnl+2);
732    db_escape_string(mdb->esc_name, mdb->path, mdb->pnl);
733
734    if (mdb->cached_path_id != 0 && mdb->cached_path_len == mdb->pnl &&
735        strcmp(mdb->cached_path, mdb->path) == 0) {
736       ar->PathId = mdb->cached_path_id;
737       return 1;
738    }
739
740    Mmsg(mdb->cmd, "SELECT PathId FROM Path WHERE Path='%s'", mdb->esc_name);
741
742    if (QUERY_DB(jcr, mdb, mdb->cmd)) {
743       mdb->num_rows = sql_num_rows(mdb);
744       if (mdb->num_rows > 1) {
745          char ed1[30];
746          Mmsg2(&mdb->errmsg, _("More than one Path!: %s for path: %s\n"),
747             edit_uint64(mdb->num_rows, ed1), mdb->path);
748          Jmsg(jcr, M_WARNING, 0, "%s", mdb->errmsg);
749       }
750       /* Even if there are multiple paths, take the first one */
751       if (mdb->num_rows >= 1) {
752          if ((row = sql_fetch_row(mdb)) == NULL) {
753             Mmsg1(&mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
754             Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
755             sql_free_result(mdb);
756             ar->PathId = 0;
757             ASSERT(ar->PathId);
758             return 0;
759          }
760          ar->PathId = str_to_int64(row[0]);
761          sql_free_result(mdb);
762          /* Cache path */
763          if (ar->PathId != mdb->cached_path_id) {
764             mdb->cached_path_id = ar->PathId;
765             mdb->cached_path_len = mdb->pnl;
766             pm_strcpy(mdb->cached_path, mdb->path);
767          }
768          ASSERT(ar->PathId);
769          return 1;
770       }
771       sql_free_result(mdb);
772    }
773
774    Mmsg(mdb->cmd, "INSERT INTO Path (Path) VALUES ('%s')", mdb->esc_name);
775
776    if (!INSERT_DB(jcr, mdb, mdb->cmd)) {
777       Mmsg2(&mdb->errmsg, _("Create db Path record %s failed. ERR=%s\n"),
778          mdb->cmd, sql_strerror(mdb));
779       Jmsg(jcr, M_FATAL, 0, "%s", mdb->errmsg);
780       ar->PathId = 0;
781       stat = 0;
782    } else {
783       ar->PathId = sql_insert_id(mdb, _("Path"));
784       stat = 1;
785    }
786
787    /* Cache path */
788    if (stat && ar->PathId != mdb->cached_path_id) {
789       mdb->cached_path_id = ar->PathId;
790       mdb->cached_path_len = mdb->pnl;
791       pm_strcpy(mdb->cached_path, mdb->path);
792    }
793    return stat;
794 }
795
796 /* Create a Unique record for the filename -- no duplicates */
797 static int db_create_filename_record(JCR *jcr, B_DB *mdb, ATTR_DBR *ar)
798 {
799    SQL_ROW row;
800
801    mdb->esc_name = check_pool_memory_size(mdb->esc_name, 2*mdb->fnl+2);
802    db_escape_string(mdb->esc_name, mdb->fname, mdb->fnl);
803
804    Mmsg(mdb->cmd, "SELECT FilenameId FROM Filename WHERE Name='%s'", mdb->esc_name);
805
806    if (QUERY_DB(jcr, mdb, mdb->cmd)) {
807       mdb->num_rows = sql_num_rows(mdb);
808       if (mdb->num_rows > 1) {
809          char ed1[30];
810          Mmsg2(&mdb->errmsg, _("More than one Filename! %s for file: %s\n"),
811             edit_uint64(mdb->num_rows, ed1), mdb->fname);
812          Jmsg(jcr, M_WARNING, 0, "%s", mdb->errmsg);
813       }
814       if (mdb->num_rows >= 1) {
815          if ((row = sql_fetch_row(mdb)) == NULL) {
816             Mmsg2(&mdb->errmsg, _("Error fetching row for file=%s: ERR=%s\n"),
817                 mdb->fname, sql_strerror(mdb));
818             Jmsg(jcr, M_ERROR, 0, "%s", mdb->errmsg);
819             ar->FilenameId = 0;
820          } else {
821             ar->FilenameId = str_to_int64(row[0]);
822          }
823          sql_free_result(mdb);
824          return ar->FilenameId > 0;
825       }
826       sql_free_result(mdb);
827    }
828
829    Mmsg(mdb->cmd, "INSERT INTO Filename (Name) VALUES ('%s')", mdb->esc_name);
830
831    if (!INSERT_DB(jcr, mdb, mdb->cmd)) {
832       Mmsg2(&mdb->errmsg, _("Create db Filename record %s failed. ERR=%s\n"),
833             mdb->cmd, sql_strerror(mdb));
834       Jmsg(jcr, M_FATAL, 0, "%s", mdb->errmsg);
835       ar->FilenameId = 0;
836    } else {
837       ar->FilenameId = sql_insert_id(mdb, _("Filename"));
838    }
839    return ar->FilenameId > 0;
840 }
841
842 #endif /* HAVE_SQLITE3 || HAVE_MYSQL || HAVE_SQLITE || HAVE_POSTGRESQL */