Example #1
0
File: fse.c Project: chregu/tmcli
int
main(int argc, char *argv[])
{
    /* Define variables and create a CFArray object containing
	CFString objects containing paths to watch.
	*/
    CFStringRef mypath = CFSTR("/");
    CFArrayRef pathsToWatch = CFArrayCreate(NULL, (const void **)&mypath, 1, NULL);
    void *callbackInfo = NULL; // could put stream-specific data here.
    FSEventStreamRef stream;
    CFAbsoluteTime latency = 3.0; /* Latency in seconds */
	struct stat Status;
 	stat("/", &Status);
	dev_t device = Status.st_dev;
	
	
	CFUUIDRef uuidO;
	CFStringRef uuid;
	uuidO = FSEventsCopyUUIDForDevice(device); 
	uuid = CFUUIDCreateString(NULL, uuidO);
	
	show(CFSTR("%@:256"), uuid);
	
	
	
    /* Create the stream, passing in a callback, */
    stream =  FSEventStreamCreateRelativeToDevice(NULL,
	&myCallbackFunction,
	callbackInfo,
	device,
	pathsToWatch,
	atoi(argv[2]), /* Or a previous event ID */
	latency,
	kFSEventStreamCreateFlagNone /* Flags explained in reference */
	);
	  /* Create the stream before calling this. */
    FSEventStreamScheduleWithRunLoop(stream, CFRunLoopGetCurrent(),         kCFRunLoopDefaultMode);
	FSEventStreamStart(stream);
	//CFRunLoopRun();
	CFRunLoopRunInMode(kCFRunLoopDefaultMode,atoi(argv[1]),false);
	//sleep(10);
	
	
  
}
Example #2
0
static fse_stream* fse_stream_make(
    const std::shared_ptr<w_root_t>& root,
    FSEventStreamEventId since,
    w_string& failure_reason) {
  FSEventStreamContext ctx;
  CFMutableArrayRef parray = nullptr;
  CFStringRef cpath = nullptr;
  double latency;
  struct stat st;
  auto watcher = watcherFromRoot(root);

  struct fse_stream* fse_stream = new struct fse_stream(root, since);

  // Each device has an optional journal maintained by fseventsd that keeps
  // track of the change events.  The journal may not be available if the
  // filesystem was mounted read-only.  The journal has an associated UUID
  // to track the version of the data.  In some cases the journal can become
  // invalidated and it will have a new UUID generated.  This can happen
  // if the EventId rolls over.
  // We need to lookup up the UUID for the associated path and use that to
  // help decide whether we can use a value of `since` other than SinceNow.
  if (stat(root->root_path.c_str(), &st)) {
    failure_reason = w_string::printf(
        "failed to stat(%s): %s\n", root->root_path.c_str(), strerror(errno));
    goto fail;
  }

  // Obtain the UUID for the device associated with the root
  fse_stream->uuid = FSEventsCopyUUIDForDevice(st.st_dev);
  if (since != kFSEventStreamEventIdSinceNow) {
    CFUUIDBytes a, b;

    if (!fse_stream->uuid) {
      // If there is no UUID available and we want to use an event offset,
      // we fail: a nullptr UUID means that the journal is not available.
      failure_reason = w_string::printf(
          "fsevents journal is not available for dev_t=%d\n", st.st_dev);
      goto fail;
    }
    // Compare the UUID with that of the current stream
    if (!watcher->stream->uuid) {
      failure_reason = w_string(
          "fsevents journal was not available for prior stream",
          W_STRING_UNICODE);
      goto fail;
    }

    a = CFUUIDGetUUIDBytes(fse_stream->uuid);
    b = CFUUIDGetUUIDBytes(watcher->stream->uuid);

    if (memcmp(&a, &b, sizeof(a)) != 0) {
      failure_reason =
          w_string("fsevents journal UUID is different", W_STRING_UNICODE);
      goto fail;
    }
  }

  memset(&ctx, 0, sizeof(ctx));
  ctx.info = fse_stream;

  parray = CFArrayCreateMutable(nullptr, 0, &kCFTypeArrayCallBacks);
  if (!parray) {
    failure_reason = w_string("CFArrayCreateMutable failed", W_STRING_UNICODE);
    goto fail;
  }

  cpath = CFStringCreateWithBytes(
      nullptr,
      (const UInt8*)root->root_path.data(),
      root->root_path.size(),
      kCFStringEncodingUTF8,
      false);
  if (!cpath) {
    failure_reason =
        w_string("CFStringCreateWithBytes failed", W_STRING_UNICODE);
    goto fail;
  }

  CFArrayAppendValue(parray, cpath);

  latency = root->config.getDouble("fsevents_latency", 0.01),
  w_log(
      W_LOG_DBG,
      "FSEventStreamCreate for path %s with latency %f seconds\n",
      root->root_path.c_str(),
      latency);

  fse_stream->stream = FSEventStreamCreate(
      nullptr,
      fse_callback,
      &ctx,
      parray,
      since,
      latency,
      kFSEventStreamCreateFlagNoDefer | kFSEventStreamCreateFlagWatchRoot |
          kFSEventStreamCreateFlagFileEvents);

  if (!fse_stream->stream) {
    failure_reason = w_string("FSEventStreamCreate failed", W_STRING_UNICODE);
    goto fail;
  }

  FSEventStreamScheduleWithRunLoop(fse_stream->stream,
      CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);

#ifdef HAVE_FSEVENTSTREAMSETEXCLUSIONPATHS
  if (!root->ignore.dirs_vec.empty() &&
      root->config.getBool("_use_fsevents_exclusions", true)) {
    CFMutableArrayRef ignarray;
    size_t i, nitems = std::min(root->ignore.dirs_vec.size(), MAX_EXCLUSIONS);

    ignarray = CFArrayCreateMutable(nullptr, 0, &kCFTypeArrayCallBacks);
    if (!ignarray) {
      failure_reason =
          w_string("CFArrayCreateMutable failed", W_STRING_UNICODE);
      goto fail;
    }

    for (i = 0; i < nitems; ++i) {
      const auto& path = root->ignore.dirs_vec[i];
      CFStringRef ignpath;

      ignpath = CFStringCreateWithBytes(
          nullptr,
          (const UInt8*)path.data(),
          path.size(),
          kCFStringEncodingUTF8,
          false);

      if (!ignpath) {
        failure_reason =
            w_string("CFStringCreateWithBytes failed", W_STRING_UNICODE);
        CFRelease(ignarray);
        goto fail;
      }

      CFArrayAppendValue(ignarray, ignpath);
      CFRelease(ignpath);
    }

    if (!FSEventStreamSetExclusionPaths(fse_stream->stream, ignarray)) {
      failure_reason =
          w_string("FSEventStreamSetExclusionPaths failed", W_STRING_UNICODE);
      CFRelease(ignarray);
      goto fail;
    }

    CFRelease(ignarray);
  }
#endif

out:
  if (parray) {
    CFRelease(parray);
  }
  if (cpath) {
    CFRelease(cpath);
  }

  return fse_stream;

fail:
  delete fse_stream;
  fse_stream = nullptr;
  goto out;
}