int DoRecursiveEditFiles(char *name,int level,struct Edit *ptr,struct stat *sb) { DIR *dirh; struct dirent *dirp; char pcwd[CF_BUFSIZE]; struct stat statbuf; int goback; if (level == -1) { return false; } Debug("RecursiveEditFiles(%s)\n",name); if (!DirPush(name,sb)) { return false; } if ((dirh = opendir(".")) == NULL) { return true; } for (dirp = readdir(dirh); dirp != NULL; dirp = readdir(dirh)) { if (!SensibleFile(dirp->d_name,name,NULL)) { continue; } if (IgnoreFile(name,dirp->d_name,ptr->ignores)) { continue; } strcpy(pcwd,name); /* Assemble pathname */ AddSlash(pcwd); if (BufferOverflow(pcwd,dirp->d_name)) { return true; } strcat(pcwd,dirp->d_name); if (!FileObjectFilter(pcwd,&statbuf,ptr->filters,editfiles)) { Verbose("Skipping filtered file %s\n",pcwd); continue; } if (TRAVLINKS) { if (lstat(dirp->d_name,&statbuf) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"Can't stat %s\n",pcwd); CfLog(cferror,OUTPUT,"stat"); continue; } if (S_ISLNK(statbuf.st_mode) && (statbuf.st_mode != getuid())) { snprintf(OUTPUT,CF_BUFSIZE,"File %s is an untrusted link. cfagent will not follow it with a destructive operation (tidy)",pcwd); continue; } if (stat(dirp->d_name,&statbuf) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"RecursiveCheck was working on %s when this happened:\n",pcwd); CfLog(cferror,OUTPUT,"stat"); continue; } } else { if (lstat(dirp->d_name,&statbuf) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"RecursiveCheck was working in %s when this happened:\n",pcwd); CfLog(cferror,OUTPUT,"lstat"); continue; } } if (S_ISDIR(statbuf.st_mode)) { if (IsMountedFileSystem(&statbuf,pcwd,level)) { continue; } else { if ((ptr->recurse > 1) || (ptr->recurse == CF_INF_RECURSE)) { goback = DoRecursiveEditFiles(pcwd,level-1,ptr,&statbuf); DirPop(goback,name,sb); } else { WrapDoEditFile(ptr,pcwd); } } } else { WrapDoEditFile(ptr,pcwd); } } closedir(dirh); return true; }
int LinkChildFiles(char *from,char *to,char type, struct Item *inclusions, struct Item *exclusions, struct Item *copy, short nofile, struct Link *ptr) { DIR *dirh; struct dirent *dirp; char pcwdto[CF_BUFSIZE],pcwdfrom[CF_BUFSIZE]; struct stat statbuf; int (*linkfiles)(char *from, char *to, struct Item *inclusions, struct Item *exclusions, struct Item *copy, short int nofile, struct Link *ptr); Debug("LinkChildFiles(%s,%s)\n",from,to); if (stat(to,&statbuf) == -1) { /* no error warning, since the higher level routine uses this */ return(false); } if ((dirh = opendir(to)) == NULL) { snprintf(g_output,CF_BUFSIZE*2,"Can't open directory %s\n",to); CfLog(cferror,g_output,"opendir"); return false; } for (dirp = readdir(dirh); dirp != NULL; dirp = readdir(dirh)) { if (!SensibleFile(dirp->d_name,to,NULL)) { continue; } /* Assemble pathnames */ strcpy(pcwdto,to); AddSlash(pcwdto); if (BufferOverflow(pcwdto,dirp->d_name)) { FatalError("Can't build filename in LinkChildFiles"); } strcat(pcwdto,dirp->d_name); strcpy(pcwdfrom,from); AddSlash(pcwdfrom); if (BufferOverflow(pcwdfrom,dirp->d_name)) { FatalError("Can't build filename in LinkChildFiles"); } strcat(pcwdfrom,dirp->d_name); switch (type) { case 's': linkfiles = LinkFiles; break; case 'r': linkfiles = RelativeLink; break; case 'a': linkfiles = AbsoluteLink; break; case 'h': linkfiles = HardLinkFiles; break; default: printf("Internal error, link type was [%c]\n",type); continue; } (*linkfiles)(pcwdfrom,pcwdto,inclusions,exclusions,copy,nofile,ptr); } closedir(dirh); return true; }
int RelativeLink(char *from, char *to, struct Item *inclusions, struct Item *exclusions, struct Item *copy, short nofile, struct Link *ptr) { char *sp, *commonto, *commonfrom; char buff[CF_BUFSIZE],linkto[CF_BUFSIZE]; int levels=0; Debug2("RelativeLink(%s,%s)\n",from,to); if (*to == '.') { return LinkFiles(from,to,inclusions,exclusions,copy,nofile,ptr); } if (!CompressPath(linkto,to)) { snprintf(g_output,CF_BUFSIZE*2,"Failed to link %s to %s\n",from,to); CfLog(cferror,g_output,""); return false; } commonto = linkto; commonfrom = from; if (strcmp(commonto,commonfrom) == 0) { CfLog(cferror,"Can't link file to itself!\n",""); snprintf(g_output,CF_BUFSIZE*2,"(%s -> %s)\n",from,to); CfLog(cferror,g_output,""); return false; } while (*commonto == *commonfrom) { commonto++; commonfrom++; } while (!((*commonto == '/') && (*commonfrom == '/'))) { commonto--; commonfrom--; } commonto++; Debug("Commonto = %s, common from = %s\n",commonto,commonfrom); for (sp = commonfrom; *sp != '\0'; sp++) { if (*sp == '/') { levels++; } } Debug("LEVELS = %d\n",levels); memset(buff,0,CF_BUFSIZE); strcat(buff,"./"); while(--levels > 0) { if (BufferOverflow(buff,"../")) { return false; } strcat(buff,"../"); } if (BufferOverflow(buff,commonto)) { return false; } strcat(buff,commonto); return LinkFiles(from,buff,inclusions,exclusions,copy,nofile,ptr); }
void LinkChildren(char *path,char type,struct stat *rootstat,uid_t uid,gid_t gid, struct Item *inclusions,struct Item *exclusions,struct Item *copy, short nofile,struct Link *ptr) { char *sp; char lastlink[CF_BUFSIZE],server[CF_BUFSIZE]; char from[CF_BUFSIZE],to[CF_BUFSIZE]; char relpath[CF_BUFSIZE]; char odir[CF_BUFSIZE]; DIR *dirh; struct dirent *dirp; struct stat statbuf; int matched = false; int (*linkfiles)(char *from, char *to, struct Item *inclusions, struct Item *exclusions, struct Item *copy, short int nofile, struct Link *ptr); Debug("LinkChildren(%s)\n",path); if (! S_ISDIR(rootstat->st_mode)) { snprintf(g_output,CF_BUFSIZE*2, "File %s is not a directory: it has no children to link!\n", path); CfLog(cferror,g_output,""); return; } Verbose("Linking the children of %s\n",path); for (sp = path+strlen(path); sp != path-1; sp--) { if (*(sp-1) == '/') { relpath[0] = '\0'; sscanf(sp,"%[^/]%s", lastlink,relpath); if (MatchAFileSystem(server,lastlink)) { strcpy(odir,server); if (BufferOverflow(odir,relpath)) { FatalError("culprit: LinkChildren()"); } strcat(odir,relpath); if ((dirh = opendir(odir)) == NULL) { snprintf(g_output,CF_BUFSIZE*2, "Can't open directory %s\n",path); CfLog(cferror,g_output,"opendir"); return; } for (dirp = readdir(dirh); dirp != NULL; dirp = readdir(dirh)) { if (!SensibleFile(dirp->d_name,odir,NULL)) { continue; } strcpy(from,path); AddSlash(from); if (BufferOverflow(from,dirp->d_name)) { FatalError("culprit: LinkChildren()"); } strcat(from,dirp->d_name); strcpy(to,odir); AddSlash(to); if (BufferOverflow(to,dirp->d_name)) { FatalError("culprit: LinkChildren()"); } strcat(to,dirp->d_name); Debug2("LinkChild from = %s to = %s\n",from,to); if (stat(to,&statbuf) == -1) { continue; } else { switch (type) { case 's': linkfiles = LinkFiles; break; case 'r': linkfiles = RelativeLink; break; case 'a': linkfiles = AbsoluteLink; break; case 'h': linkfiles = HardLinkFiles; break; default: snprintf(g_output,CF_BUFSIZE*2, "Internal error, link type was [%c]\n",type); CfLog(cferror,g_output,""); continue; } matched = (*linkfiles)(from,to,inclusions, exclusions,copy,nofile,ptr); if (matched && !g_dontdo) { chown(from,uid,gid); } } } if (matched) return; } } } snprintf(g_output,CF_BUFSIZE*2, "Couldn't link the children of %s to anything because no\n",path); CfLog(cferror,g_output,""); snprintf(g_output, CF_BUFSIZE*2, "file system was found to " "mirror it in the defined binservers list.\n"); CfLog(cferror,g_output,""); }
int RecursiveLink(struct Link *lp,char *from,char *to,int maxrecurse) { struct stat statbuf; DIR *dirh; struct dirent *dirp; char newfrom[CF_BUFSIZE]; char newto[CF_BUFSIZE]; void *bug_check; int (*linkfiles)(char *from, char *to, struct Item *inclusions, struct Item *exclusions, struct Item *copy, short int nofile, struct Link *ptr); /* reached depth limit */ if (maxrecurse == 0) { Debug2("MAXRECURSE ran out, quitting at level %s with " "endlist = %d\n", to, lp->next); return false; } if (IgnoreFile(to,"",lp->ignores)) { Verbose("%s: Ignoring directory %s\n",g_vprefix,from); return false; } /* Check for root dir */ if (strlen(to) == 0) { to = "/"; } bug_check = lp->next; if ((dirh = opendir(to)) == NULL) { snprintf(g_output,CF_BUFSIZE*2,"Can't open directory [%s]\n",to); CfLog(cferror,g_output,"opendir"); return false; } if (lp->next != bug_check) { printf("%s: solaris BSD compat bug: opendir wrecked " "the heap memory!!", g_vprefix); printf("%s: in copy to %s, using workaround...\n",g_vprefix,from); lp->next = bug_check; } for (dirp = readdir(dirh); dirp != NULL; dirp = readdir(dirh)) { if (!SensibleFile(dirp->d_name,to,NULL)) { continue; } if (IgnoreFile(to,dirp->d_name,lp->ignores)) { continue; } /* Assemble pathname */ strcpy(newfrom,from); AddSlash(newfrom); strcpy(newto,to); AddSlash(newto); if (BufferOverflow(newfrom,dirp->d_name)) { closedir(dirh); return true; } strcat(newfrom,dirp->d_name); if (BufferOverflow(newto,dirp->d_name)) { closedir(dirh); return true; } strcat(newto,dirp->d_name); if (g_travlinks) { if (stat(newto,&statbuf) == -1) { snprintf(g_output,CF_BUFSIZE*2,"Can't stat %s\n",newto); CfLog(cfverbose,g_output,""); continue; } } else { if (lstat(newto,&statbuf) == -1) { snprintf(g_output,CF_BUFSIZE*2,"Can't stat %s\n",newto); CfLog(cfverbose,g_output,""); memset(g_vbuff,0,CF_BUFSIZE); if (readlink(newto,g_vbuff,CF_BUFSIZE-1) != -1) { Verbose("File is link to -> %s\n",g_vbuff); } continue; } } if (!FileObjectFilter(newto,&statbuf,lp->filters,links)) { Debug("Skipping filtered file %s\n",newto); continue; } if (S_ISDIR(statbuf.st_mode)) { RecursiveLink(lp,newfrom,newto,maxrecurse-1); } else { switch (lp->type) { case 's': linkfiles = LinkFiles; break; case 'r': linkfiles = RelativeLink; break; case 'a': linkfiles = AbsoluteLink; break; case 'h': linkfiles = HardLinkFiles; break; default: printf("cfagent: internal error, link type was [%c]\n",lp->type); continue; } (*linkfiles)(newfrom,newto,lp->inclusions,lp->exclusions, lp->copy,lp->nofile,lp); } } closedir(dirh); return true; }
void Icom::Controller::execute(Command& command) const { bool notForUs=false; do { // Send the command if(!notForUs) { const Buffer header={ Command_base::header, Command_base::header, command->device.address, m_address}; put(header); put(command->commandData()); put(Command_base::footer); } if(command->m_reply) { // Get the reply notForUs=false; unsigned int state=0; uint8_t buffer; command->resultData().clear(); while(state<5) { buffer=get(); switch(state) { case 0: case 1: if(buffer!=Command_base::header) throw InvalidReply(); ++state; break; case 2: if(buffer!=m_address) notForUs=true; ++state; break; case 3: if(buffer!=command->device.address) notForUs=true; ++state; break; case 4: if(buffer != Command_base::footer) command->resultData().push_back(buffer); else ++state; break; } // We don't want to recieve a giant reply if(command->resultData().size() >= Command_base::bufferReserveSize) throw BufferOverflow(); } } } while(notForUs || !command->complete()); }
int ExpandLinks(char *dest, char *from, int level) { char *sp, buff[CF_BUFSIZE]; char node[CF_MAXLINKSIZE]; struct stat statbuf; int lastnode = false; memset(dest,0,CF_BUFSIZE); Debug2("ExpandLinks(%s,%d)\n",from,level); if (level >= CF_MAXLINKLEVEL) { CfLog(cferror, "Too many levels of symbolic links to evaluate " "absolute path\n",""); return false; } for (sp = from; *sp != '\0'; sp++) { if (*sp == '/') { continue; } sscanf(sp,"%[^/]",node); sp += strlen(node); if (*sp == '\0') { lastnode = true; } if (strcmp(node,".") == 0) { continue; } if (strcmp(node,"..") == 0) { if (! ChopLastNode(g_linkto)) { Debug("cfagent: used .. beyond top of filesystem!\n"); return false; } continue; } else { strcat(dest,"/"); } strcat(dest,node); /* File doesn't exist so we can stop here */ if (lstat(dest,&statbuf) == -1) { snprintf(g_output, CF_BUFSIZE*2, "Can't stat %s in ExpandLinks\n", dest); CfLog(cferror,g_output,"stat"); return false; } if (S_ISLNK(statbuf.st_mode)) { memset(buff,0,CF_BUFSIZE); if (readlink(dest,buff,CF_BUFSIZE-1) == -1) { snprintf(g_output, CF_BUFSIZE*2, "Expand links can't stat %s\n", dest); CfLog(cferror,g_output,"readlink"); return false; } else { if (buff[0] == '.') { ChopLastNode(dest); AddSlash(dest); if (BufferOverflow(dest,buff)) { return false; } strcat(dest,buff); } else if (buff[0] == '/') { strcpy(dest,buff); DeleteSlash(dest); if (strcmp(dest,from) == 0) { Debug2("No links to be expanded\n"); return true; } if (!lastnode && !ExpandLinks(buff,dest,level+1)) { return false; } } else { ChopLastNode(dest); AddSlash(dest); strcat(dest,buff); DeleteSlash(dest); if (strcmp(dest,from) == 0) { Debug2("No links to be expanded\n"); return true; } memset(buff,0,CF_BUFSIZE); if (!lastnode && !ExpandLinks(buff,dest,level+1)) { return false; } } } } } return true; }
int CompressPath(char *dest,char *src) { char *sp; char node[CF_BUFSIZE]; int nodelen; int rootlen; Debug2("CompressPath(%s,%s)\n",dest,src); memset(dest,0,CF_BUFSIZE); rootlen = RootDirLength(src); strncpy(dest,src,rootlen); for (sp = src+rootlen; *sp != '\0'; sp++) { if (IsFileSep(*sp)) { continue; } for (nodelen = 0; sp[nodelen] != '\0' && !IsFileSep(sp[nodelen]); nodelen++) { if (nodelen > CF_MAXLINKSIZE) { CfLog(cferror,"Link in path suspiciously large",""); return false; } } strncpy(node, sp, nodelen); node[nodelen] = '\0'; sp += nodelen - 1; if (strcmp(node,".") == 0) { continue; } if (strcmp(node,"..") == 0) { if (!ChopLastNode(dest)) { Debug("cfengine: used .. beyond top of filesystem!\n"); return false; } continue; } else { AddSlash(dest); } if (BufferOverflow(dest,node)) { return false; } strcat(dest,node); } return true; }
int CheckForModule(char *actiontxt,char *args) { struct stat statbuf; char line[CF_BUFSIZE],command[CF_EXPANDSIZE],name[CF_MAXVARSIZE],content[CF_BUFSIZE],ebuff[CF_EXPANDSIZE],*sp; FILE *pp; int print; if (NOMODULES) { return false; } if (*actiontxt == '/') { snprintf(OUTPUT,CF_BUFSIZE,"Absolute module path (%s) should be named relative to the authorized module directory",actiontxt); CfLog(cferror,OUTPUT,""); } if (GetMacroValue(CONTEXTID,"moduledirectory")) { ExpandVarstring("$(moduledirectory)",ebuff,NULL); } else { snprintf(ebuff,CF_BUFSIZE,"%s/modules",VLOCKDIR); } AddSlash(ebuff); strcat(ebuff,actiontxt); if (stat(ebuff,&statbuf) == -1) { snprintf(OUTPUT,CF_BUFSIZE*2,"(Plug-in %s not found)",ebuff); Banner(OUTPUT); return false; } if ((statbuf.st_uid != 0) && (statbuf.st_uid != getuid())) { snprintf(OUTPUT,CF_BUFSIZE*2,"Module %s was not owned by uid=%d executing cfagent\n",ebuff,getuid()); CfLog(cferror,OUTPUT,""); return false; } snprintf(OUTPUT,CF_BUFSIZE*2,"Plug-in `%s\'",actiontxt); Banner(OUTPUT); strcat(ebuff," "); if (BufferOverflow(ebuff,args)) { snprintf(OUTPUT,CF_BUFSIZE*2,"Culprit: class list for module (shouldn't happen)\n" ); CfLog(cferror,OUTPUT,""); return false; } strcat(ebuff,args); ExpandVarstring(ebuff,command,NULL); Verbose("Exec module [%s]\n",command); if ((pp = cfpopen(command,"r")) == NULL) { snprintf(OUTPUT,CF_BUFSIZE*2,"Couldn't open pipe from %s\n",actiontxt); CfLog(cferror,OUTPUT,"cfpopen"); return false; } while (!feof(pp)) { if (ferror(pp)) /* abortable */ { snprintf(OUTPUT,CF_BUFSIZE*2,"Shell command pipe %s\n",actiontxt); CfLog(cferror,OUTPUT,"ferror"); break; } ReadLine(line,CF_BUFSIZE,pp); if (strlen(line) > CF_BUFSIZE - 80) { snprintf(OUTPUT,CF_BUFSIZE*2,"Line from module %s is too long to be sensible\n",actiontxt); CfLog(cferror,OUTPUT,""); break; } if (ferror(pp)) /* abortable */ { snprintf(OUTPUT,CF_BUFSIZE*2,"Shell command pipe %s\n",actiontxt); CfLog(cferror,OUTPUT,"ferror"); break; } print = false; for (sp = line; *sp != '\0'; sp++) { if (! isspace((int)*sp)) { print = true; break; } } switch (*line) { case '+': Verbose("Activated classes: %s\n",line+1); CheckClass(line+1,command); AddMultipleClasses(line+1); break; case '-': Verbose("Deactivated classes: %s\n",line+1); CheckClass(line+1,command); NegateCompoundClass(line+1,&VNEGHEAP); break; case '=': content[0] = '\0'; sscanf(line+1,"%[^=]=%[^\n]",name,content); Verbose("Defined Macro: %s, Value: %s\n",name,content); AddMacroValue(CONTEXTID,name,content); break; default: if (print) { snprintf(OUTPUT,CF_BUFSIZE,"%s: %s\n",actiontxt,line); CfLog(cferror,OUTPUT,""); } } } cfpclose(pp); return true; }
BOOL BackupReadSecurityData(HANDLE hFile, BACKUPCONTEXT *pbuc, BACKUPIOFRAME *pbif) { if (!pbif->fProcessSecurity) { return(TRUE); } if (pbuc->fStreamStart) { while (TRUE) { NTSTATUS Status; DWORD cbSecurityInfo; // First try to read all the security data RtlZeroMemory(pbuc->pBuffer, pbuc->cbBuffer); Status = NtQuerySecurityObject( hFile, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION, pbuc->pBuffer, pbuc->cbBuffer, &cbSecurityInfo); if (!NT_SUCCESS(Status) && !BufferOverflow(Status)) { // Now just try everything but SACL Status = NtQuerySecurityObject( hFile, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, pbuc->pBuffer, pbuc->cbBuffer, &cbSecurityInfo); } #if 0 if (!NT_SUCCESS(Status) && !BufferOverflow(Status)) { // Now just try to read the DACL Status = NtQuerySecurityObject( hFile, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION, pbuc->pBuffer, pbuc->cbBuffer, &cbSecurityInfo); } #endif if (NT_SUCCESS(Status)) { pbuc->fBufferReady = TRUE; break; } if (!BufferOverflow(Status)) { return(TRUE); // No Security info, do next stream type } if (!GrowBuffer(pbuc, cbSecurityInfo)) { return(FALSE); // No memory } // else grow succeeded } pbuc->head.dwStreamId = mwStreamList[pbuc->StreamIndex]; pbuc->head.dwStreamAttributes = STREAM_CONTAINS_SECURITY; pbuc->head.dwStreamNameSize = 0; pbuc->cbHeader = CB_NAMELESSHEADER; pbuc->head.Size.LowPart = RtlLengthSecurityDescriptor(pbuc->pBuffer); pbuc->head.Size.HighPart = 0; pbuc->fStreamStart = FALSE; } else if (pbuc->liStreamOffset.HighPart != 0 || pbuc->liStreamOffset.LowPart >= pbuc->cbHeader) { BackupReadBuffer(pbuc, pbif); } return(TRUE); }
BOOL BackupReadEaData(HANDLE hFile, BACKUPCONTEXT *pbuc, BACKUPIOFRAME *pbif) { if (pbuc->fStreamStart) { IO_STATUS_BLOCK iosb; while (TRUE) { NTSTATUS Status; FILE_EA_INFORMATION fei; Status = NtQueryEaFile( hFile, &iosb, pbuc->pBuffer, pbuc->cbBuffer, FALSE, NULL, 0, 0, (BOOLEAN) TRUE); if (NT_SUCCESS(Status) && iosb.Information != 0) { pbuc->fBufferReady = TRUE; break; } if (!BufferOverflow(Status)) { return(TRUE); // No Eas, do next stream type } Status = NtQueryInformationFile( hFile, &iosb, &fei, sizeof(fei), FileEaInformation); if (!NT_SUCCESS(Status)) { return(TRUE); // No Eas, do next stream type } if (!GrowBuffer(pbuc, (fei.EaSize * 5) / 4)) { pbuc->fAccessError = TRUE; return(FALSE); // No memory } // else grow succeeded } pbuc->head.dwStreamId = mwStreamList[pbuc->StreamIndex]; pbuc->head.dwStreamAttributes = STREAM_NORMAL_ATTRIBUTE; pbuc->head.dwStreamNameSize = 0; pbuc->cbHeader = CB_NAMELESSHEADER; pbuc->head.Size.HighPart = 0; pbuc->head.Size.LowPart = iosb.Information; pbuc->fStreamStart = FALSE; } else if (pbuc->liStreamOffset.HighPart != 0 || pbuc->liStreamOffset.LowPart >= pbuc->cbHeader) { BackupReadBuffer(pbuc, pbif); } return(TRUE); }
BOOL BackupReadAlternateData(HANDLE hFile, BACKUPCONTEXT *pbuc, BACKUPIOFRAME *pbif) { // ALT_DATA is Macintosh stream data & other data streams. if (pbuc->fStreamStart) { NTSTATUS Status; FILE_STREAM_INFORMATION *pfsi; IO_STATUS_BLOCK iosb; // allocate a buffer big enough to hold all the necessary data. if (!pbuc->fBufferReady) { while (TRUE) { Status = NtQueryInformationFile( hFile, &iosb, pbuc->pBuffer, pbuc->cbBuffer, FileStreamInformation); if (NT_SUCCESS(Status) && iosb.Information != 0) { pbuc->iBuffer = 0; pbuc->fBufferReady = TRUE; break; } if (!BufferOverflow(Status)) { return(TRUE); // No alt. streams, do next stream type } if (!GrowBuffer(pbuc, pbuc->cbBuffer * 2)) { return(FALSE); // No memory } // else grow succeeded } } pbuc->hAlternate = NULL; pbuc->fStreamStart = FALSE; pfsi = (FILE_STREAM_INFORMATION *) &pbuc->pBuffer[pbuc->iBuffer]; // Check StreamName for default data stream and skip if found // Checking StreamNameLength for <= 1 character is OFS specific! // Checking StreamName[1] for a colon is NTFS specific! if (pfsi->StreamNameLength <= sizeof(WCHAR) || pfsi->StreamName[1] == ':') { if (pfsi->NextEntryOffset == 0) { return(TRUE); // No more, do next stream type } pbuc->iBuffer += pfsi->NextEntryOffset; } pbuc->head.Size.LowPart = 1; } else if (pbuc->hAlternate == NULL) { NTSTATUS Status; FILE_STREAM_INFORMATION *pfsi; UNICODE_STRING strName; OBJECT_ATTRIBUTES oa; IO_STATUS_BLOCK iosb; pbuc->head.Size.LowPart = 0; pbuc->head.Size.HighPart = 0; pfsi = (FILE_STREAM_INFORMATION *) &pbuc->pBuffer[pbuc->iBuffer]; strName.Length = (USHORT) pfsi->StreamNameLength; strName.MaximumLength = strName.Length; strName.Buffer = pfsi->StreamName; InitializeObjectAttributes( &oa, &strName, OBJ_CASE_INSENSITIVE, hFile, NULL); Status = NtOpenFile( &pbuc->hAlternate, FILE_GENERIC_READ, &oa, &iosb, FILE_SHARE_READ|FILE_SHARE_WRITE, FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT); if (!NT_SUCCESS(Status)) { pbuc->iBuffer += pfsi->NextEntryOffset; if (pfsi->NextEntryOffset != 0) { pbuc->head.Size.LowPart = 1; pbuc->fMultiStreamType = TRUE; // more to come } return(TRUE); } pbuc->head.dwStreamId = mwStreamList[pbuc->StreamIndex]; pbuc->head.dwStreamAttributes = STREAM_NORMAL_ATTRIBUTE; pbuc->head.dwStreamNameSize = pfsi->StreamNameLength; pbuc->cbHeader = CB_NAMELESSHEADER + pfsi->StreamNameLength; RtlCopyMemory( pbuc->head.cStreamName, pfsi->StreamName, pfsi->StreamNameLength); pbuc->head.Size.LowPart = GetFileSize( pbuc->hAlternate, &pbuc->head.Size.HighPart); if (pfsi->NextEntryOffset != 0) { pbuc->iBuffer += pfsi->NextEntryOffset; pbuc->fMultiStreamType = TRUE; // more to come after this one } } else if (pbuc->liStreamOffset.HighPart != 0 || pbuc->liStreamOffset.LowPart >= pbuc->cbHeader) { if (pbuc->liStreamOffset.LowPart == pbuc->cbHeader && pbuc->liStreamOffset.HighPart == 0) { // if we can't lock all records, return an error if (!LockFile(pbuc->hAlternate, 0, 0, 0xffffffff, 0xffffffff)) { return(FALSE); } } return(BackupReadStream(pbuc->hAlternate, pbuc, pbif)); } return(TRUE); }