Home modules.gotpike.org
Username: Password: [Create Account]
[Forgot Password?]

Modules

ADT
Database
GTK2
GUI
IP
PiJAX
Public
Sql
Stdio
Subversion
System
Tools
Xosd
lua
v4l2
wx

Recent Changes

Public.Parser.XML2 1.50
Public.ZeroMQ 1.1
Public.Template.Mustache 1.0
Public.Protocols.XMPP 1.4
Sql.Provider.jdbc 1.0

Popular Downloads

Public.Parser.JSON2 1.0
Public.Parser.JSON 0.2
GTK2 2.23
Public.Web.FCGI 1.8
Public.Parser.XML2 1.48


Module Information
Public.System.Inotify
Viewing contents of Public_System_Inotify-0.1/inotify.cmod

// vim:syntax=c
/* 
 * Pike inotify module.
 * Copyright (C) 2009 Arne Goedeke
 * 
 */

#include 
#include 

#include "global.h"
#include "interpret.h"
#include "module.h"
#include "program.h"
#include "stralloc.h"
#include "svalue.h"
#include "object.h"
#include "pike_types.h"
#include "builtin_functions.h"

DECLARATIONS

/*! @module Public
 */

/*! @module System
 */

/*! @module Inotify
 */

/*! @decl constant IN_ACCESS
 *! @decl constant IN_ATTRIB
 *! @decl constant IN_CLOSE_WRITE
 *! @decl constant IN_CLOSE_NOWRITE
 *! @decl constant IN_CREATE
 *! @decl constant IN_DELETE
 *! @decl constant IN_DELETE_SELF
 *! @decl constant IN_MODIFY
 *! @decl constant IN_MOVE_SELF
 *! @decl constant IN_MOVED_FROM
 *! @decl constant IN_MODED_TO
 *! @decl constant IN_OPEN
 *! @decl constant IN_MOVE
 *! @decl constant IN_CLOSE
 *! @decl constant IN_DONT_FOLLOW
 *! @decl constant IN_MASK_ADD
 *! @decl constant IN_ONESHOT
 *! @decl constant IN_ONLYDIR
 *! @decl constant IN_IGNORED
 *! @decl constant IN_ISDIR
 *! @decl constant IN_Q_OVERFLOW
 *! @decl constant IN_UNMOUNT
 *! 	Please have a look at the inotify(7) manpage for information about these constants. 
 *! @note
 *! 	Some constants may not be available when the module has been compiled on a machine
 *! 	with an old kernel (before 2.6.15). See the manpage for more details.
 */

/*! @decl array parse_event(string data)
 *! Parses one inotify_event struct from @expr{data@}. 
 *! @returns
 *! 	Returns an array consisting of
 *! 	@ul
 *! 		@item
 *! 			The watch descriptor returned by @[add_watch()] when the watch
 *! 			for this file was added.
 *! 		@item
 *! 			An integer that describes the event that occured. See the inotify
 *! 			manpage for a list of possible events and their numerical identifiers.
 *! 		@item
 *! 			An integer cookie that can be used to group together different events
 *! 			that were triggered by moving a file from one location to another.
 *! 		@item
 *! 			The name of the file. This will only be present if the event happened to
 *! 			a file in a directory that was watched, e.g. with @[Public.System.Inotify.IN_CREATE].
 *! 			Otherwise this will be 0.
 *! 		@item
 *! 			The length of the data that has been parsed. In case a string contains more than one
 *! 			inotify events, this parse function has to be called again with the rest as an argument.
 *! 	@endul
 */
PIKEFUN array parse_event(string data) {
	struct inotify_event * event;
	size_t len;
	pop_n_elems(args);

	if ((size_t)data->len < sizeof(struct inotify_event)) {
		Pike_error("Malformed data.\n");
	}

	event = (struct inotify_event *)data->str;

	if (event->len > data->len - sizeof(struct inotify_event)) {
		Pike_error("Data missing.\n");	
	}

	push_int((int)event->wd);
	push_int((int)event->mask);
	push_int((int)event->cookie);

	if (event->len && (len = strlen(event->name))) {
		push_string(make_shared_binary_string(event->name, len));
	} else {
		push_int(0);
	}

	push_int((int)(event->len + sizeof(struct inotify_event)));

	f_aggregate(5);
}

/*! @class _Instance
 *! 	Simple wrapper class that gives direct access to the inotify(7) interface. On create an
 *! 	inotify instance is initiated by calling inotify_init(2). Every object of this class has 
 *! 	its own inotify file descriptor. Use this class only if you want direct access to the 
 *! 	file descriptor to read from it manually. For a more user-friendly inferface use 
 *! 	@[Public.System.Inotify.Instance].
 */
PIKECLASS _Instance {
	CVAR int fd;

	/*! @decl int add_watch(string file, int mask)
	 *! Add a watch for a certain file/dir and certain events. Adding more than one watch
	 *! for a file will overwrite the previous watch unless @[Public.System.Inotify.IN_MASK_ADD]
	 *! is ORed to the mask.
	 *! @param file
	 *! 	Name of the file that should be watched. Can be either a directory or a file.
	 *! @param mask
	 *! 	Integer mask specifying the event. This can be a combination of different event types
	 *! 	combined using bitwise OR. See the inotify manpage for possible values and their description.
	 *! 	The values defined by the inotify header file are exported by @[Public.System.Inotify] 
	 *! 	as constants using the same names (e.g. @[Public.System.Inotify.IN_CREATE]).
	 *! @note
	 *! 	Subdirectories are not watched. If you want to watch subdirectories aswell, its necessary
	 *! 	to add watches for them individually.
	 */
	PIKEFUN int add_watch(string file, int mask) {
		INT32 err;
		pop_n_elems(args);

		if (file->size_shift) {
			Pike_error("Widestring filenames not allowed.\n");
		}

		err = inotify_add_watch(THIS->fd, file->str, (INT32)mask);	

		if (err == -1) {
			Pike_error("inotify_add_watch failed with errno %d", errno);
		} else {
			push_int(err);	
		}
	}

	/*! @decl int get_fd()
	 *! @returns
	 *! 	Returns the file descriptor that is associated to the inotify instance.
	 */
	PIKEFUN int get_fd() {
		push_int(THIS->fd);	
	}
	
	/*! @decl int rm_watch(int wd)
	 *! Remove a watch.
	 *! @param wd
	 *! 	The watch descriptor that was returned by @[add_watch()].
	 */
	PIKEFUN void rm_watch(int wd) {
		INT32 err;
		pop_n_elems(args);

		err = inotify_rm_watch(THIS->fd, wd);

		if (err == 0) {
			return;
		}

		if (errno == EINVAL) {
			Pike_error("Wrong argument to rm_watch().\n");
		} else if (errno == EBADF) {
			Pike_error("Oups. I feel funny inside.\n");
		}
	}

	INIT {
		THIS->fd = inotify_init();

		if (THIS->fd == -1) switch (errno) {
		case EMFILE: Pike_error("User limit on inotify instances reached.\n");
		case ENFILE: Pike_error("User limit on file descriptors reached.\n");
		case ENOMEM: Pike_error("No free kernel memory available.\n");
		}
	}

	EXIT {
		close(THIS->fd);
	}
}

/*! @endclass
 */

#define ADD_ICONST(name) do {			\
	add_integer_constant(#name, name, 0);	\
} while(0);


PIKE_MODULE_INIT {
	ADD_ICONST(IN_ACCESS);
	ADD_ICONST(IN_ATTRIB);
	ADD_ICONST(IN_CLOSE_WRITE);
	ADD_ICONST(IN_CLOSE_NOWRITE);
	ADD_ICONST(IN_CREATE);
	ADD_ICONST(IN_DELETE);
	ADD_ICONST(IN_DELETE_SELF);
	ADD_ICONST(IN_MODIFY);
	ADD_ICONST(IN_MOVE_SELF);
	ADD_ICONST(IN_MOVED_FROM);
	ADD_ICONST(IN_MOVED_TO);
	ADD_ICONST(IN_OPEN);

	ADD_ICONST(IN_MOVE);
	ADD_ICONST(IN_CLOSE);

// some of these came with 2.6.15 linux and 2.5 glibc
#ifdef IN_DONT_FOLLOW
	ADD_ICONST(IN_DONT_FOLLOW);
#endif
#ifdef IN_MASK_ADD
	ADD_ICONST(IN_MASK_ADD);
#endif
	ADD_ICONST(IN_ONESHOT);
#ifdef IN_ONLYDIR
	ADD_ICONST(IN_ONLYDIR);
#endif

	ADD_ICONST(IN_IGNORED);
	ADD_ICONST(IN_ISDIR);
	ADD_ICONST(IN_Q_OVERFLOW);
	ADD_ICONST(IN_UNMOUNT);

	INIT
}

PIKE_MODULE_EXIT {
	EXIT
}

/*! @endmodule
 */
/*! @endmodule
 */
/*! @endmodule
 */


gotpike.org | Copyright © 2004 - 2019 | Pike is a trademark of Department of Computer and Information Science, Linköping University