void *MapFile(const char *filename) { int fd; off_t size; void *address; /* Open the file and get its size */ fd=ReOpenFile(filename); size=SizeFile(filename); /* Map the file */ address=mmap(NULL,size,PROT_READ,MAP_SHARED,fd,0); if(address==MAP_FAILED) { close(fd); fprintf(stderr,"Cannot mmap file '%s' [%s].\n",filename,strerror(errno)); exit(EXIT_FAILURE); } mappedfiles=(struct mmapinfo*)realloc((void*)mappedfiles,(nmappedfiles+1)*sizeof(struct mmapinfo)); mappedfiles[nmappedfiles].filename=filename; mappedfiles[nmappedfiles].fd=fd; mappedfiles[nmappedfiles].address=address; mappedfiles[nmappedfiles].length=size; nmappedfiles++; return(address); }
Relations *LoadRelationList(const char *filename) { Relations *relations; #if SLIM int i; #endif relations=(Relations*)malloc(sizeof(Relations)); #if !SLIM relations->data=MapFile(filename); /* Copy the RelationsFile header structure from the loaded data */ relations->file=*((RelationsFile*)relations->data); /* Set the pointers in the Relations structure. */ relations->turnrelations=(TurnRelation*)(relations->data+sizeof(RelationsFile)); #else relations->fd=ReOpenFile(filename); /* Copy the RelationsFile header structure from the loaded data */ ReadFile(relations->fd,&relations->file,sizeof(RelationsFile)); relations->troffset=sizeof(RelationsFile); for(i=0;i<sizeof(relations->cached)/sizeof(relations->cached[0]);i++) relations->incache[i]=NO_RELATION; #endif if(relations->file.trnumber>0) { TurnRelation *relation; relation=LookupTurnRelation(relations,0,1); relations->via_start =relation->via; relation=LookupTurnRelation(relations,relations->file.trnumber-1,1); relations->via_end =relation->via; } return(relations); }
void SortNodeList(NodesX *nodesx) { int fd; index_t xnumber; /* Print the start message */ printf_first("Sorting Nodes"); /* Close the file (finished appending) */ nodesx->fd=CloseFile(nodesx->fd); /* Re-open the file read-only and a new file writeable */ nodesx->fd=ReOpenFile(nodesx->filename); DeleteFile(nodesx->filename); fd=OpenFileNew(nodesx->filename); /* Allocate the array of indexes */ nodesx->idata=(node_t*)malloc(nodesx->number*sizeof(node_t)); assert(nodesx->idata); /* Check malloc() worked */ /* Sort by node indexes */ xnumber=nodesx->number; nodesx->number=0; sortnodesx=nodesx; filesort_fixed(nodesx->fd,fd,sizeof(NodeX),(int (*)(const void*,const void*))sort_by_id,(int (*)(void*,index_t))deduplicate_and_index_by_id); /* Close the files */ nodesx->fd=CloseFile(nodesx->fd); CloseFile(fd); /* Print the final message */ printf_last("Sorted Nodes: Nodes=%"Pindex_t" Duplicates=%"Pindex_t,xnumber,xnumber-nodesx->number); }
void UpdateNodes(NodesX *nodesx,SegmentsX *segmentsx) { index_t i; int fd; /* Print the start message */ printf_first("Updating Super Nodes: Nodes=0"); /* Re-open the file read-only and a new file writeable */ nodesx->fd=ReOpenFile(nodesx->filename); DeleteFile(nodesx->filename); fd=OpenFileNew(nodesx->filename); /* Modify the on-disk image */ for(i=0;i<nodesx->number;i++) { NodeX nodex; ReadFile(nodesx->fd,&nodex,sizeof(NodeX)); if(IsBitSet(nodesx->super,nodex.id)) nodex.flags|=NODE_SUPER; nodex.id=segmentsx->firstnode[nodesx->gdata[nodex.id]]; WriteFile(fd,&nodex,sizeof(NodeX)); if(!((i+1)%10000)) printf_middle("Updating Super Nodes: Nodes=%"Pindex_t,i+1); } /* Close the files */ nodesx->fd=CloseFile(nodesx->fd); CloseFile(fd); /* Print the final message */ printf_last("Updated Super Nodes: Nodes=%"Pindex_t,nodesx->number); }
void SortNodeListGeographically(NodesX *nodesx) { int fd; /* Print the start message */ printf_first("Sorting Nodes Geographically"); /* Allocate the memory for the geographical index array */ nodesx->gdata=(index_t*)malloc(nodesx->number*sizeof(index_t)); assert(nodesx->gdata); /* Check malloc() worked */ /* Re-open the file read-only and a new file writeable */ nodesx->fd=ReOpenFile(nodesx->filename); DeleteFile(nodesx->filename); fd=OpenFileNew(nodesx->filename); /* Sort geographically */ sortnodesx=nodesx; filesort_fixed(nodesx->fd,fd,sizeof(NodeX),(int (*)(const void*,const void*))sort_by_lat_long,(int (*)(void*,index_t))index_by_lat_long); /* Close the files */ nodesx->fd=CloseFile(nodesx->fd); CloseFile(fd); /* Print the final message */ printf_last("Sorted Nodes Geographically"); }
void LogFile::Flush( ) { // If the file size exceed the limited. if (lenLimit) { if ((totalFileLength/1024+1) >= lenLimit) { // Add 2006-06-02, by Wu jianjin. if (FILENAME == fnMode) { MovingOldLogFile( ); } ReOpenFile( ); totalFileLength = 0L; } else { Write2File( ); } } else { Write2File( ); } /* int fd; fd = fileno(fp); if (fd != -1) { struct stat * statbuf; int r; r=fstat(fd, statbuf); if (r != -1) { if (((UINT32)(statbuf->st_size/1024)) > lenLimit) { // Add 2006-06-02, by Wu jianjin. if (FILENAME == fnMode) { MovingOldLogFile( ); } ReOpenFile( ); } // else // { // Write data into file. Write2File( ); // } } else { // Discard current data in buffers. ClearBuffer( ); } } else { // Discard current data in bufers. ClearBuffer( ); } } else { // if lenLimit==0, no limit. Write2File( ); }*/ }
char * ConfigBase::GetValue(const char * const val) { static char opBuf[256]; char *ptr=NULL; char buf[128]; int buflen=128; int stat=0; if (NULL == val) { // Exception xcpPtr->error(E_NULL_POINTER, SF_CFGBASE, g_Errstr[E_NULL_POINTER]); return NULL; } if (ReOpenFile( ) != E_SUCC) { return NULL; } while (GetLine(buf, buflen) != NULL) { ptr=buf; if (! strcmp(m_sField, "")) stat=1; else if (strstr(buf, m_sField)) { stat=1; continue; } if (stat == 0) continue; while (*ptr == '\t' || *ptr == ' ') ptr++; if (*ptr == '[') break; if ((*ptr == '\0') || (*ptr == '\n') || (*ptr == '\r') || (*ptr == ';') || (*ptr == '#')) continue; if (strncmp(ptr, val, strlen(val)) != 0) continue; ptr = strchr(ptr, '='); if (ptr!=NULL) { while (*ptr == '\t' || *ptr == ' ') ++ptr; ++ptr; if ((*ptr == '\0') || (*ptr == '\n') || (*ptr == '\r') || (*ptr == ';') || (*ptr == '#')) { // Exception handle // printf("[%s] Missing value\n",val); xcpPtr->error(E_CONFIG_MISS, SF_CFGBASE, g_Errstr[E_CONFIG_MISS]); return NULL; } if ((*ptr == '\"') || (*ptr == '\'')) { char ch = *ptr; int len = 0; ++ptr; // Ignore the start delimitation char do { if ((*ptr == '\0') || (len >= MAX_LENGTH_CFG)) { // Exception handle // opBuf[0] = '\0'; // break; xcpPtr->error(E_CONFIG_ERROR, SF_CFGBASE, "Missing delimitation char \' or \"."); return NULL; } opBuf[len] = *ptr; ++len; ++ptr; } while (*ptr != ch); opBuf[len] = '\0'; } else { int len = 0; do { opBuf[len] = *ptr; ++len; ++ptr; } while ((*ptr != ' ') && (*ptr != '\0') && (*ptr != '\n') && (*ptr != '\r') && (*ptr != '\t') && (*ptr != ';') && (*ptr != '#')); opBuf[len] = '\0'; } return opBuf; } // Exception handle // printf("[%s] Missing value\n",val); xcpPtr->error(E_CONFIG_MISS, SF_CFGBASE, "The option missing value."); return NULL; } return NULL; }
void SaveNodeList(NodesX *nodesx,const char *filename) { index_t i; int fd; NodesFile nodesfile={0}; index_t super_number=0; ll_bin2_t latlonbin=0,maxlatlonbins; index_t *offsets; /* Print the start message */ printf_first("Writing Nodes: Nodes=0"); /* Allocate the memory for the geographical offsets array */ offsets=(index_t*)malloc((nodesx->latbins*nodesx->lonbins+1)*sizeof(index_t)); assert(offsets); /* Check malloc() worked */ latlonbin=0; /* Re-open the file */ nodesx->fd=ReOpenFile(nodesx->filename); /* Write out the nodes data */ fd=OpenFileNew(filename); SeekFile(fd,sizeof(NodesFile)+(nodesx->latbins*nodesx->lonbins+1)*sizeof(index_t)); for(i=0;i<nodesx->number;i++) { NodeX nodex; Node node; ll_bin_t latbin,lonbin; ll_bin2_t llbin; ReadFile(nodesx->fd,&nodex,sizeof(NodeX)); /* Create the Node */ node.latoffset=latlong_to_off(nodex.latitude); node.lonoffset=latlong_to_off(nodex.longitude); node.firstseg=nodex.id; node.allow=nodex.allow; node.flags=nodex.flags; if(node.flags&NODE_SUPER) super_number++; /* Work out the offsets */ latbin=latlong_to_bin(nodex.latitude )-nodesx->latzero; lonbin=latlong_to_bin(nodex.longitude)-nodesx->lonzero; llbin=lonbin*nodesx->latbins+latbin; for(;latlonbin<=llbin;latlonbin++) offsets[latlonbin]=i; /* Write the data */ WriteFile(fd,&node,sizeof(Node)); if(!((i+1)%10000)) printf_middle("Writing Nodes: Nodes=%"Pindex_t,i+1); } /* Close the file */ nodesx->fd=CloseFile(nodesx->fd); /* Finish off the offset indexing and write them out */ maxlatlonbins=nodesx->latbins*nodesx->lonbins; for(;latlonbin<=maxlatlonbins;latlonbin++) offsets[latlonbin]=nodesx->number; SeekFile(fd,sizeof(NodesFile)); WriteFile(fd,offsets,(nodesx->latbins*nodesx->lonbins+1)*sizeof(index_t)); free(offsets); /* Write out the header structure */ nodesfile.number=nodesx->number; nodesfile.snumber=super_number; nodesfile.latbins=nodesx->latbins; nodesfile.lonbins=nodesx->lonbins; nodesfile.latzero=nodesx->latzero; nodesfile.lonzero=nodesx->lonzero; SeekFile(fd,0); WriteFile(fd,&nodesfile,sizeof(NodesFile)); CloseFile(fd); /* Print the final message */ printf_last("Wrote Nodes: Nodes=%"Pindex_t,nodesx->number); }
void RemoveNonHighwayNodes(NodesX *nodesx,SegmentsX *segmentsx) { NodeX nodex; index_t total=0,highway=0,nothighway=0; ll_bin_t lat_min_bin,lat_max_bin,lon_min_bin,lon_max_bin; latlong_t lat_min,lat_max,lon_min,lon_max; int fd; /* Print the start message */ printf_first("Checking Nodes: Nodes=0"); /* While we are here we can work out the range of data */ lat_min=radians_to_latlong( 2); lat_max=radians_to_latlong(-2); lon_min=radians_to_latlong( 4); lon_max=radians_to_latlong(-4); /* Re-open the file read-only and a new file writeable */ nodesx->fd=ReOpenFile(nodesx->filename); DeleteFile(nodesx->filename); fd=OpenFileNew(nodesx->filename); /* Modify the on-disk image */ while(!ReadFile(nodesx->fd,&nodex,sizeof(NodeX))) { if(!IsBitSet(segmentsx->usednode,total)) nothighway++; else { nodex.id=highway; WriteFile(fd,&nodex,sizeof(NodeX)); nodesx->idata[highway]=nodesx->idata[total]; highway++; if(nodex.latitude<lat_min) lat_min=nodex.latitude; if(nodex.latitude>lat_max) lat_max=nodex.latitude; if(nodex.longitude<lon_min) lon_min=nodex.longitude; if(nodex.longitude>lon_max) lon_max=nodex.longitude; } total++; if(!(total%10000)) printf_middle("Checking Nodes: Nodes=%"Pindex_t" Highway=%"Pindex_t" not-Highway=%"Pindex_t,total,highway,nothighway); } nodesx->number=highway; /* Close the files */ nodesx->fd=CloseFile(nodesx->fd); CloseFile(fd); /* Work out the number of bins */ lat_min_bin=latlong_to_bin(lat_min); lon_min_bin=latlong_to_bin(lon_min); lat_max_bin=latlong_to_bin(lat_max); lon_max_bin=latlong_to_bin(lon_max); nodesx->latzero=lat_min_bin; nodesx->lonzero=lon_min_bin; nodesx->latbins=(lat_max_bin-lat_min_bin)+1; nodesx->lonbins=(lon_max_bin-lon_min_bin)+1; /* Free the now-unneeded index */ free(segmentsx->usednode); segmentsx->usednode=NULL; /* Allocate and set the super-node markers */ nodesx->super=(uint8_t*)malloc((1+nodesx->number/8)*sizeof(uint8_t)); assert(nodesx->super); /* Check calloc() worked */ memset(nodesx->super,~0,(1+nodesx->number/8)); /* Print the final message */ printf_last("Checked Nodes: Nodes=%"Pindex_t" Highway=%"Pindex_t" not-Highway=%"Pindex_t,total,highway,nothighway); }
void ChooseSuperNodes(NodesX *nodesx,SegmentsX *segmentsx,WaysX *waysx) { index_t i; index_t nnodes=0; if(nodesx->number==0 || segmentsx->number==0 || waysx->number==0) return; /* Print the start message */ printf_first("Finding Super-Nodes: Nodes=0 Super-Nodes=0"); /* Allocate and set the super-node markers */ if(!nodesx->super) { nodesx->super=AllocBitMask(nodesx->number); assert(nodesx->super); /* Check AllocBitMask() worked */ SetAllBits1(nodesx->super,nodesx->number); } /* Map into memory / open the files */ #if !SLIM nodesx->data=MapFile(nodesx->filename); segmentsx->data=MapFile(segmentsx->filename); waysx->data=MapFile(waysx->filename); #else nodesx->fd=ReOpenFile(nodesx->filename); segmentsx->fd=ReOpenFile(segmentsx->filename); waysx->fd=ReOpenFile(waysx->filename); #endif /* Find super-nodes */ for(i=0;i<nodesx->number;i++) { if(IsBitSet(nodesx->super,i)) { int issuper=0; NodeX *nodex=LookupNodeX(nodesx,i,1); if(IsPrunedNodeX(nodex)) issuper=0; else if(nodex->flags&(NODE_TURNRSTRCT|NODE_TURNRSTRCT2)) issuper=1; else { int count=0,j; Way segmentway[MAX_SEG_PER_NODE]; int segmentweight[MAX_SEG_PER_NODE]; SegmentX *segmentx=FirstSegmentX(segmentsx,i,1); while(segmentx) { WayX *wayx=LookupWayX(waysx,segmentx->way,1); int nsegments; /* Segments that are loops count twice */ assert(count<MAX_SEG_PER_NODE); /* Only a limited amount of information stored. */ if(segmentx->node1==segmentx->node2) segmentweight[count]=2; else segmentweight[count]=1; segmentway[count]=wayx->way; /* If the node allows less traffic types than any connecting way then it is super */ if((wayx->way.allow&nodex->allow)!=wayx->way.allow) { issuper=1; break; } nsegments=segmentweight[count]; for(j=0;j<count;j++) if(wayx->way.allow & segmentway[j].allow) { /* If two ways are different in any attribute and there is a type of traffic that can use both then it is super */ if(WaysCompare(&segmentway[j],&wayx->way)) { issuper=1; break; } /* If there are two other segments that can be used by the same types of traffic as this one then it is super */ nsegments+=segmentweight[j]; if(nsegments>2) { issuper=1; break; } } if(issuper) break; segmentx=NextSegmentX(segmentsx,segmentx,i); count++; } } /* Mark the node as super if it is. */ if(issuper) nnodes++; else ClearBit(nodesx->super,i); } if(!((i+1)%10000)) printf_middle("Finding Super-Nodes: Nodes=%"Pindex_t" Super-Nodes=%"Pindex_t,i+1,nnodes); } /* Unmap from memory / close the files */ #if !SLIM nodesx->data=UnmapFile(nodesx->filename); segmentsx->data=UnmapFile(segmentsx->filename); waysx->data=UnmapFile(waysx->filename); #else nodesx->fd=CloseFile(nodesx->fd); segmentsx->fd=CloseFile(segmentsx->fd); waysx->fd=CloseFile(waysx->fd); #endif /* Print the final message */ printf_last("Found Super-Nodes: Nodes=%"Pindex_t" Super-Nodes=%"Pindex_t,nodesx->number,nnodes); }
SegmentsX *MergeSuperSegments(SegmentsX *segmentsx,SegmentsX *supersegmentsx) { index_t i,j; index_t merged=0,added=0; SegmentsX *mergedsegmentsx; mergedsegmentsx=NewSegmentList(0); if(segmentsx->number==0) return(mergedsegmentsx); /* Print the start message */ printf_first("Merging Segments: Segments=0 Super=0 Merged=0 Added=0"); /* Map into memory / open the files */ #if !SLIM segmentsx->data=MapFile(segmentsx->filename); if(supersegmentsx->number>0) supersegmentsx->data=MapFile(supersegmentsx->filename); #else segmentsx->fd=ReOpenFile(segmentsx->filename); if(supersegmentsx->number>0) supersegmentsx->fd=ReOpenFile(supersegmentsx->filename); #endif /* Loop through and create a new list of combined segments */ for(i=0,j=0;i<segmentsx->number;i++) { int super=0; SegmentX *segmentx=LookupSegmentX(segmentsx,i,1); while(j<supersegmentsx->number) { SegmentX *supersegmentx=LookupSegmentX(supersegmentsx,j,1); if(segmentx->node1 ==supersegmentx->node1 && segmentx->node2 ==supersegmentx->node2 && segmentx->distance==supersegmentx->distance) { merged++; j++; /* mark as super-segment and normal segment */ super=1; break; } else if((segmentx->node1==supersegmentx->node1 && segmentx->node2==supersegmentx->node2) || (segmentx->node1==supersegmentx->node1 && segmentx->node2>supersegmentx->node2) || (segmentx->node1>supersegmentx->node1)) { /* mark as super-segment */ AppendSegment(mergedsegmentsx,supersegmentx->way,supersegmentx->node1,supersegmentx->node2,supersegmentx->distance|SEGMENT_SUPER); added++; j++; } else { /* mark as normal segment */ break; } } if(super) AppendSegment(mergedsegmentsx,segmentx->way,segmentx->node1,segmentx->node2,segmentx->distance|SEGMENT_SUPER|SEGMENT_NORMAL); else AppendSegment(mergedsegmentsx,segmentx->way,segmentx->node1,segmentx->node2,segmentx->distance|SEGMENT_NORMAL); if(!((i+1)%10000)) printf_middle("Merging Segments: Segments=%"Pindex_t" Super=%"Pindex_t" Merged=%"Pindex_t" Added=%"Pindex_t,i+1,j,merged,added); } /* Unmap from memory / close the files */ #if !SLIM segmentsx->data=UnmapFile(segmentsx->filename); if(supersegmentsx->number>0) supersegmentsx->data=UnmapFile(supersegmentsx->filename); #else segmentsx->fd=CloseFile(segmentsx->fd); if(supersegmentsx->number>0) supersegmentsx->fd=CloseFile(supersegmentsx->fd); #endif /* Print the final message */ printf_last("Merged Segments: Segments=%"Pindex_t" Super=%"Pindex_t" Merged=%"Pindex_t" Added=%"Pindex_t,segmentsx->number,supersegmentsx->number,merged,added); return(mergedsegmentsx); }
SegmentsX *CreateSuperSegments(NodesX *nodesx,SegmentsX *segmentsx,WaysX *waysx) { index_t i; SegmentsX *supersegmentsx; index_t sn=0,ss=0; supersegmentsx=NewSegmentList(0); if(segmentsx->number==0 || waysx->number==0) return(supersegmentsx); /* Print the start message */ printf_first("Creating Super-Segments: Super-Nodes=0 Super-Segments=0"); /* Map into memory / open the files */ #if !SLIM segmentsx->data=MapFile(segmentsx->filename); waysx->data=MapFile(waysx->filename); #else segmentsx->fd=ReOpenFile(segmentsx->filename); waysx->fd=ReOpenFile(waysx->filename); #endif /* Create super-segments for each super-node. */ for(i=0;i<nodesx->number;i++) { if(IsBitSet(nodesx->super,i)) { SegmentX *segmentx; int count=0,match; Way prevway[MAX_SEG_PER_NODE]; segmentx=FirstSegmentX(segmentsx,i,1); while(segmentx) { WayX *wayx=LookupWayX(waysx,segmentx->way,1); /* Check that this type of way hasn't already been routed */ match=0; if(count>0) { int j; for(j=0;j<count;j++) if(!WaysCompare(&prevway[j],&wayx->way)) { match=1; break; } } assert(count<MAX_SEG_PER_NODE); /* Only a limited amount of history stored. */ prevway[count++]=wayx->way; /* Route the way and store the super-segments. */ if(!match) { Results *results=FindRoutesWay(nodesx,segmentsx,waysx,i,&wayx->way); Result *result=FirstResult(results); while(result) { if(IsBitSet(nodesx->super,result->node) && result->segment!=NO_SEGMENT) { if(wayx->way.type&Way_OneWay && result->node!=i) AppendSegment(supersegmentsx,segmentx->way,i,result->node,DISTANCE((distance_t)result->score)|ONEWAY_1TO2); else AppendSegment(supersegmentsx,segmentx->way,i,result->node,DISTANCE((distance_t)result->score)); ss++; } result=NextResult(results,result); } FreeResultsList(results); } segmentx=NextSegmentX(segmentsx,segmentx,i); } sn++; if(!(sn%10000)) printf_middle("Creating Super-Segments: Super-Nodes=%"Pindex_t" Super-Segments=%"Pindex_t,sn,ss); } } /* Unmap from memory / close the files */ #if !SLIM segmentsx->data=UnmapFile(segmentsx->filename); waysx->data=UnmapFile(waysx->filename); #else segmentsx->fd=CloseFile(segmentsx->fd); waysx->fd=CloseFile(waysx->fd); #endif /* Print the final message */ printf_last("Created Super-Segments: Super-Nodes=%"Pindex_t" Super-Segments=%"Pindex_t,sn,ss); return(supersegmentsx); }
/* Open a file * Return values: * < 0 => errno * == 0 => Opening file succeeded * > 0 => It is a symlink which needs to be redirected (target written) */ static int open_file(HANDLE *hFile, struct mount_point *mp, const char *pathname, DWORD desired_access, DWORD create_disposition, DWORD attributes, int flags, BOOL bInherit, char *target, int buflen, char *drive_letter) { WCHAR buf[PATH_MAX]; UNICODE_STRING name; name.Buffer = buf; name.MaximumLength = name.Length = 2 * filename_to_nt_pathname(mp, pathname, buf, PATH_MAX); if (name.Length == 0) return -L_ENOENT; *drive_letter = buf[4]; OBJECT_ATTRIBUTES attr; attr.Length = sizeof(OBJECT_ATTRIBUTES); attr.RootDirectory = NULL; attr.ObjectName = &name; attr.Attributes = (bInherit? OBJ_INHERIT: 0); attr.SecurityDescriptor = NULL; attr.SecurityQualityOfService = NULL; NTSTATUS status; IO_STATUS_BLOCK status_block; HANDLE handle; DWORD create_options = FILE_SYNCHRONOUS_IO_NONALERT; /* For synchronous I/O */ if (desired_access & GENERIC_ALL) create_options |= FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_REMOTE_INSTANCE; else { if (desired_access & GENERIC_READ) create_options |= FILE_OPEN_FOR_BACKUP_INTENT; if (desired_access & GENERIC_WRITE) create_options |= FILE_OPEN_REMOTE_INSTANCE; } desired_access |= SYNCHRONIZE | FILE_READ_ATTRIBUTES; status = NtCreateFile(&handle, desired_access, &attr, &status_block, NULL, attributes, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, create_disposition, create_options, NULL, 0); if (status == STATUS_OBJECT_NAME_COLLISION) { log_warning("File already exists."); return -L_EEXIST; } else if (!NT_SUCCESS(status)) { log_warning("Unhandled NtCreateFile error, status: %x, returning ENOENT.", status); return -L_ENOENT; } FILE_ATTRIBUTE_TAG_INFORMATION attribute_info; status = NtQueryInformationFile(handle, &status_block, &attribute_info, sizeof(attribute_info), FileAttributeTagInformation); if (!NT_SUCCESS(status)) { log_error("NtQueryInformationFile(FileAttributeTagInformation) failed, status: %x", status); NtClose(handle); return -L_EIO; } /* Test if the file is a symlink */ int is_symlink = 0; if (!(attribute_info.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) && (attribute_info.FileAttributes & FILE_ATTRIBUTE_SYSTEM)) { /* The file has system flag set. A potential symbolic link. */ if (!(desired_access & GENERIC_READ)) { /* But the handle does not have READ access, try reopening file */ HANDLE read_handle = ReOpenFile(handle, desired_access | GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_FLAG_BACKUP_SEMANTICS); if (read_handle == INVALID_HANDLE_VALUE) { log_warning("Reopen symlink file failed, error code %d. Assume not symlink.", GetLastError()); *hFile = handle; return 0; } NtClose(handle); handle = read_handle; } if (winfs_read_symlink_unsafe(handle, target, buflen) > 0) { if (!(flags & O_NOFOLLOW)) { NtClose(handle); return 1; } if (!(flags & O_PATH)) { NtClose(handle); log_info("Specified O_NOFOLLOW but not O_PATH, returning ELOOP."); return -L_ELOOP; } } } else if (!(attribute_info.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) && (flags & O_DIRECTORY)) { log_warning("Not a directory."); return -L_ENOTDIR; } *hFile = handle; return 0; }
static int winfs_open(const char *pathname, int flags, int mode, struct file **fp, char *target, int buflen) { /* TODO: mode */ DWORD desiredAccess, shareMode, creationDisposition; HANDLE handle; FILE_ATTRIBUTE_TAG_INFO attributeInfo; WCHAR wpathname[PATH_MAX]; struct winfs_file *file; int pathlen = strlen(pathname); if (utf8_to_utf16_filename(pathname, pathlen + 1, wpathname, PATH_MAX) <= 0) return -ENOENT; if (wpathname[0] == 0) { /* CreateFile() does not accept empty filename. */ wpathname[0] = '.'; wpathname[1] = 0; } if (flags & O_PATH) desiredAccess = 0; else if (flags & O_RDWR) desiredAccess = GENERIC_READ | GENERIC_WRITE; else if (flags & O_WRONLY) desiredAccess = GENERIC_WRITE; else desiredAccess = GENERIC_READ; if (flags & __O_DELETE) desiredAccess |= DELETE; shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE; creationDisposition; if (flags & O_EXCL) creationDisposition = CREATE_NEW; else if (flags & O_CREAT) creationDisposition = OPEN_ALWAYS; else creationDisposition = OPEN_EXISTING; //log_debug("CreateFileW(): %s\n", pathname); SECURITY_ATTRIBUTES attr; attr.nLength = sizeof(SECURITY_ATTRIBUTES); attr.lpSecurityDescriptor = NULL; attr.bInheritHandle = (fp != NULL); handle = CreateFileW(wpathname, desiredAccess, shareMode, &attr, creationDisposition, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, NULL); if (handle == INVALID_HANDLE_VALUE) { DWORD err = GetLastError(); if (err == ERROR_FILE_EXISTS || err == ERROR_ALREADY_EXISTS) { log_warning("File already exists.\n"); return -EEXIST; } else { log_warning("Unhandled CreateFileW() failure, error code: %d, returning ENOENT.\n", GetLastError()); return -ENOENT; } } if (!GetFileInformationByHandleEx(handle, FileAttributeTagInfo, &attributeInfo, sizeof(attributeInfo))) { CloseHandle(handle); return -EIO; } /* Test if the file is a symlink */ int is_symlink = 0; if (attributeInfo.FileAttributes != INVALID_FILE_ATTRIBUTES && (attributeInfo.FileAttributes & FILE_ATTRIBUTE_SYSTEM)) { log_info("The file has system flag set.\n"); if (!(desiredAccess & GENERIC_READ)) { /* We need to get a readable handle */ log_info("But the handle does not have READ access, try reopening file...\n"); HANDLE read_handle = ReOpenFile(handle, desiredAccess | GENERIC_READ, shareMode, FILE_FLAG_BACKUP_SEMANTICS); if (read_handle == INVALID_HANDLE_VALUE) { log_warning("Reopen file failed, error code %d. Assume not symlink.\n", GetLastError()); goto after_symlink_test; } CloseHandle(handle); log_info("Reopen succeeded.\n"); handle = read_handle; } if (winfs_read_symlink(handle, target, buflen) > 0) { if (!(flags & O_NOFOLLOW)) { CloseHandle(handle); return 1; } if (!(flags & O_PATH)) { CloseHandle(handle); log_info("Specified O_NOFOLLOW but not O_PATH, returning ELOOP.\n"); return -ELOOP; } is_symlink = 1; } log_info("Opening file directly.\n"); } else if (attributeInfo.FileAttributes != INVALID_FILE_ATTRIBUTES && !(attributeInfo.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) && (flags & O_DIRECTORY)) { log_warning("Not a directory.\n"); return -ENOTDIR; } after_symlink_test: if (!is_symlink && (flags & O_TRUNC) && ((flags & O_WRONLY) || (flags & O_RDWR))) { /* Truncate the file */ FILE_END_OF_FILE_INFORMATION info; info.EndOfFile.QuadPart = 0; IO_STATUS_BLOCK status_block; NTSTATUS status = NtSetInformationFile(handle, &status_block, &info, sizeof(info), FileEndOfFileInformation); if (!NT_SUCCESS(status)) log_error("NtSetInformationFile() failed, status: %x\n", status); } if (fp) { file = (struct winfs_file *)kmalloc(sizeof(struct winfs_file) + pathlen); file->base_file.op_vtable = &winfs_ops; file->base_file.ref = 1; file->base_file.flags = flags; file->handle = handle; file->restart_scan = 1; file->pathlen = pathlen; memcpy(file->pathname, pathname, pathlen); *fp = (struct file *)file; } else CloseHandle(handle); return 0; }