|
|
@@ -39,14 +39,12 @@ |
|
|
|
#include <sys/signalfd.h> |
|
|
|
#include <sys/stat.h> |
|
|
|
#include <sys/wait.h> |
|
|
|
#include <unistd.h> |
|
|
|
#include <time.h> |
|
|
|
#include <libgen.h> |
|
|
|
#include <dirent.h> |
|
|
|
#include <ftw.h> |
|
|
|
#include <list> |
|
|
|
#include <getopt.h> |
|
|
|
#include <sys/time.h> |
|
|
|
#include <fts.h> |
|
|
|
|
|
|
|
#include "Endpoint.hpp" |
|
|
|
/* for locking */ |
|
|
@@ -1677,51 +1675,141 @@ OSC_HANDLER( new ) |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
int |
|
|
|
fts_comparer_to_process_files_before_dirs( const FTSENT ** first, const FTSENT ** second ) |
|
|
|
{ |
|
|
|
/* |
|
|
|
The argument compar() specifies a user-defined function which may |
|
|
|
be used to order the traversal of the hierarchy. It takes two |
|
|
|
pointers to pointers to FTSENT structures as arguments and should |
|
|
|
return a negative value, zero, or a positive value to indicate if |
|
|
|
the file referenced by its first argument comes before, in any |
|
|
|
order with respect to, or after, the file referenced by its |
|
|
|
second argument. The fts_accpath, fts_path, and fts_pathlen |
|
|
|
fields of the FTSENT structures may never be used in this |
|
|
|
comparison. If the fts_info field is set to FTS_NS or FTS_NSOK, |
|
|
|
the fts_statp field may not either. If the compar() argument is |
|
|
|
NULL, the directory traversal order is in the order listed in |
|
|
|
path_argv for the root paths, and in the order listed in the |
|
|
|
directory for everything else. |
|
|
|
*/ |
|
|
|
|
|
|
|
if ( (*first)->fts_info & FTS_F ) |
|
|
|
return (-1); //first |
|
|
|
else if ( (*second)->fts_info & FTS_F ) |
|
|
|
return (1); //last |
|
|
|
else |
|
|
|
return strcmp((*first)->fts_name, (*second)->fts_name); |
|
|
|
//return (0); //doesn't matter |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static lo_address list_response_address; |
|
|
|
|
|
|
|
int |
|
|
|
list_file ( const char *fpath, const struct stat *sb, int tflag ) |
|
|
|
OSC_HANDLER( list ) |
|
|
|
{ |
|
|
|
if ( tflag == FTW_F ) |
|
|
|
{ |
|
|
|
char *s; |
|
|
|
s = strdup( fpath ); |
|
|
|
if ( ! strcmp( "session.nsm", basename( s ) ) ) |
|
|
|
{ |
|
|
|
free( s ); |
|
|
|
s = strdup( fpath ); |
|
|
|
//Parse the session_root recursively for session.nsm files and send names with /nsm/server/list |
|
|
|
//Sessions can be structured with sub-directories. |
|
|
|
//The file session.nsm marks a real session and is a 'leaf' of the session tree. |
|
|
|
//No other sessions are allowed below a dir containing session.nsm . |
|
|
|
|
|
|
|
s = dirname( s ); |
|
|
|
GUIMSG( "Listing sessions" ); |
|
|
|
list_response_address = lo_message_get_source( msg ); |
|
|
|
|
|
|
|
memmove( s, s + strlen( session_root ) + 1, (strlen( s ) - strlen( session_root )) + 1); |
|
|
|
//Use fts to walk the session_root |
|
|
|
/* An array of paths to traverse. Each path must be null |
|
|
|
* terminated and the list must end with a NULL pointer. */ |
|
|
|
char *paths[] = { session_root, NULL }; |
|
|
|
|
|
|
|
osc_server->send( list_response_address, "/reply", "/nsm/server/list", s ); |
|
|
|
/* 2nd parameter: An options parameter. Must include either |
|
|
|
FTS_PHYSICAL or FTS_LOGICAL---they change how symbolic links |
|
|
|
are handled. |
|
|
|
|
|
|
|
free( s ); |
|
|
|
} |
|
|
|
else |
|
|
|
free( s ); |
|
|
|
} |
|
|
|
Last parameter is a comparator which you can optionally provide |
|
|
|
to change the traversal of the filesystem hierarchy. |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
Our comparator processes files before directories, so we can depend on that |
|
|
|
to remember if we are already in a session-dir. |
|
|
|
*/ |
|
|
|
|
|
|
|
OSC_HANDLER( list ) |
|
|
|
{ |
|
|
|
GUIMSG( "Listing sessions" ); |
|
|
|
FTS *ftsp = fts_open(paths, FTS_LOGICAL, fts_comparer_to_process_files_before_dirs); |
|
|
|
if(ftsp == NULL) |
|
|
|
{ |
|
|
|
FATAL( "fts_open" ); |
|
|
|
exit(EXIT_FAILURE); |
|
|
|
} |
|
|
|
|
|
|
|
list_response_address = lo_message_get_source( msg ); |
|
|
|
FTSENT * currentSession = NULL; |
|
|
|
while( 1 ) // call fts_read() enough times to get each file |
|
|
|
{ |
|
|
|
FTSENT *ent = fts_read(ftsp); // get next entry (could be file or directory). |
|
|
|
if( ent == NULL ) |
|
|
|
{ |
|
|
|
if( errno == 0 ) |
|
|
|
break; // No more items, bail out of while loop |
|
|
|
else |
|
|
|
{ |
|
|
|
// fts_read() had an error. |
|
|
|
FATAL( "fts_read" ); |
|
|
|
exit(EXIT_FAILURE); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
ftw( session_root, list_file, 20 ); |
|
|
|
// Handle Types of Files |
|
|
|
|
|
|
|
// osc_server->send( lo_message_get_source( msg ), path, ERR_OK, "Done." ); |
|
|
|
// Given a "entry", determine if it is a file or directory |
|
|
|
if( ent->fts_info & FTS_D ) // We are entering into a directory |
|
|
|
{ |
|
|
|
//printf( "Enter dir: %s\n", ent->fts_path ); |
|
|
|
if ( currentSession != NULL ) |
|
|
|
{ |
|
|
|
//printf( "already found current session.nsm: %s . Waiting to leave dir. Ignoring %s\n", currentSession->fts_name, ent->fts_path ); |
|
|
|
|
|
|
|
// Setup that no descendants of this file are visited. |
|
|
|
int err = fts_set( ftsp, ent, FTS_SKIP ); |
|
|
|
if ( err != 0 ) |
|
|
|
{ |
|
|
|
FATAL( "fts_set" ); |
|
|
|
exit(EXIT_FAILURE); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
else if( ent->fts_info & FTS_DP ) // We are exiting a directory |
|
|
|
{ |
|
|
|
//printf( "Exit dir: %s\n", ent->fts_path ); |
|
|
|
if ( ent == currentSession ) |
|
|
|
{ |
|
|
|
//printf( "Exit current session dir: %s\n", ent->fts_path ); |
|
|
|
currentSession = NULL; |
|
|
|
} |
|
|
|
} |
|
|
|
else if( ent->fts_info & FTS_F ) // The entry is a file. |
|
|
|
{ |
|
|
|
//printf( "File: %s\n", ent->fts_path ); |
|
|
|
if ( ! strcmp( "session.nsm", basename( ent->fts_path ) ) ) |
|
|
|
{ |
|
|
|
//Convert path to session name: |
|
|
|
char *s; |
|
|
|
s = strdup( ent->fts_path ); |
|
|
|
s = dirname( s ); |
|
|
|
memmove( s, s + strlen( session_root ) + 1, (strlen( s ) - strlen( session_root )) + 1); |
|
|
|
osc_server->send( list_response_address, "/reply", "/nsm/server/list", s ); |
|
|
|
free( s ); |
|
|
|
currentSession = ent->fts_parent; //save the directory entry. not the session.nsm entry. |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// close fts and check for error closing. |
|
|
|
if(fts_close(ftsp) == -1) |
|
|
|
FATAL( "fts_close" ); |
|
|
|
|
|
|
|
// As marker that all sessions were sent reply with an empty string, which is impossible to conflict with a session name |
|
|
|
osc_server->send( list_response_address, "/reply", "/nsm/server/list", "" ); |
|
|
|
|
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
OSC_HANDLER( open ) |
|
|
|
{ |
|
|
|
lo_address sender_addr; |
|
|
|