#include "bacula.h"
/*
- * Append an item to the list
+ * Private grow list function. Used to insure that
+ * at least one more "slot" is available.
*/
-void alist::append(void *item) {
+void alist::grow_list()
+{
if (num_items == 0) {
if (num_grow == 0) {
num_grow = 1; /* default if not initialized */
max_items += num_grow;
items = (void **)realloc(items, max_items * sizeof(void *));
}
+}
+
+void *alist::first()
+{
+ cur_item = 1;
+ if (num_items == 0) {
+ return NULL;
+ } else {
+ return items[0];
+ }
+}
+
+void *alist::last()
+{
+ if (num_items == 0) {
+ return NULL;
+ } else {
+ cur_item = num_items;
+ return items[num_items-1];
+ }
+}
+
+void *alist::next()
+{
+ if (cur_item >= num_items) {
+ return NULL;
+ } else {
+ return items[cur_item++];
+ }
+}
+
+void *alist::prev()
+{
+ if (cur_item <= 1) {
+ return NULL;
+ } else {
+ return items[--cur_item];
+ }
+}
+
+/*
+ * prepend an item to the list
+ */
+void alist::prepend(void *item) {
+ grow_list();
+ if (num_items == 0) {
+ items[num_items++] = item;
+ return;
+ }
+ for (int i=num_items; i > 0; i--) {
+ items[i] = items[i-1];
+ }
+ items[0] = item;
+ num_items++;
+}
+
+
+/*
+ * Append an item to the list
+ */
+void alist::append(void *item) {
+ grow_list();
items[num_items++] = item;
}
+/* Remove an item from the list */
+void * alist::remove(int index)
+{
+ void *item;
+ if (index < 0 || index >= num_items) {
+ return NULL;
+ }
+ item = items[index];
+ num_items--;
+ for (int i=index; i < num_items; i++) {
+ items[i] = items[i+1];
+ }
+ return item;
+}
+
+
/* Get the index item -- we should probably allow real indexing here */
void * alist::get(int index)
{
*/
+/*
+ * There is a lot of extra casting here to work around the fact
+ * that some compilers (Sun and Visual C++) do not accept
+ * (void *) as an lvalue on the left side of an equal.
+ *
+ * Loop var through each member of list
+ */
+#define foreach_alist(var, list) \
+ for((*((void **)&(var))=(void*)((list)->first())); (var); (*((void **)&(var))=(void*)((list)->next())))
+
+#ifdef the_easy_way
+#define foreach_dlist(var, list) \
+ for((void*(var))=(list)->first(); (var); (void *(var))=(list)->next(var)); )
+#endif
+
+
/* Second arg of init */
enum {
owned_by_alist = true,
not_owned_by_alist = false
};
-
/*
* Array list -- much like a simplified STL vector
* array of pointers to inserted items
int num_items;
int max_items;
int num_grow;
+ int cur_item;
bool own_items;
+ void grow_list(void);
public:
alist(int num = 1, bool own=true);
void init(int num = 1, bool own=true);
void append(void *item);
+ void prepend(void *item);
+ void *remove(int index);
void *get(int index);
+ bool empty();
+ void *prev();
+ void *next();
+ void *first();
+ void *last();
void * operator [](int index) const;
int size();
void destroy();
return items[index];
}
+inline bool alist::empty()
+{
+ return num_items == 0;
+}
+
/*
* This allows us to do explicit initialization,
* allowing us to mix C++ classes inside malloc'ed
if (stat(mp_chr(fname), &statp) == 0) {
/* File exists, see what we have */
*pidbuf = 0;
- if ((pidfd = open(mp_chr(fname), O_RDONLY)) < 0 ||
+ if ((pidfd = open(mp_chr(fname), O_RDONLY|O_BINARY, 0)) < 0 ||
read(pidfd, &pidbuf, sizeof(pidbuf)) < 0 ||
sscanf(pidbuf, "%d", &oldpid) != 1) {
Emsg2(M_ERROR_TERM, 0, _("Cannot open pid file. %s ERR=%s\n"), fname, strerror(errno));
unlink(mp_chr(fname)); /* remove stale pid file */
}
/* Create new pid file */
- if ((pidfd = open(mp_chr(fname), O_CREAT | O_TRUNC | O_WRONLY, 0644)) >= 0) {
+ if ((pidfd = open(mp_chr(fname), O_CREAT | O_TRUNC | O_WRONLY | O_BINARY, 0644)) >= 0) {
len = sprintf(pidbuf, "%d\n", (int)getpid());
write(pidfd, pidbuf, len);
close(pidfd);
void read_state_file(char *dir, const char *progname, int port)
{
int sfd;
+ ssize_t stat;
POOLMEM *fname = get_pool_memory(PM_FNAME);
struct s_state_hdr hdr;
+ int hdr_size = sizeof(hdr);
Mmsg(&fname, "%s/%s.%d.state", dir, progname, port);
/* If file exists, see what we have */
- if ((sfd = open(mp_chr(fname), O_RDONLY, 0)) < 0 ||
- read(sfd, &hdr, sizeof(hdr)) < 0 ||
- hdr.version != state_hdr.version) {
- Dmsg2(000, "Could not open or read state file. sfd=%d: ERR=%s\n",
- sfd, strerror(errno));
+ Dmsg1(10, "O_BINARY=%d\n", O_BINARY);
+ if ((sfd = open(mp_chr(fname), O_RDONLY|O_BINARY, 0)) < 0) {
+ Dmsg3(010, "Could not open state file. sfd=%d size=%d: ERR=%s\n",
+ sfd, sizeof(hdr), strerror(errno));
+ goto bail_out;
+ }
+ if ((stat=read(sfd, &hdr, hdr_size)) != hdr_size) {
+ Dmsg4(010, "Could not read state file. sfd=%d stat=%d size=%d: ERR=%s\n",
+ sfd, (int)stat, hdr_size, strerror(errno));
goto bail_out;
}
+ if (hdr.version != state_hdr.version) {
+ Dmsg2(010, "Bad hdr version. Wanted %d got %d\n",
+ state_hdr.version, hdr.version);
+ }
hdr.id[13] = 0;
if (strcmp(hdr.id, state_hdr.id) != 0) {
- Dmsg0(000, "State file header invalid.\n");
+ Dmsg0(000, "State file header id invalid.\n");
goto bail_out;
}
+ Dmsg1(010, "Read header of %d bytes.\n", sizeof(hdr));
read_last_jobs_list(sfd, hdr.last_jobs_addr);
bail_out:
if (sfd >= 0) {
Mmsg(&fname, "%s/%s.%d.state", dir, progname, port);
/* Create new state file */
- if ((sfd = open(mp_chr(fname), O_CREAT | O_TRUNC | O_WRONLY, 0640)) < 0) {
+ if ((sfd = open(mp_chr(fname), O_CREAT|O_TRUNC|O_WRONLY|O_BINARY, 0640)) < 0) {
Dmsg2(000, _("Could not create state file. %s ERR=%s\n"), fname, strerror(errno));
Emsg2(M_ERROR, 0, _("Could not create state file. %s ERR=%s\n"), fname, strerror(errno));
goto bail_out;
}
- if (write(sfd, &state_hdr, sizeof(state_hdr)) < 0) {
- Dmsg1(000, "Write error: ERR=%s\n", strerror(errno));
+ if (write(sfd, &state_hdr, sizeof(state_hdr)) != sizeof(state_hdr)) {
+ Dmsg1(000, "Write hdr error: ERR=%s\n", strerror(errno));
goto bail_out;
}
+ Dmsg1(010, "Wrote header of %d bytes\n", sizeof(state_hdr));
state_hdr.last_jobs_addr = sizeof(state_hdr);
state_hdr.reserved[0] = write_last_jobs_list(sfd, state_hdr.last_jobs_addr);
+ Dmsg1(010, "write last job end = %d\n", (int)state_hdr.reserved[0]);
if (lseek(sfd, 0, SEEK_SET) < 0) {
Dmsg1(000, "lseek error: ERR=%s\n", strerror(errno));
goto bail_out;
}
- write(sfd, &state_hdr, sizeof(state_hdr));
+ if (write(sfd, &state_hdr, sizeof(state_hdr)) != sizeof(state_hdr)) {
+ Dmsg1(000, "Write final hdr error: ERR=%s\n", strerror(errno));
+ }
+
bail_out:
if (sfd >= 0) {
close(sfd);
struct s_last_job *je, job;
uint32_t num;
+ Dmsg1(010, "read_last_jobs seek to %d\n", (int)addr);
if (addr == 0 || lseek(fd, addr, SEEK_SET) < 0) {
return;
}
- if (read(fd, &num, sizeof(num)) < 0) {
+ if (read(fd, &num, sizeof(num)) != sizeof(num)) {
return;
}
+ Dmsg1(010, "Read num_items=%d\n", num);
if (num > 4 * MAX_LAST_JOBS) { /* sanity check */
return;
}
for ( ; num; num--) {
- if (read(fd, &job, sizeof(job)) < 0) {
+ if (read(fd, &job, sizeof(job)) != sizeof(job)) {
+ Dmsg1(000, "Read job entry. ERR=%s\n", strerror(errno));
return;
}
if (job.JobId > 0) {
struct s_last_job *je;
uint32_t num;
+ Dmsg1(010, "write_last_jobs seek to %d\n", (int)addr);
if (lseek(fd, addr, SEEK_SET) < 0) {
return 0;
}
if (last_jobs) {
/* First record is number of entires */
num = last_jobs->size();
- if (write(fd, &num, sizeof(num)) < 0) {
+ if (write(fd, &num, sizeof(num)) != sizeof(num)) {
+ Dmsg1(000, "Error writing num_items: ERR=%s\n", strerror(errno));
return 0;
}
foreach_dlist(je, last_jobs) {
- if (write(fd, je, sizeof(struct s_last_job)) < 0) {
+ if (write(fd, je, sizeof(struct s_last_job)) != sizeof(struct s_last_job)) {
+ Dmsg1(000, "Error writing job: ERR=%s\n", strerror(errno));
return 0;
}
}