@@ -710,9 +710,6 @@ drop_find_dir_handle(Window *w, uint32_t id) {
710710 * send the listing to the client as a t=d:x=handle_id response. */
711711static void
712712drop_send_dir_listing (Window * w , const char * path ) {
713- struct stat st ;
714- if (stat (path , & st ) < 0 ) { drop_send_error (w , EIO ); return ; }
715-
716713 DIR * dir = opendir (path );
717714 if (!dir ) {
718715 switch (errno ) {
@@ -723,17 +720,11 @@ drop_send_dir_listing(Window *w, const char *path) {
723720 return ;
724721 }
725722
726- /* Build null-separated payload: unique_id\0entry1 \0entry2\0... */
723+ /* Build null-separated payload: entry1 \0entry2\0... */
727724 size_t payload_cap = 4096 , payload_sz = 0 ;
728725 char * payload = malloc (payload_cap );
729726 if (!payload ) { closedir (dir ); drop_send_error (w , EIO ); return ; }
730727
731- /* First entry: unique identifier (device:inode) */
732- char uid [64 ];
733- int uid_len = snprintf (uid , sizeof (uid ), "%llu:%llu" ,
734- (unsigned long long )st .st_dev ,
735- (unsigned long long )st .st_ino );
736-
737728#define APPEND (s , n ) do { \
738729 size_t _n = (size_t)(n); \
739730 size_t _need = payload_sz + _n + 1; \
@@ -748,8 +739,6 @@ drop_send_dir_listing(Window *w, const char *path) {
748739 payload[payload_sz++] = 0; \
749740} while(0)
750741
751- APPEND (uid , uid_len );
752-
753742 /* Collect directory entries */
754743 size_t ents_cap = 16 , ents_num = 0 ;
755744 char * * ents = malloc (sizeof (char * ) * ents_cap );
@@ -909,8 +898,8 @@ do_drop_handle_dir_request(Window *w, uint32_t handle_id, int32_t entry_num) {
909898 drop_send_error (w , EIO ); return true;
910899 }
911900
912- struct stat st ;
913- if (stat (full , & st ) < 0 ) {
901+ struct stat lst ;
902+ if (lstat (full , & lst ) < 0 ) {
914903 switch (errno ) {
915904 case ENOENT : case ENOTDIR : case ELOOP : drop_send_error (w , ENOENT ); break ;
916905 case EACCES : case EPERM : drop_send_error (w , EPERM ); break ;
@@ -919,10 +908,32 @@ do_drop_handle_dir_request(Window *w, uint32_t handle_id, int32_t entry_num) {
919908 return true;
920909 }
921910
922- if (S_ISDIR (st .st_mode )) {
911+ if (S_ISLNK (lst .st_mode )) {
912+ /* Symlink: send the symlink target as t=r:X=1 */
913+ char target [PATH_MAX ];
914+ ssize_t tlen = readlink (full , target , sizeof (target ) - 1 );
915+ if (tlen < 0 ) {
916+ switch (errno ) {
917+ case ENOENT : case ENOTDIR : drop_send_error (w , ENOENT ); break ;
918+ case EACCES : case EPERM : drop_send_error (w , EPERM ); break ;
919+ default : drop_send_error (w , EIO ); break ;
920+ }
921+ return true;
922+ }
923+ target [tlen ] = '\0' ;
924+ char hdr [128 ];
925+ int hdr_sz = snprintf (hdr , sizeof (hdr ), "\x1b]%d;t=r:X=1" , DND_CODE );
926+ if (w -> drop .current_request_id )
927+ hdr_sz += snprintf (hdr + hdr_sz , sizeof (hdr ) - hdr_sz , ":r=%u" , (unsigned )w -> drop .current_request_id );
928+ queue_payload_to_child (w -> id , w -> drop .client_id , & w -> drop .pending , hdr , hdr_sz , target , (size_t )tlen , true);
929+ queue_payload_to_child (w -> id , w -> drop .client_id , & w -> drop .pending , hdr , hdr_sz , NULL , 0 , true);
930+ return true;
931+ }
932+
933+ if (S_ISDIR (lst .st_mode )) {
923934 drop_send_dir_listing (w , full );
924935 return true;
925- } else if (S_ISREG (st .st_mode )) {
936+ } else if (S_ISREG (lst .st_mode )) {
926937 return drop_send_file_data (w , full );
927938 } else {
928939 drop_send_error (w , EINVAL );
0 commit comments