File:  [ELWIX - Embedded LightWeight unIX -] / embedtools / src / Attic / upd.c
Revision 1.1.2.10: download - view: text, annotated - select for diffs - revision graph
Wed Jun 8 09:15:32 2011 UTC (13 years, 1 month ago) by misho
Branches: tools1_0
openbsd fix

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

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