void inssort( void *base, uint32_t len, uint32_t esize, cmpfn_t cmp ) { uint32_t i,j; void *temp; temp = malloc(esize); if (!temp) { exit(EXIT_FAILURE); } if ( len <= 1 ) { return; } for ( i = 1; i < len; i++ ) { s_memcpy(temp, base + i*esize, esize); for ( j = 1; j <= i; j++ ) { if ( (*cmp)( temp, base + (i-j)*esize ) > 0 ) { break; } s_memcpy(base + (i-j+1)*esize, base + (i-j)*esize, esize); } s_memcpy(base + (i-j+1)*esize, temp, esize); dbgprintl(base, len, esize); } free(temp); }
void get_hdr(pkt *Pkt) { if (Pkt != NULL && Pkt->Hdr != NULL && Pkt->datagram != NULL) { s_memcpy(&(Pkt->Hdr->checksum), Pkt->datagram + HDR_CHECKSUM_OFFSET, sizeof(uint16_t)); s_memcpy(&(Pkt->Hdr->flag), Pkt->datagram + HDR_FLAG_OFFSET, sizeof(uint8_t)); // Pkt->Hdr->flag = ntohs(Pkt->Hdr->flag); s_memcpy(&(Pkt->Hdr->seq), Pkt->datagram + HDR_SEQ_OFFSET, sizeof(uint32_t)); Pkt->Hdr->seq = ntohl(Pkt->Hdr->seq); } }
void create_hdr(pkt *Pkt, uint32_t seq, uint8_t flag) { uint16_t n_checksum = 0; uint32_t n_seq = htonl(seq); if (Pkt != NULL) { memset(Pkt->datagram, 0, HDR_LEN); s_memcpy(Pkt->datagram + HDR_SEQ_OFFSET, &n_seq, sizeof(uint32_t)); s_memcpy(Pkt->datagram + HDR_FLAG_OFFSET, &flag, sizeof(uint8_t)); n_checksum = in_cksum((unsigned short *)Pkt->datagram, Pkt->datagram_len); s_memcpy(Pkt->datagram + HDR_CHECKSUM_OFFSET, &n_checksum, sizeof(uint16_t)); } else { fprintf(stderr, "create_hdr Pkt is NULL\n"); } }
/* tfsread(): * Similar to a standard read call to a file. * MONLIB NOTICE: this function is accessible through monlib.c. */ int tfsread(int fd, char *buf, int cnt) { struct tfsdat *tdat; uchar *from; if (tfsTrace > 1) printf("tfsread(%d,0x%lx,%d)\n",fd,(ulong)buf,cnt); /* Verify valid range of incoming file descriptor. */ if ((cnt < 1) || (fd < 0) || (fd >= TFS_MAXOPEN)) return(TFSERR_BADARG); tdat = &tfsSlots[fd]; /* Make sure the file pointed to by the incoming descriptor is active. */ if (tdat->offset == -1) return(TFSERR_BADFD); if (tdat->offset >= tdat->hdr.filsize) return(TFSERR_EOF); from = (uchar *) tdat->base + tdat->offset; /* If request size is within the range of the file and current * then copy the data to the requestors buffer, increment offset * and return the count. */ if ((tdat->offset + cnt) <= tdat->hdr.filsize) { if (s_memcpy((char *)buf, (char *)from, cnt,0,0) != 0) return(TFSERR_MEMFAIL); } /* If request size goes beyond the size of the file, then copy * to the end of the file and return that smaller count. */ else { cnt = tdat->hdr.filsize - tdat->offset; if (s_memcpy((char *)buf, (char *)from, cnt, 0, 0) != 0) return(TFSERR_MEMFAIL); } tdat->offset += cnt; return(cnt); }
void CStringBuffer::_alloc_Buffer2(dword size, dword lenCh) { CPointer buffer = _alloc_Buffer(size); if ( _string ) { s_memcpy(buffer, _string, lenCh * szchar); _free_Buffer(); } _string = buffer; }
void create_pkt(pkt *Pkt, uint8_t flag, uint32_t seq, uint8_t *data, uint32_t data_len) { if (Pkt != NULL && ((data == NULL && data_len == 0)||(data != NULL && data_len > 0)))//MAGICNUM { Pkt->data_len = data_len; Pkt->datagram_len = HDR_LEN + data_len; memset(Pkt->datagram, 0,Pkt->datagram_len); if (data != NULL) s_memcpy(Pkt->data, data, Pkt->data_len); create_hdr(Pkt, seq, flag); get_hdr(Pkt); } else { fprintf(stderr, "creat_pkt invalid arguments\n"); } }
sock *client_sock(char *remote_address, uint16_t remote_port, uint32_t buffsize, uint32_t window_size) { struct hostent *hp; sock *Client = s_malloc(sizeof(sock)); Client->sock = s_socket(SOCK_DOMAIN, SOCK_TYPE, DEFAULT_PROTOCOL); Client->buffsize = buffsize; Client->window_size = window_size; //Remote Socket Address Set Up Client->remote.sin_family = SOCK_DOMAIN; hp = s_gethostbyname(remote_address); s_memcpy(&(Client->remote.sin_addr), hp->h_addr, hp->h_length); Client->remote.sin_port = htons(remote_port); Client->seq = 0; return Client; }
/* tfswrite(): * Similar to a standard write call to a file. * MONLIB NOTICE: this function is accessible through monlib.c. */ int tfswrite(int fd, char *buf, int cnt) { struct tfsdat *tdat; if (tfsTrace > 1) printf("tfswrite(%d,0x%lx,%d)\n", fd,(ulong)buf,cnt); /* Verify valid range of incoming file descriptor. */ if ((cnt < 1) || (fd < 0) || (fd >= TFS_MAXOPEN)) return(TFSERR_BADARG); /* Make sure the file pointed to by the incoming descriptor is active. */ if (tfsSlots[fd].offset == -1) return(TFSERR_BADARG); tdat = &tfsSlots[fd]; /* Make sure file is not opened as read-only */ if (tdat->flagmode & TFS_RDONLY) return(TFSERR_RDONLY); if (s_memcpy((char *)tdat->base+tdat->offset,(char *)buf,cnt,0,0) != 0) return(TFSERR_MEMFAIL); tdat->offset += cnt; /* If new offset is greater than current high-water point, then * adjust the high water point so that it is always reflecting the * highest offset into which the file has had some data written. */ if (tdat->offset > tdat->hwp) tdat->hwp = tdat->offset; return(TFS_OKAY); }
int ImgFileCheck(char *pIn, int inLen, int type, char **ppOut, int *pOutLen) { char *p; char ImgFileFlag[] = "NRCA"; char CodeFlag[] = "CODE"; char DBDataFlag[] = "DBDT"; char WebFileFlag[] = "WEBF"; char FontFlag[] = "FONT"; char Hash[16]; int fLen; if (inLen < (50+32)) { return -1; } //跳过前面的50字节的MAC+KEY+SN p = pIn + 50; //判断文件头 if (s_memcmp(p, (char *)ImgFileFlag, 4) != 0) { return -1; } p += 4; //判断文件版本 if (p[0] != 0x01) { return -1; } p ++; //跳过3字节保留字 p += 3; //判断文件类型 if (! ( ((s_memcmp(p, CodeFlag, 4) == 0) && (type == IMGFILETYPE_CODE)) || ((s_memcmp(p, DBDataFlag, 4) == 0) && (type == IMGFILETYPE_DBDATA)) || ((s_memcmp(p, WebFileFlag, 4) == 0) && (type == IMGFILETYPE_WEBFILE)) || ((s_memcmp(p, FontFlag, 4) == 0) && (type == IMGFILETYPE_FONT)) ) ) { return -1; } p += 4; //判断文件长度 fLen = ((unsigned char)p[0] << 24) + ((unsigned char)p[1] << 16) + ((unsigned char)p[2] << 8) + ((unsigned char)p[3] << 0); if (fLen > (inLen-50)) { return -1; } p += 4; s_memcpy(Hash, p, 16); s_memset(p, 0, 16); MD5_Init (&context); MD5_Update (&context, (unsigned char *)pIn, fLen+50); MD5_Final ((unsigned char *)digest, &context); if (s_memcmp(Hash, digest, 16) != 0) { return -1; } *ppOut = p + 16; *pOutLen = fLen - 32; return 0; }
int ns__getClientUpdate(struct soap *soap, struct clientUpdateInfoRequest sClientUpdateInfo, struct clientUpdateResponse* lpsResponse) { unsigned int er = erSuccess; ClientVersion sCurrentVersion = {0}; ClientVersion sLatestVersion; unsigned int ulLicenseResponse = 0; unsigned char *lpLicenseResponse = NULL; ECLicenseClient *lpLicenseClient = NULL; std::string strClientMSIName; std::string strPath; FILE *fd = NULL; int res; unsigned int ulUserID = 0; ECSession *lpecSession = NULL; ECDatabase *lpDatabase = NULL; std::string strCurVersion; std::string strLatestVersion; std::string strQuery; time_t tNow = 0; char *lpszClientUpdatePath = g_lpConfig->GetSetting("client_update_path"); unsigned int ulLogLevel = atoui(g_lpConfig->GetSetting("client_update_log_level")); if (!parseBool(g_lpConfig->GetSetting("client_update_enabled"))) { // do not set on high loglevel, since by default the client updater is installed, and this will be quite often in your log g_lpLogger->Log(EC_LOGLEVEL_NOTICE, "Client update: trackid: 0x%08X, Config option 'client_update_enabled' has disabled this feature.", sClientUpdateInfo.ulTrackId); er = ZARAFA_E_NO_SUPPORT; goto exit; } // setup soap soap_set_imode(soap, SOAP_IO_KEEPALIVE | SOAP_C_UTFSTRING | SOAP_ENC_ZLIB | SOAP_ENC_MTOM); soap_set_omode(soap, SOAP_IO_KEEPALIVE | SOAP_C_UTFSTRING | SOAP_ENC_ZLIB | SOAP_ENC_MTOM | SOAP_IO_CHUNK); if (!lpszClientUpdatePath || lpszClientUpdatePath[0] == 0) { g_lpLogger->Log(EC_LOGLEVEL_ERROR, "Client update: trackid: 0x%08X, The configuration field 'client_update_path' is empty.", sClientUpdateInfo.ulTrackId); er = ZARAFA_E_NO_ACCESS; goto exit; } er = g_lpSessionManager->CreateSessionInternal(&lpecSession); if(er != erSuccess) goto exit; // Lock the session lpecSession->Lock(); er = lpecSession->GetDatabase(&lpDatabase); if (er != erSuccess) goto exit; //@TODO change loglevel? g_lpLogger->Log(EC_LOGLEVEL_ERROR, "Client update: trackid: 0x%08X, computername: %s, username: %s, clientversion: %s, windowsversion: %s, iplist: %s, soapip: %s", sClientUpdateInfo.ulTrackId, (sClientUpdateInfo.szComputerName) ? sClientUpdateInfo.szComputerName : "-", (sClientUpdateInfo.szUsername) ? sClientUpdateInfo.szUsername : "******", (sClientUpdateInfo.szClientVersion) ? sClientUpdateInfo.szClientVersion : "-", (sClientUpdateInfo.szWindowsVersion) ? sClientUpdateInfo.szWindowsVersion : "-", (sClientUpdateInfo.szClientIPList) ? sClientUpdateInfo.szClientIPList : "-", PrettyIP(soap->ip).c_str() ); if (!sClientUpdateInfo.szComputerName) sClientUpdateInfo.szComputerName = ""; //Client has no name? if(!sClientUpdateInfo.szUsername) { er = ZARAFA_E_NO_ACCESS; g_lpLogger->Log(EC_LOGLEVEL_ERROR, "Client update: trackid: 0x%08X, Client did not send a username", sClientUpdateInfo.ulTrackId); } // validate user name er = lpecSession->GetUserManagement()->SearchObjectAndSync(sClientUpdateInfo.szUsername, 0x01/*EMS_AB_ADDRESS_LOOKUP*/, &ulUserID); if (er != erSuccess) { er = ZARAFA_E_NO_ACCESS; g_lpLogger->Log(EC_LOGLEVEL_ERROR, "Client update: trackid: 0x%08X, unknown username '%s'", sClientUpdateInfo.ulTrackId, sClientUpdateInfo.szUsername); } if(lpecSession->GetUserManagement()->IsInternalObject(ulUserID)) { er = ZARAFA_E_NO_ACCESS; g_lpLogger->Log(EC_LOGLEVEL_ERROR, "Client update: trackid: 0x%08X, Wrong user data. User name '%s' is a reserved user", sClientUpdateInfo.ulTrackId, sClientUpdateInfo.szUsername); goto exit; } // Check if the user connect to the right server, else redirect if (lpecSession->GetSessionManager()->IsDistributedSupported() ) { objectdetails_t sUserDetails; er = lpecSession->GetUserManagement()->GetObjectDetails(ulUserID, &sUserDetails); if (er != erSuccess) goto exit; /* Check if this is the correct server */ string strServerName = sUserDetails.GetPropString(OB_PROP_S_SERVERNAME); if (strServerName.empty()) { g_lpLogger->Log(EC_LOGLEVEL_ERROR, "Client update: trackid: 0x%08X, User '%s' has no default server", sClientUpdateInfo.ulTrackId, sClientUpdateInfo.szUsername); er = ZARAFA_E_NO_ACCESS; goto exit; } if (stricmp(strServerName.c_str(), g_lpSessionManager->GetConfig()->GetSetting("server_name")) != 0) { string strServerPath; er = GetBestServerPath(soap, lpecSession, strServerName, &strServerPath); if (er != erSuccess) goto exit; lpsResponse->lpszServerPath = s_strcpy(soap, strServerPath.c_str());// Server Path must always utf8 (also in 6.40.x) g_lpSessionManager->GetLogger()->Log(EC_LOGLEVEL_INFO, "Client update: trackid: 0x%08X, User '%s' is redirected to '%s'", sClientUpdateInfo.ulTrackId, sClientUpdateInfo.szUsername, lpsResponse->lpszServerPath); g_lpStatsCollector->Increment(SCN_REDIRECT_COUNT, 1); er = ZARAFA_E_UNABLE_TO_COMPLETE; goto exit; } } lpLicenseClient = new ECLicenseClient(g_lpConfig->GetSetting("license_socket"), atoui(g_lpConfig->GetSetting("license_timeout"))); er = lpLicenseClient->Auth(sClientUpdateInfo.sLicenseReq.__ptr, sClientUpdateInfo.sLicenseReq.__size, &lpLicenseResponse, &ulLicenseResponse); if (er != erSuccess) { g_lpLogger->Log(EC_LOGLEVEL_ERROR, "Client update: trackid: 0x%08X, Invalid license request, error: 0x%08X.", sClientUpdateInfo.ulTrackId, er); goto exit; } if (sClientUpdateInfo.szClientVersion == NULL || sClientUpdateInfo.szClientVersion[0] == '\0') { g_lpLogger->Log(EC_LOGLEVEL_INFO, "Client update: trackid: 0x%08X, The client did not sent the current version number.", sClientUpdateInfo.ulTrackId); } else if (!GetVersionFromString(sClientUpdateInfo.szClientVersion, &sCurrentVersion)) { g_lpLogger->Log(EC_LOGLEVEL_ERROR, "Client update: trackid: 0x%08X, Failed in getting version from input data.", sClientUpdateInfo.ulTrackId); goto exit; //@fixme can we give the latest? } if (!GetLatestVersionAtServer(lpszClientUpdatePath, sClientUpdateInfo.ulTrackId, &sLatestVersion)) { g_lpLogger->Log(EC_LOGLEVEL_ERROR, "Client update: trackid: 0x%08X, No updates found on server.", sClientUpdateInfo.ulTrackId); er = ZARAFA_E_NO_ACCESS; goto exit; } res = CompareVersions(sCurrentVersion, sLatestVersion); if (res == 0) { g_lpLogger->Log(EC_LOGLEVEL_INFO, "Client update: trackid: 0x%08X, Client already has the latest version.", sClientUpdateInfo.ulTrackId); goto ok; } else if (res > 0) { g_lpLogger->Log(EC_LOGLEVEL_INFO, "Client update: trackid: 0x%08X, Client has newer version than server.", sClientUpdateInfo.ulTrackId); goto ok; } if (!GetClientMSINameFromVersion(sLatestVersion, &strClientMSIName)) { g_lpLogger->Log(EC_LOGLEVEL_INFO, "Client update: trackid: 0x%08X, No suitable version available.", sClientUpdateInfo.ulTrackId); er = ZARAFA_E_NO_ACCESS; goto exit; } if (ConvertAndValidatePath(lpszClientUpdatePath, strClientMSIName, &strPath) != true) { g_lpLogger->Log(EC_LOGLEVEL_ERROR, "Client update: trackid: 0x%08X, Error in path conversion and validation.", sClientUpdateInfo.ulTrackId); er = ZARAFA_E_NO_ACCESS; goto exit; } fd = fopen(strPath.c_str(), "rb"); if (!fd) { g_lpLogger->Log(EC_LOGLEVEL_ERROR, "Client update: trackid: 0x%08X, Path not found %s.", sClientUpdateInfo.ulTrackId, strPath.c_str()); er = ZARAFA_E_NO_ACCESS; goto exit; } // Update auto update client status VersionToString(sCurrentVersion, &strCurVersion); VersionToString(sLatestVersion, &strLatestVersion); tNow = time(NULL); // Get current time strQuery = "REPLACE INTO clientupdatestatus(userid, trackid, updatetime, currentversion, latestversion, computername, status) VALUES ("+ stringify(ulUserID)+", "+stringify(sClientUpdateInfo.ulTrackId)+", FROM_UNIXTIME("+ stringify(tNow) + "), \"" + strCurVersion + "\", \"" + strLatestVersion + "\", \"" + lpDatabase->Escape(sClientUpdateInfo.szComputerName).c_str()+"\", "+ stringify(UPDATE_STATUS_PENDING) + ")"; // ignore error in database tracking, SQL error logged in server, still send new client lpDatabase->DoUpdate(strQuery); soap->fmimereadopen = &mime_file_read_open; soap->fmimeread = &mime_file_read; soap->fmimereadclose = &mime_file_read_close; // Setup the MTOM Attachments lpsResponse->sStreamData.xop__Include.__ptr = (unsigned char*)fd; lpsResponse->sStreamData.xop__Include.__size = 0; lpsResponse->sStreamData.xop__Include.type = s_strcpy(soap, "application/binary"); lpsResponse->sStreamData.xop__Include.id = s_strcpy(soap, "zarafaclient"); g_lpLogger->Log(EC_LOGLEVEL_ERROR, "Client update: trackid: 0x%08X, Sending new installer %s", sClientUpdateInfo.ulTrackId, strClientMSIName.c_str()); ok: // Client is already up to date lpsResponse->sLicenseResponse.__size = ulLicenseResponse; lpsResponse->sLicenseResponse.__ptr = (unsigned char *)s_memcpy(soap, (const char *)lpLicenseResponse, ulLicenseResponse); lpsResponse->ulLogLevel = ulLogLevel; // 0 = none, 1 = on errors, 2 = always exit: if(lpecSession) { lpecSession->Unlock(); g_lpSessionManager->RemoveSessionInternal(lpecSession); } lpsResponse->er = er; if (lpLicenseResponse) delete [] lpLicenseResponse; if (lpLicenseClient) delete lpLicenseClient; if (er && fd) fclose(fd); return SOAP_OK; }
/* _tfsclean(): * This is an alternative to the complicated defragmentation above. * It simply scans through the file list and copies all valid files * to RAM; then flash is erased and the RAM is copied back to flash. * <<< WARNING >>> * THIS FUNCTION SHOULD NOT BE INTERRUPTED AND IT WILL BLOW AWAY * ANY APPLICATION CURRENTLY IN CLIENT RAM SPACE. */ int _tfsclean(TDEV *tdp, int notused, int verbose) { ulong appramstart; TFILE *tfp, *lasttfp; uchar *tbuf, *cp1, *cp2; int dtot, nfadd, len, err, chkstat; if (TfsCleanEnable < 0) return(TFSERR_CLEANOFF); appramstart = getAppRamStart(); /* Determine how many "dead" files exist. */ dtot = 0; tfp = (TFILE *)tdp->start; while(validtfshdr(tfp)) { if (!TFS_FILEEXISTS(tfp)) dtot++; tfp = nextfp(tfp,tdp); } if (dtot == 0) return(TFS_OKAY); printf("TFS device '%s' non-powersafe defragmentation\n",tdp->prefix); tbuf = (uchar *)appramstart; lasttfp = tfp = (TFILE *)(tdp->start); nfadd = tdp->start; while(validtfshdr(tfp)) { if (TFS_FILEEXISTS(tfp)) { len = TFS_SIZE(tfp) + sizeof(struct tfshdr); if (len % TFS_FSIZEMOD) len += TFS_FSIZEMOD - (len % TFS_FSIZEMOD); nfadd += len; if (s_memcpy((char *)tbuf,(char *)tfp,len,0,0) != 0) return(TFSERR_MEMFAIL); ((struct tfshdr *)tbuf)->next = (struct tfshdr *)nfadd; tbuf += len; } lasttfp = tfp; tfp = nextfp(tfp,tdp); } /* We've now copied all of the active files from flash to ram. * Now we want to see how much of the flash space needs to be * erased. We only need to erase the sectors that have changed... */ cp1 = (uchar *)tdp->start; cp2 = (uchar *)appramstart; while(cp2 < tbuf) { if (*cp1 != *cp2) break; cp1++; cp2++; } #if INCLUDE_FLASH if ((cp2 != tbuf) || (!TFS_FILEEXISTS(lasttfp))) { int first, last; if (addrtosector(cp1,&first,0,0) == -1) return(TFSERR_FLASHFAILURE); if (addrtosector((uchar *)tdp->end,&last,0,0) == -1) return(TFSERR_FLASHFAILURE); printf("Erasing sectors %d-%d...\n",first,last); while(first<last) { if (flasherase(first++) == 0) return(TFSERR_FLASHFAILURE); } } #endif /* Copy data placed in RAM back to flash: */ printf("Restoring flash...\n"); if (TFS_DEVTYPE_ISRAM(tdp)) { memcpy((char *)(tdp->start),(char *)appramstart, (tbuf-(uchar*)appramstart)); } else { #if INCLUDE_FLASH err = AppFlashWrite((uchar *)(tdp->start),(uchar *)appramstart, (tbuf-(uchar*)appramstart)); if (err < 0) #endif return(TFSERR_FLASHFAILURE); } /* All defragmentation is done, so verify sanity of files... */ chkstat = tfscheck(tdp,verbose); return(chkstat); }
/* _tfsclean(): * This is an alternative to the complicated defragmentation above. * It simply scans through the file list and copies all valid files * to RAM; then flash is erased and the RAM is copied back to flash. * <<< WARNING >>> * THIS FUNCTION SHOULD NOT BE INTERRUPTED AND IT WILL BLOW AWAY * ANY APPLICATION CURRENTLY IN CLIENT RAM SPACE. */ int _tfsclean(TDEV *tdp, int notused, int verbose) { TFILE *tfp; uchar *tbuf; ulong appramstart; int dtot, nfadd, len, err, chkstat; if (TfsCleanEnable < 0) return(TFSERR_CLEANOFF); appramstart = getAppRamStart(); /* Determine how many "dead" files exist. */ dtot = 0; tfp = (TFILE *)tdp->start; while(validtfshdr(tfp)) { if (!TFS_FILEEXISTS(tfp)) dtot++; tfp = nextfp(tfp,tdp); } if (dtot == 0) return(TFS_OKAY); printf("Reconstructing device %s with %d dead file%s removed...\n", tdp->prefix, dtot,dtot>1 ? "s":""); tbuf = (char *)appramstart; tfp = (TFILE *)(tdp->start); nfadd = tdp->start; while(validtfshdr(tfp)) { if (TFS_FILEEXISTS(tfp)) { len = TFS_SIZE(tfp) + sizeof(struct tfshdr); if (len % TFS_FSIZEMOD) len += TFS_FSIZEMOD - (len % TFS_FSIZEMOD); nfadd += len; if (s_memcpy(tbuf,(uchar *)tfp,len,0,0) != 0) return(TFSERR_MEMFAIL); ((struct tfshdr *)tbuf)->next = (struct tfshdr *)nfadd; tbuf += len; } tfp = nextfp(tfp,tdp); } /* Erase the flash device: */ err = _tfsinit(tdp); if (err != TFS_OKAY) return(err); /* Copy data placed in RAM back to flash: */ err = AppFlashWrite((ulong *)(tdp->start),(ulong *)appramstart, (tbuf-(uchar*)appramstart)); if (err < 0) return(TFSERR_FLASHFAILURE); /* All defragmentation is done, so verify sanity of files... */ chkstat = tfscheck(tdp,verbose); return(chkstat); }
/* tfsopen(): * Open a file for reading or creation. If file is opened for writing, * then the caller must provide a RAM buffer pointer to be used for * the file storage until it is transferred to flash by tfsclose(). * Note that the "buf" pointer is only needed for opening a file for * creation or append (writing). * MONLIB NOTICE: this function is accessible through monlib.c. */ int tfsopen(char *file,long flagmode,char *buf) { register int i; int errno, retval; long fmode; TFILE *fp; struct tfsdat *slot; errno = TFS_OKAY; fmode = flagmode & (TFS_RDONLY | TFS_APPEND | TFS_CREATE | TFS_CREATERM); /* See if file exists... */ fp = tfsstat(file); /* If file exists, do a crc32 on the data. * If the file is in-place-modifiable, then the only legal flagmode * is TFS_RDONLY. Plus, in this case, the crc32 test is skipped. */ if (fp) { if (!((fmode == TFS_RDONLY) && (fp->flags & TFS_IPMOD))) { if (crc32((unsigned char *)TFS_BASE(fp),fp->filsize) != fp->filcrc) { retval = TFSERR_BADCRC; goto done; } } } /* This switch verifies... * - that the file exists if TFS_RDONLY or TFS_APPEND * - that the file does not exist if TFS_CREATE */ switch(fmode) { case TFS_RDONLY: /* Read existing file only, no change to file at all. */ if (!fp) { if (_tfsstat(file,0)) errno = TFSERR_LINKERROR; else errno = TFSERR_NOFILE; } else { if ((fp->flags & TFS_UNREAD) && (TFS_USRLVL(fp) > getUsrLvl())) errno = TFSERR_USERDENIED; } break; case TFS_APPEND: /* Append to the end of the current file. */ if (!fp) errno = TFSERR_NOFILE; else { if (TFS_USRLVL(fp) > getUsrLvl()) errno = TFSERR_USERDENIED; } break; case TFS_CREATERM: /* Create a new file, allow tfsadd() to remove */ fmode = TFS_CREATE; /* it if it exists. */ break; case TFS_CREATE: /* Create a new file, error if it exists. */ if (fp) errno = TFSERR_FILEEXISTS; break; case (TFS_APPEND|TFS_CREATE): /* If both mode bits are set, clear one */ if (fp) { /* based on the presence of the file. */ if (TFS_USRLVL(fp) > getUsrLvl()) errno = TFSERR_USERDENIED; fmode = TFS_APPEND; } else { fmode = TFS_CREATE; } break; default: errno = TFSERR_BADARG; break; } if (errno != TFS_OKAY) { retval = errno; goto done; } /* Find an empty slot... */ slot = tfsSlots; for (i=0;i<TFS_MAXOPEN;i++,slot++) { if (slot->offset == -1) break; } /* Populate the slot structure if a slot is found to be * available... */ if (i < TFS_MAXOPEN) { retval = i; slot->hwp = 0; slot->offset = 0; slot->flagmode = fmode; if (fmode & TFS_CREATE) { strncpy(slot->hdr.name,file,TFSNAMESIZE); slot->flagmode |= (flagmode & TFS_FLAGMASK); slot->base = (uchar *)buf; } else if (fmode & TFS_APPEND) { memcpy((char *)&slot->hdr,(char *)fp,sizeof(struct tfshdr)); if (s_memcpy((char *)buf,(char *)(TFS_BASE(fp)), fp->filsize,0,0) != 0) { retval = TFSERR_MEMFAIL; goto done; } slot->flagmode = fp->flags; slot->flagmode |= TFS_APPEND; slot->base = (uchar *)buf; slot->hwp = fp->filsize; slot->offset = fp->filsize; } else { slot->base = (uchar *) (TFS_BASE(fp)); memcpy((char *)&slot->hdr,(char *)fp,sizeof(struct tfshdr)); } } else { retval = TFSERR_NOSLOT; } done: if (tfsTrace > 0) printf("tfsopen(%s,0x%lx,0x%lx)=%d\n",file,flagmode,(ulong)buf,retval); return(retval); }