/*
Bacula® - The Network Backup Solution
- Copyright (C) 2000-2008 Free Software Foundation Europe e.V.
-
- The main author of Bacula is Kern Sibbald, with contributions from
- many others, a complete list can be found in the file AUTHORS.
- This program is Free Software; you can redistribute it and/or
- modify it under the terms of version two of the GNU General Public
- License as published by the Free Software Foundation and included
- in the file LICENSE.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA.
-
- Bacula® is a registered trademark of John Walker.
- The licensor of Bacula is the Free Software Foundation Europe
- (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
- Switzerland, email:ftf@fsfeurope.org.
+ Copyright (C) 2000-2014 Free Software Foundation Europe e.V.
+
+ The main author of Bacula is Kern Sibbald, with contributions from many
+ others, a complete list can be found in the file AUTHORS.
+
+ You may use this file and others of this release according to the
+ license defined in the LICENSE file, which includes the Affero General
+ Public License, v3.0 ("AGPLv3") and some additional permissions and
+ terms pursuant to its AGPLv3 Section 7.
+
+ Bacula® is a registered trademark of Kern Sibbald.
*/
/*
http://www.fourmilab.ch/smartall/
-
- Version $Id$
-
*/
+#define _LOCKMGR_COMPLIANT
+
#include "bacula.h"
/* Use the real routines here */
#undef realloc
* If you want it, simply #ifdef all the
* following off.
*/
+#ifdef no_debug_xxxxx
#undef Dmsg1
#undef Dmsg2
#undef Dmsg3
#define Dmsg2(l,f,a1,a2)
#define Dmsg3(l,f,a1,a2,a3)
#define Dmsg4(l,f,a1,a2,a3,a4)
+#endif
uint64_t sm_max_bytes = 0;
extern char my_name[]; /* daemon name */
-typedef unsigned short sm_ushort;
-
#define EOS '\0' /* End of string sentinel */
#define sm_min(a, b) ((a) < (b) ? (a) : (b))
struct abufhead {
struct b_queue abq; /* Links on allocated queue */
- unsigned ablen; /* Buffer length in bytes */
+ uint32_t ablen; /* Buffer length in bytes */
const char *abfname; /* File name pointer */
- sm_ushort ablineno; /* Line number of allocation */
+ uint32_t ablineno; /* Line number of allocation */
bool abin_use; /* set when malloced and cleared when free */
};
qinsert(&abqueue, (struct b_queue *) buf);
head->ablen = nbytes;
head->abfname = bufimode ? NULL : fname;
- head->ablineno = (sm_ushort)lineno;
+ head->ablineno = (uint32_t)lineno;
head->abin_use = true;
/* Emplace end-clobber detector at end of buffer */
- buf[nbytes - 1] = (uint8_t)((((long) buf) & 0xFF) ^ 0xC5);
+ buf[nbytes - 1] = (uint8_t)((((intptr_t) buf) & 0xFF) ^ 0xC5);
buf += HEAD_SIZE; /* Increment to user data start */
if (++sm_buffers > sm_max_buffers) {
sm_max_buffers = sm_buffers;
} else {
Emsg0(M_ABORT, 0, _("Out of memory\n"));
}
- Dmsg4(1150, "smalloc %d at %x from %s:%d\n", nbytes, buf, fname, lineno);
+ Dmsg4(DT_MEMORY|50, "smalloc %d at %p from %s:%d\n", nbytes, buf, fname, lineno);
#if SMALLOC_SANITY_CHECK > 0
if (sm_bytes > SMALLOC_SANITY_CHECK) {
Emsg0(M_ABORT, 0, _("Too much memory used."));
{
buf -= HEAD_SIZE; /* Decrement to header */
((struct abufhead *)buf)->abfname = bufimode ? NULL : fname;
- ((struct abufhead *)buf)->ablineno = (sm_ushort) lineno;
+ ((struct abufhead *)buf)->ablineno = (uint32_t) lineno;
((struct abufhead *)buf)->abin_use = true;
return;
}
{
char *cp = (char *) fp;
struct b_queue *qp;
+ uint32_t lineno = line;
if (cp == NULL) {
- Emsg2(M_ABORT, 0, _("Attempt to free NULL called from %s:%d\n"), file, line);
+ Emsg2(M_ABORT, 0, _("Attempt to free NULL called from %s:%d\n"), file, lineno);
}
cp -= HEAD_SIZE;
struct abufhead *head = (struct abufhead *)cp;
P(mutex);
- Dmsg4(1150, "sm_free %d at %x from %s:%d\n",
+ Dmsg4(DT_MEMORY|50, "sm_free %d at %p from %s:%d\n",
head->ablen, fp,
- head->abfname, head->ablineno);
+ get_basename(head->abfname), head->ablineno);
if (!head->abin_use) {
V(mutex);
- Emsg2(M_ABORT, 0, _("double free from %s:%d\n"), file, line);
+ Emsg2(M_ABORT, 0, _("double free from %s:%d\n"), file, lineno);
}
head->abin_use = false;
of an address which isn't an allocated buffer. */
if (qp->qnext->qprev != qp) {
V(mutex);
- Emsg2(M_ABORT, 0, _("qp->qnext->qprev != qp called from %s:%d\n"), file, line);
+ Emsg2(M_ABORT, 0, _("qp->qnext->qprev != qp called from %s:%d\n"), file, lineno);
}
if (qp->qprev->qnext != qp) {
V(mutex);
- Emsg2(M_ABORT, 0, _("qp->qprev->qnext != qp called from %s:%d\n"), file, line);
+ Emsg2(M_ABORT, 0, _("qp->qprev->qnext != qp called from %s:%d\n"), file, lineno);
}
/* The following assertion detects storing off the end of the
allocated space in the buffer by comparing the end of buffer
checksum with the address of the buffer. */
- if (((unsigned char *)cp)[head->ablen - 1] != ((((long) cp) & 0xFF) ^ 0xC5)) {
+ if (((unsigned char *)cp)[head->ablen - 1] != ((((intptr_t) cp) & 0xFF) ^ 0xC5)) {
V(mutex);
- Emsg2(M_ABORT, 0, _("Buffer overrun called from %s:%d\n"), file, line);
+ Emsg6(M_ABORT, 0, _("Overrun buffer: len=%d addr=%p allocated: %s:%d called from %s:%d\n"),
+ head->ablen, fp, get_basename(head->abfname), head->ablineno, file, line);
}
if (sm_buffers > 0) {
sm_buffers--;
void *buf;
char *cp = (char *) ptr;
- Dmsg4(400, "sm_realloc %s:%d 0x%x %d\n", fname, lineno, ptr, size);
+ Dmsg4(DT_MEMORY|50, "sm_realloc %s:%d %p %d\n", get_basename(fname), (uint32_t)lineno, ptr, size);
if (size <= 0) {
e_msg(fname, lineno, M_ABORT, 0, _("sm_realloc size: %d\n"), size);
}
}
/* All done. Free and dechain the original buffer. */
- sm_free(__FILE__, __LINE__, ptr);
+ sm_free(fname, lineno, ptr);
}
- Dmsg4(150, _("sm_realloc %d at %x from %s:%d\n"), size, buf, fname, lineno);
+ Dmsg4(DT_MEMORY|60, _("sm_realloc %d at %p from %s:%d\n"), size, buf, get_basename(fname), (uint32_t)lineno);
return buf;
}
void *actuallyrealloc(void *ptr, unsigned int size)
{
- Dmsg2(400, "Actuallyrealloc 0x%x %d\n", ptr, size);
+ Dmsg2(DT_MEMORY|40, "Actuallyrealloc %p %d\n", ptr, size);
return realloc(ptr, size);
}
/* SM_DUMP -- Print orphaned buffers (and dump them if BUFDUMP is
* True).
- * N.B. DO NOT USE any Bacula print routines (Dmsg, Jmsg, Emsg, ...)
- * as they have all been shut down at this point.
*/
-void sm_dump(bool bufdump, bool in_use)
+void sm_dump(bool bufdump, bool in_use)
{
struct abufhead *ap;
if ((ap == NULL) ||
(ap->abq.qnext->qprev != (struct b_queue *) ap) ||
(ap->abq.qprev->qnext != (struct b_queue *) ap)) {
- fprintf(stderr, _(
+ Pmsg1(0, _(
"\nOrphaned buffers exist. Dump terminated following\n"
" discovery of bad links in chain of orphaned buffers.\n"
" Buffer address with bad links: %p\n"), ap);
}
if (ap->abfname != NULL) {
- unsigned memsize = ap->ablen - (HEAD_SIZE + 1);
char errmsg[500];
+ uint32_t memsize = ap->ablen - (HEAD_SIZE + 1);
char *cp = ((char *)ap) + HEAD_SIZE;
- bsnprintf(errmsg, sizeof(errmsg),
- _("%s buffer: %s %6u bytes buf=%p allocated at %s:%d\n"),
+ Pmsg6(0, "%s buffer: %s %d bytes at %p from %s:%d\n",
in_use?"In use":"Orphaned",
- my_name, memsize, cp, ap->abfname, ap->ablineno
- );
- fprintf(stderr, "%s", errmsg);
+ my_name, memsize, cp, get_basename(ap->abfname), ap->ablineno);
if (bufdump) {
char buf[20];
unsigned llen = 0;
if (llen >= 16) {
bstrncat(errmsg, "\n", sizeof(errmsg));
llen = 0;
- fprintf(stderr, "%s", errmsg);
+ Pmsg1(0, "%s", errmsg);
errmsg[0] = EOS;
}
bsnprintf(buf, sizeof(buf), " %02X",
llen++;
memsize--;
}
- fprintf(stderr, "%s\n", errmsg);
+ Pmsg1(0, "%s\n", errmsg);
}
}
ap = (struct abufhead *) ap->abq.qnext;
{
if (!sm_check_rtn(fname, lineno, bufdump)) {
Emsg2(M_ABORT, 0, _("Damaged buffer found. Called from %s:%d\n"),
- fname, lineno);
+ get_basename(fname), (uint32_t)lineno);
}
}
P(mutex);
ap = (struct abufhead *) abqueue.qnext;
- while (ap != (struct abufhead *) &abqueue) {
+ while (ap != (struct abufhead *)&abqueue) {
bad = 0;
- if ((ap == NULL) ||
- (ap->abq.qnext->qprev != (struct b_queue *) ap)) {
- bad = 0x1;
- }
- if (ap->abq.qprev->qnext != (struct b_queue *) ap) {
- bad |= 0x2;
- }
- if (((unsigned char *) ap)[((struct abufhead *) ap)->ablen - 1] !=
- ((((long) ap) & 0xFF) ^ 0xC5)) {
- bad |= 0x4;
+ if (ap != NULL) {
+ if (ap->abq.qnext->qprev != (struct b_queue *)ap) {
+ bad = 0x1;
+ }
+ if (ap->abq.qprev->qnext != (struct b_queue *)ap) {
+ bad |= 0x2;
+ }
+ if (((unsigned char *) ap)[((struct abufhead *)ap)->ablen - 1] !=
+ ((((intptr_t) ap) & 0xFF) ^ 0xC5)) {
+ bad |= 0x4;
+ }
+ } else {
+ bad = 0x8;
}
badbuf |= bad;
if (bad) {
- fprintf(stderr,
- _("\nDamaged buffers found at %s:%d\n"), fname, lineno);
+ Pmsg2(0,
+ _("\nDamaged buffers found at %s:%d\n"), get_basename(fname), (uint32_t)lineno);
if (bad & 0x1) {
- fprintf(stderr, _(" discovery of bad prev link.\n"));
+ Pmsg0(0, _(" discovery of bad prev link.\n"));
}
if (bad & 0x2) {
- fprintf(stderr, _(" discovery of bad next link.\n"));
+ Pmsg0(0, _(" discovery of bad next link.\n"));
}
if (bad & 0x4) {
- fprintf(stderr, _(" discovery of data overrun.\n"));
+ Pmsg0(0, _(" discovery of data overrun.\n"));
+ }
+ if (bad & 0x8) {
+ Pmsg0(0, _(" NULL pointer.\n"));
}
- fprintf(stderr, _(" Buffer address: %p\n"), ap);
+ if (!ap) {
+ goto get_out;
+ }
+ Pmsg1(0, _(" Buffer address: %p\n"), ap);
if (ap->abfname != NULL) {
- unsigned memsize = ap->ablen - (HEAD_SIZE + 1);
+ uint32_t memsize = ap->ablen - (HEAD_SIZE + 1);
char errmsg[80];
- fprintf(stderr,
+ Pmsg4(0,
_("Damaged buffer: %6u bytes allocated at line %d of %s %s\n"),
- memsize, ap->ablineno, my_name, ap->abfname
+ memsize, ap->ablineno, my_name, get_basename(ap->abfname)
);
if (bufdump) {
unsigned llen = 0;
if (llen >= 16) {
strcat(errmsg, "\n");
llen = 0;
- fprintf(stderr, "%s", errmsg);
+ Pmsg1(0, "%s", errmsg);
errmsg[0] = EOS;
}
if (*cp < 0x20) {
llen++;
memsize--;
}
- fprintf(stderr, "%s\n", errmsg);
+ Pmsg1(0, "%s\n", errmsg);
}
}
}
- ap = (struct abufhead *) ap->abq.qnext;
+ ap = (struct abufhead *)ap->abq.qnext;
}
+get_out:
V(mutex);
return badbuf ? 0 : 1;
}
void operator delete(void *buf)
{
-// Dmsg1(000, "free called 0x%x\n", buf);
+// Dmsg1(000, "free called %p\n", buf);
sm_free(__FILE__, __LINE__, buf);
}
#endif