--- src/dired.c 2020-10-13 20:09:48.235962328 +0200 +++ ../dired.c 2020-10-13 20:09:10.865527164 +0200 @@ -22,6 +22,12 @@ #include +#if __linux__ +#include +#elif _WIN32 +#include +#endif + #ifdef HAVE_PWD_H #include #endif @@ -39,6 +45,7 @@ #include "systime.h" #include "buffer.h" #include "coding.h" +#include "blockinput.h" #ifdef MSDOS #include "msdos.h" /* for fstatat */ @@ -929,7 +936,7 @@ struct stat s; /* An array to hold the mode string generated by filemodestring, - including its terminating space and null byte. */ + including its terminating space and NUL byte. */ char modes[sizeof "-rwxr-xr-x "]; char *uname = NULL, *gname = NULL; @@ -1078,6 +1085,119 @@ return groups; } +DEFUN ("directory-empty-p", Fdirectory_empty_p, + Sdirectory_empty_p, 1, 1, 0, + doc: /* Returns t if directory DIRNAME does not contain any + user files (special files . and .. are excluded + automatically), nil otherwise. */) +(Lisp_Object dirname) +{ + const char* name; + Lisp_Object handler; + + if(!STRINGP(dirname)) + error("Directory name not a string object."); + + dirname = Fexpand_file_name(dirname, Qnil); + + /* If the file name has special constructs in it, + call the corresponding file name handler. */ + handler = Ffind_file_name_handler (dirname, Qdirectory_empty_p); + if (!NILP (handler)) + return call2 (handler, Qdirectory_empty_p, dirname); + + name = SSDATA(dirname); + +#ifdef __linux__ + { + typedef struct dirent* pdirent; +#define BSIZE 1024 + pdirent d; + char buf[BSIZE]; + int fd, n = 0, p = 0, c = 0; + + fd = open (name, O_RDONLY | O_DIRECTORY); + + if( fd == -1 ) + error("Can't open directory."); + + //block_input(); + /* 32-bit version of getdents should be good enough; + we are just looking at first 3 files*/ + n = syscall(SYS_getdents,fd,buf, BSIZE); + if(n == -1) + error("Can't read directory data."); + + while(p < n && c < 3) { + d = (pdirent) (buf + p); + p += d->d_reclen; + c++; + } + //unblock_input(); + + close(fd); + return (c > 2) ? Qnil : Qt; + } +#elif _WIN32 + { + int len, c = 0; + HANDLE h = INVALID_HANDLE_VALUE; + + if(w32_unicode_filenames){ + WIN32_FIND_DATAW ffd; + wchar_t wname[MAX_PATH]; + filename_to_utf16(name, wname); + len = wcslen(wname); + + if (!len) + error(TEXT("Can't read directory name.")); + + if(len > MAX_PATH - 3) + error(TEXT("Directory path too long.")); + + wcscat(wname, L"\\*"); + + h = FindFirstFileW(wname, &ffd); + if (h == INVALID_HANDLE_VALUE) + error(TEXT("Can't open directory.")); + + while (FindNextFileW(h, &ffd) && c < 1){ + if(wcscmp(ffd.cFileName, L".") && + wcscmp(ffd.cFileName, L"..")) + c++; + } + }else { + WIN32_FIND_DATAA ffd; + char aname[MAX_UTF8_PATH]; + filename_to_ansi(name, aname); + len = strlen(aname); + + if (!len) + error(TEXT("Can't read directory name.")); + + if(len > MAX_PATH - 3) + error(TEXT("Directory path too long.")); + + strcat(aname, "\\*"); + + h = FindFirstFileA(aname, &ffd); + if (h == INVALID_HANDLE_VALUE) + error(TEXT("Can't open directory.")); + + while (FindNextFileA(h, &ffd) && c < 1){ + if(strcmp(ffd.cFileName, ".") && + strcmp(ffd.cFileName, "..")) + c++; + } + } + + FindClose(h); + return (c > 0) ? Qnil : Qt; + } +#endif +} + + void syms_of_dired (void) { @@ -1089,7 +1209,8 @@ DEFSYM (Qfile_attributes_lessp, "file-attributes-lessp"); DEFSYM (Qdefault_directory, "default-directory"); DEFSYM (Qdecomposed_characters, "decomposed-characters"); - + DEFSYM (Qdirectory_empty_p, "directory-empty-p") + defsubr (&Sdirectory_files); defsubr (&Sdirectory_files_and_attributes); defsubr (&Sfile_name_completion); @@ -1098,6 +1219,7 @@ defsubr (&Sfile_attributes_lessp); defsubr (&Ssystem_users); defsubr (&Ssystem_groups); + defsubr (&Sdirectory_empty_p); DEFVAR_LISP ("completion-ignored-extensions", Vcompletion_ignored_extensions, doc: /* Completion ignores file names ending in any string in this list.