libpurple/protocols/gg/lib/dcc.c

branch
release-2.x.y
changeset 35627
fd11790cc4d6
parent 35617
c9069e0e3c36
child 35630
8e5d0d726b09
child 37180
cf498d4b54bb
--- a/libpurple/protocols/gg/lib/dcc.c	Sun Mar 02 10:34:51 2014 +0100
+++ b/libpurple/protocols/gg/lib/dcc.c	Fri Mar 07 23:17:08 2014 +0100
@@ -138,19 +138,24 @@
 		return -1;
 	}
 
-	if (stat(local_filename, &st) == -1) {
-		gg_debug(GG_DEBUG_MISC, "// gg_dcc_fill_file_info2() stat() failed (%s)\n", strerror(errno));
+	if ((d->file_fd = open(local_filename, O_RDONLY)) == -1) {
+		gg_debug(GG_DEBUG_MISC, "// gg_dcc_fill_file_info2() open() failed (%s)\n", strerror(errno));
+		return -1;
+	}
+
+	if (fstat(d->file_fd, &st) == -1) {
+		gg_debug(GG_DEBUG_MISC, "// gg_dcc_fill_file_info2() "
+			"fstat() failed (%s)\n", strerror(errno));
+		close(d->file_fd);
+		d->file_fd = -1;
 		return -1;
 	}
 
 	if ((st.st_mode & S_IFDIR)) {
 		gg_debug(GG_DEBUG_MISC, "// gg_dcc_fill_file_info2() that's a directory\n");
 		errno = EINVAL;
-		return -1;
-	}
-
-	if ((d->file_fd = open(local_filename, O_RDONLY)) == -1) {
-		gg_debug(GG_DEBUG_MISC, "// gg_dcc_fill_file_info2() open() failed (%s)\n", strerror(errno));
+		close(d->file_fd);
+		d->file_fd = -1;
 		return -1;
 	}
 
@@ -209,7 +214,8 @@
 		}
 	}
 
-	gg_debug(GG_DEBUG_MISC, "// gg_dcc_fill_file_info2() short name \"%s\", dos name \"%s\"\n", name, d->file_info.short_filename);
+	gg_debug(GG_DEBUG_MISC, "// gg_dcc_fill_file_info2() short name \"%s\","
+		" dos name \"%s\"\n", name, d->file_info.short_filename);
 	strncpy((char*) d->file_info.filename, name, sizeof(d->file_info.filename) - 1);
 
 	return 0;
@@ -233,7 +239,9 @@
 
 	addr.s_addr = ip;
 
-	gg_debug(GG_DEBUG_FUNCTION, "** gg_dcc_transfer(%s, %d, %ld, %ld, %s);\n", inet_ntoa(addr), port, my_uin, peer_uin, (type == GG_SESSION_DCC_SEND) ? "SEND" : "GET");
+	gg_debug(GG_DEBUG_FUNCTION, "** gg_dcc_transfer(%s, %d, %u, %u, "
+		"%s);\n", inet_ntoa(addr), port, my_uin, peer_uin,
+		(type == GG_SESSION_DCC_SEND) ? "SEND" : "GET");
 
 	if (!ip || ip == INADDR_NONE || !port || !my_uin || !peer_uin) {
 		gg_debug(GG_DEBUG_MISC, "// gg_dcc_transfer() invalid arguments\n");
@@ -504,11 +512,15 @@
 	\
 	if (_tmp < (int) size) { \
 		if (_tmp == -1) { \
-			gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() recv() failed (errno=%d, %s)\n", errno, strerror(errno)); \
+			gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() recv() failed " \
+				"(errno=%d, %s)\n", errno, strerror(errno)); \
 		} else if (_tmp == 0) { \
-			gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() recv() failed, connection broken\n"); \
+			gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() recv() failed, " \
+				"connection broken\n"); \
 		} else { \
-			gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() recv() failed (%d bytes, %d needed)\n", _tmp, size); \
+			gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() recv() failed " \
+				"(%d bytes, %" GG_SIZE_FMT " needed)\n", \
+				_tmp, size); \
 		} \
 		e->type = GG_EVENT_DCC_ERROR; \
 		e->event.dcc_error = GG_ERROR_DCC_HANDSHAKE; \
@@ -531,9 +543,12 @@
 	write_res = send(fd, buf, size, 0); \
 	if (write_res < (int) size) { \
 		if (write_res == -1) { \
-			gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() send() failed (errno=%d, %s)\n", errno, strerror(errno)); \
+			gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() send() " \
+				"failed (errno=%d, %s)\n", errno, strerror(errno)); \
 		} else { \
-			gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() send() failed (%d needed, %d done)\n", size, write_res); \
+			gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() send() " \
+				"failed (%" GG_SIZE_FMT " needed, %d done)\n", \
+				size, write_res); \
 		} \
 		e->type = GG_EVENT_DCC_ERROR; \
 		e->event.dcc_error = GG_ERROR_DCC_HANDSHAKE; \
@@ -561,7 +576,12 @@
 
 	gg_debug(GG_DEBUG_FUNCTION, "** gg_dcc_watch_fd(%p);\n", h);
 
-	if (!h || (h->type != GG_SESSION_DCC && h->type != GG_SESSION_DCC_SOCKET && h->type != GG_SESSION_DCC_SEND && h->type != GG_SESSION_DCC_GET && h->type != GG_SESSION_DCC_VOICE)) {
+	if (!h || (h->type != GG_SESSION_DCC &&
+		h->type != GG_SESSION_DCC_SOCKET &&
+		h->type != GG_SESSION_DCC_SEND &&
+		h->type != GG_SESSION_DCC_GET &&
+		h->type != GG_SESSION_DCC_VOICE))
+	{
 		gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() invalid argument\n");
 		errno = EINVAL;
 		return NULL;
@@ -578,24 +598,23 @@
 		struct sockaddr_in sin;
 		struct gg_dcc *c;
 		int fd;
-#ifdef FIONBIO
-		int one = 1;
-#endif
 		socklen_t sin_len = sizeof(sin);
 
 		if ((fd = accept(h->fd, (struct sockaddr*) &sin, &sin_len)) == -1) {
-			gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() can't accept() new connection (errno=%d, %s)\n", errno, strerror(errno));
+			gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() can't "
+				"accept() new connection (errno=%d, %s)\n",
+				errno, strerror(errno));
 			return e;
 		}
 
-		gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() new direct connection from %s:%d\n", inet_ntoa(sin.sin_addr), htons(sin.sin_port));
+		gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() new direct "
+			"connection from %s:%d\n", inet_ntoa(sin.sin_addr),
+			htons(sin.sin_port));
 
-#ifdef FIONBIO
-		if (ioctl(fd, FIONBIO, &one) == -1) {
-#else
-		if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1) {
-#endif
-			gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() can't set nonblocking (errno=%d, %s)\n", errno, strerror(errno));
+		if (!gg_fd_set_nonblocking(fd)) {
+			gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() can't set"
+				" nonblocking (errno=%d, %s)\n",
+				errno, strerror(errno));
 			close(fd);
 			e->type = GG_EVENT_DCC_ERROR;
 			e->event.dcc_error = GG_ERROR_DCC_HANDSHAKE;
@@ -644,7 +663,9 @@
 			{
 				uin_t uin;
 
-				gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_READING_UIN_%d\n", (h->state == GG_STATE_READING_UIN_1) ? 1 : 2);
+				gg_debug(GG_DEBUG_MISC,
+					"// gg_dcc_watch_fd() GG_READING_UIN_%d\n",
+					(h->state == GG_STATE_READING_UIN_1) ? 1 : 2);
 
 				gg_dcc_read(h->fd, &uin, sizeof(uin));
 
@@ -667,7 +688,7 @@
 			case GG_STATE_SENDING_ACK:
 				gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_SENDING_ACK\n");
 
-				gg_dcc_write(h->fd, ack, 4);
+				gg_dcc_write(h->fd, ack, (size_t)4);
 
 				h->state = GG_STATE_READING_TYPE;
 				h->check = GG_CHECK_READ;
@@ -705,7 +726,8 @@
 						break;
 
 					default:
-						gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() unknown dcc type (%.4x) from %ld\n", small_pkt.type, h->peer_uin);
+						gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() unknown dcc type "
+							"(%.4x) from %u\n", small_pkt.type, h->peer_uin);
 						e->type = GG_EVENT_DCC_ERROR;
 						e->event.dcc_error = GG_ERROR_DCC_HANDSHAKE;
 				}
@@ -738,7 +760,9 @@
 						break;
 
 					default:
-						gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() unknown dcc request (%.4x) from %ld\n", small_pkt.type, h->peer_uin);
+						gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() unknown "
+							"dcc request (%.4x) from %u\n",
+							small_pkt.type, h->peer_uin);
 						e->type = GG_EVENT_DCC_ERROR;
 						e->event.dcc_error = GG_ERROR_DCC_HANDSHAKE;
 				}
@@ -806,13 +830,16 @@
 				tmp = recv(h->fd, h->chunk_buf + h->chunk_offset, h->chunk_size - h->chunk_offset, 0);
 
 				if (tmp == -1) {
-					gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() recv() failed (errno=%d, %s)\n", errno, strerror(errno));
+					gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() recv() "
+						"failed (errno=%d, %s)\n", errno, strerror(errno));
 					e->type = GG_EVENT_DCC_ERROR;
 					e->event.dcc_error = GG_ERROR_DCC_NET;
 					return e;
 				}
 
-				gg_dcc_debug_data("read", h->fd, h->chunk_buf + h->chunk_offset, h->chunk_size - h->chunk_offset);
+				gg_dcc_debug_data("read", h->fd,
+					h->chunk_buf + h->chunk_offset,
+					h->chunk_size - h->chunk_offset);
 
 				h->chunk_offset += tmp;
 
@@ -860,10 +887,12 @@
 						h->established = 1;
 						break;
 					case 0x04:	/* XXX */
-						gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() peer breaking connection\n");
+						gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() "
+							"peer breaking connection\n");
 						/* XXX zwracać odpowiedni event */
 					default:
-						gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() unknown request (%.2x)\n", tiny_pkt.type);
+						gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() "
+							"unknown request (%.2x)\n", tiny_pkt.type);
 						e->type = GG_EVENT_DCC_ERROR;
 						e->event.dcc_error = GG_ERROR_DCC_HANDSHAKE;
 				}
@@ -878,7 +907,8 @@
 				small_pkt.type = gg_fix32(small_pkt.type);
 
 				if (small_pkt.type < 16 || small_pkt.type > sizeof(buf)) {
-					gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() invalid voice frame size (%d)\n", small_pkt.type);
+					gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() "
+						"invalid voice frame size (%d)\n", small_pkt.type);
 					e->type = GG_EVENT_DCC_ERROR;
 					e->event.dcc_error = GG_ERROR_DCC_NET;
 
@@ -906,9 +936,12 @@
 				tmp = recv(h->fd, h->voice_buf + h->chunk_offset, h->chunk_size - h->chunk_offset, 0);
 				if (tmp < 1) {
 					if (tmp == -1) {
-						gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() recv() failed (errno=%d, %s)\n", errno, strerror(errno));
+						gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() "
+							"recv() failed (errno=%d, %s)\n",
+							errno, strerror(errno));
 					} else {
-						gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() recv() failed, connection broken\n");
+						gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() "
+							"recv() failed, connection broken\n");
 					}
 					e->type = GG_EVENT_DCC_ERROR;
 					e->event.dcc_error = GG_ERROR_DCC_NET;
@@ -940,7 +973,10 @@
 
 				res = 0;
 				if ((foo = getsockopt(h->fd, SOL_SOCKET, SO_ERROR, &res, &res_size)) || res) {
-					gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() connection failed (fd=%d,errno=%d(%s),foo=%d,res=%d(%s))\n", h->fd, errno, strerror(errno), foo, res, strerror(res));
+					gg_debug(GG_DEBUG_MISC,
+						"// gg_dcc_watch_fd() connection failed "
+						"(fd=%d,errno=%d(%s),foo=%d,res=%d(%s))\n",
+						h->fd, errno, strerror(errno), foo, res, strerror(res));
 					e->type = GG_EVENT_DCC_ERROR;
 					e->event.dcc_error = GG_ERROR_DCC_HANDSHAKE;
 					return e;
@@ -963,7 +999,7 @@
 			case GG_STATE_READING_ACK:
 				gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_READING_ACK\n");
 
-				gg_dcc_read(h->fd, buf, 4);
+				gg_dcc_read(h->fd, buf, (size_t)4);
 
 				if (strncmp(buf, ack, 4)) {
 					gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() did't get ack\n");
@@ -995,7 +1031,8 @@
 			case GG_STATE_SENDING_REQUEST:
 				gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_SENDING_REQUEST\n");
 
-				small_pkt.type = (h->type == GG_SESSION_DCC_GET) ? gg_fix32(0x0003) : gg_fix32(0x0002);	/* XXX */
+				small_pkt.type = (h->type == GG_SESSION_DCC_GET) ?
+					gg_fix32(0x0003) : gg_fix32(0x0002); /* XXX */
 
 				gg_dcc_write(h->fd, &small_pkt, sizeof(small_pkt));
 
@@ -1076,7 +1113,9 @@
 				gg_dcc_read(h->fd, &tiny_pkt, sizeof(tiny_pkt));
 
 				if (tiny_pkt.type != 0x01) {
-					gg_debug(GG_DEBUG_MISC, "// invalid reply (%.2x), connection refused\n", tiny_pkt.type);
+					gg_debug(GG_DEBUG_MISC, "// invalid "
+						"reply (%.2x), connection "
+						"refused\n", tiny_pkt.type);
 					e->type = GG_EVENT_DCC_ERROR;
 					e->event.dcc_error = GG_ERROR_DCC_REFUSED;
 					return e;
@@ -1119,11 +1158,15 @@
 				if ((utmp = h->chunk_size - h->chunk_offset) > sizeof(buf))
 					utmp = sizeof(buf);
 
-				gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() offset=%d, size=%d\n", h->offset, h->file_info.size);
+				gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() "
+					"offset=%d, size=%d\n",
+					h->offset, h->file_info.size);
 
 				/* koniec pliku? */
 				if (h->file_info.size == 0) {
-					gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() read() reached eof on empty file\n");
+					gg_debug(GG_DEBUG_MISC,
+						"// gg_dcc_watch_fd() read()"
+						"reached eof on empty file\n");
 					e->type = GG_EVENT_DCC_DONE;
 
 					return e;
@@ -1135,13 +1178,26 @@
 					return e;
 				}
 
-				lseek(h->file_fd, h->offset, SEEK_SET);
+				if (lseek(h->file_fd, h->offset, SEEK_SET) != (off_t)h->offset) {
+					gg_debug(GG_DEBUG_MISC,
+						"// gg_dcc_watch_fd() lseek() "
+						"failed. (errno=%d, %s)\n",
+						errno, strerror(errno));
+
+					e->type = GG_EVENT_DCC_ERROR;
+					e->event.dcc_error = GG_ERROR_DCC_FILE;
+
+					return e;
+				}
 
 				size = read(h->file_fd, buf, utmp);
 
 				/* błąd */
 				if (size == -1) {
-					gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() read() failed. (errno=%d, %s)\n", errno, strerror(errno));
+					gg_debug(GG_DEBUG_MISC,
+						"// gg_dcc_watch_fd() read() "
+						"failed. (errno=%d, %s)\n",
+						errno, strerror(errno));
 
 					e->type = GG_EVENT_DCC_ERROR;
 					e->event.dcc_error = GG_ERROR_DCC_FILE;
@@ -1160,11 +1216,17 @@
 
 				/* jeśli wczytaliśmy więcej, utnijmy. */
 				if (h->offset + size > h->file_info.size) {
-					gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() read() too much (read=%d, ofs=%d, size=%d)\n", size, h->offset, h->file_info.size);
+					gg_debug(GG_DEBUG_MISC,
+						"// gg_dcc_watch_fd() read() "
+						"too much (read=%d, ofs=%d, "
+						"size=%d)\n", size, h->offset,
+						h->file_info.size);
 					size = h->file_info.size - h->offset;
 
 					if (size < 1) {
-						gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() reached EOF after cutting\n");
+						gg_debug(GG_DEBUG_MISC,
+							"// gg_dcc_watch_fd() "
+							"reached EOF after cutting\n");
 						e->type = GG_EVENT_DCC_DONE;
 						return e;
 					}
@@ -1173,14 +1235,18 @@
 				tmp = send(h->fd, buf, size, 0);
 
 				if (tmp == -1) {
-					gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() send() failed (%s)\n", strerror(errno));
+					gg_debug(GG_DEBUG_MISC,
+						"// gg_dcc_watch_fd() send() "
+						"failed (%s)\n", strerror(errno));
 					e->type = GG_EVENT_DCC_ERROR;
 					e->event.dcc_error = GG_ERROR_DCC_NET;
 					return e;
 				}
 
 				if (tmp == 0) {
-					gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() send() failed (connection reset)\n");
+					gg_debug(GG_DEBUG_MISC,
+						"// gg_dcc_watch_fd() send() "
+						"failed (connection reset)\n");
 					e->type = GG_EVENT_DCC_ERROR;
 					e->event.dcc_error = GG_ERROR_DCC_NET;
 					return e;
@@ -1222,11 +1288,16 @@
 
 				size = recv(h->fd, buf, utmp, 0);
 
-				gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() ofs=%d, size=%d, recv()=%d\n", h->offset, h->file_info.size, size);
+				gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() "
+					"ofs=%d, size=%d, recv()=%d\n",
+					h->offset, h->file_info.size, size);
 
 				/* błąd */
 				if (size == -1) {
-					gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() recv() failed. (errno=%d, %s)\n", errno, strerror(errno));
+					gg_debug(GG_DEBUG_MISC,
+						"// gg_dcc_watch_fd() recv() "
+						"failed. (errno=%d, %s)\n",
+						errno, strerror(errno));
 
 					e->type = GG_EVENT_DCC_ERROR;
 					e->event.dcc_error = GG_ERROR_DCC_NET;
@@ -1246,7 +1317,11 @@
 				tmp = write(h->file_fd, buf, size);
 
 				if (tmp == -1 || tmp < size) {
-					gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() write() failed (%d:fd=%d:res=%d:%s)\n", tmp, h->file_fd, size, strerror(errno));
+					gg_debug(GG_DEBUG_MISC,
+						"// gg_dcc_watch_fd() write() "
+						"failed (%d:fd=%d:res=%d:%s)\n",
+						tmp, h->file_fd, size,
+						strerror(errno));
 					e->type = GG_EVENT_DCC_ERROR;
 					e->event.dcc_error = GG_ERROR_DCC_NET;
 					return e;

mercurial