Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/azatoth/minidlna.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Fürstenberg <azatoth@gmail.com>2011-04-04 21:38:27 +0400
committerCarl Fürstenberg <azatoth@gmail.com>2011-04-05 01:13:31 +0400
commit8b51f511f8f08123146923e02f03f8e840d0529b (patch)
tree7190ffdaa0ae06fd6bd28aba61fee45e33ef819e
parent0922cc147cf811c36e2a39e8f7dddd1043e0e784 (diff)
-rw-r--r--getifaddr.c48
-rw-r--r--inotify.c332
-rw-r--r--minidlna.c47
-rw-r--r--upnpglobalvars.c7
-rw-r--r--upnphttp.c92
-rw-r--r--utils.c5
-rw-r--r--uuid.c11
7 files changed, 541 insertions, 1 deletions
diff --git a/getifaddr.c b/getifaddr.c
index ab8da71..52569c3 100644
--- a/getifaddr.c
+++ b/getifaddr.c
@@ -43,6 +43,7 @@
#include <sys/sockio.h>
#endif
+#include "config.h"
#include "getifaddr.h"
#include "log.h"
@@ -86,18 +87,65 @@ getsysaddr(char * buf, int len)
int s = socket(PF_INET, SOCK_STREAM, 0);
struct sockaddr_in addr;
struct ifreq ifr;
+#ifdef cygwin
+ struct ifconf ifc;
+ char *ptr;
+ int result;
+ char buffer[1024];
+#endif
int ret = -1;
+#ifdef cygwin
+ ifc.ifc_buf = buffer;
+ ifc.ifc_len = (sizeof(buffer)/sizeof(buffer[0]));
+
+ s = socket(AF_INET, SOCK_DGRAM, 0);
+ if (s < 0) {
+ DPRINTF(E_ERROR, L_GENERAL, "Couldn't open socket\n");
+ return -1;
+ }
+
+ result = ioctl(s, SIOCGIFCONF, &ifc);
+
+ ptr = buffer;
+#endif
+
+#ifndef cygwin
for (i=1; i > 0; i++)
+#else /* cygwin */
+ for (i=1; i > 0; i++, ptr += sizeof(struct ifreq))
+#endif /* cygwin */
{
ifr.ifr_ifindex = i;
+#ifndef cygwin
if( ioctl(s, SIOCGIFNAME, &ifr) < 0 )
break;
if(ioctl(s, SIOCGIFADDR, &ifr, sizeof(struct ifreq)) < 0)
continue;
+#else /* cygwin */
+ if (ptr >= buf + ifc.ifc_len)
+ break;
+ memcpy(&ifr, ptr, sizeof(ifr));
+ result = ioctl(s, SIOCGIFADDR, &ifr, sizeof(struct ifreq));
+ if (ifr.ifr_addr.sa_family != AF_INET)
+ continue;
+#endif /* cygwin */
memcpy(&addr, &ifr.ifr_addr, sizeof(addr));
+#ifndef cygwin
if(strncmp(inet_ntoa(addr.sin_addr), "127.", 4) == 0)
continue;
+#else /* cygwin */
+ if( (strncmp(inet_ntoa(addr.sin_addr), "127.", 4) == 0)
+ || (strncmp(inet_ntoa(addr.sin_addr), "169.", 4) == 0) )
+ {
+ //DPRINTF(E_ERROR, L_GENERAL, "found address #%d= %s : Not used\n", i, inet_ntoa(addr.sin_addr));
+ printf("found address #%d= %s : Not used\n", i, inet_ntoa(addr.sin_addr));
+ continue;
+ }
+ else
+ //DPRINTF(E_ERROR, L_GENERAL, "found address #%d= %s : used\n", i, inet_ntoa(addr.sin_addr));
+ printf("found address #%d= %s : used\n", i, inet_ntoa(addr.sin_addr));
+#endif /* cygwin */
if(!inet_ntop(AF_INET, &addr.sin_addr, buf, len))
{
DPRINTF(E_ERROR, L_GENERAL, "inet_ntop(): %s\n", strerror(errno));
diff --git a/inotify.c b/inotify.c
index 7353940..4857973 100644
--- a/inotify.c
+++ b/inotify.c
@@ -31,11 +31,14 @@
#include <sys/time.h>
#include <sys/resource.h>
#include <poll.h>
+#include "config.h"
#ifdef HAVE_INOTIFY_H
#include <sys/inotify.h>
#else
+#ifndef cygwin
#include "linux/inotify.h"
#include "linux/inotify-syscalls.h"
+#endif /* cygwin */
#endif
#include "upnpglobalvars.h"
@@ -48,6 +51,14 @@
#include "playlist.h"
#include "log.h"
+#ifdef cygwin
+
+#include <sys/cygwin.h>
+#define PATH_BUF_SIZE PATH_MAX
+static time_t next_pl_fill = 0;
+
+#else /* cygwin */
+
#define EVENT_SIZE ( sizeof (struct inotify_event) )
#define BUF_LEN ( 1024 * ( EVENT_SIZE + 16 ) )
#define DESIRED_WATCH_LIMIT 65536
@@ -274,6 +285,7 @@ int add_dir_watch(int fd, char * path, char * filename)
return(i);
}
+#endif /* cygwin */
int
inotify_insert_file(char * name, const char * path)
@@ -419,6 +431,9 @@ inotify_insert_file(char * name, const char * path)
if( !depth )
{
//DEBUG DPRINTF(E_DEBUG, L_INOTIFY, "Inserting %s\n", name);
+#ifdef cygwin
+ DPRINTF(E_DEBUG, L_INOTIFY, "Inserting %s:%s\n", name, path);
+#endif /* cygwin */
insert_file(name, path, id+2, get_next_available_id("OBJECTS", id));
free(id);
if( (is_audio(path) || is_playlist(path)) && next_pl_fill != 1 )
@@ -438,7 +453,9 @@ inotify_insert_directory(int fd, char *name, const char * path)
char * sql;
char **result;
char *id=NULL, *path_buf, *parent_buf, *esc_name;
+#ifndef cygwin
int wd;
+#endif /* cygwin */
int rows;
enum file_types type = TYPE_UNKNOWN;
enum media_types dir_type = ALL_MEDIA;
@@ -457,6 +474,7 @@ inotify_insert_directory(int fd, char *name, const char * path)
free(parent_buf);
sqlite3_free(sql);
+#ifndef cygwin
wd = add_watch(fd, path);
if( wd == -1 )
{
@@ -466,6 +484,7 @@ inotify_insert_directory(int fd, char *name, const char * path)
{
DPRINTF(E_INFO, L_INOTIFY, "Added watch to %s [%d]\n", path, wd);
}
+#endif /* cygwin */
media_path = media_dirs;
while( media_path )
@@ -608,7 +627,9 @@ inotify_remove_directory(int fd, const char * path)
sqlite_int64 detailID = 0;
int rows, i, ret = 1;
+#ifndef cygwin
remove_watch(fd, path);
+#endif /* cygwin */
sql = sqlite3_mprintf("SELECT ID from DETAILS where PATH glob '%q/*'"
" UNION ALL SELECT ID from DETAILS where PATH = '%q'", path, path);
if( (sql_get_table(db, sql, &result, &rows, NULL) == SQLITE_OK) )
@@ -632,6 +653,7 @@ inotify_remove_directory(int fd, const char * path)
return ret;
}
+#ifndef cygwin
void *
start_inotify()
{
@@ -746,3 +768,313 @@ quitting:
return 0;
}
+
+#else /* cygwin */
+
+
+#include <windows.h>
+//#include <dirent.h> // for opendir()
+#include <unistd.h> // for stat()
+
+#define BUFF_SIZE (128*1024)
+
+#define WATCH_LIMIT 16
+
+// Required parameters for ReadDirectoryChangesW().
+static FILE_NOTIFY_INFORMATION *m_Buffer[WATCH_LIMIT];
+static HANDLE m_hDirectory[WATCH_LIMIT];
+static OVERLAPPED m_Overlapped[WATCH_LIMIT];
+static char *search_path_win[WATCH_LIMIT];
+
+
+static VOID
+insert_to_delete_from_db(int searchNo)
+{
+ FILE_NOTIFY_INFORMATION *m_BufferTmp;
+
+ int NextOff, FileNumLenMB;
+ char path_buf[PATH_BUF_SIZE], fullPath[PATH_BUF_SIZE];
+ //DIR *dp;
+ int fd=0;
+ char * esc_name = NULL;
+ struct stat file_stat;
+
+ m_BufferTmp = m_Buffer[searchNo];
+ do {
+#if 0
+ char *Action[] = {
+ "FILE_ACTION_ADDED",
+ "FILE_ACTION_REMOVED",
+ "FILE_ACTION_MODIFIED",
+ "FILE_ACTION_RENAMED_OLD_NAME",
+ "FILE_ACTION_RENAMED_NEW_NAME"
+ };
+
+ printf ("NextEntryOffset = %d\n", m_BufferTmp->NextEntryOffset);
+ printf ("Action = %08x : %s\n", m_BufferTmp->Action, Action[m_BufferTmp->Action-1]);
+ printf ("FileNameLength = %d byte(s)\n", m_BufferTmp->FileNameLength);
+ FileNumLenMB = WideCharToMultiByte (CP_UTF8, 0, &(m_BufferTmp->FileName[0]), m_BufferTmp->FileNameLength/2, path_buf, PATH_BUF_SIZE, NULL, NULL);
+ path_buf[FileNumLenMB] = '\0';
+ sprintf(fullPath, "%s\\%s", search_path_win[searchNo], path_buf);
+ cygwin_conv_path (CCP_WIN_A_TO_POSIX | CCP_ABSOLUTE, fullPath, path_buf, PATH_BUF_SIZE);
+
+ //dp = opendir(path_buf); // check whether fullPath is directory
+ stat(path_buf, &file_stat);
+ //if (dp == NULL) {
+ if (!S_ISDIR(file_stat.st_mode)) { // file
+ printf ("FileName = %s\n\n", path_buf);
+ } else {
+ printf ("FileName = %s : directory\n\n", path_buf);
+ //closedir(dp);
+ }
+#else
+ FileNumLenMB = WideCharToMultiByte (CP_UTF8, 0, &(m_BufferTmp->FileName[0]), m_BufferTmp->FileNameLength/2, path_buf, PATH_BUF_SIZE, NULL, NULL);
+ path_buf[FileNumLenMB] = '\0';
+ sprintf(fullPath, "%s\\%s", search_path_win[searchNo], path_buf);
+ cygwin_conv_path (CCP_WIN_A_TO_POSIX | CCP_ABSOLUTE, fullPath, path_buf, PATH_BUF_SIZE);
+
+ //DPRINTF(E_DEBUG, L_INOTIFY, "path_buf:%s, rindex:%s\n", path_buf, rindex(path_buf, '/')+1);
+ esc_name = modifyString(strdup(rindex(path_buf, '/')+1), "&", "&amp;amp;", 0);
+ //DPRINTF(E_DEBUG, L_INOTIFY, "esc_name %s\n", esc_name);
+
+ if (m_BufferTmp->Action == FILE_ACTION_REMOVED) { // there is no way to distinguish file/dir in case delete.
+ // so try to delete both file and directory. it looks work
+ DPRINTF(E_DEBUG, L_INOTIFY, "The file/directory %s was deleted.\n", path_buf);
+ inotify_remove_file(path_buf);
+ inotify_remove_directory(fd, path_buf);
+ }
+ else {
+ //dp = opendir(path_buf); // check whether fullPath is directory
+ stat(path_buf, &file_stat);
+ //if (dp == NULL) { // file
+ if (!S_ISDIR(file_stat.st_mode)) { // file
+ if ( (m_BufferTmp->Action == FILE_ACTION_ADDED)
+ || (m_BufferTmp->Action == FILE_ACTION_MODIFIED)
+ || (m_BufferTmp->Action == FILE_ACTION_RENAMED_NEW_NAME)) {
+ DPRINTF(E_DEBUG, L_INOTIFY, "The file %s was %s.\n",
+ path_buf, m_BufferTmp->Action == FILE_ACTION_MODIFIED ? "changed" : "moved here");
+ inotify_insert_file(esc_name, path_buf);
+ } else
+ if ( (m_BufferTmp->Action == FILE_ACTION_REMOVED)
+ || (m_BufferTmp->Action == FILE_ACTION_RENAMED_OLD_NAME)) {
+ DPRINTF(E_DEBUG, L_INOTIFY, "The file %s was %s.\n",
+ path_buf, m_BufferTmp->Action == FILE_ACTION_RENAMED_OLD_NAME ? "moved away" : "deleted");
+ inotify_remove_file(path_buf);
+ }
+ }
+ else { // directory
+ //closedir(dp);
+ if ( (m_BufferTmp->Action == FILE_ACTION_ADDED)
+ || (m_BufferTmp->Action == FILE_ACTION_RENAMED_NEW_NAME)) {
+ DPRINTF(E_DEBUG, L_INOTIFY, "The directory %s was %s.\n",
+ path_buf, m_BufferTmp->Action == FILE_ACTION_RENAMED_NEW_NAME ? "moved here" : "created");
+ inotify_insert_directory(fd, esc_name, path_buf);
+ } else
+ if ( (m_BufferTmp->Action == FILE_ACTION_REMOVED)
+ || (m_BufferTmp->Action == FILE_ACTION_RENAMED_OLD_NAME)) {
+ DPRINTF(E_DEBUG, L_INOTIFY, "The directory %s was %s.\n",
+ path_buf, m_BufferTmp->Action == FILE_ACTION_RENAMED_OLD_NAME ? "moved away" : "deleted");
+ inotify_remove_directory(fd, path_buf);
+ }
+ }
+ }
+ free(esc_name);
+#endif
+ NextOff = m_BufferTmp->NextEntryOffset;
+ m_BufferTmp = (FILE_NOTIFY_INFORMATION *)((char *)m_BufferTmp + NextOff);
+ } while (NextOff != 0);
+
+}
+
+
+HANDLE
+add_watch(char *path)
+{
+ HANDLE hret;
+
+ hret = CreateFile(
+ path, // pointer to the file name
+ FILE_LIST_DIRECTORY, // access (read/write) mode
+ FILE_SHARE_READ // share mode
+ | FILE_SHARE_WRITE
+ | FILE_SHARE_DELETE,
+ NULL, // security descriptor
+ OPEN_EXISTING, // how to create
+ FILE_FLAG_BACKUP_SEMANTICS // file attributes
+ | FILE_FLAG_OVERLAPPED,
+ NULL); // file with attributes to copy
+
+ if (hret == INVALID_HANDLE_VALUE)
+ {
+ DPRINTF(E_ERROR, L_HTTP, "can not open directory : %s\n", path);
+ }
+
+ return hret;
+}
+
+
+BOOL
+registerReadDirChg_block(HANDLE hDirectory, FILE_NOTIFY_INFORMATION *buf, OVERLAPPED *overlapped)
+{
+ BOOL success;
+ DWORD dwBytes;
+ BOOL m_bChildren = 1;
+
+ // This call needs to be reissued after every APC.
+ success = ReadDirectoryChangesW(
+ hDirectory, // handle to directory
+ buf, // read results buffer
+ BUFF_SIZE, // length of buffer
+ m_bChildren, // monitoring option
+ FILE_NOTIFY_CHANGE_LAST_WRITE
+ |FILE_NOTIFY_CHANGE_CREATION
+ |FILE_NOTIFY_CHANGE_SIZE
+ |FILE_NOTIFY_CHANGE_DIR_NAME
+ |FILE_NOTIFY_CHANGE_FILE_NAME, // filter conditions
+ &dwBytes, // bytes returned
+ overlapped, // overlapped buffer
+ NULL); // completion routine : Not used
+
+ return success;
+}
+
+
+int
+inotify_create_watches()
+{
+ struct media_dir_s * media_path;
+ HANDLE hret;
+ int num_watches=0;
+
+ media_path = media_dirs;
+ for (num_watches = 0 ; media_path && (num_watches < WATCH_LIMIT) ; num_watches++)
+ {
+ char path_win_style[PATH_BUF_SIZE];
+ cygwin_conv_path (CCP_POSIX_TO_WIN_A | CCP_ABSOLUTE, media_path->path, path_win_style, PATH_BUF_SIZE);
+ hret = add_watch(path_win_style);
+ if (hret == INVALID_HANDLE_VALUE) break;
+ m_hDirectory[num_watches] = hret;
+ if ((m_Buffer[num_watches] = (FILE_NOTIFY_INFORMATION *)malloc(BUFF_SIZE)) == NULL) {
+ DPRINTF(E_ERROR, L_HTTP, "can not malloc for inotify\n\n");
+ break;
+ }
+ if ((search_path_win[num_watches] = (char *)malloc(PATH_BUF_SIZE)) == NULL) {
+ DPRINTF(E_ERROR, L_HTTP, "can not malloc for inotify\n\n");
+ break;
+ }
+ strcpy(search_path_win[num_watches], path_win_style);
+ DPRINTF(E_INFO, L_INOTIFY, "add directry : %s : %s\n", media_path->path, path_win_style);
+ media_path = media_path->next;
+ }
+
+ return num_watches;
+}
+
+
+void *
+start_inotify()
+{
+ HANDLE hEvents[WATCH_LIMIT];
+ BOOL bResult;
+ DWORD dwError, dwResult;
+ int i, eventNo;
+ DWORD dwBytes=0;
+ DWORD timeout = 1000;
+ int num_watches=0;
+
+ while( scanning )
+ {
+ if( quitting )
+ goto quitting;
+ sleep(1);
+ }
+
+ num_watches = inotify_create_watches();
+ if (!num_watches) {
+ DPRINTF(E_WARN, L_INOTIFY, "Failed to create watch\n");
+ return 0;
+ }
+
+ if (setpriority(PRIO_PROCESS, 0, 19) == -1)
+ DPRINTF(E_WARN, L_INOTIFY, "Failed to reduce inotify thread priority\n");
+////////////return 0;
+
+ for (i=0 ; i<num_watches ; i++) {
+ // Fill OVERLAPPED structure
+ memset(&m_Overlapped[i], 0, sizeof(OVERLAPPED));
+
+ m_Overlapped[i].hEvent = CreateEvent(
+ NULL, // security attributes
+ TRUE, // manually reset
+ FALSE, // unsignaled
+ NULL); // name
+
+ hEvents[i] = m_Overlapped[i].hEvent;
+
+ bResult = registerReadDirChg_block(m_hDirectory[i], m_Buffer[i], &m_Overlapped[i]);
+ dwError = GetLastError();
+ }
+
+ while( !quitting )
+ {
+ // Wait for overlapped result and for stop event
+ //DPRINTF(E_DEBUG, L_INOTIFY, "Wait for %d overlapped result and for stop event\n", num_watches);
+ dwResult = WaitForMultipleObjects(num_watches, hEvents, FALSE, timeout);
+ dwError = GetLastError();
+ //DPRINTF(E_DEBUG, L_INOTIFY, "event occured WAIT_OBJECT_0+%d\n", dwResult - WAIT_OBJECT_0);
+ if( dwResult == WAIT_TIMEOUT )
+ {
+ if( next_pl_fill && (time(NULL) >= next_pl_fill) )
+ {
+ fill_playlists();
+ next_pl_fill = 0;
+ }
+ continue;
+ }
+ else if( (WAIT_OBJECT_0 <= dwResult) && (dwResult < (WAIT_OBJECT_0 + num_watches)) ) {
+ // overlapped operation finished
+ eventNo = dwResult - WAIT_OBJECT_0;
+ bResult = GetOverlappedResult( m_hDirectory[eventNo], &m_Overlapped[eventNo], &dwBytes, TRUE );
+ dwError = GetLastError();
+
+ if ( ! bResult )
+ {
+ DPRINTF(E_ERROR, L_INOTIFY, "read failed!\n");
+ }
+ else
+ {
+ // handle results of asynchronous operation
+ insert_to_delete_from_db(eventNo);
+ // It is better to call registerReadDirChg_block() then NotificationCompletion()
+ // in order to avoid miss catch the events, but ...
+ // Get the new read issued as fast as possible. The documentation
+ // says that the original OVERLAPPED structure will not be used
+ // again once the completion routine is called.
+ bResult = registerReadDirChg_block(m_hDirectory[eventNo], m_Buffer[eventNo], &m_Overlapped[eventNo]);
+ dwError = GetLastError();
+ }
+ continue;
+ }
+ else if( dwResult == WAIT_FAILED)
+ {
+ //if( (errno == EINTR) || (errno == EAGAIN) )
+ // continue;
+ //else
+ DPRINTF(E_ERROR, L_INOTIFY, "read failed!\n");
+ break;
+ }
+ else {
+ DPRINTF(E_ERROR, L_INOTIFY, "read failed!\n");
+ break;
+ }
+ }
+ for (i=0 ; i<num_watches ; i++) {
+ CloseHandle(m_hDirectory[i]);
+ free(m_Buffer[i]);
+ free(search_path_win[i]);
+ }
+quitting:
+
+ return 0;
+}
+#endif /* cygwin */
diff --git a/minidlna.c b/minidlna.c
index dcc93bb..15674c2 100644
--- a/minidlna.c
+++ b/minidlna.c
@@ -98,6 +98,9 @@
#include "tivo_beacon.h"
#include "tivo_utils.h"
#endif
+#ifdef cygwin
+#include <sys/cygwin.h>
+#endif /* cygwin */
#if SQLITE_VERSION_NUMBER < 3005001
# warning "Your SQLite3 library appears to be too old! Please use 3.5.1 or newer."
@@ -352,6 +355,10 @@ init(int argc, char * * argv)
char * path;
char real_path[PATH_MAX];
char ext_ip_addr[INET_ADDRSTRLEN] = {'\0'};
+#ifdef cygwin
+ ssize_t ret;
+ char cygwin_path[PATH_MAX];
+#endif /* cygwin */
#ifdef ENABLE_TRANSCODE
int transcode_video_options_len = 0;
int transcode_audio_ffmpeg_options_len = 0;
@@ -397,6 +404,7 @@ init(int argc, char * * argv)
{
switch(ary_options[i].id)
{
+#ifndef cygwin
case UPNPIFNAME:
if(getifaddr(ary_options[i].value, ext_ip_addr, INET_ADDRSTRLEN) >= 0)
{
@@ -406,6 +414,7 @@ init(int argc, char * * argv)
else
fprintf(stderr, "Interface %s not found, ignoring.\n", ary_options[i].value);
break;
+#endif /* cygwin */
case UPNPLISTENING_IP:
if(n_lan_addr < MAX_LAN_ADDR)
{
@@ -461,7 +470,25 @@ init(int argc, char * * argv)
case 'p':
if( ary_options[i].value[0] == 'P' || ary_options[i].value[0] == 'p' )
type = IMAGES_ONLY;
+#ifndef cygwin
myval = index(ary_options[i].value, '/');
+#else /* cygwin */
+ case 'M':
+ case 'm':
+ myval = index(ary_options[i].value, '/');
+ if (!myval) {
+ myval = index(ary_options[i].value, '\\');
+ if (myval) {
+ ret = cygwin_conv_path(CCP_WIN_A_TO_POSIX | CCP_ABSOLUTE, &ary_options[i].value[2], cygwin_path, PATH_MAX);
+ if (ret == 0)
+ myval = cygwin_path;
+ else {
+ myval = NULL;
+ fprintf(stderr, "invalid path : %s\n", &ary_options[i].value[2]);
+ }
+ }
+ }
+#endif /* cygwin */
case '/':
path = realpath(myval ? myval:ary_options[i].value, real_path);
if( !path )
@@ -801,7 +828,11 @@ init(int argc, char * * argv)
else
{
#ifdef USE_DAEMON
+#ifndef cygwin
if(daemon(0, 0)<0) {
+#else
+ if(daemon(1, 0)<0) { // keep cuurend cwd
+#endif /* cygwin */
perror("daemon()");
}
pid = getpid();
@@ -900,6 +931,18 @@ main(int argc, char * * argv)
textdomain("minidlna");
#endif
+#ifdef cygwin
+ {
+ char *localappdata;
+ if ((localappdata = getenv("LOCALAPPDATA")) == NULL) // Windows7, Vista
+ localappdata = getenv("APPDATA"); // Windows XP
+ if (localappdata != NULL)
+ //cygwin_conv_path (CCP_WIN_A_TO_POSIX | CCP_ABSOLUTE, localappdata, db_path, PATH_MAX);
+ //strcat(db_path, "/minidlna");
+ sprintf(db_path, "%s\\minidlna", localappdata);
+ }
+#endif /* cygwin */
+
if(init(argc, argv) != 0)
return 1;
@@ -921,6 +964,10 @@ main(int argc, char * * argv)
#endif
LIST_INIT(&upnphttphead);
+#ifdef cygwin
+ DPRINTF(E_INFO, L_GENERAL, "db_path = %s\n", db_path);
+#endif /* cygwin */
+
new_db = open_db();
if( !new_db )
{
diff --git a/upnpglobalvars.c b/upnpglobalvars.c
index 0c71f42..bc64076 100644
--- a/upnpglobalvars.c
+++ b/upnpglobalvars.c
@@ -48,13 +48,18 @@
*/
#include <sys/types.h>
#include <netinet/in.h>
-#include <linux/limits.h>
+//#include <linux/limits.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include "upnpglobalvars.h"
#include "upnpdescstrings.h"
+#ifndef cygwin
+#include <linux/limits.h>
+#else
+#include <sys/cygwin.h>
+#endif /* cygwin */
/* LAN address */
/*const char * listen_addr = 0;*/
diff --git a/upnphttp.c b/upnphttp.c
index 2e5048f..9a529d5 100644
--- a/upnphttp.c
+++ b/upnphttp.c
@@ -67,7 +67,9 @@
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
+#ifndef cygwin
#include <sys/sendfile.h>
+#endif /* cygwin */
#include <arpa/inet.h>
#include "upnpglobalvars.h"
@@ -81,9 +83,18 @@
#include "tivo_utils.h"
#include "tivo_commands.h"
#endif
+#ifndef cygwin
//#define MAX_BUFFER_SIZE 4194304 // 4MB -- Too much?
#define MAX_BUFFER_SIZE 2147483647 // 2GB -- Too much?
#define MIN_BUFFER_SIZE 65536
+#else
+#define MAX_BUFFER_SIZE 4194304 // 4MB for Cygwin
+#define MIN_BUFFER_SIZE 65536
+#define MSG_MORE 0
+#include <sys/cygwin.h>
+#include<io.h>
+#include <string.h>
+#endif
#ifdef ENABLE_TRANSCODE
#define MAX_BUFFER_SIZE_TRANSCODE 1048576 // 1MB
@@ -1176,10 +1187,20 @@ send_file(struct upnphttp * h, int sendfd, off_t offset, off_t end_offset)
off_t send_size;
off_t ret;
char *buf = NULL;
+#ifndef cygwin
int try_sendfile = 1;
+#else /* cygwin */
+ if (EOF == setmode(sendfd, O_BINARY))
+ DPRINTF(E_INFO, L_HTTP, "cannot set BINARY mode for pipe");
+ if (EOF == setmode(h->socket, O_BINARY))
+ DPRINTF(E_INFO, L_HTTP, "cannot set BINARY mode for socket");
+
+ DPRINTF(E_INFO, L_HTTP, "start sendfile, offset=%lld, end=%lld\n", offset, end_offset);
+#endif /* cygwin */
while( offset < end_offset )
{
+#ifndef cygwin
if( try_sendfile )
{
send_size = ( ((end_offset - offset) < MAX_BUFFER_SIZE) ? (end_offset - offset + 1) : MAX_BUFFER_SIZE);
@@ -1199,6 +1220,7 @@ send_file(struct upnphttp * h, int sendfd, off_t offset, off_t end_offset)
continue;
}
}
+#endif /* cygwin */
/* Fall back to regular I/O */
if( !buf )
buf = malloc(MIN_BUFFER_SIZE);
@@ -1225,6 +1247,12 @@ send_file(struct upnphttp * h, int sendfd, off_t offset, off_t end_offset)
#ifdef ENABLE_TRANSCODE
+#ifdef cygwin
+#ifdef LINK_FFMPEG
+int ffmpeg_main(int argc, char **argv);
+#endif // LINK_FFMPEG
+#endif /* cygwin */
+
/* options for transcode specified in .conf file */
enum transcode_audio_enable transcode_audio = TRANSCODE_AUDIO_PCM;
enum transcode_video_transcoder transcode_video = TRANSCODE_VIDEO_MENCODER;
@@ -1266,6 +1294,15 @@ int exec_transcode(char *source_path, int *fd_r, int transcodeAV, int offset, in
char *pDst, *pSrc, *pTmp;
int options=0;
+#ifndef cygwin
+#else /* cygwin */
+ int numOfArg;
+ char *args[60], *ptr;
+ char source_path_win[PATH_MAX];
+ cygwin_conv_path (CCP_POSIX_TO_WIN_A | CCP_ABSOLUTE, source_path, source_path_win, 1024);
+ //DPRINTF(E_INFO, L_HTTP, "filename converterd to windows path =%s\n", source_path_win);
+#endif /* cygwin */
+
sprintf(position, "%d.%d", offset/1000, offset%1000);
sprintf(duration, "%d.%d", (end_offset - offset + 1)/1000, (end_offset - offset + 1)%1000);
//DPRINTF(E_DEBUG, L_HTTP, "position=%s, duration=%s\n", position, duration);
@@ -1302,8 +1339,13 @@ int exec_transcode(char *source_path, int *fd_r, int transcodeAV, int offset, in
options |= DURATION_DONE;
} else if (strncmp(pSrc, "$SOURCE", 7) == 0) {
pSrc += 7;
+#ifndef cygwin
ret = sprintf(pDst, "\"%s\" ", source_path);
pDst += ret;
+#else /* cygwin */
+ *pDst = '\0';
+ pDst = options_tmp2;
+#endif /* cygwin */
options |= SOURCE_DONE;
} else
pSrc++;
@@ -1318,8 +1360,25 @@ int exec_transcode(char *source_path, int *fd_r, int transcodeAV, int offset, in
//printf("%s %s \n", transcoder, options_tmp);
+#ifndef cygwin
sprintf(cmd, "%s %s", transcoder, options_tmp);
DPRINTF(E_INFO, L_HTTP, "exec %s as following:\n%s\n", transcoder, cmd);
+#else
+ sprintf(cmd, "%s.exe %s", transcoder, options_tmp);
+ DPRINTF(E_INFO, L_HTTP, "exec %s as following:\n%s \"%s\" %s\n", transcoder, cmd, strstr(transcoder, "ffmpeg") ? source_path : source_path_win, options_tmp2);
+
+ for (numOfArg= 0 ; numOfArg < 60 ; numOfArg++ ) {
+ ptr = strtok( numOfArg==0 ? cmd : NULL, " " );
+ if (ptr == NULL) break;
+ args[numOfArg] = ptr;
+ }
+ args[numOfArg++] = strstr(transcoder, "ffmpeg") ? source_path : source_path_win;
+ for ( ; numOfArg < 60 ; numOfArg++ ) {
+ ptr = strtok( ptr==NULL ? options_tmp2 : NULL, " " );
+ args[numOfArg] = ptr;
+ if (ptr == NULL) break;
+ }
+#endif /* cygwin */
/* Create a pipe. */
if(pipe(pipe_c2p)<0) {
@@ -1338,8 +1397,33 @@ int exec_transcode(char *source_path, int *fd_r, int transcodeAV, int offset, in
close(pipe_c2p[R]);
dup2(pipe_c2p[W],1);
close(pipe_c2p[W]);
+#ifndef cygwin
ret = execlp("sh", "sh", "-c", cmd, NULL);
//ret = execlp("cmd", "cmd", "/c", cmd, NULL);
+#else
+#if 0
+ for (numOfArg= 0 ; numOfArg < 60 ; numOfArg++ ) {
+ ptr = strtok( numOfArg==0 ? cmd : NULL, " " );
+ if (ptr == NULL) break;
+ args[numOfArg] = ptr;
+ }
+ args[numOfArg++] = strstr(transcoder, "ffmpeg") ? source_path : source_path_win;
+ for ( ; numOfArg < 60 ; numOfArg++ ) {
+ ptr = strtok( ptr==NULL ? options34 : NULL, " " );
+ args[numOfArg] = ptr;
+ if (ptr == NULL) break;
+ }
+#endif
+#ifdef LINK_FFMPEG
+ if (strstr(transcoder, "ffmpeg"))
+ {
+ ffmpeg_main(numOfArg, args);
+ exit(0);
+ }
+ else
+#endif // LINK_FFMPEG
+ ret = execvp(args[0], args);
+#endif
if (ret < 0) {
perror("exec_transcode");
close(pipe_c2p[W]);
@@ -1376,6 +1460,14 @@ send_file_transcode(struct upnphttp * h, int sendfd, int offset, int end_offset,
total_byte_read=0; total_byte_send=0;
+#if 0
+//#ifdef cygwin
+ if (EOF == setmode(fd_r, O_BINARY))
+ DPRINTF(E_INFO, L_HTTP, "cannot set BINARY mode for pipe");
+ if (EOF == setmode(h->socket, O_BINARY))
+ DPRINTF(E_INFO, L_HTTP, "cannot set BINARY mode for socket");
+#endif
+
while(1)
{
read_stream_size = read(fd_r, buf, MAX_BUFFER_SIZE_TRANSCODE); // read from PIPE
diff --git a/utils.c b/utils.c
index 9192d20..f253c16 100644
--- a/utils.c
+++ b/utils.c
@@ -19,7 +19,12 @@
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
+#include "config.h"
+#ifndef cygwin
#include <linux/limits.h>
+#else
+#include <sys/cygwin.h>
+#endif /* cygwin */
#include <sys/stat.h>
#include <unistd.h>
#include <sys/types.h>
diff --git a/uuid.c b/uuid.c
index bdb4abc..928e167 100644
--- a/uuid.c
+++ b/uuid.c
@@ -28,7 +28,10 @@
#include <time.h>
#include <fcntl.h>
#include <unistd.h>
+#include "config.h"
+#ifndef cygwin
#include <sys/syscall.h>
+#endif /* cygwin */
#include <string.h>
#include <net/if.h>
#include <sys/ioctl.h>
@@ -51,7 +54,11 @@ monotonic_us(void)
{
struct timespec ts;
+#ifndef cygwin
syscall(__NR_clock_gettime, CLOCK_MONOTONIC, &ts);
+#else
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+#endif //cygwin
return ts.tv_sec * 1000000ULL + ts.tv_nsec / 1000;
}
@@ -162,7 +169,11 @@ generate_uuid(unsigned char uuid_out[16])
* nanosecond intervals since 00:00:00.00, 15 October 1582 (the date of
* Gregorian reform to the Christian calendar).
*/
+#ifndef cygwin
syscall(__NR_clock_gettime, CLOCK_REALTIME, &ts);
+#else
+ clock_gettime(CLOCK_REALTIME, &ts);
+#endif //cygwin
time_all = ((u_int64_t)ts.tv_sec) * (NSEC_PER_SEC / 100);
time_all += ts.tv_nsec / 100;