#include #include #include #include #include #include #include #include #include #include #include #include #include "js_util_functions.h" #include "file.h" #include "directory.h" static JSBool Directory_ctor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval); static JSBool Directory_getTotalFiles(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval); static JSBool Directory_getTotalDirectories(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval); static JSBool Directory_getSize(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval); static char *staterrorstr(int e); static JSBool directory_open(DirectoryInformation *info); static JSBool directory_close(DirectoryInformation *info); static JSBool directory_read(DirectoryInformation *info, char **entry); static JSObject *DirectoryPrototype=NULL; static JSClass js_Directory_class = { "Directory", JSCLASS_HAS_PRIVATE, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub, JSCLASS_NO_OPTIONAL_MEMBERS }; static JSFunctionSpec Directory_methods[] = { {"getSize", Directory_getSize, 0, 0, 0}, {"getTotalFiles", Directory_getTotalFiles, 0, 0 ,0}, {"getTotalDirectories", Directory_getTotalDirectories, 0, 0, 0}, {NULL} }; static char *staterrorstr(int e){ char *msg = NULL; switch (e){ case ENOENT: msg = strdup("File does not exist."); break; case EACCES: msg = strdup("Permission denied to check file."); break; case EBADF: msg = strdup("Bad file descriptor"); break; case ELOOP: msg = strdup("Symbolic link loop encountered."); break; case ENAMETOOLONG: msg = strdup("File name too long, not supported."); break; case ENOMEM: msg = strdup("Out of memory."); break; case ENOTDIR: msg = strdup("Path component not a directory."); break; default: msg = strdup("Unknown error occured."); } return msg; } JSBool register_class_Directory(JSContext *cx){ JSObject *globalObj = JS_GetGlobalObject(cx); JSObject *proto=File_getPrototypeObject(); /* Define the file object. */ DirectoryPrototype = JS_InitClass(cx, globalObj, proto, &js_Directory_class, Directory_ctor, 1, NULL, Directory_methods, NULL, NULL); if (!DirectoryPrototype){ return JS_FALSE; } return JS_TRUE; } JSObject *Directory_getPrototypeObject(){ return DirectoryPrototype; } static JSBool Directory_ctor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ if (argc < 1){ char *str = strdup("Not enough parameters to Directory constructor."); JSString *exceptionDescription = JS_NewString(cx, str, strlen(str)); JS_SetPendingException(cx, STRING_TO_JSVAL(exceptionDescription)); return JS_FALSE; } else { char *path=NULL; size_t pathLength=0; DirectoryInformation *info = malloc(sizeof(*info)); info->fileInfo.filename = NULL; info->dirHandle = NULL; pathLength = JSString_to_CString(JS_ValueToString(cx, argv[0]), &path); info->fileInfo.filename = strdup(path); JS_SetPrivate(cx, obj, info); } return JS_TRUE; } static JSBool Directory_getTotalFiles(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ DirectoryInformation *info = (DirectoryInformation*)JS_GetPrivate(cx, obj); int count=0; if (directory_open(info)){ char *entry=NULL; while (directory_read(info, &entry) == JS_TRUE){ struct stat statInfo; char *fullPath = NULL; fullPath = malloc(strlen(info->fileInfo.filename)+strlen(entry)+2); sprintf(fullPath, "%s/%s", info->fileInfo.filename, entry); if (stat(fullPath, &statInfo) == 0){ if (S_ISREG(statInfo.st_mode)){ count++; } } free(entry); free(fullPath); } directory_close(info); *rval = INT_TO_JSVAL(count); return JS_TRUE; } else{ char *msg = staterrorstr(errno); jsval exception = printf_exception(cx, "Unable to open directory. (%d) (%s)", errno, msg); free(msg); JS_SetPendingException(cx, exception); return JS_FALSE; } } static JSBool Directory_getTotalDirectories(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ DirectoryInformation *info = (DirectoryInformation*)JS_GetPrivate(cx, obj); int count=0; if (directory_open(info)){ char *entry=NULL; while (directory_read(info, &entry) == JS_TRUE){ struct stat statInfo; char *fullPath = NULL; fullPath = malloc(strlen(info->fileInfo.filename)+strlen(entry)+2); sprintf(fullPath, "%s/%s", info->fileInfo.filename, entry); if (stat(fullPath, &statInfo) == 0){ if (S_ISDIR(statInfo.st_mode)){ /*Ignore . and .. */ if (strcmp(entry, ".") != 0 && strcmp(entry, "..") != 0){ count++; } } } free(entry); free(fullPath); } directory_close(info); *rval = INT_TO_JSVAL(count); return JS_TRUE; } else{ char *msg = staterrorstr(errno); jsval exception = printf_exception(cx, "Unable to open directory. (%d) (%s)", errno, msg); free(msg); JS_SetPendingException(cx, exception); return JS_FALSE; } } static JSBool Directory_getSize(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ DirectoryInformation *info = (DirectoryInformation*)JS_GetPrivate(cx, obj); int count=0; if (directory_open(info)){ char *entry=NULL; while (directory_read(info, &entry) == JS_TRUE){ struct stat statInfo; char *fullPath = NULL; fullPath = malloc(strlen(info->fileInfo.filename)+strlen(entry)+2); sprintf(fullPath, "%s/%s", info->fileInfo.filename, entry); if (stat(fullPath, &statInfo) == 0){ /*Ignore . and .. */ if (!S_ISDIR(statInfo.st_mode) || (strcmp(entry, ".") != 0 && strcmp(entry, "..") != 0)){ count++; } } free(entry); free(fullPath); } directory_close(info); *rval = INT_TO_JSVAL(count); return JS_TRUE; } else{ char *msg = staterrorstr(errno); jsval exception = printf_exception(cx, "Unable to open directory. (%d) (%s)", errno, msg); free(msg); JS_SetPendingException(cx, exception); return JS_FALSE; } } static JSBool directory_open(DirectoryInformation *info){ if (info->dirHandle == NULL){ info->dirHandle = opendir(info->fileInfo.filename); if (info->dirHandle == NULL){ return JS_FALSE; } return JS_TRUE; } return JS_TRUE; } static JSBool directory_close(DirectoryInformation *info){ if (info->dirHandle == NULL){ return JS_TRUE; } else { if (closedir(info->dirHandle) == 0){ info->dirHandle = NULL; return JS_TRUE; } return JS_FALSE; } } static JSBool directory_read(DirectoryInformation *info, char **entry){ struct dirent *ent=NULL; errno = 0; ent = readdir(info->dirHandle); if (ent == NULL){ return JS_FALSE; } else { *entry = strdup(ent->d_name); return JS_TRUE; } }