|
|
1.1.1.2 ! root 1: This is documentation for the dmsdos library. 10Sep1998 1.1 root 2: 3: 4: The dmsdos library, libdmsdos.a, provides the dmsdos interface that is known 5: from the kernel to a user-level process. This is acchieved by compiling the 6: dmsdos code simply in a different way (well, with some rather dirty tricks). 7: 8: The library is intended to export the following functions: 9: 1.1.1.2 ! root 10: open_cvf ! 11: close_cvf ! 12: dbl_bitfat_value ! 13: dbl_fat_nextcluster ! 14: dbl_mdfat_cluster2sector ! 15: dbl_mdfat_value ! 16: dmsdos_read_cluster ! 17: dmsdos_write_cluster ! 18: raw_bread ! 19: raw_brelse ! 20: raw_getblk ! 21: raw_mark_buffer_dirty ! 22: raw_set_uptodate ! 23: simple_check ! 24: stac_bitfat_state 1.1 root 25: 26: In fact, it exports much more, but only these listed here are guaranteed 27: to be kept in future versions. Well, one thing should be important to know: 28: The library does NOT export virtual sector management. It will never do. 29: 30: The functions are just used like in the kernel. For prototypes, see file 1.1.1.2 ! root 31: dmsdos.h. How to use them see the sources. There's some example code ! 32: how to use the library (dcread.c). 1.1 root 33: 34: The first two, open_cvf and close_cvf, are special. They are called instead 35: of mounting and unmounting the CVF. 36: 37: How to "mount" a CVF (example code): 38: 1.1.1.2 ! root 39: #include "lib_interface.h" ! 40: #include "dmsdos.h" ! 41: 1.1 root 42: struct super_block*sb; 43: sb=open_cvf("CVF_Filename",rwflag /*0=RDONLY or 1=RDWR*/); 44: if(sb==NULL) 45: { fprintf(stderr,"open CVF failed\n"); 46: exit(1); 47: } 48: 49: Keep the sb pointer. It must be passed to a lot of functions. It can be used 50: in the same way as in the kernel. The sb pointer is used to distinguish 51: between several open CVFs (in fact, in sb->s_dev the file descriptor is 52: stored). 53: 54: After use, the CVF must be "unmounted" again: 55: 56: close_cvf(sb); 57: 58: If you want to see more example code, look at the dcread utility source 59: (file dcread.c in the src directory). 60: 61: Notes: 62: * The user-level functions are single-threaded. You cannot run several 63: processes on the same CVF unless all are only reading. The library 64: uses flock in order to detect such situations and just denies access 65: in that case. You can however use different CVFs in parallel, even 66: read-write, even in one program. 1.1.1.2 ! root 67: * You should use this library only to access a CVF that is currently ! 68: _not_ mounted. There's a high risk of destroying the CVF or even ! 69: crashing the system otherwise. ! 70: * You should not touch CVFs that are currently used by dosemu with ! 71: wholedisk or partition access. Again there's a high risk of destroying ! 72: the CVF or crashing dosemu otherwise. 1.1 root 73: * If you do not intend to write to the CVF, open it in read-only mode. 74: Then the CVF is not locked exclusively and other processes are allowed 75: to read the CVF at the same time. 76: * The library prints the "kernel" messages to stderr. It obeys the 1.1.1.2 ! root 77: loglevel variable. The only way to make libdmsdos quiet is to ! 78: direct stderr into a file or to /dev/null. 1.1 root 79: * The first call of open_cvf initializes the library and prints some 80: version information to stderr. 81: * open_cvf does not do a filesystem check. If you do want the same 82: simple filesystem check that dmsdos usually does when mounting, call 83: simple_check afterwards. 84: * open_cvf may open the filesystem read-only though you request 85: read-write access. This happens if write access is denied or if the 86: dmsdos subsystem detects unexpected problems with the CVF. You may 87: not like this behaviour, but it's best for long life of your CVFs :) 88: Programmers please check sb->s_flags for the MS_RDONLY flag after 89: calling open_cvf to be sure. 90: * To compile your application using the dmsdos library you should under 91: no cirumstances define the macro __KERNEL__ for the whole program. 1.1.1.2 ! root 92: It causes problems with libc6. 1.1 root 93: 94: As an idea what the dmsdos library might be good for: 95: 1.1.1.2 ! root 96: * A mtools clone for CVFs, for example called dtools. (A simple program, ! 97: dcread, exists but its quatilty cannot be compared to mtools. Sorry.) ! 98: * A fsck.dmsdos. (An incomplete alpha test version exists.) ! 99: * A defragmentation program. (Not yet written.) 1.1 root 100: * For debugging dmsdos at user level (it's the same source code). 1.1.1.2 ! root 101: * An external fs for midnight commander. (A read-only interface program, ! 102: mcdmsdos, exists.) 1.1 root 103: * ... add your favourite idea here :) 1.1.1.2 ! root 104: * ... I've even received mail about whether it would be possible to ! 105: port libdmsdos to Win32 and use it for a Win95/98/NT driver :)) 1.1 root 106: 107: Support for a shared dmsdos library 108: ----------------------------------- 109: 1.1.1.2 ! root 110: libdmsdos can be compiled as a shared library. You must edit the ! 111: Makefile in the src directory for that purpose. Note that the default ! 112: installation does not compile the shared library. This is intended. If ! 113: you are not an experienced shared library hacker please be careful. It's ! 114: easy to screw up some binaries with shared libraries :) 1.1 root 115: 116: You should not use the dmsdos shared library for now as there's currently no 117: standard that ensures that future versions will be backwards compatible. 118: Link statically with libdmsdos.a unless disk space or memory is very critical. 119: 120: WARNING: If there's a shared dmsdos library lying around, gcc defaults to 1.1.1.2 ! root 121: linking *dynamically* all programs that need this library. For example, if 1.1 root 122: libdmsdos.so is present and you recompile dmsdosfsck, the binary will be 1.1.1.2 ! root 123: dynamically linked against that library. This can be very confusing and may ! 124: not do what you want :( ! 125: ! 126: Built-in direct translation access mode ! 127: --------------------------------------- ! 128: ! 129: This feature has been added to the library for convenience. It only works ! 130: for FAT12 or FAT16 MSDOS filesystems. It does not work, for example, for ! 131: CVFs on a cdrom or in a FAT32 or non-FAT filesystem. ! 132: ! 133: The dmsdos library can access a CVF that resides in an uncompressed FAT12 or ! 134: FAT16 MSDOS host partition even if the uncompressed host partition is not ! 135: mounted (this was programmed in fact by cut'n'paste of some old dmsdosfs ! 136: functions). If there are more than one CVF in that partition, the first ! 137: valid CVF found in the root directory of the uncompressed host partition ! 138: is used. If you want to select one of more CVFs, append a colon and the ! 139: extension of the CVF to the filename. ! 140: ! 141: For example, if your uncompressed host partition is /dev/hda1 and you want ! 142: to access the CVF DRVSPACE.001 on that partition, use "/dev/hda1:001" as ! 143: filename when calling open_cvf. If DRVSPACE.001 is the only CVF inside ! 144: /dev/hda1 you can even use "/dev/hda1" and it will find the CVF. ! 145: ! 146: This special feature allows, for example, dmsdosfsck to check a CVF in ! 147: a partition that has not yet been mounted. This may be useful at boot time ! 148: to check CVFs :) ! 149: ! 150: Standard C library functions that libdmsdos needs ! 151: ------------------------------------------------- ! 152: ! 153: If you want to use libdmsdos in an environment where the standard C library ! 154: functions are not available then you must write an emulation for all these ! 155: functions and link your code against it instead of the standard C library. ! 156: The emulation needn't be full-featured like the C library. Look at the source ! 157: if you are in doubt. ! 158: ! 159: close (4) ! 160: errno ! 161: exit (3) ! 162: flock (only if compiled with -DUSE_FLOCK) (4) ! 163: sopen (only if compiled with -DUSE_SOPEN) (4) (8) ! 164: fprintf (2) ! 165: free (6) ! 166: lseek (1) (7) ! 167: malloc (6) ! 168: memcpy ! 169: memmove ! 170: memset ! 171: open (only if _not_ compiled with -DUSE_SOPEN) (8) ! 172: read (1) ! 173: strcat ! 174: strerror ! 175: strncat ! 176: strncmp ! 177: strncpy ! 178: strrchr ! 179: time (5) ! 180: vsprintf (2) (9) ! 181: write (1) ! 182: ! 183: (1) only used in aligned 512 byte blocks ! 184: (2) only used for logging to stderr, no other files are used ! 185: (3) used for abort in case of fatal error ! 186: (4) locking may be left out ! 187: (5) a time-proportional counter would be enough, needn't be exact ! 188: (6) called quite often, be aware of possible memory fragmentation ! 189: (7) only used on 512 byte boundaries with SEEK_SET, also used to find out ! 190: file size with SEEK_END ! 191: (8) must parse filename (invent your own syntax if necessary) ! 192: (9) a free, portable emulation is in linux/lib/vsprint.c ! 193: ! 194: If possible, please avoid hacking around in dmsdos kernel code if the library ! 195: does not work in your environment (unless it's a bug). The only files that ! 196: should be modified due to OS or compiler differences are lib_interface.c and ! 197: lib_interface.h. Please surround your changes with appropriate #ifdef's so ! 198: the modified code still compiles under all those environments where it worked ! 199: before. Please do not violate portability of the code. Hardware comes and ! 200: goes, OSses are born and die, but portable code survives :) ! 201: ! 202: ! 203: dmsdos library reference guide ! 204: ------------------------------ ! 205: ! 206: All functions need the header files lib_interface.h and dmsdos.h. Error ! 207: checking is not always possible. This is because some of the low-level kernel ! 208: functions dmsdos calls when running as kernel module never fail. In user ! 209: space, there may be failures, however. This means, libdmsdos is currently ! 210: not 100% error-safe. As a workaround (that works under the standard C library) ! 211: you can set errno to NO_ERROR before calling the function and afterwards ! 212: check whether it has changed to an error value. ! 213: ! 214: open_cvf: ! 215: ! 216: struct super_block* open_cvf(char*filename,int rwflag) ! 217: ! 218: Opens CVF described by filename. rwflag is 0 for read-only, otherwise ! 219: the file is opened read-write. The file is locked read-only or ! 220: read-write, depending on rwflag (by calling flock or sopen). ! 221: ! 222: filename is interpreted in a special way if it contains a colon. ! 223: See chapter 'Built-in direct translation access mode' above. The colon ! 224: and the rest of the string after it are stripped off before the filename ! 225: is forwarded to the libc function open or sopen. ! 226: ! 227: Return Value: Pointer to valid super_block structure (which can be ! 228: interpreted as a kind of file handle), NULL if failed. ! 229: ! 230: Note: Keep the super_block pointer. Most dmsdos functions need it in ! 231: order to identify the CVF. ! 232: ! 233: Note: The CVF may be opened read-only though you opened it in read-write ! 234: mode. This happens if the dmsdos code detects unexpected errors in the ! 235: CVF. Please check sb->s_flags for the MS_RDONLY bit after calling ! 236: open_cvf. ! 237: ! 238: close_cvf: ! 239: ! 240: void close_cvf(struct super_block*sb) ! 241: ! 242: Closes the CVF. If necessary, the file is unlocked before. ! 243: ! 244: dbl_bitfat_value: ! 245: ! 246: int dbl_bitfat_value(struct super_block*sb,int sectornr,int*new) ! 247: ! 248: Reads or writes bitfat value that belongs to sector sectornr. ! 249: *** This is a low-level function you are probably never interested in. ! 250: Bitfat values are CVF format specific. You do not need to know them ! 251: unless debugging write access :)) ! 252: ! 253: If new is NULL the value is read and returned. ! 254: Otherwise the actual value is replaced with that one found in *new. ! 255: ! 256: Return value: read access: read value. write access: undefined. A ! 257: negative value indicates an error. ! 258: ! 259: dbl_fat_nextcluster: ! 260: ! 261: int dbl_fat_nextcluster(struct super_block*sb,int clusternr,int*new) ! 262: ! 263: Reads or writes the FAT entry for cluster clusternr. (You should know ! 264: what a FAT is, otherwise please read a good book on Dos disk access.) ! 265: ! 266: If new is NULL the value is read and returned. ! 267: Otherwise the actual value is replaced with that one found in *new. ! 268: ! 269: Return value: read access: read value. write access: undefined. ! 270: -1 means the cluster is marked as last cluster in a file or an error ! 271: occured. Errors may also be represented by other negative results. ! 272: ! 273: Note: -1 can also be used for write access in order to indicate end of ! 274: file mark. It is automatically converted to the right value for the FAT ! 275: size. ! 276: ! 277: Note: if clusternr is invalid a -1 is returned. This usually makes ! 278: runaway FAT reading loops break as if there was an EOF in the cluster ! 279: chain. There's no means to find out whether a -1 is an error or an EOF ! 280: except making sure a valid cluster number is given. ! 281: ! 282: dbl_mdfat_cluster2sector: ! 283: ! 284: int dbl_mdfat_cluster2sector(struct super_block*sb,int clusternr) ! 285: ! 286: This is a low-level function that reads the mdfat and extracts the ! 287: starting sector information from it. It may be useful for write ! 288: access with dmsdos_write_cluster. It returns the starting sector number ! 289: of cluster clusternr. ! 290: *** Do not use the standard formula that is used in a normal FAT ! 291: filesystem (multiplying the cluster number with the number of sectors ! 292: per cluster and adding some offsets) - that formula is not valid in a ! 293: compressed filesystem. Use dbl_mdfat_cluster2sector instead. ! 294: ! 295: Return value: starting sector of the cluster clusternr. If negative, ! 296: an error occured. ! 297: ! 298: Note: see dmsdos_write_cluster what this function is useful for. ! 299: ! 300: dbl_mdfat_value: ! 301: ! 302: int dbl_mdfat_value(struct super_block* sb,int clusternr, ! 303: Mdfat_entry*new,Mdfat_entry*mde) ! 304: ! 305: Reads or writes the mdfat/allocmap entry that belongs to cluster ! 306: clusternr. ! 307: *** This is a low-level function you are probably never interested in. ! 308: Mdfat values are CVF format specific. You do not need to know them ! 309: unless debugging dmsdos :)) ! 310: ! 311: If new is NULL the value is read and stored in *mde. ! 312: Otherwise the actual value is replaced with that one found in *new. ! 313: ! 314: Return value: A negative value indicates an error. ! 315: Note: consider *mde as undefined after write access. ! 316: ! 317: dmsdos_read_cluster: ! 318: ! 319: int dmsdos_read_cluster(struct super_block*sb, ! 320: unsigned char*clusterd, int clusternr) ! 321: ! 322: Reads cluster clusternr in clusterd. The dmsdos library handles all ! 323: low-level access including decompression of the data. ! 324: ! 325: *** Be sure to have reserved enough memory for the data that this ! 326: function writes into clusterd. Usually, use a full cluster size. ! 327: How to determine the full cluster size see the dcread example code. ! 328: ! 329: Return value: number of bytes actually read (clusters may be shorter ! 330: than the full size in a CVF, which is not possible in an uncompressed ! 331: FAT filesystem). Usually, you can ignore this unless you use write ! 332: access. (A cluster may even have length zero.) Just in case, if the ! 333: cluster is shorter than full size the unused slack is zero'd out. On ! 334: error, a negative value is returned. ! 335: ! 336: Note: This function cannot read the root directory (cluster 0). You must ! 337: use low-level disk access for that (i.e. raw_bread). See also the dcread ! 338: example code. ! 339: ! 340: dmsdos_write_cluster: ! 341: ! 342: int dmsdos_write_cluster(struct super_block*sb, unsigned char* clusterd, ! 343: int length, int clusternr, int near_sector, ! 344: int ucflag) ! 345: ! 346: Writes cluster clusternr from clusterd back to disk. The dmsdos ! 347: library handles all low-level disk access including compression. ! 348: ! 349: length is the position of the last valid byte plus 1 in clusterd. ! 350: This is usually the value that dmsdos_read_cluster returned when you ! 351: read this cluster before unless you modified some bytes beyond that ! 352: value. The idiot-proof value is always the full cluster size. ! 353: *** Warning: if length is too low, the data may be truncated during ! 354: write access. If it is too high disk space is wasted. ! 355: ! 356: ucflag is a flag that indicates whether libdmsdos should try to ! 357: compress the data. 0 means try to compress, 1 means write the data ! 358: without compression. Please do not use other values than 0 and 1 ! 359: (they do exist but have some very special meanings). ! 360: ! 361: near_sector can be used to control where libdmsdos tries to place ! 362: the data on disk. For good performance on large files, it should ! 363: be set to the start sector value of the cluster that preceeds the ! 364: actual cluster in the file. The start sector value can be obtained with ! 365: dbl_mdfat_cluster2sector on that preceeding cluster. (This way actually ! 366: helps avoiding low-level fragmentation _and_ file data fragmentation in ! 367: the CVF.) ! 368: *** Do not use the standard formula that is used in a normal FAT ! 369: filesystem (multiplying the cluster number with the number of sectors ! 370: per cluster and adding some offsets) - that formula is not valid in a ! 371: compressed filesystem. ! 372: ! 373: The near_sector value is just meant as a hint. If there's not enough ! 374: free space on the disk around near_sector, dmsdos writes the data ! 375: somewhere else. If near_sector is set to zero, dmsdos uses an internal ! 376: way to find out a good value that avoids low-level fragmentation but ! 377: that is not necessarily good for performance on the file that is being ! 378: written. Nevertheless, 0 always works. ! 379: ! 380: WARNING: If you are writing a directory cluster you should not compress ! 381: the data (it would hurt performance a lot). Some of the original CVF Dos ! 382: software versions never compress directories, so you shouldn't do ! 383: either (it may cause compatibility problems otherwise). You also should ! 384: always use full cluster size for directories on some CVF versions. In ! 385: order to feel safe you can use the DIR_MAY_BE_COMPRESSED and ! 386: DIR_MAY_BE_SHORT macros. Have a look at their definition in file ! 387: dmsdos.h. ! 388: ! 389: Return value: A negative value indicates an error. ! 390: ! 391: Note: The data in clusterd are not destroyed by this function. ! 392: ! 393: raw_bread: ! 394: ! 395: struct buffer_head* raw_bread(struct super_block*sb,int block) ! 396: ! 397: Read a 512 byte block from the CVF. The data are read without further ! 398: modification. Block numbering scheme begins with zero. ! 399: ! 400: Return value: pointer to a buffer_head structure that contains the 512 ! 401: bytes of data that represent the data block. The data are in ! 402: buffer_head->b_data in an unsigned character array (see the dcread ! 403: example). On error, NULL is returned. ! 404: ! 405: Note: The data are returned in dynamically allocated memory. If you ! 406: do not need the data any more, you must free them by calling raw_brelse ! 407: in the buffer_head structure pointer. ! 408: ! 409: Note: You may modify the data. You must call raw_mark_buffer_dirty ! 410: after modification (this writes the data back to disk) and before ! 411: raw_brelse. ! 412: ! 413: Note: If you want to overwrite the whole block, use raw_getblk instead ! 414: of raw_bread (this leaves out the unnecessary disk read access). ! 415: ! 416: raw_brelse: ! 417: ! 418: void raw_brelse(struct super_block*sb,struct buffer_head*bh) ! 419: ! 420: Release dynamic memory for the data read by raw_bread. ! 421: ! 422: raw_getblk: ! 423: ! 424: struct buffer_head* raw_getblk(struct super_block*sb,int block) ! 425: ! 426: Like raw_bread, but leaves out the actual disk access. This is intended ! 427: to leave out unnecessary disk read access if you want to overwrite the ! 428: whole block. Consider the data as undefined. See raw_bread. ! 429: ! 430: Note: raw_getblk should be followed by a call of raw_set_uptodate ! 431: for compatibility. See there. ! 432: ! 433: raw_mark_buffer_dirty: ! 434: ! 435: void raw_mark_buffer_dirty(struct super_block*sb,struct buffer_head*bh, ! 436: int dirty_val) ! 437: ! 438: Write data back to disk after they have been modified. ! 439: ! 440: dirty_val must be always 1 (due to a misunderstanding/bug in dmsdos). ! 441: ! 442: Note: This function does not indicate an error. This is bad, but it is ! 443: because the Linux kernel interface also does not return error codes with ! 444: this function. As a hack (that works with libc) you can set errno to ! 445: NO_ERROR and check it afterwards, but note that this will not work in ! 446: the dmsdos kernel driver. Usually, there cannot be an error during that ! 447: kind of write access unless the disk has bad sectors. ! 448: ! 449: raw_set_uptodate: ! 450: ! 451: void raw_set_uptodate(struct super_block*sb,struct buffer_head*bh,int v) ! 452: ! 453: No longer used (does nothing in libdmsdos). ! 454: ! 455: For compatibility with the kernel driver, this should be called with ! 456: v=1 after raw_getblk on the buffer_head pointer that raw_getblk returned ! 457: (unless it's NULL due to failure). ! 458: ! 459: simple_check: ! 460: ! 461: int simple_check(struct super_block*sb,int repair) ! 462: ! 463: Check some internal filesystem tables for consistency. ! 464: ! 465: If repair is 1 libdmsdos tries to correct errors (the CVF must have been ! 466: opened read-write in that case). If it is 0 the tables are just checked. ! 467: ! 468: Return value: a negative value indicates an error, i.e. either the ! 469: tables are inconsistent or the errors, if any, could not be repaired. ! 470: ! 471: Note: It is strongly recommended to run simple_check immediately after ! 472: opening the CVF if you want to write to it. Do not write to a CVF if ! 473: simple_check fails on it (you may detroy some files in the CVF). As ! 474: CVFs are known to be very prone to so-called bitfat errors, you probably ! 475: want to give the program that you are writing a kind of "expert option" ! 476: that lets simple_check run with repair=1. The same warnings apply as to ! 477: the dmsdos mount option bitfaterrs:repair :)) ! 478: ! 479: stac_bitfat_state: ! 480: ! 481: int stac_bitfat_state(struct super_block*sb,int new_state) ! 482: ! 483: Stacker has a kind of clean/dirty flag that indicates whether the CVF ! 484: was correctly unmounted. This function can be used to manipulate it. ! 485: *** This is a low-level function you should not use unless you are a ! 486: dmsdos and Stacker expert. See the dmsdos source code. ! 487: ! 488: Note: Do not call this function on non-Stacker CVFs. ! 489: ! 490: ! 491: Programming notes ! 492: ----------------- ! 493: ! 494: In a normal libdmsdos application, you open the CVF with open_cvf. If you ! 495: intend to write to the CVF later, you should call simple_check after that ! 496: and refuse write access if an error is found. ! 497: ! 498: Then you use dmsdos_read_cluster and dmsdos_write_cluster to access the ! 499: CVF. Only for the root directory you need raw_bread, raw_mark_buffer_dirty ! 500: and raw_brelse. For following files you need to read the FAT with ! 501: dbl_fat_nextcluster. ! 502: ! 503: You write to the FAT with dbl_fat_nextcluster in order to truncate files or ! 504: append data to them, or even to delete files and directories and to create ! 505: new ones - all like in a usual FAT filesystem. ! 506: ! 507: If you are done, don't forget to close the CVF with close_cvf. ! 508: ! 509: Here is a simple example that illustrates the usage of all important ! 510: libdmsdos functions. You should not compile and execute this example as ! 511: it's not always correct C syntax. Things like error handling have been left ! 512: out to simplify the code (which is not good). Furthermore, the program just ! 513: pokes around in the CVF which would be bad for your data :) ! 514: ! 515: ! 516: #include "lib_interface.h" ! 517: #include "dmsdos.h" ! 518: ! 519: struct super_block*sb; ! 520: struct Dblsb*dblsb; ! 521: ! 522: /* open the CVF read-write */ ! 523: sb=open_cvf("dblspace.001",1); ! 524: if(sb==NULL)...error... ! 525: ! 526: /* check the CVF */ ! 527: if(simple_check(sb,0)<0)...error... ! 528: ! 529: /* read and display cluster 2 as hex numbers */ ! 530: int i; ! 531: int size; ! 532: int full_size; ! 533: unsigned char* clusterd; ! 534: ! 535: /* determine full size */ ! 536: dblsb=MSDOS_SB(sb)->private_data; ! 537: full_size=dblsp->s_sectperclust*512; ! 538: ! 539: clusterd=malloc(full_size); ! 540: if(clusterd==NULL)...error... ! 541: ! 542: size=dmsdos_read_cluster(sb,clusterd,2); ! 543: if(size<0)...error... ! 544: for(i=0;i<size;++i) printf("%x ",clusterd[i]); ! 545: printf("\n"); ! 546: ! 547: /* modify one byte at position 4234 and write cluster 2 back */ ! 548: int pos; ! 549: ! 550: pos=4234; ! 551: clusterd[4234]=123; ! 552: if(size<=pos)size=pos+1; /* adapt size */ ! 553: ! 554: if(dmsdos_write_cluster(sb,clusterd,size,2,0,0)<0)...error... ! 555: ! 556: free(clusterd); /* free memory that is no longer needed */ ! 557: ! 558: /* determine which cluster follows cluster 2 in fat */ ! 559: int fatval; ! 560: ! 561: fatval=dbl_fat_nextcluster(sb,2,NULL); ! 562: if(fatval==0) printf("cluster 2 is unused\n"); ! 563: else if(fatval==-1) printf("cluster 2 is marked as EOF\n"); ! 564: else printf("cluster 2 is followed by cluster %d in FAT\n"); ! 565: ! 566: /* mark it as EOF */ ! 567: int new; ! 568: ! 569: new=-1; ! 570: dbl_fat_nextcluster(sb,2,&new); ! 571: ! 572: /* read root directory */ ! 573: int i; ! 574: unsigned char*data; ! 575: int number; ! 576: struct buffer_head*bh; ! 577: ! 578: dblsb=MSDOS_SB(sb)->private_data; ! 579: number=dblsb->s_rootdirentries*32/512; ! 580: startblock=dblsb->s_rootdir; ! 581: ! 582: data=malloc(number*512); ! 583: if(data==NULL)...error... ! 584: ! 585: for(i=0;i<number;++i) ! 586: { bh=raw_bread(sb,startblock+i); ! 587: if(bh==NULL)...error... ! 588: memcpy(data+i*512,bh->b_data,512); ! 589: raw_brelse(sb,bh); ! 590: } ! 591: /* complete root directory is now in data */ ! 592: ! 593: /* modify root directory */ ! 594: ...modify data where you like... ! 595: ! 596: /* write it back completely */ ! 597: for(i=0;i<number;++i) ! 598: { bh=raw_getblk(sb,startblock+i); /* or raw_bread(...) */ ! 599: if(bh==NULL)...error... ! 600: raw_set_uptodate(sb,bh,1); /* leave out if raw_bread used above */ ! 601: memcpy(bh->data,data+i*512,512); ! 602: raw_mark_buffer_dirty(sb,bh,1); ! 603: raw_brelse(sb,bh); ! 604: } ! 605: ! 606: free(data); /* free memory that is no longer needed */ ! 607: ! 608: /* we are done */ ! 609: close_cvf(sb); ! 610: ! 611: ! 612: For a piece of code that actually compiles and runs and does something ! 613: eventually useful and ... does not kill your data :-)) see the dcread ! 614: example program (file dcread.c).
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.