Exemple #1
0
static void check_c_tmpname(void **state)
{
    char tmpl[22]={0};
    char prev[22]={0};
    char *tmp;
    int i = 0;

    (void) state; /* unused */

    srand((unsigned)time(NULL));

    /* remember the last random value and compare the new one against.
     * They may never be the same. */
    for(i = 0; i < 100; i++){
        strcpy(tmpl, "check_tmpname.XXXXXX");
        tmp = c_tmpname(tmpl);
        assert_non_null(tmp);

        if (strlen(prev)) {
            assert_string_not_equal(tmp, prev);
        }
        strcpy(prev, tmp);
        SAFE_FREE(tmp);
    }
}
Exemple #2
0
static void setup_toplevel_dir( void **state ) {
    char basepath[255];

    strcpy( basepath, "tXXXXXX");
    assert_int_equal( c_tmpname(basepath), 0 );
    printf("Using top testing dir %s\n", basepath);
    assert_int_equal( test_mkdir( basepath ), 0 );
    *state = (void*) c_strdup(basepath);
}
Exemple #3
0
static int _csync_push_file(CSYNC *ctx, csync_file_stat_t *st) {
  enum csync_replica_e srep = -1;
  enum csync_replica_e drep = -1;
  enum csync_replica_e rep_bak = -1;

  char *suri = NULL;
  char *duri = NULL;
  char *turi = NULL;
  char *tdir = NULL;

  csync_vio_handle_t *sfp = NULL;
  csync_vio_handle_t *dfp = NULL;

  csync_vio_file_stat_t *tstat = NULL;

  char errbuf[256] = {0};
  char buf[MAX_XFER_BUF_SIZE] = {0};
  ssize_t bread = 0;
  ssize_t bwritten = 0;
  struct timeval times[2];

  int rc = -1;
  int count = 0;
  int flags = 0;

  rep_bak = ctx->replica;

  switch (ctx->current) {
    case LOCAL_REPLICA:
      srep = ctx->local.type;
      drep = ctx->remote.type;
      if (asprintf(&suri, "%s/%s", ctx->local.uri, st->path) < 0) {
        rc = -1;
        goto out;
      }
      if (asprintf(&duri, "%s/%s", ctx->remote.uri, st->path) < 0) {
        rc = -1;
        goto out;
      }
      break;
    case REMOTE_REPLCIA:
      srep = ctx->remote.type;
      drep = ctx->local.type;
      if (asprintf(&suri, "%s/%s", ctx->remote.uri, st->path) < 0) {
        rc = -1;
        goto out;
      }
      if (asprintf(&duri, "%s/%s", ctx->local.uri, st->path) < 0) {
        rc = -1;
        goto out;
      }
      break;
    default:
      break;
  }

  /* Open the source file */
  ctx->replica = srep;
  flags = O_RDONLY|O_NOFOLLOW;
  /* O_NOATIME can only be set by the owner of the file or the superuser */
  if (st->uid == ctx->pwd.uid || ctx->pwd.euid == 0) {
    flags |= O_NOATIME;
  }
  sfp = csync_vio_open(ctx, suri, flags, 0);
  if (sfp == NULL) {
    if (errno == ENOMEM) {
      rc = -1;
    } else {
      rc = 1;
    }
    CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR,
        "file: %s, command: open(O_RDONLY), error: %s",
        suri,
        strerror_r(errno, errbuf, sizeof(errbuf)));
    goto out;
  }

  /* create the temporary file name */
  if (asprintf(&turi, "%s.XXXXXX", duri) < 0) {
    rc = -1;
    goto out;
  }

  /* We just want a random file name here, open checks if the file exists. */
  if (c_tmpname(turi) < 0) {
    rc = -1;
    goto out;
  }

  /* Create the destination file */
  ctx->replica = drep;
  while ((dfp = csync_vio_open(ctx, turi, O_CREAT|O_EXCL|O_WRONLY|O_NOCTTY,
          C_FILE_MODE)) == NULL) {
    switch (errno) {
      case EEXIST:
        if (count++ > 10) {
          CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR,
              "file: %s, command: open(O_CREAT), error: max count exceeded",
              duri);
          rc = 1;
          goto out;
        }
        if (c_tmpname(turi) < 0) {
          rc = -1;
          goto out;
        }
        break;
      case ENOENT:
        /* get the directory name */
        tdir = c_dirname(turi);
        if (tdir == NULL) {
          rc = -1;
          goto out;
        }

        if (csync_vio_mkdirs(ctx, tdir, C_DIR_MODE) < 0) {
          CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN,
              "dir: %s, command: mkdirs, error: %s",
              tdir,
              strerror_r(errno, errbuf, sizeof(errbuf)));
        }
        break;
      case ENOMEM:
        rc = -1;
        CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR,
            "file: %s, command: open(O_CREAT), error: %s",
            turi,
            strerror_r(errno, errbuf, sizeof(errbuf)));
        goto out;
        break;
      default:
        CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR,
            "file: %s, command: open(O_CREAT), error: %s",
            turi,
            strerror_r(errno, errbuf, sizeof(errbuf)));
        rc = 1;
        goto out;
        break;
    }

  }

  /* copy file */
  for (;;) {
    ctx->replica = srep;
    bread = csync_vio_read(ctx, sfp, buf, MAX_XFER_BUF_SIZE);

    if (bread < 0) {
      /* read error */
      CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR,
          "file: %s, command: read, error: %s",
          suri,
          strerror_r(errno, errbuf, sizeof(errbuf)));
      rc = 1;
      goto out;
    } else if (bread == 0) {
      /* done */
      break;
    }

    ctx->replica = drep;
    bwritten = csync_vio_write(ctx, dfp, buf, bread);

    if (bwritten < 0 || bread != bwritten) {
      CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR,
          "file: %s, command: write, error: bread = %zu, bwritten = %zu - %s",
          duri,
          bread,
          bwritten,
          strerror_r(errno, errbuf, sizeof(errbuf)));
      rc = 1;
      goto out;
    }
  }

  ctx->replica = srep;
  if (csync_vio_close(ctx, sfp) < 0) {
    CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR,
        "file: %s, command: close, error: %s",
        suri,
        strerror_r(errno, errbuf, sizeof(errbuf)));
  }
  sfp = NULL;

  ctx->replica = drep;
  if (csync_vio_close(ctx, dfp) < 0) {
    dfp = NULL;
    switch (errno) {
      /* stop if no space left or quota exceeded */
      case ENOSPC:
      case EDQUOT:
        CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR,
            "file: %s, command: close, error: %s",
            turi,
            strerror_r(errno, errbuf, sizeof(errbuf)));
        rc = -1;
        goto out;
        break;
      default:
        CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR,
            "file: %s, command: close, error: %s",
            turi,
            strerror_r(errno, errbuf, sizeof(errbuf)));
        break;
    }
  }
  dfp = NULL;

  /*
   * Check filesize
   */
  ctx->replica = drep;
  tstat = csync_vio_file_stat_new();
  if (tstat == NULL) {
    CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR,
        "file: %s, command: stat, error: %s",
        turi,
        strerror_r(errno, errbuf, sizeof(errbuf)));
    rc = -1;
    goto out;
  }

  if (csync_vio_stat(ctx, turi, tstat) < 0) {
    switch (errno) {
      case ENOMEM:
        rc = -1;
        break;
      default:
        rc = 1;
        break;
    }
    CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR,
        "file: %s, command: stat, error: %s",
        turi,
        strerror_r(errno, errbuf, sizeof(errbuf)));
    goto out;
  }

  if (st->size != tstat->size) {
    CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR,
        "file: %s, error: incorrect filesize (size: %jd should be %jd)",
        turi, tstat->size, st->size);
    rc = 1;
    goto out;
  }

  /* override original file */
  ctx->replica = drep;
  if (csync_vio_rename(ctx, turi, duri) < 0) {
    switch (errno) {
      case ENOMEM:
        rc = -1;
        break;
      default:
        rc = 1;
        break;
    }
    CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR,
        "file: %s, command: rename, error: %s",
        duri,
        strerror_r(errno, errbuf, sizeof(errbuf)));
    goto out;
  }

  /* set mode only if it is not the default mode */
  if ((st->mode & 07777) != C_FILE_MODE) {
    if (csync_vio_chmod(ctx, duri, st->mode) < 0) {
      switch (errno) {
        case ENOMEM:
          rc = -1;
          break;
        default:
          rc = 1;
          break;
      }
      CSYNC_LOG(CSYNC_LOG_PRIORITY_ERROR,
          "file: %s, command: chmod, error: %s",
          duri,
          strerror_r(errno, errbuf, sizeof(errbuf)));
      goto out;
    }
  }

  /* set owner and group if possible */
  if (ctx->pwd.euid == 0) {
    csync_vio_chown(ctx, duri, st->uid, st->gid);
  }

  /* sync time */
  times[0].tv_sec = times[1].tv_sec = st->modtime;
  times[0].tv_usec = times[1].tv_usec = 0;

  ctx->replica = drep;
  csync_vio_utimes(ctx, duri, times);

  /* set instruction for the statedb merger */
  st->instruction = CSYNC_INSTRUCTION_UPDATED;

  CSYNC_LOG(CSYNC_LOG_PRIORITY_DEBUG, "PUSHED  file: %s", duri);

  rc = 0;

out:
  ctx->replica = srep;
  csync_vio_close(ctx, sfp);

  ctx->replica = drep;
  csync_vio_close(ctx, dfp);

  csync_vio_file_stat_destroy(tstat);

  /* set instruction for the statedb merger */
  if (rc != 0) {
    st->instruction = CSYNC_INSTRUCTION_ERROR;
    csync_vio_unlink(ctx, turi);
  }

  SAFE_FREE(suri);
  SAFE_FREE(duri);
  SAFE_FREE(turi);
  SAFE_FREE(tdir);

  ctx->replica = rep_bak;

  return rc;
}
Exemple #4
0
static csync_vio_method_handle_t *owncloud_open(const char *durl,
                                                int flags,
                                                mode_t mode) {
    char *uri = NULL;
    char *dir = NULL;
    char getUrl[PATH_MAX];
    int put = 0;
    int rc = NE_OK;
#ifdef _WIN32
    int gtp = 0;
    char tmpname[13];
#endif

    struct transfer_context *writeCtx = NULL;
    csync_stat_t statBuf;
    memset( getUrl, '\0', PATH_MAX );

    (void) mode; /* unused on webdav server */
    DEBUG_WEBDAV(( "=> open called for %s\n", durl ));

    uri = _cleanPath( durl );
    if( ! uri ) {
        DEBUG_WEBDAV(("Failed to clean path for %s\n", durl ));
        errno = EACCES;
        rc = NE_ERROR;
    }

    if( rc == NE_OK )
        dav_connect( durl );

    if (flags & O_WRONLY) {
        put = 1;
    }
    if (flags & O_RDWR) {
        put = 1;
    }
    if (flags & O_CREAT) {
        put = 1;
    }


    if( rc == NE_OK && put ) {
        /* check if the dir name exists. Otherwise return ENOENT */
        dir = c_dirname( durl );
	if (dir == NULL) {
            errno = ENOMEM;
	    return NULL;
	}
        DEBUG_WEBDAV(("Stating directory %s\n", dir ));
        if( c_streq( dir, _lastDir )) {
            DEBUG_WEBDAV(("Dir %s is there, we know it already.\n", dir));
        } else {
            if( owncloud_stat( dir, (csync_vio_method_handle_t*)(&statBuf) ) == 0 ) {
                DEBUG_WEBDAV(("Directory of file to open exists.\n"));
                SAFE_FREE( _lastDir );
                _lastDir = c_strdup(dir);

            } else {
                DEBUG_WEBDAV(("Directory %s of file to open does NOT exist.\n", dir ));
                /* the directory does not exist. That is an ENOENT */
                errno = ENOENT;
                SAFE_FREE( dir );
                return NULL;
            }
        }
    }

    writeCtx = c_malloc( sizeof(struct transfer_context) );
    writeCtx->bytes_written = 0;
    if( rc == NE_OK ) {
        /* open a temp file to store the incoming data */
#ifdef _WIN32
        memset( tmpname, '\0', 13 );
        gtp = GetTempPath( PATH_MAX, getUrl );
        DEBUG_WEBDAV(("win32 tmp path: %s\n", getUrl ));
        if ( gtp > MAX_PATH || (gtp == 0) ) {
            DEBUG_WEBDAV(("Failed to compute Win32 tmp path, trying /tmp\n"));
            strcpy( getUrl, "/tmp/");
        }
        strcpy( tmpname, "csync.XXXXXX" );
        if( c_tmpname( tmpname ) == 0 ) {
            _fmode = _O_BINARY;
            strcat( getUrl, tmpname );
            writeCtx->tmpFileName = c_strdup( getUrl );
            writeCtx->fd = open( writeCtx->tmpFileName, O_RDWR | O_CREAT | O_EXCL, 0600 );
	} else {
	   writeCtx->fd = -1;
	}
#else
        writeCtx->tmpFileName = c_strdup( "/tmp/csync.XXXXXX" );
        writeCtx->fd = mkstemp( writeCtx->tmpFileName );
#endif
        DEBUG_WEBDAV(("opening temp directory %s: %d\n", writeCtx->tmpFileName, writeCtx->fd ));
        if( writeCtx->fd == -1 ) {
	    DEBUG_WEBDAV(("Failed to open temp file, errno = %d\n", errno ));
            rc = NE_ERROR;
            /* errno is set by the mkstemp call above. */
        }
    }

    if( rc == NE_OK && put) {
        DEBUG_WEBDAV(("PUT request on %s!\n", uri));
        /* reset the write buffer */
        writeCtx->bytes_written = 0;
        writeCtx->fileWritten = 0;   /* flag to indicate if contents was pushed to file */

        writeCtx->req = ne_request_create(dav_session.ctx, "PUT", uri);
	writeCtx->method = "PUT";
    }


    if( rc == NE_OK && ! put ) {
        writeCtx->req = 0;
        writeCtx->method = "GET";

        /* Download the data into a local temp file. */
        /* the download via the get function requires a full uri */
        snprintf( getUrl, PATH_MAX, "%s://%s%s", ne_get_scheme( dav_session.ctx),
                  ne_get_server_hostport( dav_session.ctx ), uri );
        DEBUG_WEBDAV(("GET request on %s\n", getUrl ));

#define WITH_HTTP_COMPRESSION
#ifdef WITH_HTTP_COMPRESSION
        writeCtx->req = ne_request_create( dav_session.ctx, "GET", getUrl );

        /* Allow compressed content by setting the header */
        ne_add_request_header( writeCtx->req, "Accept-Encoding", "gzip,deflate" );

        /* hook called before the content is parsed to set the correct reader,
         * either the compressed- or uncompressed reader.
         */
        ne_hook_post_headers( dav_session.ctx, install_content_reader, writeCtx );

        /* actually do the request */
        rc = ne_request_dispatch(writeCtx->req );
        /* possible return codes are:
         *  NE_OK, NE_AUTH, NE_CONNECT, NE_TIMEOUT, NE_ERROR (from ne_request.h)
         */

        if( rc != NE_OK || (rc == NE_OK && ne_get_status(writeCtx->req)->klass != 2) ) {
            DEBUG_WEBDAV(("request_dispatch failed with rc=%d\n", rc ));
            if( rc == NE_OK ) rc = NE_ERROR;
            errno = EACCES;
        }

        /* delete the hook again, otherwise they get chained as they are with the session */
        ne_unhook_post_headers( dav_session.ctx, install_content_reader, writeCtx );

        /* if the compression handle is set through the post_header hook, delete it. */
        if( writeCtx->decompress ) {
            ne_decompress_destroy( writeCtx->decompress );
        }

        /* delete the request in any case */
        ne_request_destroy(writeCtx->req);
#else
        DEBUG_WEBDAV(("GET Compression not supported!\n"));
        rc = ne_get( dav_session.ctx, getUrl, writeCtx->fd );  /* FIX_ESCAPE? */
#endif
        if( rc != NE_OK ) {
            DEBUG_WEBDAV(("Download to local file failed: %d.\n", rc));
            errno = EACCES;
        }
        if( close( writeCtx->fd ) == -1 ) {
            DEBUG_WEBDAV(("Close of local download file failed.\n"));
            writeCtx->fd = -1;
            rc = NE_ERROR;
            errno = EACCES;
        }

        writeCtx->fd = -1;
    }

    if( rc != NE_OK ) {
        SAFE_FREE( writeCtx );
    }

    SAFE_FREE( uri );
    SAFE_FREE( dir );

    return (csync_vio_method_handle_t *) writeCtx;
}