+const struct vol *getvolumes(void)
+{
+ return Volumes;
+}
+
+void unload_volumes_and_extmap(void)
+{
+ LOG(log_debug, logtype_afpd, "unload_volumes_and_extmap");
+ free_extmap();
+ free_volumes();
+}
+
+/*
+ * Get a volumes UUID from the config file.
+ * If there is none, it is generated and stored there.
+ *
+ * Returns pointer to allocated storage on success, NULL on error.
+ */
+static char *get_vol_uuid(const AFPObj *obj, const char *volname)
+{
+ char *volname_conf;
+ char buf[1024], uuid[UUID_PRINTABLE_STRING_LENGTH], *p;
+ FILE *fp;
+ struct stat tmpstat;
+ int fd;
+
+ if ((fp = fopen(obj->options.uuidconf, "r")) != NULL) { /* read open? */
+ /* scan in the conf file */
+ while (fgets(buf, sizeof(buf), fp) != NULL) {
+ p = buf;
+ while (p && isblank(*p))
+ p++;
+ if (!p || (*p == '#') || (*p == '\n'))
+ continue; /* invalid line */
+ if (*p == '"') {
+ p++;
+ if ((volname_conf = strtok( p, "\"" )) == NULL)
+ continue; /* syntax error */
+ } else {
+ if ((volname_conf = strtok( p, " \t" )) == NULL)
+ continue; /* syntax error: invalid name */
+ }
+ p = strchr(p, '\0');
+ p++;
+ if (*p == '\0')
+ continue; /* syntax error */
+
+ if (strcmp(volname, volname_conf) != 0)
+ continue; /* another volume name */
+
+ while (p && isblank(*p))
+ p++;
+
+ if (sscanf(p, "%36s", uuid) == 1 ) {
+ for (int i=0; uuid[i]; i++)
+ uuid[i] = toupper(uuid[i]);
+ LOG(log_debug, logtype_afpd, "get_uuid('%s'): UUID: '%s'", volname, uuid);
+ fclose(fp);
+ return strdup(uuid);
+ }
+ }
+ }
+
+ if (fp)
+ fclose(fp);
+
+ /* not found or no file, reopen in append mode */
+
+ if (stat(obj->options.uuidconf, &tmpstat)) { /* no file */
+ if (( fd = creat(obj->options.uuidconf, 0644 )) < 0 ) {
+ LOG(log_error, logtype_afpd, "ERROR: Cannot create %s (%s).",
+ obj->options.uuidconf, strerror(errno));
+ return NULL;
+ }
+ if (( fp = fdopen( fd, "w" )) == NULL ) {
+ LOG(log_error, logtype_afpd, "ERROR: Cannot fdopen %s (%s).",
+ obj->options.uuidconf, strerror(errno));
+ close(fd);
+ return NULL;
+ }
+ } else if ((fp = fopen(obj->options.uuidconf, "a+")) == NULL) { /* not found */
+ LOG(log_error, logtype_afpd, "Cannot create or append to %s (%s).",
+ obj->options.uuidconf, strerror(errno));
+ return NULL;
+ }
+ fseek(fp, 0L, SEEK_END);
+ if(ftell(fp) == 0) { /* size = 0 */
+ fprintf(fp, "# DON'T TOUCH NOR COPY THOUGHTLESSLY!\n");
+ fprintf(fp, "# This file is auto-generated by afpd\n");
+ fprintf(fp, "# and stores UUIDs for TM volumes.\n\n");
+ } else {
+ fseek(fp, -1L, SEEK_END);
+ if(fgetc(fp) != '\n') fputc('\n', fp); /* last char is \n? */
+ }
+
+ /* generate uuid and write to file */
+ atalk_uuid_t id;
+ const char *cp;
+ randombytes((void *)id, 16);
+ cp = uuid_bin2string(id);
+
+ LOG(log_debug, logtype_afpd, "get_uuid('%s'): generated UUID '%s'", volname, cp);
+
+ fprintf(fp, "\"%s\"\t%36s\n", volname, cp);
+ fclose(fp);
+
+ return strdup(cp);
+}