ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

io.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.