Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenio.c
Go to the documentation of this file.
00001 /* io.c - Virtual disk input/output */ 00002 00003 /* Written 1993 by Werner Almesberger */ 00004 00005 /* 00006 * Thu Feb 26 01:15:36 CET 1998: Martin Schulze <joey@infodrom.north.de> 00007 * Fixed nasty bug that caused every file with a name like 00008 * xxxxxxxx.xxx to be treated as bad name that needed to be fixed. 00009 */ 00010 00011 /* FAT32, VFAT, Atari format support, and various fixes additions May 1998 00012 * by Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> */ 00013 00014 00015 #include "vfatlib.h" 00016 00017 #define NDEBUG 00018 #include <debug.h> 00019 00020 #define FSCTL_IS_VOLUME_DIRTY CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 30, METHOD_BUFFERED, FILE_ANY_ACCESS) 00021 00022 typedef struct _change { 00023 void *data; 00024 loff_t pos; 00025 int size; 00026 struct _change *next; 00027 } CHANGE; 00028 00029 00030 static CHANGE *changes,*last; 00031 static int did_change = 0; 00032 static HANDLE fd; 00033 static LARGE_INTEGER CurrentOffset; 00034 00035 unsigned device_no; 00036 00037 static int WIN32close(HANDLE fd); 00038 #define close WIN32close 00039 static int WIN32read(HANDLE fd, void *buf, unsigned int len); 00040 #define read WIN32read 00041 static int WIN32write(HANDLE fd, void *buf, unsigned int len); 00042 #define write WIN32write 00043 static loff_t WIN32llseek(HANDLE fd, loff_t offset, int whence); 00044 #ifdef llseek 00045 #undef llseek 00046 #endif 00047 #define llseek WIN32llseek 00048 00049 //static int is_device = 0; 00050 00051 void fs_open(PUNICODE_STRING DriveRoot,int rw) 00052 { 00053 OBJECT_ATTRIBUTES ObjectAttributes; 00054 IO_STATUS_BLOCK Iosb; 00055 NTSTATUS Status; 00056 00057 InitializeObjectAttributes(&ObjectAttributes, 00058 DriveRoot, 00059 0, 00060 NULL, 00061 NULL); 00062 00063 Status = NtOpenFile(&fd, 00064 FILE_GENERIC_READ | (rw ? FILE_GENERIC_WRITE : 0), 00065 &ObjectAttributes, 00066 &Iosb, 00067 rw ? 0 : FILE_SHARE_READ, 00068 FILE_SYNCHRONOUS_IO_ALERT); 00069 if (!NT_SUCCESS(Status)) 00070 { 00071 DPRINT1("NtOpenFile() failed with status 0x%.08x\n", Status); 00072 return; 00073 } 00074 00075 // If rw is specified, then the volume should be exclusively locked 00076 if (rw) fs_lock(TRUE); 00077 00078 // Query geometry and partition info, to have bytes per sector, etc 00079 00080 CurrentOffset.QuadPart = 0LL; 00081 00082 changes = last = NULL; 00083 did_change = 0; 00084 } 00085 00086 BOOLEAN fs_isdirty() 00087 { 00088 ULONG DirtyMask = 0; 00089 NTSTATUS Status; 00090 IO_STATUS_BLOCK IoSb; 00091 00092 /* Check if volume is dirty */ 00093 Status = NtFsControlFile(fd, 00094 NULL, NULL, NULL, &IoSb, 00095 FSCTL_IS_VOLUME_DIRTY, 00096 NULL, 0, &DirtyMask, sizeof(DirtyMask)); 00097 00098 if (!NT_SUCCESS(Status)) 00099 { 00100 DPRINT1("NtFsControlFile() failed with Status 0x%08x\n", Status); 00101 return FALSE; 00102 } 00103 00104 /* Convert Dirty mask to a boolean value */ 00105 return (DirtyMask & 1); 00106 } 00107 00108 NTSTATUS fs_lock(BOOLEAN LockVolume) 00109 { 00110 NTSTATUS Status; 00111 IO_STATUS_BLOCK IoSb; 00112 00113 /* Check if volume is dirty */ 00114 Status = NtFsControlFile(fd, 00115 NULL, NULL, NULL, &IoSb, 00116 LockVolume ? FSCTL_LOCK_VOLUME : 00117 FSCTL_UNLOCK_VOLUME, 00118 NULL, 0, NULL, 0); 00119 00120 if (!NT_SUCCESS(Status)) 00121 { 00122 DPRINT1("NtFsControlFile() failed with Status 0x%08x\n", Status); 00123 } 00124 00125 return Status; 00126 } 00127 00128 void fs_dismount() 00129 { 00130 NTSTATUS Status; 00131 IO_STATUS_BLOCK IoSb; 00132 00133 /* Check if volume is dirty */ 00134 Status = NtFsControlFile(fd, 00135 NULL, NULL, NULL, &IoSb, 00136 FSCTL_DISMOUNT_VOLUME, 00137 NULL, 0, NULL, 0); 00138 00139 if (!NT_SUCCESS(Status)) 00140 { 00141 DPRINT1("NtFsControlFile() failed with Status 0x%08x\n", Status); 00142 } 00143 } 00144 00145 void fs_read(loff_t pos,int size,void *data) 00146 { 00147 CHANGE *walk; 00148 int got; 00149 #if 1 // TMN 00150 const size_t readsize_aligned = (size % 512) ? (size + (512 - (size % 512))) : size; // TMN: 00151 const loff_t seekpos_aligned = pos - (pos % 512); // TMN: 00152 const size_t seek_delta = (size_t)(pos - seekpos_aligned); // TMN: 00153 const size_t readsize = (size_t)(pos - seekpos_aligned) + readsize_aligned; // TMN: 00154 char* tmpBuf = vfalloc(readsize_aligned); // TMN: 00155 if (llseek(fd,seekpos_aligned,0) != seekpos_aligned) pdie("Seek to %I64d",pos); 00156 if ((got = read(fd,tmpBuf,readsize_aligned)) < 0) pdie("Read %d bytes at %I64d",size,pos); 00157 assert(got >= size); 00158 got = size; 00159 assert(seek_delta + size <= readsize); 00160 memcpy(data, tmpBuf+seek_delta, size); 00161 vffree(tmpBuf); 00162 #else // TMN: 00163 if (llseek(fd,pos,0) != pos) pdie("Seek to %lld",pos); 00164 if ((got = read(fd,data,size)) < 0) pdie("Read %d bytes at %lld",size,pos); 00165 #endif // TMN: 00166 if (got != size) die("Got %d bytes instead of %d at %I64d",got,size,pos); 00167 for (walk = changes; walk; walk = walk->next) { 00168 if (walk->pos < pos+size && walk->pos+walk->size > pos) { 00169 if (walk->pos < pos) 00170 memcpy(data,(char *) walk->data+pos-walk->pos,min((size_t)size, 00171 (size_t)(walk->size-pos+walk->pos))); 00172 else memcpy((char *) data+walk->pos-pos,walk->data,min((size_t)walk->size, 00173 (size_t)(size+pos-walk->pos))); 00174 } 00175 } 00176 } 00177 00178 00179 int fs_test(loff_t pos,int size) 00180 { 00181 void *scratch; 00182 int okay; 00183 00184 #if 1 // TMN 00185 const size_t readsize_aligned = (size % 512) ? (size + (512 - (size % 512))) : size; // TMN: 00186 const loff_t seekpos_aligned = pos - (pos % 512); // TMN: 00187 scratch = vfalloc(readsize_aligned); 00188 if (llseek(fd,seekpos_aligned,0) != seekpos_aligned) pdie("Seek to %lld",pos); 00189 okay = read(fd,scratch,readsize_aligned) == (int)readsize_aligned; 00190 vffree(scratch); 00191 #else // TMN: 00192 if (llseek(fd,pos,0) != pos) pdie("Seek to %lld",pos); 00193 scratch = vfalloc(size); 00194 okay = read(fd,scratch,size) == size; 00195 vffree(scratch); 00196 #endif // TMN: 00197 return okay; 00198 } 00199 00200 00201 void fs_write(loff_t pos,int size,void *data) 00202 { 00203 CHANGE *new; 00204 int did; 00205 00206 #if 1 //SAE 00207 if (FsCheckFlags & FSCHECK_IMMEDIATE_WRITE) { 00208 void *scratch; 00209 const size_t readsize_aligned = (size % 512) ? (size + (512 - (size % 512))) : size; 00210 const loff_t seekpos_aligned = pos - (pos % 512); 00211 const size_t seek_delta = (size_t)(pos - seekpos_aligned); 00212 boolean use_read = (seek_delta != 0) || ((readsize_aligned-size) != 0); 00213 00214 /* Aloc temp buffer if write is not aligned */ 00215 if (use_read) 00216 scratch = vfalloc(readsize_aligned); 00217 else 00218 scratch = data; 00219 00220 did_change = 1; 00221 if (llseek(fd,seekpos_aligned,0) != seekpos_aligned) pdie("Seek to %I64d",seekpos_aligned); 00222 00223 if (use_read) 00224 { 00225 /* Read aligned data */ 00226 if (read(fd,scratch,readsize_aligned) < 0) pdie("Read %d bytes at %I64d",size,pos); 00227 00228 /* Patch data in memory */ 00229 memcpy((char *)scratch+seek_delta, data, size); 00230 } 00231 00232 /* Write it back */ 00233 if ((did = write(fd,scratch,readsize_aligned)) == (int)readsize_aligned) 00234 { 00235 if (use_read) vffree(scratch); 00236 return; 00237 } 00238 if (did < 0) pdie("Write %d bytes at %I64d",size,pos); 00239 die("Wrote %d bytes instead of %d at %I64d",did,size,pos); 00240 } 00241 00242 new = vfalloc(sizeof(CHANGE)); 00243 new->pos = pos; 00244 memcpy(new->data = vfalloc(new->size = size),data,size); 00245 new->next = NULL; 00246 if (last) last->next = new; 00247 else changes = new; 00248 last = new; 00249 00250 #else //SAE 00251 if (write_immed) { 00252 did_change = 1; 00253 if (llseek(fd,pos,0) != pos) pdie("Seek to %lld",pos); 00254 if ((did = write(fd,data,size)) == size) return; 00255 if (did < 0) pdie("Write %d bytes at %lld",size,pos); 00256 die("Wrote %d bytes instead of %d at %lld",did,size,pos); 00257 } 00258 new = vfalloc(sizeof(CHANGE)); 00259 new->pos = pos; 00260 memcpy(new->data = vfalloc(new->size = size),data,size); 00261 new->next = NULL; 00262 if (last) last->next = new; 00263 else changes = new; 00264 last = new; 00265 #endif //SAE 00266 } 00267 00268 00269 static void fs_flush(void) 00270 { 00271 CHANGE *this; 00272 int old_write_immed = (FsCheckFlags & FSCHECK_IMMEDIATE_WRITE); 00273 00274 /* Disable writes to the list now */ 00275 FsCheckFlags |= FSCHECK_IMMEDIATE_WRITE; 00276 00277 while (changes) { 00278 this = changes; 00279 changes = changes->next; 00280 00281 fs_write(this->pos, this->size, this->data); 00282 00283 vffree(this->data); 00284 vffree(this); 00285 } 00286 00287 /* Restore values */ 00288 if (!old_write_immed) FsCheckFlags ^= FSCHECK_IMMEDIATE_WRITE; 00289 } 00290 00291 00292 int fs_close(int write) 00293 { 00294 CHANGE *next; 00295 int changed; 00296 00297 changed = !!changes; 00298 if (write) fs_flush(); 00299 else while (changes) { 00300 next = changes->next; 00301 vffree(changes->data); 00302 vffree(changes); 00303 changes = next; 00304 } 00305 if (close(fd) < 0) pdie("closing file system"); 00306 return changed || did_change; 00307 } 00308 00309 00310 int fs_changed(void) 00311 { 00312 return !!changes || did_change; 00313 } 00314 00315 /* Local Variables: */ 00316 /* tab-width: 8 */ 00317 /* End: */ 00318 00319 static int WIN32close(HANDLE FileHandle) 00320 { 00321 if (!NT_SUCCESS(NtClose(FileHandle))) return -1; 00322 00323 return 0; 00324 } 00325 00326 static int WIN32read(HANDLE FileHandle, void *buf, unsigned int len) 00327 { 00328 IO_STATUS_BLOCK IoStatusBlock; 00329 NTSTATUS Status; 00330 00331 Status = NtReadFile(FileHandle, 00332 NULL, 00333 NULL, 00334 NULL, 00335 &IoStatusBlock, 00336 buf, 00337 len, 00338 &CurrentOffset, 00339 NULL); 00340 if (!NT_SUCCESS(Status)) 00341 { 00342 DPRINT1("NtReadFile() failed (Status %lx)\n", Status); 00343 return -1; 00344 } 00345 00346 CurrentOffset.QuadPart += len; 00347 return (int)len; 00348 } 00349 00350 static int WIN32write(HANDLE FileHandle, void *buf, unsigned int len) 00351 { 00352 IO_STATUS_BLOCK IoStatusBlock; 00353 NTSTATUS Status; 00354 00355 Status = NtWriteFile(FileHandle, 00356 NULL, 00357 NULL, 00358 NULL, 00359 &IoStatusBlock, 00360 buf, 00361 len, 00362 &CurrentOffset, 00363 NULL); 00364 if (!NT_SUCCESS(Status)) 00365 { 00366 DPRINT1("NtWriteFile() failed (Status %lx)\n", Status); 00367 return -1; 00368 } 00369 00370 CurrentOffset.QuadPart += len; 00371 return (int)len; 00372 } 00373 00374 static loff_t WIN32llseek(HANDLE fd, loff_t offset, int whence) 00375 { 00376 CurrentOffset.QuadPart = (ULONGLONG)offset; 00377 00378 return offset; 00379 } Generated on Sun May 27 2012 04:27:44 for ReactOS by
1.7.6.1
|