char abspath[MAXPATHLEN];
char *p;
- if (stat(path, &st) != 0) {
- return NULL;
- }
+ strlcpy(abspath, path, sizeof(abspath));
+
+ /* we might be called from `ad cp ...` with non existing target */
+ if (stat(abspath, &st) != 0) {
+ if (errno != ENOENT)
+ return NULL;
+
+ if (NULL == (p = strrchr(abspath, '/')) )
+ /* single component `ad cp SOURCEFILE TARGETFILE`, use "." instead */
+ strcpy(abspath, ".");
+ else
+ /* try without the last path element */
+ *p = '\0';
- strlcpy (abspath, path, sizeof(abspath));
+ if (stat(abspath, &st) != 0) {
+ return NULL;
+ }
+ }
- if (!S_ISDIR(st.st_mode)) {
- if (NULL == (p=strrchr(abspath, '/')) )
+ if (S_ISREG(st.st_mode)) {
+ /* single file copy SOURCE */
+ if (NULL == (p = strrchr(abspath, '/')) )
+ /* no path, use "." instead */
strcpy(abspath, ".");
else
+ /* try without the last path element */
*p = '\0';
}
}
break;
case CNIDDBDPORT:
- vol->v_dbd_port = atoi(value);
- break;
- case CNID_DBPATH:
- if ((vol->v_dbpath = strdup(value)) == NULL) {
+ if ((vol->v_dbd_port = strdup(value)) == NULL) {
fprintf (stderr, "strdup: %s", strerror(errno));
- return -1;
+ return -1;
}
break;
+ case CNID_DBPATH:
+ if ((vol->v_dbpath = malloc(MAXPATHLEN+1)) == NULL)
+ return -1;
+ strcpy(vol->v_dbpath, value);
+ break;
case ADOUBLE_VER:
if (strcasecmp(value, "v1") == 0) {
vol->v_adouble = AD_VERSION1;
char volinfofile[MAXPATHLEN];
char buf[MAXPATHLEN];
struct flock lock;
- int fd;
+ int fd, len;
FILE *fp;
if ( !path || !vol)
return -1;
if ((vol->v_path = strdup(volinfofile)) == NULL ) {
- fprintf (stderr, "strdup: %s", strerror(errno));
+ fprintf (stderr, "strdup: %s", strerror(errno));
return (-1);
}
+ /* Remove trailing slashes */
+ len = strlen(vol->v_path);
+ while (len && (vol->v_path[len-1] == '/')) {
+ vol->v_path[len-1] = 0;
+ len--;
+ }
+
strlcat(volinfofile, ".AppleDesktop/", sizeof(volinfofile));
strlcat(volinfofile, VOLINFOFILE, sizeof(volinfofile));
if ((vol->v_flags & AFPVOL_INV_DOTS))
vol->v_ad_options |= ADVOL_INVDOTS;
+ vol->retaincount = 1;
+
fclose(fp);
return 0;
}
+/*!
+ * Allocate a struct volinfo object for refcounting usage with retain and close, and
+ * call loadvolinfo with it
+ */
+struct volinfo *allocvolinfo(char *path)
+{
+ struct volinfo *p = malloc(sizeof(struct volinfo));
+ if (p == NULL)
+ return NULL;
+
+ if (loadvolinfo(path, p) == -1)
+ return NULL;
+
+ p->malloced = 1;
+
+ return p;
+}
+
+void retainvolinfo(struct volinfo *vol)
+{
+ vol->retaincount++;
+}
+
+/*!
+ * Decrement retain count, free resources when retaincount reaches 0
+ */
+int closevolinfo(struct volinfo *volinfo)
+{
+ if (volinfo->retaincount <= 0)
+ abort();
+
+ volinfo->retaincount--;
+
+ if (volinfo->retaincount == 0) {
+ free(volinfo->v_name); volinfo->v_name = NULL;
+ free(volinfo->v_path); volinfo->v_path = NULL;
+ free(volinfo->v_cnidscheme); volinfo->v_cnidscheme = NULL;
+ free(volinfo->v_dbpath); volinfo->v_dbpath = NULL;
+ free(volinfo->v_volcodepage); volinfo->v_volcodepage = NULL;
+ free(volinfo->v_maccodepage); volinfo->v_maccodepage = NULL;
+ free(volinfo->v_dbd_host); volinfo->v_dbd_host = NULL;
+ free(volinfo->v_dbd_port); volinfo->v_dbd_port = NULL;
+ if (volinfo->malloced) {
+ volinfo->malloced = 0;
+ free(volinfo);
+ }
+ }
+
+ return 0;
+}
+
/*
* Save the volume options to a file, used by shell utilities. Writing the file
* everytime a volume is opened is unnecessary, but it shouldn't hurt much.
strlcat(item, "\n", sizeof(item));
strlcat(buf, item, sizeof(buf));
- /* ExtendedAttrbutes */
+ /* ExtendedAttributes */
strcpy(item, "EXTATTRTYPE:");
- if (vol->v_vfs_ea & AFPVOL_EA_AD)
- strlcat(item, "AFPVOL_EA_AD", sizeof(item));
- else if (vol->v_vfs_ea & AFPVOL_EA_SYS)
- strlcat(item, "AFPVOL_EA_SYS", sizeof(item));
- else
- strlcat(item, "AFPVOL_EA_UNKNOWN", sizeof(item));
+ switch (vol->v_vfs_ea) {
+ case AFPVOL_EA_SYS:
+ strlcat(item, "AFPVOL_EA_SYS\n", sizeof(item));
+ break;
+ case AFPVOL_EA_AD:
+ strlcat(item, "AFPVOL_EA_AD\n", sizeof(item));
+ break;
+ case AFPVOL_EA_NONE:
+ strlcat(item, "AFPVOL_EA_NONE\n", sizeof(item));
+ break;
+ default:
+ strlcat(item, "AFPVOL_EA_UNKNOWN\n", sizeof(item));
+ }
+
strlcat(buf, item, sizeof(buf));
if (strlen(buf) >= sizeof(buf)-1)