File:  [ELWIX - Embedded LightWeight unIX -] / embedtools / src / Attic / upd.c
Revision 1.1.2.8: download - view: text, annotated - select for diffs - revision graph
Tue Nov 17 14:56:03 2009 UTC (14 years, 7 months ago) by misho
Branches: tools1_0
added tftp server feature

    1: #include "global.h"
    2: #include "upd.h"
    3: 
    4: 
    5: int Kill;
    6: 
    7: 
    8: static inline int ChkImg(const char *csImg, char *psDir)
    9: {
   10: 	int res = 0;
   11: 
   12: 	getcwd(psDir, MAXPATHLEN);
   13: 	if (access(csImg, R_OK) == -1) {
   14: 		printf("Error:: Unable to find new image %s #%d - %s\n", 
   15: 				csImg, errno, strerror(errno));
   16: 		res = -1;
   17: 	} else {
   18: 		strlcat(psDir, "/", MAXPATHLEN);
   19: 		strlcat(psDir, csImg, MAXPATHLEN);
   20: 	}
   21: 
   22: 	return res;
   23: }
   24: 
   25: // -------------------------------
   26: 
   27: int Activate(const char *csImg)
   28: {
   29: 	char szDir[MAXPATHLEN];
   30: 
   31: 	if (ChkImg(csImg, szDir) == -1)
   32: 		return -1;
   33: 
   34: 	VERB(3) printf("Activate procedure for %s\n", szDir);
   35: 
   36: 	unlink(FIRMWARE_IMG);
   37: 	if (symlink(szDir, FIRMWARE_IMG) == -1) {
   38: 		printf("Error:: Unable to activate new image %s #%d - %s\n", 
   39: 				csImg, errno, strerror(errno));
   40: 		return -2;
   41: 	}
   42: 
   43: 	syslog(LOG_NOTICE, "Activate new image %s", csImg);
   44: 	VERB(1) printf("Activate new image %s\n", csImg);
   45: 	return 0;
   46: }
   47: 
   48: int Install(const char *csImg, const char *psDir)
   49: {
   50: 	int src, dst, len;
   51: 	u_char buf[BUFSIZ];
   52: 	char szDir[MAXPATHLEN], szFile[MAXPATHLEN];
   53: 	struct stat ss, ds;
   54: 
   55: 	strlcpy(szFile, psDir, MAXPATHLEN);
   56: 	strlcat(szFile, "/", MAXPATHLEN);
   57: 	strlcat(szFile, csImg, MAXPATHLEN);
   58: 	if (access(szFile, R_OK) == -1) {
   59: 		printf("Error:: Unable to find new image %s #%d - %s\n", 
   60: 				csImg, errno, strerror(errno));
   61: 		return -1;
   62: 	} else {
   63: 		memset(&ss, 0, sizeof ss);
   64: 		if (stat(szFile, &ss) == -1) {
   65: 			printf("Error:: Unable to find new image %s #%d - %s\n", 
   66: 					csImg, errno, strerror(errno));
   67: 			return -1;
   68: 		}
   69: 	}
   70: 
   71: 	getcwd(szDir, MAXPATHLEN);
   72: 	VERB(3) printf("Install procedure from %s to %s\n", szFile, szDir);
   73: 	strlcat(szDir, "/", MAXPATHLEN);
   74: 	strlcat(szDir, csImg, MAXPATHLEN);
   75: 	memset(&ds, 0, sizeof ds);
   76: 	if (stat(szDir, &ds) == -1 && ENOENT != errno) {
   77: 		printf("Error:: Unable to stat target #%d - %s\n", 
   78: 				errno, strerror(errno));
   79: 		return -1;
   80: 	}
   81: 
   82: 	if (ss.st_dev == ds.st_dev && ss.st_ino == ds.st_ino) {
   83: 		printf("Error:: Unable to install into self ...\n");
   84: 		return -1;
   85: 	}
   86: 
   87: 	dst = open(szDir, O_WRONLY | O_CREAT | O_TRUNC, 0644);
   88: 	if (dst == -1) {
   89: 		printf("Error:: in create image %s #%d - %s\n", 
   90: 				szDir, errno, strerror(errno));
   91: 		return -1;
   92: 	}
   93: 	src = open(szFile, O_RDONLY);
   94: 	if (src == -1) {
   95: 		printf("Error:: in open image %s #%d - %s\n", 
   96: 				szFile, errno, strerror(errno));
   97: 		close(dst);
   98: 		unlink(szDir);
   99: 		return -1;
  100: 	}
  101: 
  102: 	while ((len = read(src, buf, BUFSIZ)) > 0)
  103: 		if (write(dst, buf, len) == -1) {
  104: 			printf("Error:: in write image #%d - %s\n", 
  105: 					errno, strerror(errno));
  106: 			close(src);
  107: 			close(dst);
  108: 			unlink(szDir);
  109: 
  110: 			len = -1;
  111: 			break;
  112: 		}
  113: 
  114: 	close(src);
  115: 	close(dst);
  116: 
  117: 	if (!len) {
  118: 		syslog(LOG_NOTICE, "Install image %s to %s", csImg, szDir);
  119: 		VERB(1) printf("Install image %s to %s\n", csImg, szDir);
  120: 	}
  121: 	return len;
  122: }
  123: 
  124: int Rollback(const char *csImg)
  125: {
  126: 	int src, dst, len;
  127: 	u_char buf[BUFSIZ];
  128: 	char szDir[MAXPATHLEN], szFile[MAXPATHLEN];
  129: 	struct stat ss, ds;
  130: 
  131: 	getcwd(szFile, MAXPATHLEN);
  132: 	strlcat(szFile, "/", MAXPATHLEN);
  133: 	strlcat(szFile, FIRMWARE_BAK, MAXPATHLEN);
  134: 	if (access(szFile, R_OK) == -1) {
  135: 		printf("Error:: Unable to find backup image #%d - %s\n", 
  136: 				errno, strerror(errno));
  137: 		return -1;
  138: 	} else {
  139: 		memset(&ss, 0, sizeof ss);
  140: 		if (stat(szFile, &ss) == -1) {
  141: 			printf("Error:: Unable to find backup image #%d - %s\n", 
  142: 					errno, strerror(errno));
  143: 			return -1;
  144: 		}
  145: 	}
  146: 
  147: 	getcwd(szDir, MAXPATHLEN);
  148: 	strlcat(szDir, "/", MAXPATHLEN);
  149: 	strlcat(szDir, csImg, MAXPATHLEN);
  150: 	VERB(3) printf("Rollback procedure for image %s from backup!\n", csImg);
  151: 	memset(&ds, 0, sizeof ds);
  152: 	if (stat(szDir, &ds) == -1 && ENOENT != errno) {
  153: 		printf("Error:: Unable to stat target #%d - %s\n", 
  154: 				errno, strerror(errno));
  155: 		return -1;
  156: 	}
  157: 
  158: 	if (ss.st_dev == ds.st_dev && ss.st_ino == ds.st_ino) {
  159: 		printf("Error:: Unable to rollback into self ...\n");
  160: 		return -1;
  161: 	}
  162: 
  163: 	src = open(szFile, O_RDONLY);
  164: 	if (src == -1) {
  165: 		printf("Error:: in open backup %s #%d - %s\n", 
  166: 				szFile, errno, strerror(errno));
  167: 		return -1;
  168: 	}
  169: 	dst = open(szDir, O_WRONLY | O_CREAT | O_TRUNC, 0644);
  170: 	if (dst == -1) {
  171: 		printf("Error:: in create image %s #%d - %s\n", 
  172: 				szDir, errno, strerror(errno));
  173: 		close(src);
  174: 		return -1;
  175: 	}
  176: 
  177: 	while ((len = read(src, buf, BUFSIZ)) > 0)
  178: 		if (write(dst, buf, len) == -1) {
  179: 			printf("Error:: in write image #%d - %s\n", 
  180: 					errno, strerror(errno));
  181: 			close(dst);
  182: 			close(src);
  183: 			unlink(szDir);
  184: 
  185: 			len = -1;
  186: 			break;
  187: 		}
  188: 
  189: 	close(dst);
  190: 	close(src);
  191: 
  192: 	if (!len) {
  193: 		syslog(LOG_NOTICE, "Rollback image %s to %s", csImg, szDir);
  194: 		VERB(1) printf("Rollback image %s to %s\n", csImg, szDir);
  195: 	}
  196: 	return len;
  197: 
  198: 	return 0;
  199: }
  200: 
  201: int tFTP(const char *csImg, const char *psDir)
  202: {
  203: 	int src, dst, len;
  204: 	u_char buf[BUFSIZ];
  205: 	char szDir[MAXPATHLEN], szFile[MAXPATHLEN];
  206: 	struct stat ss, ds;
  207: 
  208: 	if (ChkImg(csImg, szDir) == -1)
  209: 		return -1;
  210: 	else {
  211: 		memset(&ss, 0, sizeof ss);
  212: 		if (stat(szDir, &ss) == -1) {
  213: 			printf("Error:: Unable to find image %s #%d - %s\n", 
  214: 					szDir, errno, strerror(errno));
  215: 			return -1;
  216: 		}
  217: 	}
  218: 
  219: 	VERB(3) printf("tFTP procedure for %s to %s\n", szDir, psDir);
  220: 	strlcpy(szFile, psDir, MAXPATHLEN);
  221: 	strlcat(szFile, "/", MAXPATHLEN);
  222: 	strlcat(szFile, csImg, MAXPATHLEN);
  223: 	memset(&ds, 0, sizeof ds);
  224: 	if (stat(szFile, &ds) == -1 && ENOENT != errno) {
  225: 		printf("Error:: Unable to stat target %s #%d - %s\n", 
  226: 				szFile, errno, strerror(errno));
  227: 		return -1;
  228: 	}
  229: 
  230: 	if (ss.st_dev == ds.st_dev && ss.st_ino == ds.st_ino) {
  231: 		printf("Error:: Unable to copy into self ...\n");
  232: 		return -1;
  233: 	}
  234: 
  235: 	dst = open(szFile, O_WRONLY | O_CREAT | O_TRUNC, 0644);
  236: 	if (dst == -1) {
  237: 		printf("Error:: in create backup %s #%d - %s\n", 
  238: 				szFile, errno, strerror(errno));
  239: 		return -1;
  240: 	}
  241: 	src = open(szDir, O_RDONLY);
  242: 	if (src == -1) {
  243: 		printf("Error:: in open image %s #%d - %s\n", 
  244: 				szDir, errno, strerror(errno));
  245: 		close(dst);
  246: 		unlink(szFile);
  247: 		return -1;
  248: 	}
  249: 
  250: 	while ((len = read(src, buf, BUFSIZ)) > 0)
  251: 		if (write(dst, buf, len) == -1) {
  252: 			printf("Error:: in write backup #%d - %s\n", 
  253: 					errno, strerror(errno));
  254: 			close(src);
  255: 			close(dst);
  256: 			unlink(szFile);
  257: 
  258: 			len = -1;
  259: 			break;
  260: 		}
  261: 
  262: 	close(src);
  263: 	close(dst);
  264: 
  265: 	if (!len) {
  266: 		syslog(LOG_NOTICE, "Export tFTP image %s to %s", csImg, psDir);
  267: 		VERB(1) printf("Export tFTP image %s to %s\n", csImg, psDir);
  268: 	}
  269: 	return len;
  270: }
  271: 
  272: int Backup(const char *csImg)
  273: {
  274: 	int src, dst, len;
  275: 	u_char buf[BUFSIZ];
  276: 	char szDir[MAXPATHLEN], szFile[MAXPATHLEN];
  277: 
  278: 	if (ChkImg(csImg, szDir) == -1)
  279: 		return -1;
  280: 
  281: 	getcwd(szFile, MAXPATHLEN);
  282: 	strlcat(szFile, "/", MAXPATHLEN);
  283: 	strlcat(szFile, FIRMWARE_BAK, MAXPATHLEN);
  284: 	VERB(3) printf("Backup procedure for %s\n", szDir);
  285: 
  286: 	dst = open(szFile, O_WRONLY | O_CREAT | O_TRUNC, 0644);
  287: 	if (dst == -1) {
  288: 		printf("Error:: in create backup %s #%d - %s\n", 
  289: 				szFile, errno, strerror(errno));
  290: 		return -1;
  291: 	}
  292: 	src = open(szDir, O_RDONLY);
  293: 	if (src == -1) {
  294: 		printf("Error:: in open image %s #%d - %s\n", 
  295: 				szDir, errno, strerror(errno));
  296: 		close(dst);
  297: 		unlink(szFile);
  298: 		return -1;
  299: 	}
  300: 
  301: 	while ((len = read(src, buf, BUFSIZ)) > 0)
  302: 		if (write(dst, buf, len) == -1) {
  303: 			printf("Error:: in write backup #%d - %s\n", 
  304: 					errno, strerror(errno));
  305: 			close(src);
  306: 			close(dst);
  307: 			unlink(szFile);
  308: 
  309: 			len = -1;
  310: 			break;
  311: 		}
  312: 
  313: 	close(src);
  314: 	close(dst);
  315: 
  316: 	if (!len) {
  317: 		syslog(LOG_NOTICE, "Backup image %s", csImg);
  318: 		VERB(1) printf("Backup image %s\n", csImg);
  319: 	}
  320: 	return len;
  321: }
  322: 
  323: int Clean(const char *csImg)
  324: {
  325: 	char szDir[MAXPATHLEN], szFile[MAXPATHLEN];
  326: 
  327: 	if (ChkImg(csImg, szDir) == -1)
  328: 		return -1;
  329: 
  330: 	getcwd(szFile, MAXPATHLEN);
  331: 	strlcat(szFile, "/", MAXPATHLEN);
  332: 	strlcat(szFile, FIRMWARE_BAK, MAXPATHLEN);
  333: 
  334: 	VERB(3) printf("Clean procedure for %s\n", szDir);
  335: 
  336: 	if (unlink(szFile) == -1) {
  337: 		printf("Error:: in clean backup #%d - %s\n", errno, strerror(errno));
  338: 		return -1;
  339: 	}
  340: 
  341: 	syslog(LOG_NOTICE, "Clean backup for image %s", csImg);
  342: 	VERB(1) printf("Clean backup for image %s\n", csImg);
  343: 	return 0;
  344: }
  345: 
  346: // ----------------------------------
  347: 
  348: static void Signal(int sig)
  349: {
  350: 	int stat;
  351: 
  352: 	switch (sig) {
  353: 		case SIGHUP:
  354: 			VERB(5) printf("Info(5):: Signal arrived #%d\n", sig);
  355: 			break;
  356: 		case SIGCHLD:
  357: 			while (waitpid(-1, &stat, WNOHANG) > 0);
  358: 			break;
  359: 		case SIGTERM:
  360: 			Kill = 1;
  361: 			VERB(5) printf("Info(5):: Signal arrived #%d\n", sig);
  362: 			break;
  363: 	}
  364: }
  365: 
  366: int Daemonize(struct sockaddr_in sin, const char *csTFTP)
  367: {
  368: 	int s, n = 1;
  369: 	pid_t pid;
  370: 	fd_set rfd;
  371: 	u_short seq = 0xffff;
  372: 	int clilen, len, f, retry;
  373: 	struct sockaddr_in cli, rcv;
  374: 	struct sigaction sa;
  375: 	u_char buf[TFTP_BUF], *pos;
  376: 	char szFName[MAX_STR];
  377: 	struct tftphdr *tftp = (struct tftphdr*) buf;
  378: 	struct timeval tv = { TFTP_TIMEOUT, 0 };
  379: 
  380: 	VERB(3) printf("Daemonize procedure for %s:%d to %s\n", 
  381: 			inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), csTFTP);
  382: 
  383: 	memset(&sa, 0, sizeof sa);
  384: 	sigemptyset(&sa.sa_mask);
  385: 	sa.sa_handler = Signal;
  386: 	sigaction(SIGCHLD, &sa, NULL);
  387: 	sigaction(SIGTERM, &sa, NULL);
  388: 	sigaction(SIGHUP, &sa, NULL);
  389: 
  390: 	s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
  391: 	if (s == -1) {
  392: 		printf("Error:: in create socket #%d - %s\n", errno, strerror(errno));
  393: 		return -1;
  394: 	}
  395: 	if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &n, sizeof n) == -1) {
  396: 		printf("Error:: in socket options #%d - %s\n", errno, strerror(errno));
  397: 		close(s);
  398: 		return -1;
  399: 	}
  400: 	if (bind(s, (struct sockaddr*) &sin, sizeof sin) == -1) {
  401: 		printf("Error:: in bind #%d - %s\n", errno, strerror(errno));
  402: 		close(s);
  403: 		return -1;
  404: 	}
  405: 
  406: 	switch ((pid = fork())) {
  407: 		case -1:
  408: 			printf("Error:: in socket options #%d - %s\n", errno, strerror(errno));
  409: 			close(s);
  410: 			return -1;
  411: 		case 0:
  412: 			setsid();
  413: 
  414: 			while (!Kill) {
  415: 				FD_ZERO(&rfd);
  416: 				FD_SET(s, &rfd);
  417: 				if (select(s + 1, &rfd, NULL, NULL, NULL) == -1)
  418: 					continue;
  419: 
  420: 				memset(buf, 0, TFTP_BUF);
  421: 				clilen = sizeof cli;
  422: 				len = recvfrom(s, buf, TFTP_BUF, 0, (struct sockaddr*) &cli, 
  423: 						(socklen_t*) &clilen);
  424: 				if (len == -1) {
  425: 					VERB(5) printf("Error:: in recvfrom #%d - %s\n", 
  426: 							errno, strerror(errno));
  427: 					continue;
  428: 				}
  429: 
  430: 				tftp = (struct tftphdr*) (pos = buf);
  431: 				VERB(5) printf("Info(5):: Received packet from %s len %d with opcode=%hd\n", 
  432: 						inet_ntoa(cli.sin_addr), len, ntohs(tftp->th_opcode));
  433: 				switch (ntohs(tftp->th_opcode)) {
  434: 					case WRQ:
  435: 						len -= 2;
  436: 						pos += 2;
  437: 						strlcpy(szFName, (char*) pos, MAX_STR);
  438: 						VERB(5) printf("Info(5):: Get filename %s\n", szFName);
  439: 						len -= strlen((char*) pos) + 1;
  440: 						pos += strlen((char*) pos) + 1;
  441: 						VERB(5) printf("Info(5):: Get mode %s len=%d\n", pos, len);
  442: 						if (strncmp((char*) pos, "octet", len)) {
  443: 							memset(buf, 0, TFTP_BUF);
  444: 							tftp->th_opcode = htons(ERROR);
  445: 							tftp->th_code = htons(EBADOP);
  446: 							strncpy(tftp->th_data, "Error:: mode not supported", 27);
  447: 							sendto(s, buf, 31, 0, (struct sockaddr*) &cli, sizeof cli);
  448: 							continue;
  449: 						}
  450: 						VERB(2) printf("Info(2):: Receive file %s from %s\n", 
  451: 								szFName, inet_ntoa(cli.sin_addr));
  452: 
  453: 						f = open(szFName, O_WRONLY | O_CREAT | O_EXCL, 0644);
  454: 						if (f == -1) {
  455: 							memset(buf, 0, TFTP_BUF);
  456: 							tftp->th_opcode = htons(ERROR);
  457: 							switch (errno) {
  458: 								case EACCES:
  459: 								case EPERM:
  460: 									tftp->th_code = htons(EACCESS);
  461: 									break;
  462: 								case EEXIST:
  463: 									tftp->th_code = htons(EEXISTS);
  464: 									break;
  465: 								default:
  466: 									tftp->th_code = htons(ENOSPACE);
  467: 							}
  468: 							sprintf(tftp->th_data, "Error:: in file %s", 
  469: 									strerror(errno));
  470: 							sendto(s, buf, strlen(tftp->th_data) + 4, 0, 
  471: 									(struct sockaddr*) &cli, sizeof cli);
  472: 							continue;
  473: 						}
  474: 
  475: 						memset(buf, 0, TFTP_BUF);
  476: 						tftp->th_opcode = htons(ACK);
  477: 						tftp->th_block = seq = 0;
  478: 						sendto(s, tftp, 4, 0, (struct sockaddr*) &cli, sizeof cli);
  479: 
  480: 						for (retry = TFTP_RETRY; retry;) {
  481: 							FD_ZERO(&rfd);
  482: 							FD_SET(s, &rfd);
  483: 							if (select(s + 1, &rfd, NULL, NULL, &tv) < 1) {
  484: 								retry--;
  485: 								continue;
  486: 							}
  487: 							memset(buf, 0, TFTP_BUF);
  488: 							clilen = sizeof sin;
  489: 							if ((len = recvfrom(s, buf, TFTP_BUF, 0, 
  490: 										(struct sockaddr*) &rcv, 
  491: 										(socklen_t*) &clilen)) == -1) {
  492: 								VERB(5) printf("Error:: in recvfrom #%d - %s\n", 
  493: 										errno, strerror(errno));
  494: 								retry--;
  495: 								continue;
  496: 							} else
  497: 								if (cli.sin_addr.s_addr != rcv.sin_addr.s_addr)
  498: 									continue;
  499: 
  500: 							VERB(5) printf("Info(5):: received opcode=%d block=%d seq=%d\n", 
  501: 									ntohs(tftp->th_opcode), ntohs(tftp->th_block), seq);
  502: 							if (ERROR == ntohs(tftp->th_opcode)) {
  503: 								syslog(LOG_ERR, "Error:: in tftp receiving #%d - %s", 
  504: 										tftp->th_code, tftp->th_data);
  505: 								close(f);
  506: 								unlink(szFName);
  507: 								break;
  508: 							}
  509: 							if (DATA == ntohs(tftp->th_opcode) && 
  510: 									++seq == ntohs(tftp->th_block)) {
  511: 								if (write(f, tftp->th_data, len - 4) == -1) {
  512: 									syslog(LOG_ERR, "Error:: Can`t write to file %s\n", 
  513: 											szFName);
  514: 									close(f);
  515: 									unlink(szFName);
  516: 									break;
  517: 								}
  518: 
  519: 								memset(buf, 0, TFTP_BUF);
  520: 								tftp->th_opcode = htons(ACK);
  521: 								tftp->th_block = htons(seq);
  522: 								sendto(s, tftp, 4, 0, (struct sockaddr*) &rcv, sizeof rcv);
  523: 								VERB(5) printf("Info(5):: Send ACK for %s block=%d\n", 
  524: 										inet_ntoa(cli.sin_addr), seq);
  525: 
  526: 								if (SEGSIZE > len - 4) {
  527: 									close(f);
  528: 									syslog(LOG_INFO, "TFTP transfer complete to %s", 
  529: 											szFName);
  530: 									break;
  531: 								}
  532: 							} else {
  533: 								memset(buf, 0, TFTP_BUF);
  534: 								tftp->th_opcode = htons(ERROR);
  535: 								tftp->th_code = htons(EBADID);
  536: 								sprintf(tftp->th_data, "Error:: in transfer #%d", seq);
  537: 								sendto(s, buf, strlen(tftp->th_data) + 4, 0, 
  538: 										(struct sockaddr*) &cli, sizeof cli);
  539: 								retry--;
  540: 							}
  541: 						}
  542: 						if (!retry) {
  543: 							close(f);
  544: 							unlink(szFName);
  545: 							syslog(LOG_ERR, "Error:: transfer aborted - timeout!");
  546: 						}
  547: 
  548: 						break;
  549: 					case RRQ:
  550: 						len -= 2;
  551: 						pos += 2;
  552: 						strlcpy(szFName, (char*) pos, MAX_STR);
  553: 						VERB(5) printf("Info(5):: Get filename %s\n", szFName);
  554: 						len -= strlen((char*) pos) + 1;
  555: 						pos += strlen((char*) pos) + 1;
  556: 						VERB(5) printf("Info(5):: Get mode %s len=%d\n", pos, len);
  557: 						if (strncmp((char*) pos, "octet", len)) {
  558: 							memset(buf, 0, TFTP_BUF);
  559: 							tftp->th_opcode = htons(ERROR);
  560: 							tftp->th_code = htons(EBADOP);
  561: 							strncpy(tftp->th_data, "Error:: mode not supported", 27);
  562: 							sendto(s, buf, 31, 0, (struct sockaddr*) &cli, sizeof cli);
  563: 							continue;
  564: 						}
  565: 						VERB(2) printf("Info(2):: Send file %s to %s\n", 
  566: 								szFName, inet_ntoa(cli.sin_addr));
  567: 
  568: 						f = open(szFName, O_RDONLY);
  569: 						if (f == -1) {
  570: 							memset(buf, 0, TFTP_BUF);
  571: 							tftp->th_opcode = htons(ERROR);
  572: 							switch (errno) {
  573: 								case EACCES:
  574: 								case EPERM:
  575: 									tftp->th_code = htons(EACCESS);
  576: 									break;
  577: 								case ENOENT:
  578: 									tftp->th_code = htons(ENOTFOUND);
  579: 									break;
  580: 								default:
  581: 									tftp->th_code = htons(ENOSPACE);
  582: 							}
  583: 							sprintf(tftp->th_data, "Error:: in file %s", 
  584: 									strerror(errno));
  585: 							sendto(s, buf, strlen(tftp->th_data) + 4, 0, 
  586: 									(struct sockaddr*) &cli, sizeof cli);
  587: 							continue;
  588: 						} else
  589: 							seq = 1;
  590: 
  591: 						for (retry = TFTP_RETRY; retry;) {
  592: 							tftp->th_opcode = htons(DATA);
  593: 							tftp->th_block = htons(seq);
  594: 							if ((len = read(f, tftp->th_data, SEGSIZE)) == -1) {
  595: 								syslog(LOG_ERR, "Error:: Can`t read from file %s\n", 
  596: 										szFName);
  597: 								close(f);
  598: 								break;
  599: 							} else
  600: 								sendto(s, buf, len + 4, 0, 
  601: 										(struct sockaddr*) &cli, sizeof cli);
  602: 
  603: 							FD_ZERO(&rfd);
  604: 							FD_SET(s, &rfd);
  605: 							if (select(s + 1, &rfd, NULL, NULL, &tv) < 1) {
  606: 								retry--;
  607: 								continue;
  608: 							}
  609: 							memset(buf, 0, TFTP_BUF);
  610: 							clilen = sizeof sin;
  611: 							if (recvfrom(s, buf, TFTP_BUF, 0, (struct sockaddr*) &rcv, 
  612: 										(socklen_t*) &clilen) == -1) {
  613: 								VERB(5) printf("Error:: in recvfrom #%d - %s\n", 
  614: 										errno, strerror(errno));
  615: 								retry--;
  616: 								continue;
  617: 							} else
  618: 								if (cli.sin_addr.s_addr != rcv.sin_addr.s_addr)
  619: 									continue;
  620: 
  621: 							VERB(5) printf("Info(5):: received opcode=%d block=%d seq=%d\n", 
  622: 									ntohs(tftp->th_opcode), ntohs(tftp->th_block), seq);
  623: 							if (ERROR == ntohs(tftp->th_opcode)) {
  624: 								syslog(LOG_ERR, "Error:: in tftp sending #%d - %s", 
  625: 										tftp->th_code, tftp->th_data);
  626: 								if (lseek(f, len * -1, SEEK_CUR) == -1) {
  627: 									syslog(LOG_ERR, "Error:: revert sending #%d - %s", 
  628: 											errno, strerror(errno));
  629: 									close(f);
  630: 									break;
  631: 								}
  632: 								retry--;
  633: 								continue;
  634: 							}
  635: 							if (ACK == ntohs(tftp->th_opcode) && 
  636: 									seq == ntohs(tftp->th_block)) {
  637: 								seq++;
  638: 								if (SEGSIZE > len) {
  639: 									close(f);
  640: 									syslog(LOG_INFO, "TFTP transfer complete to %s", 
  641: 											szFName);
  642: 									break;
  643: 								}
  644: 							} else {
  645: 								memset(buf, 0, TFTP_BUF);
  646: 								tftp->th_opcode = htons(ERROR);
  647: 								tftp->th_code = htons(EBADID);
  648: 								sprintf(tftp->th_data, "Error:: in transfer #%d", seq);
  649: 								sendto(s, buf, strlen(tftp->th_data) + 4, 0, 
  650: 										(struct sockaddr*) &cli, sizeof cli);
  651: 								retry--;
  652: 							}
  653: 						}
  654: 						if (!retry) {
  655: 							close(f);
  656: 							syslog(LOG_ERR, "Error:: transfer aborted - timeout!");
  657: 						}
  658: 
  659: 						break;
  660: 					case DATA:
  661: 						if (seq == 0xffff)
  662: 							VERB(5) printf("Error:: not specified operation!\n");
  663: 						break;
  664: 				}
  665: 			}
  666: 
  667: 			break;
  668: 	}
  669: 
  670: 
  671: 	close(s);
  672: 	return 0;
  673: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>