/*
- $Id: cmd_dbd_scanvol.c,v 1.15 2009-12-21 06:41:09 franklahm Exp $
+ $Id: cmd_dbd_scanvol.c,v 1.18 2009-12-22 09:43:15 franklahm Exp $
Copyright (c) 2009 Frank Lahm <franklahm@gmail.com>
return( upath );
}
+#if 0
+/*
+ Check if "name" is pointing to
+ a) an object inside the current volume (return 0)
+ b) an object outside the current volume (return 1)
+ Then stats the pointed to object and if it is a dir ors ADFLAGS_DIR to *adflags
+ Return -1 on any serious error.
+ */
+static int check_symlink(const char *name, int *adflags)
+{
+ int cwd;
+ ssize_t len;
+ char pathbuf[MAXPATHLEN + 1];
+ char *sep;
+ struct stat st;
+
+ if ((len = readlink(name, pathbuf, MAXPATHLEN)) == -1) {
+ dbd_log(LOGSTD, "Error reading link info for '%s/%s': %s",
+ cwdbuf, name, strerror(errno));
+ return -1;
+ }
+ pathbuf[len] = 0;
+
+ if ((stat(pathbuf, &st)) != 0) {
+ dbd_log(LOGSTD, "stat error '%s': %s", pathbuf, strerror(errno));
+ }
+
+ /* Remember cwd */
+ if ((cwd = open(".", O_RDONLY)) < 0) {
+ dbd_log(LOGSTD, "error opening cwd '%s': %s", cwdbuf, strerror(errno));
+ return -1;
+ }
+
+ if (S_ISDIR(st.st_mode)) {
+ *adflags |= ADFLAGS_DIR;
+ } else { /* file */
+ /* get basename from path */
+ if ((sep = strrchr(pathbuf, '/')) == NULL)
+ /* just a file at the same level */
+ return 0;
+ sep = 0; /* pathbuf now contains the directory*/
+ }
+
+ /* fchdir() to pathbuf so we can easily get its path with getcwd() */
+ if ((chdir(pathbuf)) != 0) {
+ dbd_log(LOGSTD, "Cant chdir to '%s': %s", pathbuf, strerror(errno));
+ return -1;
+ }
+
+ if ((getcwd(pathbuf, MAXPATHLEN)) == NULL) {
+ dbd_log(LOGSTD, "Cant get symlink'ed dir '%s/%s': %s", cwdbuf, pathbuf, strerror(errno));
+ if ((fchdir(cwd)) != 0)
+ /* We're foobared */
+ longjmp(jmp, 1); /* this jumps back to cmd_dbd_scanvol() */
+ return -1;
+ }
+
+ if ((fchdir(cwd)) != 0)
+ /* We're foobared */
+ longjmp(jmp, 1); /* this jumps back to cmd_dbd_scanvol() */
+
+ /*
+ We now have the symlink target dir as absoulte path in pathbuf
+ and can compare it with the currents volume path
+ */
+ int i = 0;
+ while (volinfo->v_path[i]) {
+ if ((pathbuf[i] == 0) || (volinfo->v_path[i] != pathbuf[i])) {
+ dbd_log( LOGDEBUG, "extra-share symlink '%s/%s', following", cwdbuf, name);
+ return 1;
+ }
+ i++;
+ }
+
+ dbd_log( LOGDEBUG, "intra-share symlink '%s/%s', not following", cwdbuf, name);
+ return 0;
+}
+#endif
+
/*
Check for wrong encoding e.g. "." at the beginning is not CAP encoded (:2e) although volume is default !AFPVOL_USEDOTS.
We do it by roundtripiping from volcharset to UTF8-MAC and back and then compare the result.
eaname = ea_path(&ea, (*ea.ea_entries)[count].ea_name, 0);
- if (stat(eaname, &st) != 0) {
+ if (lstat(eaname, &st) != 0) {
if (errno == ENOENT)
dbd_log(LOGSTD, "Missing EA: %s/%s", cwdbuf, eaname);
else
ad_close_metadata(&ad);
/* Inherit owner/group from "." to ".AppleDouble" and ".Parent" */
- if ((stat(".", &st)) != 0) {
+ if ((lstat(".", &st)) != 0) {
dbd_log( LOGSTD, "Couldnt stat %s: %s", cwdbuf, strerror(errno));
return -1;
}
if (STRCMP(ep->d_name, ==, ".Parent"))
continue;
- if ((stat(ep->d_name, &st)) < 0) {
+ if ((lstat(ep->d_name, &st)) < 0) {
dbd_log( LOGSTD, "Lost file or dir while enumeratin dir '%s/%s/%s', probably removed: %s",
cwdbuf, ADv2_DIRNAME, ep->d_name, strerror(errno));
continue;
if (STRCMP(ep->d_name, == , ADv2_DIRNAME))
continue;
- if ((ret = stat(ep->d_name, &st)) < 0) {
+ if ((ret = lstat(ep->d_name, &st)) < 0) {
dbd_log( LOGSTD, "Lost file while reading dir '%s/%s', probably removed: %s", cwdbuf, ep->d_name, strerror(errno));
continue;
}
- if (S_ISREG(st.st_mode))
+
+ switch (st.st_mode & S_IFMT) {
+ case S_IFREG:
adflags = 0;
- else
+ break;
+ case S_IFDIR:
adflags = ADFLAGS_DIR;
+ break;
+ case S_IFLNK:
+ dbd_log(LOGDEBUG, "Ignoring symlink %s/%s", cwdbuf, ep->d_name);
+#if 0
+ ret = check_symlink(ep->d_name, &adflags);
+ if (ret == 1)
+ break;
+ if (ret == -1)
+ dbd_log(LOGSTD, "Error checking symlink %s/%s", cwdbuf, ep->d_name);
+#endif
+ continue;
+ default:
+ dbd_log(LOGSTD, "Bad filetype: %s/%s", cwdbuf, ep->d_name);
+ if ( ! (dbd_flags & DBD_FLAGS_SCAN)) {
+ if ((unlink(ep->d_name)) != 0) {
+ dbd_log(LOGSTD, "Error removing: %s/%s: %s", cwdbuf, ep->d_name, strerror(errno));
+ }
+ }
+ continue;
+ }
/**************************************************************************
Tests
/* Run with umask 0 */
umask(0);
- /* chdir to vol */
+ /* Remove trailing slash from volume, chdir to vol */
+ if (volinfo->v_path[strlen(volinfo->v_path) - 1] == '/')
+ volinfo->v_path[strlen(volinfo->v_path) - 1] = 0;
strcpy(cwdbuf, volinfo->v_path);
- if (cwdbuf[strlen(cwdbuf) - 1] == '/')
- cwdbuf[strlen(cwdbuf) - 1] = 0;
chdir(volinfo->v_path);
/* Start recursion */