Diff between b594920572e4a719a745f1487f822fdff5a20709 and 606f56714d1a4da4405163b23b71fc9abe9aac45

Changed Files

File Additions Deletions Status
obexd/src/bluetooth.c +7 -3 modified
obexd/src/bluetooth.h +3 -2 modified
obexd/src/ftp.c +59 -11 modified
obexd/src/main.c +9 -4 modified
obexd/src/obex.h +1 -0 modified

Full Patch

diff --git a/obexd/src/bluetooth.c b/obexd/src/bluetooth.c
index 10f3f8f..37d7b99 100644
--- a/obexd/src/bluetooth.c
+++ b/obexd/src/bluetooth.c
@@ -172,7 +172,8 @@ static gint server_stop(struct server *server)
 
 static gint server_register(guint16 service, const gchar *name, guint8 channel,
 			const gchar *folder, gboolean secure,
-			gboolean auto_accept, const gchar *capability)
+			gboolean auto_accept, gboolean symlinks,
+			const gchar *capability)
 {
 	struct server *server;
 	int err;
@@ -182,6 +183,7 @@ static gint server_register(guint16 service, const gchar *name, guint8 channel,
 	server->name = g_strdup(name);
 	server->folder = g_strdup(folder);
 	server->auto_accept = auto_accept;
+	server->symlinks = symlinks;
 	server->capability = g_strdup(capability);
 	server->channel = channel;
 	server->secure = secure;
@@ -203,10 +205,12 @@ static gint server_register(guint16 service, const gchar *name, guint8 channel,
 
 gint bluetooth_init(guint service, const gchar *name, const gchar *folder,
 				guint8 channel, gboolean secure,
-				gboolean auto_accept, const gchar *capability)
+				gboolean auto_accept, gboolean symlinks,
+				const gchar *capability)
 {
 	return server_register(service, name, channel, folder,
-					secure, auto_accept, capability);
+					secure, auto_accept, symlinks,
+					capability);
 }
 
 void bluetooth_exit(void)
diff --git a/obexd/src/bluetooth.h b/obexd/src/bluetooth.h
index df74ca5..7871177 100644
--- a/obexd/src/bluetooth.h
+++ b/obexd/src/bluetooth.h
@@ -28,8 +28,9 @@
 #endif
 
 gint bluetooth_init(guint service, const gchar *name, const gchar *folder,
-			guint8 channel, gboolean secure, gboolean auto_accept,
-			const gchar *capability);
+				guint8 channel, gboolean secure,
+				gboolean auto_accept, gboolean symlinks,
+				const gchar *capability);
 void bluetooth_exit(void);
 void bluetooth_start(void);
 void bluetooth_stop(void);
diff --git a/obexd/src/ftp.c b/obexd/src/ftp.c
index 9ab13c5..5c442fc 100644
--- a/obexd/src/ftp.c
+++ b/obexd/src/ftp.c
@@ -114,16 +114,25 @@ static gboolean folder_listing(struct obex_session *os, guint32 *size)
 	struct dirent *ep;
 	DIR *dp;
 	GString *listing;
+	gboolean root;
+	int err;
 
 	listing = g_string_new(FL_VERSION);
 	listing = g_string_append(listing, FL_TYPE);
 	listing = g_string_append(listing, FL_BODY_BEGIN);
 
-	if (strcmp(os->current_folder,os->server->folder))
+	root = g_str_equal(os->current_folder, os->server->folder);
+
+	if (root && os->server->symlinks)
+		err = stat(os->current_folder, &dstat);
+	else {
 		listing = g_string_append(listing, FL_PARENT_FOLDER_ELEMENT);
+		err = lstat(os->current_folder, &dstat);
+	}
 
-	if (lstat(os->current_folder, &dstat) < 0) {
-		error("lstat: %s(%d)", strerror(errno), errno);
+	if (err < 0) {
+		error("%s: %s(%d)", root ? "stat" : "lstat",
+				strerror(errno), errno);
 		goto failed;
 	}
 
@@ -149,8 +158,14 @@ static gboolean folder_listing(struct obex_session *os, guint32 *size)
 
 		fullname = g_build_filename(os->current_folder, ep->d_name, NULL);
 
-		if (lstat(fullname, &fstat) < 0) {
-			debug("lstat: %s(%d)", strerror(errno), errno);
+		if (root && os->server->symlinks)
+			err = stat(fullname, &fstat);
+		else
+			err = lstat(fullname, &fstat);
+
+		if (err < 0) {
+			debug("%s: %s(%d)", root ? "stat" : "lstat",
+					strerror(errno), errno);
 			g_free(name);
 			g_free(fullname);
 			continue;
@@ -229,6 +244,30 @@ static gboolean get_by_type(struct obex_session *os, gchar *type, guint32 *size)
 	return FALSE;
 }
 
+static gboolean ftp_prepare_get(struct obex_session *os, gchar *file,
+				guint32 *size)
+{
+	gboolean root;
+
+	root = g_str_equal(os->server->folder, os->current_folder);
+
+	if (!root || !os->server->symlinks) {
+		struct stat dstat;
+		int err;
+
+		err = lstat(file, &dstat);
+		if (err < 0) {
+			debug("lstat: %s(%d)", strerror(errno), errno);
+			return FALSE;
+		}
+
+		if (S_ISLNK(dstat.st_mode))
+			return FALSE;
+	}
+
+	return os_prepare_get(os, file, size);
+}
+
 void ftp_get(obex_t *obex, obex_object_t *obj)
 {
 	obex_headerdata_t hv;
@@ -248,10 +287,9 @@ void ftp_get(obex_t *obex, obex_object_t *obj)
 		if (!os->name)
 			goto fail;
 
-		path = g_build_filename(os->current_folder,
-					os->name, NULL);
+		path = g_build_filename(os->current_folder, os->name, NULL);
 
-		ret = os_prepare_get(os, path, &size);
+		ret = ftp_prepare_get(os, path, &size);
 
 		g_free(path);
 
@@ -357,6 +395,8 @@ void ftp_setpath(obex_t *obex, obex_object_t *obj)
 	guint8 *nonhdr;
 	gchar *fullname;
 	struct stat dstat;
+	gboolean root;
+	int err;
 
 	os = OBEX_GetUserData(obex);
 
@@ -367,12 +407,14 @@ void ftp_setpath(obex_t *obex, obex_object_t *obj)
 		return;
 	}
 
+	root = g_str_equal(os->server->folder, os->current_folder);
+
 	/* Check flag "Backup" */
 	if ((nonhdr[0] & 0x01) == 0x01) {
 
 		debug("Set to parent path");
 
-		if (strcmp(os->server->folder, os->current_folder) == 0) {
+		if (root) {
 			OBEX_ObjectSetRsp(obj, OBEX_RSP_FORBIDDEN, OBEX_RSP_FORBIDDEN);
 			return;
 		}
@@ -414,9 +456,15 @@ void ftp_setpath(obex_t *obex, obex_object_t *obj)
 
 	debug("Fullname: %s", fullname);
 
-	if (lstat(fullname, &dstat) < 0) {
+	if (root && os->server->symlinks)
+		err = stat(fullname, &dstat);
+	else
+		err = lstat(fullname, &dstat);
+
+	if (err < 0) {
 		int err = errno;
-		debug("lstat: %s(%d)", strerror(err), err);
+		debug("%s: %s(%d)", root ? "stat" : "lstat",
+				strerror(err), err);
 		if (err == ENOENT)
 			goto not_found;
 
diff --git a/obexd/src/main.c b/obexd/src/main.c
index 18bc496..0315f55 100644
--- a/obexd/src/main.c
+++ b/obexd/src/main.c
@@ -124,6 +124,7 @@ static gboolean option_opp = FALSE;
 static gboolean option_ftp = FALSE;
 static gboolean option_pbap = FALSE;
 static gboolean option_pcsuite = FALSE;
+static gboolean option_symlinks = FALSE;
 
 static GOptionEntry options[] = {
 	{ "nodaemon", 'n', G_OPTION_FLAG_REVERSE,
@@ -133,6 +134,8 @@ static GOptionEntry options[] = {
 				"Enable debug information output" },
 	{ "root", 'r', 0, G_OPTION_ARG_STRING, &option_root,
 				"Specify root folder location", "PATH" },
+	{ "symlinks", 'l', 0, G_OPTION_ARG_NONE, &option_symlinks,
+				"Enable symlinks on root folder" },
 	{ "capability", 'c', 0, G_OPTION_ARG_STRING, &option_capability,
 				"Sepcify capability file", "FILE" },
 	{ "tty", 't', 0, G_OPTION_ARG_STRING, &option_devnode,
@@ -266,27 +269,29 @@ int main(int argc, char *argv[])
 	if (option_opp == TRUE) {
 		services |= OBEX_OPP;
 		bluetooth_init(OBEX_OPP, "Object Push server", option_root,
-				OPP_CHANNEL, FALSE, option_autoaccept, NULL);
+				OPP_CHANNEL, FALSE, option_autoaccept,
+				option_symlinks, NULL);
 	}
 
 	if (option_ftp == TRUE) {
 		services |= OBEX_FTP;
 		bluetooth_init(OBEX_FTP, "File Transfer server", option_root,
 				FTP_CHANNEL, TRUE, option_autoaccept,
-				option_capability);
+				option_symlinks, option_capability);
 	}
 
 	if (option_pbap == TRUE) {
 		services |= OBEX_PBAP;
 		bluetooth_init(OBEX_PBAP, "Phonebook Access server", NULL,
-				PBAP_CHANNEL, TRUE, FALSE, NULL);
+				PBAP_CHANNEL, TRUE, FALSE, FALSE, NULL);
 	}
 
 	if (option_pcsuite == TRUE) {
 		services |= OBEX_PCSUITE;
 		bluetooth_init(OBEX_PCSUITE, "Nokia OBEX PC Suite Services",
 				option_root, PCSUITE_CHANNEL, TRUE,
-				option_autoaccept, option_capability);
+				option_autoaccept, option_symlinks,
+				option_capability);
 	}
 
 	if (option_devnode)
diff --git a/obexd/src/obex.h b/obexd/src/obex.h
index 28dfdbc..b13219d 100644
--- a/obexd/src/obex.h
+++ b/obexd/src/obex.h
@@ -52,6 +52,7 @@ struct server {
 	gboolean	auto_accept;
 	gchar		*name;
 	gchar		*folder;
+	gboolean	symlinks;
 	gchar		*capability;
 	guint32		handle;
 	uint8_t		channel;