Annotation of dmsdos/doc/libdmsdos.doc, revision 1.1.1.2

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).

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.