+ return 1;
+}
+
+
+/*
+ * Given a full filename, split it into its path
+ * and filename parts. They are returned in pool memory
+ * in the arguments provided.
+ */
+void split_path_and_filename(const char *fname, POOLMEM **path, int *pnl,
+ POOLMEM **file, int *fnl)
+{
+ const char *f;
+ int slen;
+ int len = slen = strlen(fname);
+
+ /*
+ * Find path without the filename.
+ * I.e. everything after the last / is a "filename".
+ * OK, maybe it is a directory name, but we treat it like
+ * a filename. If we don't find a / then the whole name
+ * must be a path name (e.g. c:).
+ */
+ f = fname + len - 1;
+ /* "strip" any trailing slashes */
+ while (slen > 1 && IsPathSeparator(*f)) {
+ slen--;
+ f--;
+ }
+ /* Walk back to last slash -- begin of filename */
+ while (slen > 0 && !IsPathSeparator(*f)) {
+ slen--;
+ f--;
+ }
+ if (IsPathSeparator(*f)) { /* did we find a slash? */
+ f++; /* yes, point to filename */
+ } else { /* no, whole thing must be path name */
+ f = fname;
+ }
+ Dmsg2(200, "after strip len=%d f=%s\n", len, f);
+ *fnl = fname - f + len;
+ if (*fnl > 0) {
+ *file = check_pool_memory_size(*file, *fnl+1);
+ memcpy(*file, f, *fnl); /* copy filename */
+ }
+ (*file)[*fnl] = 0;
+
+ *pnl = f - fname;
+ if (*pnl > 0) {
+ *path = check_pool_memory_size(*path, *pnl+1);
+ memcpy(*path, fname, *pnl);
+ }
+ (*path)[*pnl] = 0;
+
+ Dmsg2(200, "pnl=%d fnl=%d\n", *pnl, *fnl);
+ Dmsg3(200, "split fname=%s path=%s file=%s\n", fname, *path, *file);
+}
+
+/*
+ * Extremely simple sscanf. Handles only %(u,d,ld,qd,qu,lu,lld,llu,c,nns)
+ */
+const int BIG = 1000;
+int bsscanf(const char *buf, const char *fmt, ...)
+{
+ va_list ap;
+ int count = 0;
+ void *vp;
+ char *cp;
+ int l = 0;
+ int max_len = BIG;
+ uint64_t value;
+ bool error = false;
+
+ va_start(ap, fmt);
+ while (*fmt && !error) {
+// Dmsg1(000, "fmt=%c\n", *fmt);
+ if (*fmt == '%') {
+ fmt++;
+// Dmsg1(000, "Got %% nxt=%c\n", *fmt);
+switch_top:
+ switch (*fmt++) {
+ case 'u':
+ case 'd':
+ value = 0;
+ while (B_ISDIGIT(*buf)) {
+ value = B_TIMES10(value) + *buf++ - '0';
+ }
+ vp = (void *)va_arg(ap, void *);
+// Dmsg2(000, "val=%lld at 0x%lx\n", value, (long unsigned)vp);
+ if (l == 0) {
+ *((int *)vp) = (int)value;
+ } else if (l == 1) {
+ *((uint32_t *)vp) = (uint32_t)value;
+// Dmsg0(000, "Store 32 bit int\n");
+ } else {
+ *((uint64_t *)vp) = (uint64_t)value;
+// Dmsg0(000, "Store 64 bit int\n");
+ }
+ count++;
+ l = 0;
+ break;
+ case 'l':
+// Dmsg0(000, "got l\n");
+ l = 1;
+ if (*fmt == 'l') {
+ l++;
+ fmt++;
+ }
+ if (*fmt == 'd' || *fmt == 'u') {
+ goto switch_top;
+ }
+// Dmsg1(000, "fmt=%c !=d,u\n", *fmt);
+ error = true;
+ break;
+ case 'q':
+ l = 2;
+ if (*fmt == 'd' || *fmt == 'u') {
+ goto switch_top;
+ }
+// Dmsg1(000, "fmt=%c !=d,u\n", *fmt);
+ error = true;
+ break;
+ case 's':
+// Dmsg1(000, "Store string max_len=%d\n", max_len);
+ cp = (char *)va_arg(ap, char *);
+ while (*buf && !B_ISSPACE(*buf) && max_len-- > 0) {
+ *cp++ = *buf++;
+ }
+ *cp = 0;
+ count++;
+ max_len = BIG;
+ break;
+ case 'c':
+ cp = (char *)va_arg(ap, char *);
+ *cp = *buf++;
+ count++;
+ break;
+ case '%':
+ if (*buf++ != '%') {
+ error = true;
+ }
+ break;
+ default:
+ fmt--;
+ max_len = 0;
+ while (B_ISDIGIT(*fmt)) {
+ max_len = B_TIMES10(max_len) + *fmt++ - '0';
+ }
+// Dmsg1(000, "Default max_len=%d\n", max_len);
+ if (*fmt == 's') {
+ goto switch_top;
+ }
+// Dmsg1(000, "Default c=%c\n", *fmt);
+ error = true;
+ break; /* error: unknown format */
+ }
+ continue;
+
+ /* White space eats zero or more whitespace */
+ } else if (B_ISSPACE(*fmt)) {
+ fmt++;
+ while (B_ISSPACE(*buf)) {
+ buf++;
+ }
+ /* Plain text must match */
+ } else if (*buf++ != *fmt++) {
+// Dmsg2(000, "Mismatch buf=%c fmt=%c\n", *--buf, *--fmt);
+ error = true;
+ break;