コード例 #1
0
ファイル: mailbox-list-maildir.c プロジェクト: bdraco/dovecot
static int
maildir_list_rename_mailbox(struct mailbox_list *oldlist, const char *oldname,
			    struct mailbox_list *newlist, const char *newname)
{
	const char *oldpath, *newpath, *root_path;
	int ret;
        bool found;

	/* NOTE: it's possible to rename a nonexistent mailbox which has
	   children. In that case we should ignore the rename() error. */
	if (mailbox_list_get_path(oldlist, oldname,
				  MAILBOX_LIST_PATH_TYPE_MAILBOX, &oldpath) <= 0 ||
	    mailbox_list_get_path(newlist, newname,
				  MAILBOX_LIST_PATH_TYPE_MAILBOX, &newpath) <= 0)
		i_unreached();

	root_path = mailbox_list_get_root_forced(oldlist,
						 MAILBOX_LIST_PATH_TYPE_MAILBOX);
	if (strcmp(oldpath, root_path) == 0) {
		/* most likely INBOX */
		mailbox_list_set_error(oldlist, MAIL_ERROR_NOTPOSSIBLE,
			t_strdup_printf("Renaming %s isn't supported.",
					oldname));
		return -1;
	}

	/* if we're renaming under another mailbox, require its permissions
	   to be same as ours. */
	if (strchr(newname, mailbox_list_get_hierarchy_sep(newlist)) != NULL) {
		struct mailbox_permissions old_perm, new_perm;

		mailbox_list_get_permissions(oldlist, oldname, &old_perm);
		mailbox_list_get_permissions(newlist, newname, &new_perm);

		if ((new_perm.file_create_mode != old_perm.file_create_mode ||
		     new_perm.dir_create_mode != old_perm.dir_create_mode ||
		     new_perm.file_create_gid != old_perm.file_create_gid)) {
			mailbox_list_set_error(oldlist, MAIL_ERROR_NOTPOSSIBLE,
				"Renaming not supported across conflicting "
				"directory permissions");
			return -1;
		}
	}


	ret = rename(oldpath, newpath);
	if (ret == 0 || errno == ENOENT) {
		(void)rename_dir(oldlist, oldname, newlist, newname,
				 MAILBOX_LIST_PATH_TYPE_CONTROL);
		(void)rename_dir(oldlist, oldname, newlist, newname,
				 MAILBOX_LIST_PATH_TYPE_INDEX);

		found = ret == 0;
		T_BEGIN {
			ret = maildir_rename_children(oldlist, oldname,
						      newlist, newname);
		} T_END;
		if (ret < 0)
			return -1;
		if (!found && ret == 0) {
			mailbox_list_set_error(oldlist, MAIL_ERROR_NOTFOUND,
				T_MAIL_ERR_MAILBOX_NOT_FOUND(oldname));
			return -1;
		}

		return 0;
	}
コード例 #2
0
ファイル: wxftp.c プロジェクト: wangkendy/wxFtp
int main()
{
	char HOME[128];
	int client_len;
	struct sockaddr_in client_address;
	int result;
	fd_set readfds, testfds;

	struct sigaction act;
	act.sa_handler = sigint_handler;
	sigemptyset(&act.sa_mask);
	act.sa_flags = 0;
	sigaction(SIGINT, &act, 0);

	get_home_dir(HOME);
	printf("HOME:%s\n", HOME);

	//global variable server_sockfd will be set.
	create_server_socket();

	FD_ZERO(&readfds);
	FD_SET(server_sockfd, &readfds);

	while(1) {
		char buf[128];
		int fd;
		int nread;
	
		testfds = readfds;

		printf("server waiting\n");
		result = select(FD_SETSIZE, &testfds, (fd_set *)0, (fd_set *)0, (struct timeval *)0);

		if(result < 1) {
			perror("ftp_server");
			exit(1);
		}

		for(fd = 0; fd < FD_SETSIZE; fd++) {
			if(FD_ISSET(fd, &testfds)) {
				if(fd == server_sockfd) {//有新来的客户链接
					client_len = sizeof(client_address);
					client_sockfd = accept(server_sockfd, (struct sockaddr *)&client_address, &client_len);
					FD_SET(client_sockfd, &readfds);
					client[client_sockfd].cmd_sockfd = client_sockfd;
					client[client_sockfd].sin_addr.s_addr = client_address.sin_addr.s_addr;
					sprintf(client[client_sockfd].cwd, "/");
					printf("adding client on fd %d\n", client_sockfd);
					sprintf(buf, "220 (wxftp 1.0)\r\n");
					write(client_sockfd, buf, strlen(buf));
				} else {//客户链接发来数据
					ioctl(fd, FIONREAD, &nread);
					if(nread == 0) {//无数据可读,表示客户已主动断开链接
						close(fd);
						memset(&client[fd], 0, sizeof(struct Client));
						FD_CLR(fd, &readfds);
						printf("removing client on fd %d\n", fd);
					} else {//读取数据并当作命令来处理。
						read(fd, buf, nread);
						buf[nread] = '\0';
						printf("serving client on fd %d: %s\n", fd, buf);
						if(strncmp(buf, "USER", 4) == 0) {
							sscanf(&buf[4], "%s", client[fd].user);
							//printf("user %s\n", client[fd].user);
							sprintf(buf, "331 Password required for %s.\r\n", client[fd].user);
							write(fd, buf, strlen(buf));
						} else if(strncmp(buf, "PASS", 4) == 0) {
							sscanf(&buf[4], "%s", client[fd].pass);
							if (authenticate(client[fd].user, client[fd].pass) == 0) {
								client[fd].authorized = 1;
								sprintf(buf, "230 Login successful.\r\n");
							} else {
								client[fd].authorized = 0;
								sprintf(buf, "530 Login or Password incorrect.\r\n");
							}
							write(fd, buf, strlen(buf));
						} else if(strncmp(buf, "SYST", 4) == 0) {
							sprintf(buf, "215 Linux.\r\n");
							write(fd, buf, strlen(buf));
						} else if(strncmp(buf, "FEAT", 4) == 0) {
							sprintf(buf, "550 Not support.\r\n");
							write(fd, buf, strlen(buf));
						} else if(strncmp(buf, "PWD", 3) == 0) {
							sprintf(buf, "257 \"%s\" is current directory.\r\n", client[fd].cwd);
							write(fd, buf, strlen(buf));
						} else if(strncmp(buf, "CWD", 3) == 0) {
							char dir[128];
							sscanf(&buf[3], "%s", dir);
							if (strncmp(dir, "..", 2) == 0) {
								if(strlen(client[fd].cwd) == 1) {
									sprintf(buf, "250 \"/\" is current directory.\r\n");
								} else {
									int i;
									char *cwd = client[fd].cwd;
									int len = strlen(cwd);
									for(i = len - 1; i >= 0; i--) {
										if(cwd[i] == '/' && i != len - 1) {
											cwd[i+1] = '\0';
											break;
										}
									}
									sprintf(buf, "250 CWD command successful. \"%s\" is current directory.\r\n", client[fd].cwd);
								}
							} else if(file_exist(client[fd].cwd, dir) == 0) {
								//client[fd].cwd = ;
								char *cwd = client[fd].cwd;
								int len = strlen(cwd);
								if(cwd[len-1] == '/') {
									sprintf(&client[fd].cwd[len], "%s", dir);
								} else {
									sprintf(&client[fd].cwd[len], "/%s", dir);
								}
								sprintf(buf,"250 CWD command successful. \"%s\" is current directory.\r\n",client[fd].cwd );
							} else {
								sprintf(buf,"550 CWD failed. \"%s\": no such file or directory.\r\n", dir);
							}
							write(fd, buf, strlen(buf));
						} else if(strncmp(buf, "CDUP", 4) == 0) {
							if(strlen(client[fd].cwd) == 1) {
								sprintf(buf, "250 \"/\" is current directory.\r\n");
							} else {
								//make some change to client[fd].cwd
								int i;
								char *cwd = client[fd].cwd;
								int len = strlen(cwd);
								printf("%s: %d\n", cwd, len);
								for(i = len - 1; i >= 0; i--) {
									printf("%d: %c\n", i, client[fd].cwd[i]);
									if(client[fd].cwd[i] == '/' && i != len - 1) {
										client[fd].cwd[i+1] = '\0';
										break;
									}
								}
								sprintf(buf, "250 \"%s\" is current directory.\r\n",client[fd].cwd);
							}
							write(fd, buf, strlen(buf));
						} else if (strncmp(buf, "MKD", 3) == 0) {
							char dir[128];
							sscanf(&buf[3], "%s", dir);
							if (file_exist(client[fd].cwd, dir) == 0) {
								sprintf(buf, "550 Command failed. %s exists.\r\n", dir);
								write(fd, buf, strlen(buf));
							} else {
								make_dir(client[fd].cwd, dir);
								sprintf(buf, "250 Command ok. %s made.\r\n", dir);
								write(fd, buf, strlen(buf));
							}
						} else if (strncmp(buf, "RMD", 3) == 0) {
							char dir[128];
							sscanf(&buf[3], "%s", dir);
							if (file_exist(client[fd].cwd, dir) == 0) {
								remove_dir(client[fd].cwd, dir);
								sprintf(buf, "250 Command ok. %s removed.\r\n", dir);
								write(fd, buf, strlen(buf));
							} else {
								sprintf(buf, "550 Command failed. %s doesn't exist.\r\n", dir);
								write(fd, buf, strlen(buf));
							}
						} else if (strncmp(buf, "RNFR", 4) == 0) {
							char dir[128];
							sscanf(&buf[4], "%s", dir);
							if (file_exist(client[fd].cwd, dir) == 0) {
								sscanf(&buf[4], "%s", client[fd].rnfr);
								sprintf(buf, "350 File exists, ready for destination name.\r\n");
								write(fd, buf, strlen(buf));
							} else {
								sprintf(buf, "550 File/directory not found.\r\n");
								write(fd, buf, strlen(buf));
							}
						} else if (strncmp(buf, "RNTO", 4) == 0) {
							char dir[128];
							sscanf(&buf[4], "%s", dir);
							if (file_exist(client[fd].cwd, dir) == 0) {
								sprintf(buf, "550 Comman failed. %s exists.\r\n", dir);
								write(fd, buf, strlen(buf));
							} else {
								rename_dir(client[fd].cwd, client[fd].rnfr, dir);
								sprintf(buf, "250 File rename successfully.\r\n");
								write(fd, buf, strlen(buf));
							}
						} else if(strncmp(buf, "TYPE", 4) == 0) {
							char type[10];
							sscanf(&buf[4], "%s", type);
							sprintf(buf, "200 Type set to %s.\r\n", type);
							write(fd, buf, strlen(buf));
						} else if(strncmp(buf, "PASV", 4) == 0) {
							int port = rand() % 1000 + 8000;
							client[fd].data_port = port;
							client[fd].mode = kDataConnModePassive;
							struct sockaddr_in name;
							int name_len = sizeof(struct sockaddr_in);
							getsockname(fd, (struct sockaddr*)&name, &name_len);
							printf("server ip address is : %s\n port: %d\n", inet_ntoa(name.sin_addr), port);
							sprintf(buf, "227 Entering Passive Mode (210,25,132,182,%d,%d)\r\n", port / 256, port % 256);
							write(fd, buf, strlen(buf));
							int sockfd = data_conn_passive(port);
							printf("PASV sockfd: %d\n", sockfd);
							client[fd].data_sockfd = sockfd;
						} else if(strncmp(buf, "PORT", 4) == 0) {
							int ip[4], port[2];
							sscanf(&buf[4], "%d,%d,%d,%d,%d,%d", &ip[0], &ip[1], &ip[2], &ip[3], &port[0], &port[1]);
							sprintf(client[fd].data_ip, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
							client[fd].data_port = port[0] * 256 + port[1];
							client[fd].mode = kDataConnModeActive;
							printf("IP:%s, Port:%d\n", client[fd].data_ip, client[fd].data_port);
							sprintf(buf, "200 Port command successful.\r\n");
							write(fd, buf, strlen(buf));
						} else if(strncmp(buf, "LIST", 4) == 0 || strncmp(buf, "NLST", 4) == 0) {
							int sockfd;
							if(client[fd].mode == kDataConnModeActive) {
								sockfd = data_conn_active(&client[fd].sin_addr, client[fd].data_port);
							} else if (client[fd].mode == kDataConnModePassive) {
								//sockfd = data_conn_passive(client[fd].data_port);
								sockfd = client[fd].data_sockfd;
							}
							int result = 0;
							if (sockfd != -1) {
								sprintf(buf,"150 Opening data connection for directory list.\r\n");
								write(fd, buf, strlen(buf));
								if(send_list(sockfd, client[fd].cwd) == 0) {
									sprintf(buf, "226 Transfer ok.\r\n");
								} else {
									sprintf(buf, "550 Error encountered.\r\n");
								}
								write(fd, buf, strlen(buf));
								close(sockfd);
							} else {
								printf("CREATE DATA_CONN FAILE.\n");
							}
						} else if (strncmp(buf, "RETR", 4) == 0) {
							char filename[64];
							sscanf(&buf[4], "%s", filename);
							if(file_exist(client[fd].cwd, filename) != 0) {
								sprintf(buf, "550 \"%s\": no such file.\r\n", filename);
								write(fd, buf, strlen(buf));
							} else {
								int sockfd;
								if(client[fd].mode == kDataConnModeActive) {
									sockfd = data_conn_active(&client[fd].sin_addr, client[fd].data_port);
								} else if (client[fd].mode == kDataConnModePassive) {
									sockfd = data_conn_passive(client[fd].data_port);
								}
								int result = 0;
								if (sockfd != -1) {
									sprintf(buf, "150 Opening data connection for %s\r\n", filename);
									write(fd, buf, strlen(buf));
									char filedir[128];
									int len = strlen(client[fd].cwd);
									if(client[fd].cwd[len-1] == '/') {
										sprintf(filedir, "%s%s%s", HOME, client[fd].cwd, filename);
									} else {
										sprintf(filedir, "%s%s/%s", HOME, client[fd].cwd, filename);
									}	
									result = send_file(sockfd, filedir);
									printf("send result: %d\n", result);
									if (result != -1) {
										close(sockfd);
										sprintf(buf, "226 File sent ok.\r\n");
										write(fd, buf, strlen(buf));
									}
								}
							}
						} else if (strncmp(buf, "STOR", 4) == 0) {
							char filename[64];
							sscanf(&buf[4], "%s", filename);
							int sockfd;
							if(client[fd].mode == kDataConnModeActive) {
								sockfd = data_conn_active(&client[fd].sin_addr, client[fd].data_port);
							} else if (client[fd].mode == kDataConnModePassive) {
								sockfd = data_conn_passive(client[fd].data_port);
							}
							int result = 0;
							if (sockfd != -1) {
								sprintf(buf, "150 Opening data connection for %s\r\n", filename);
								write(fd, buf, strlen(buf));
								char filedir[128];
								int len = strlen(client[fd].cwd);
								if(client[fd].cwd[len-1] == '/') {
									sprintf(filedir, "%s%s%s", HOME, client[fd].cwd, filename);
								} else {
									sprintf(filedir, "%s%s/%s", HOME, client[fd].cwd, filename);
								}	
								result = recv_file(sockfd, /*filename*/filedir);
								printf("recv result: %d\n", result);
								if (result != -1) {
									close(sockfd);
									sprintf(buf, "226 File received ok.\r\n");
									write(fd, buf, strlen(buf));
								}
							}
						} else if (strncmp(buf, "QUIT", 4) == 0) {
							sprintf(buf, "221 Goodbye.\r\n");
							write(fd, buf, strlen(buf));
							close(fd);
							memset(&client[fd], 0, sizeof(struct Client));
							FD_CLR(fd, &readfds);
							printf("removing client on fd %d\n", fd);
						} else {
							sprintf(buf, "550 Unknown command.\r\n");
							write(fd, buf, strlen(buf));
						}
					}
				}
			}
		}
	}
	return 0;
}
コード例 #3
0
ファイル: mailbox-list-maildir.c プロジェクト: bdraco/dovecot
static int
maildir_rename_children(struct mailbox_list *oldlist, const char *oldname,
			struct mailbox_list *newlist, const char *newname)
{
	struct mailbox_list_iterate_context *iter;
        const struct mailbox_info *info;
	ARRAY(const char *) names_arr;
	const char *pattern, *oldpath, *newpath, *old_childname, *new_childname;
	const char *const *names, *old_vname, *new_vname;
	unsigned int i, count, old_vnamelen;
	pool_t pool;
	char old_ns_sep;
	int ret;

	ret = 0;

	/* first get the list of the children and save them to memory, because
	   we can't rely on readdir() not skipping files while the directory
	   is being modified. this doesn't protect against modifications by
	   other processes though. */
	pool = pool_alloconly_create("Maildir++ children list", 1024);
	i_array_init(&names_arr, 64);

	old_vname = mailbox_list_get_vname(oldlist, oldname);
	old_vnamelen = strlen(old_vname);

	new_vname = mailbox_list_get_vname(newlist, newname);

	old_ns_sep = mail_namespace_get_sep(oldlist->ns);
	pattern = t_strdup_printf("%s%c*", old_vname, old_ns_sep);
	iter = mailbox_list_iter_init(oldlist, pattern,
				      MAILBOX_LIST_ITER_RETURN_NO_FLAGS |
				      MAILBOX_LIST_ITER_RAW_LIST);
	while ((info = mailbox_list_iter_next(iter)) != NULL) {
		const char *name;

		/* verify that the prefix matches, otherwise we could have
		   problems with mailbox names containing '%' and '*' chars */
		if (strncmp(info->vname, old_vname, old_vnamelen) == 0 &&
		    info->vname[old_vnamelen] == old_ns_sep) {
			name = p_strdup(pool, info->vname + old_vnamelen);
			array_append(&names_arr, &name, 1);
		}
	}
	if (mailbox_list_iter_deinit(&iter) < 0) {
		ret = -1;
		names = NULL; count = 0;
	} else {
		names = array_get(&names_arr, &count);
	}

	for (i = 0; i < count; i++) {
		old_childname = mailbox_list_get_storage_name(oldlist,
					t_strconcat(old_vname, names[i], NULL));
		if (strcmp(old_childname, new_vname) == 0) {
			/* When doing RENAME "a" "a.b" we see "a.b" here.
			   We don't want to rename it anymore to "a.b.b". */
			continue;
		}

		new_childname = mailbox_list_get_storage_name(newlist,
					t_strconcat(new_vname, names[i], NULL));
		if (mailbox_list_get_path(oldlist, old_childname,
					  MAILBOX_LIST_PATH_TYPE_MAILBOX,
					  &oldpath) <= 0 ||
		    mailbox_list_get_path(newlist, new_childname,
					  MAILBOX_LIST_PATH_TYPE_MAILBOX,
					  &newpath) <= 0)
			i_unreached();

		/* FIXME: it's possible to merge two mailboxes if either one of
		   them doesn't have existing root mailbox. We could check this
		   but I'm not sure if it's worth it. It could be even
		   considered as a feature.

		   Anyway, the bug with merging is that if both mailboxes have
		   identically named child mailbox they conflict. Just ignore
		   those and leave them under the old mailbox. */
		if (rename(oldpath, newpath) == 0 || EDESTDIREXISTS(errno))
			ret = 1;
		else {
			mailbox_list_set_critical(oldlist,
				"rename(%s, %s) failed: %m", oldpath, newpath);
			ret = -1;
			break;
		}

		(void)rename_dir(oldlist, old_childname, newlist, new_childname,
				 MAILBOX_LIST_PATH_TYPE_CONTROL);
		(void)rename_dir(oldlist, old_childname, newlist, new_childname,
				 MAILBOX_LIST_PATH_TYPE_INDEX);
	}
	array_free(&names_arr);
	pool_unref(&pool);

	return ret;
}