Annotation of mstools/samples/sdktools/windiff/scandir.c, revision 1.1.1.1

1.1       root        1: 
                      2: /******************************************************************************\
                      3: *       This is a part of the Microsoft Source Code Samples. 
                      4: *       Copyright (C) 1993 Microsoft Corporation.
                      5: *       All rights reserved. 
                      6: *       This source code is only intended as a supplement to 
                      7: *       Microsoft Development Tools and/or WinHelp documentation.
                      8: *       See these sources for detailed information regarding the 
                      9: *       Microsoft samples programs.
                     10: \******************************************************************************/
                     11: 
                     12: /****************************** Module Header *******************************
                     13: * Module Name: SCANDIR.C
                     14: *
                     15: * Scan a directory tree and build a sorted list of filenames within that
                     16: * tree.
                     17: *
                     18: * Functions:
                     19: *
                     20: * dir_buildlist()
                     21: * dir_delete()
                     22: * dir_isfile()
                     23: * dir_firstitem()
                     24: * dir_nextitem()
                     25: * dir_findnextfile()
                     26: * dir_getrelname()
                     27: * dir_getfullname()
                     28: * dir_getroot_list()
                     29: * dir_getroot_item()
                     30: * dir_freerelname()
                     31: * dir_freefullname()
                     32: * dir_freeroot_list()
                     33: * dir_freerootitem()
                     34: * dir_getopenname()
                     35: * dir_freeopenname()
                     36: * dir_openfile()
                     37: * dir_closefile()
                     38: * dir_filesize()
                     39: * dir_startcopy()
                     40: * dir_endcopy()
                     41: * dir_copy()
                     42: * dir_finalelem()
                     43: * dir_cleardirect()
                     44: * dir_adddirect()
                     45: * dir_addfile()
                     46: * dir_scan()
                     47: * dir_isvaliddir()
                     48: * dir_isvalidfile()
                     49: * dir_fileinit()
                     50: * dir_dirinit()
                     51: * dir_getpathsize()
                     52: * dir_findnextfile()
                     53: *
                     54: * Comments:
                     55: *
                     56: * The call dir_buildlist takes a pathname and returns a handle. Subsequent
                     57: * calls to dir_firstitem and dir_nextitem return handles to
                     58: * items within the list, from which you can get the name of the
                     59: * file (relative to the original pathname, or complete), and filesize.
                     60: *
                     61: * The list can be either built entirely during the build call, or
                     62: * built one directory at a time as required by dir_nextitem calls. This
                     63: * option affects only relative performance, and is taken as a
                     64: * recommendation only (ie some of the time we will ignore the flag).
                     65: *
                     66: * The list is ordered alphabetically (case-insensitive using lstrcmpi).
                     67: * within any one directory, we list filenames before going on
                     68: * to subdirectory contents.
                     69: *
                     70: * All memory is allocated from a gmem_* heap hHeap declared
                     71: * and initialised elsewhere.
                     72: *
                     73: * The caller gets handles to two things: a DIRLIST, representing the
                     74: * entire list of filenames, and a DIRITEM: one item within the list.
                     75: *
                     76: * From the DIRITEM he can get the filename (including or excluding the
                     77: * tree root passed to dir_build*) - and also he can get to the next
                     78: * DIRITEM.
                     79: *
                     80: * We permit lazy building of the tree (usually so the caller can keep
                     81: * the user-interface up-to-date as we go along). In this case,
                     82: * we need to store information about how far we have scanned and
                     83: * what is next to do. We need to scan an entire directory at a time and then
                     84: * sort it so we can return files in the correct order.
                     85: *
                     86: * We scan an entire directory and store it in a DIRECT struct. This contains
                     87: * a list of DIRITEMs for the files in the current directory, and a list of
                     88: * DIRECTs for the subdirectories (possible un-scanned).
                     89: *
                     90: * dir_nextitem will use the list functions to get the next DIRITEM on the list.
                     91: * When the end of the list is reached, it will use the backpointer back to the
                     92: * DIRECT struct to find the next directory to scan.
                     93: *
                     94: ****************************************************************************/
                     95: 
                     96: #include <windows.h>
                     97: #include <stdlib.h>
                     98: #include <string.h>
                     99: #include <dos.h>
                    100: #include <direct.h>
                    101: 
                    102: #include "gutils.h"
                    103: #include "list.h"
                    104: #include "scandir.h"
                    105: #include "windiff.h"
                    106: #include "wdiffrc.h"
                    107: 
                    108: /*
                    109:  * Hold name and information about a given file (one ITEM in a DIRectory)
                    110:  * caller's DIRITEM handle is a pointer to one of these structures
                    111:  */
                    112: struct diritem {
                    113:         LPSTR name;             /* ptr to filename (final element only) */
                    114:         long size;              /* filesize */
                    115:         struct direct FAR * direct; /* containing directory */
                    116:         LPSTR localname;        /* name of temp copy of file */
                    117:         BOOL bLocalIsTemp;      /* true if localname is tempfile.
                    118:                                  */
                    119: };
                    120: 
                    121: 
                    122: /* DIRECT: Hold state about directory and current position in list of filenames.
                    123:  */
                    124: typedef struct direct {
                    125:         LPSTR relname;          /* name of dir relative to DIRLIST root */
                    126:         DIRLIST head;           /* back ptr (to get fullname) */
                    127:         struct direct FAR * parent; /* parent directory (NULL if above tree root)*/
                    128: 
                    129:         BOOL bScanned;          /* TRUE if scanned */
                    130:         LIST diritems;          /* list of DIRITEMs for files in cur. dir */
                    131:         LIST directs;           /* list of DIRECTs for child dirs */
                    132: 
                    133:         int pos;                /* where are we begin, files, dirs */
                    134:         struct direct FAR * curdir; /* subdir being scanned (ptr to list element)*/
                    135: } FAR * DIRECT;
                    136: 
                    137: /* Values for direct.pos */
                    138: #define DL_FILES        1       /* reading files from the diritems */
                    139: #define DL_DIRS         2       /* in the dirs: List_Next on curdir */
                    140: 
                    141: 
                    142: /*
                    143:  * The DIRLIST handle returned from a build function is in fact
                    144:  * a pointer to one of these
                    145:  */
                    146: struct dirlist {
                    147: 
                    148:         char rootname[256];        /* name of root of tree */
                    149:         BOOL bFile;             /* TRUE if root of tree is file, not dir */
                    150:         DIRECT dot;             /* dir  for '.' - for tree root dir */
                    151: };
                    152: 
                    153: extern BOOL bAbort;             /* from windiff.c (read only here). */
                    154: 
                    155: 
                    156: /* ------ memory allocation ---------------------------------------------*/
                    157: 
                    158: /* All memory is allocated from a heap created by the application */
                    159: extern HANDLE hHeap;
                    160: 
                    161: /*-- forward declaration of internal functions ---------------------------*/
                    162: 
                    163: LPSTR dir_finalelem(LPSTR path);
                    164: void dir_cleardirect(DIRECT dir);
                    165: void dir_adddirect(DIRECT dir, LPSTR path);
                    166: void dir_addfile(DIRECT dir, LPSTR path, DWORD size);
                    167: void dir_scan(DIRECT dir, BOOL bRecurse);
                    168: BOOL dir_isvaliddir(LPSTR path);
                    169: BOOL dir_isvalidfile(LPSTR path);
                    170: void dir_fileinit(DIRITEM pfile, DIRECT dir, LPSTR path, long size);
                    171: void dir_dirinit(DIRECT dir, DIRLIST head, DIRECT parent, LPSTR name);
                    172: long dir_getpathsize(LPSTR path);
                    173: DIRITEM dir_findnextfile(DIRLIST dl, DIRECT curdir);
                    174: 
                    175: 
                    176: 
                    177: /***************************************************************************
                    178:  * Function: dir_buildlist
                    179:  *
                    180:  * Purpose:
                    181:  *
                    182:  * Build a list of filenames
                    183:  *
                    184:  * Optionally build the list on demand, in which case we scan the
                    185:  * entire directory but don't recurse into subdirs until needed
                    186:  *
                    187:  */
                    188: 
                    189: DIRLIST
                    190: dir_buildlist(LPSTR path, BOOL bOnDemand)
                    191: {
                    192:         DIRLIST dl;
                    193:         BOOL bFile;
                    194:         
                    195:         /* first check if the path is valid */
                    196:         if (dir_isvaliddir(path)) {
                    197:                 bFile = FALSE;
                    198:         } else if (dir_isvalidfile(path)) {
                    199:                 bFile = TRUE;
                    200:         } else {
                    201:                 /* not valid */
                    202:                 return(NULL);
                    203:         }
                    204: 
                    205: 
                    206:         /* alloc and init the DIRLIST head */
                    207: 
                    208:         dl = (DIRLIST) gmem_get(hHeap, sizeof(struct dirlist));
                    209:         memset(dl, 0, sizeof(struct dirlist));
                    210: 
                    211:         /* convert the pathname to an absolute path */
                    212: 
                    213:         _fullpath(dl->rootname, path, sizeof(dl->rootname));
                    214: 
                    215:         dl->bFile = bFile;
                    216:         /* make a '.' directory for the current directory -
                    217:          * all files and subdirs will be listed from here
                    218:          */
                    219:         dl->dot = (DIRECT) gmem_get(hHeap, sizeof(struct direct));
                    220:         dir_dirinit(dl->dot, dl, NULL, ".");
                    221: 
                    222:         /* were we given a file or a directory ? */
                    223:         if (bFile) {
                    224:                 /* its a file. create a single file entry
                    225:                  * and set the state accordingly
                    226:                  */
                    227:                 dl->dot->bScanned = TRUE;
                    228: 
                    229:                 dir_addfile(dl->dot, dir_finalelem(path),
                    230:                                 dir_getpathsize(path));
                    231: 
                    232:                 return(dl);
                    233:         }
                    234: 
                    235:         /* scan the root directory and return. if we are asked
                    236:          * to scan the whole thing, this will cause a recursive
                    237:          * scan all the way down the tree
                    238:          */
                    239:         dir_scan(dl->dot, (!bOnDemand) );
                    240: 
                    241:         return(dl);
                    242: } /* dir_buildlist */
                    243: 
                    244: /***************************************************************************
                    245:  * Function: dir_delete
                    246:  *
                    247:  * Purpose:
                    248:  *
                    249:  * Free up the DIRLIST and all associated memory 
                    250:  */
                    251: void
                    252: dir_delete(DIRLIST dl)
                    253: {
                    254:         if (dl == NULL) {
                    255:                 return;
                    256:         }
                    257:         dir_cleardirect(dl->dot);
                    258:         gmem_free(hHeap, (LPSTR) dl->dot, sizeof(struct direct));
                    259: 
                    260: 
                    261:         gmem_free(hHeap, (LPSTR) dl, sizeof(struct dirlist));
                    262: }
                    263: 
                    264: 
                    265: 
                    266: /***************************************************************************
                    267:  * Function: dir_isfile
                    268:  *
                    269:  * Purpose:
                    270:  *
                    271:  * Was the original build request a file or a directory ? 
                    272:  */
                    273: BOOL
                    274: dir_isfile(DIRLIST dl)
                    275: {
                    276:         if (dl == NULL) {
                    277:                 return(FALSE);
                    278:         }
                    279: 
                    280:         return(dl->bFile);
                    281: }
                    282: 
                    283: /***************************************************************************
                    284:  * Function: dir_firstitem
                    285:  *
                    286:  * Purpose:
                    287:  *
                    288:  * Return the first file in the list, or NULL if no files found.
                    289:  * Returns a DIRITEM. This can be used to get filename, size and chcksum.
                    290:  * If there are no files in the root, we recurse down until we find a file.
                    291:  */
                    292: DIRITEM
                    293: dir_firstitem(DIRLIST dl)
                    294: {
                    295:         if (dl == NULL) {
                    296:                 return(NULL);
                    297:         }
                    298:         /*
                    299:          * reset the state to indicate that no files have been read yet
                    300:          */
                    301:         dl->dot->pos = DL_FILES;
                    302:         dl->dot->curdir = NULL;
                    303: 
                    304:         /* now get the next filename */
                    305:         return(dir_findnextfile(dl, dl->dot));
                    306: } /* dir_firstitem */
                    307: 
                    308: 
                    309: /***************************************************************************
                    310:  * Function:dir_nextitem
                    311:  *
                    312:  * Purpose:
                    313:  *
                    314:  * Get the next filename after the one given.
                    315:  *
                    316:  * The List_Next function can give us the next element on the list of files.
                    317:  * If this is null, we need to go back to the DIRECT and find the
                    318:  * next list of files to traverse (in the next subdir).
                    319:  *
                    320:  * After scanning all the subdirs, return to the parent to scan further
                    321:  * dirs that are peers of this, if there are any. If we have reached the end of
                    322:  * the tree (no more dirs in dl->dot to scan), return NULL.
                    323:  *
                    324:  * Don't recurse to lower levels unless fDeep is TRUE
                    325:  */
                    326: DIRITEM
                    327: dir_nextitem(DIRLIST dl, DIRITEM cur, BOOL fDeep)
                    328: {
                    329:         DIRITEM next;
                    330: 
                    331:         if ((dl == NULL) || (cur == NULL)) {
                    332:                 return(NULL);
                    333:         }
                    334:         if (bAbort) return NULL;  /* user requested abort */
                    335: 
                    336:         if ( (next = List_Next(cur)) != NULL) {
                    337:                 /* there was another file on this list */
                    338:                 return(next);
                    339:         }
                    340:         if (!fDeep) return NULL;
                    341: 
                    342:         /* get the head of the next list of filenames from the directory */
                    343:         cur->direct->pos = DL_DIRS;
                    344:         cur->direct->curdir = NULL;
                    345:         return(dir_findnextfile(dl, cur->direct));
                    346: } /* dir_nextitem */
                    347: 
                    348: /***************************************************************************
                    349:  * Function: dir_findnextfile
                    350:  *
                    351:  * Purpose:
                    352:  *
                    353:  * Gets the next file in the directory
                    354:  */
                    355: DIRITEM
                    356: dir_findnextfile(DIRLIST dl, DIRECT curdir)
                    357: {
                    358:         DIRITEM curfile;
                    359: 
                    360:         if ((dl == NULL) || (curdir == NULL)) {
                    361:                 return(NULL);
                    362:         }
                    363: 
                    364:         /* scan the subdir if necessary */
                    365:         if (!curdir->bScanned) {
                    366:                 dir_scan(curdir, FALSE);
                    367:         }
                    368: 
                    369:         /* have we already read the files in this directory ? */
                    370:         if (curdir->pos == DL_FILES) {
                    371:                 /* no - return head of file list */
                    372:                 curfile = (DIRITEM) List_First(curdir->diritems);
                    373:                 if (curfile != NULL) {
                    374:                         return(curfile);
                    375:                 }
                    376: 
                    377:                 /* no more files - try the subdirs */
                    378:                 curdir->pos = DL_DIRS;
                    379:         }
                    380: 
                    381:         /* try the next subdir on the list, if any */
                    382:         /* is this the first or the next */
                    383:         if (curdir->curdir == NULL) {
                    384:                 curdir->curdir = (DIRECT) List_First(curdir->directs);
                    385:         } else {
                    386:                 curdir->curdir = (DIRECT) List_Next(curdir->curdir);
                    387:         }
                    388:         /* did we find a subdir ? */
                    389:         if (curdir->curdir == NULL) {
                    390: 
                    391:                 /* no more dirs - go back to parent if there is one */
                    392:                 if (curdir->parent == NULL) {
                    393:                         /* no parent - we have exhausted the tree */
                    394:                         return(NULL);
                    395:                 }
                    396: 
                    397:                 /* reset parent state to indicate this is the current
                    398:                  * directory - so that next gets the next after this.
                    399:                  * this ensures that multiple callers of dir_nextitem()
                    400:                  * to the same tree work.
                    401:                  */
                    402:                 curdir->parent->pos = DL_DIRS;
                    403:                 curdir->parent->curdir = curdir;
                    404: 
                    405:                 return(dir_findnextfile(dl, curdir->parent));
                    406:         }
                    407: 
                    408:         /* there is a next directory - set it to the
                    409:          * beginning and get the first file from it
                    410:          */
                    411:         curdir->curdir->pos = DL_FILES;
                    412:         curdir->curdir->curdir = NULL;
                    413:         return(dir_findnextfile(dl, curdir->curdir));
                    414: 
                    415: } /* dir_findnextfile */
                    416: 
                    417: 
                    418: /*-- pathnames ----
                    419:  *
                    420:  * This module supports two types of pathnames, called relative and full.
                    421:  * Relative names are relative to the root passed in the initial call
                    422:  * to dir_build*, and full names include the tree root.
                    423:  *
                    424:  * Note that this is a different distinction to relative vs absolute
                    425:  * pathnames, since the tree root may still be either relative or absolute.
                    426:  *
                    427:  * Examples:
                    428:  *
                    429:  *  - if you called dir_buildlist("c:\")
                    430:  *              getrelname gives:               ".\config.sys"
                    431:  *              getfullname gives:              "c:\config.sys"
                    432:  *
                    433:  * - if you called dir_buildlist(".\geraintd")
                    434:  *              getrelname gives:               ".\source\scandir.h"
                    435:  *              getfullname gives either
                    436:  *                      ".\geraintd\source\scandir.h"
                    437:  *                    or "c:\geraintd\source\scandir.h"
                    438:  *                   (depending on the implementation).
                    439:  *
                    440:  * To support this, we maintain the tree root name in the DIRLIST head, and
                    441:  * in each directory, the name of that directory relative to tree root.
                    442:  * Files just have the filename, so we need to prepend the directory name,
                    443:  * and (for getfullname) the tree root name as well
                    444:  *
                    445:  * We store the directory name with a trailing
                    446:  * slash to make concatenation easier
                    447:  *
                    448:  * -----
                    449:  */
                    450: 
                    451: /***************************************************************************
                    452:  * Function: dir_getrelname
                    453:  *
                    454:  * Purpose:
                    455:  *
                    456:  * Return the name of the current file relative to tree root
                    457:  */
                    458: LPSTR
                    459: dir_getrelname(DIRITEM cur)
                    460: {
                    461:         LPSTR name;
                    462:         int size;
                    463: 
                    464:         /* check this is a valid item */
                    465:         if (cur == NULL) {
                    466:                 return(NULL);
                    467:         }
                    468:         /* remember to include the NULL when sizing */
                    469:         size = lstrlen(cur->direct->relname) + lstrlen(cur->name) + 1;
                    470:         name = gmem_get(hHeap, size);
                    471:         lstrcpy(name, cur->direct->relname);
                    472:         lstrcat(name, cur->name);
                    473: 
                    474:         return(name);
                    475: } /* dir_getrelname */
                    476: 
                    477: /***************************************************************************
                    478:  * Function: dir_getfullname
                    479:  *
                    480:  * Purpose:
                    481:  *
                    482:  * Return the fullname of the file (including the tree root passed in) 
                    483:  */
                    484: LPSTR
                    485: dir_getfullname(DIRITEM cur)
                    486: {
                    487:         LPSTR name;
                    488:         int size;
                    489:         LPSTR head;
                    490: 
                    491:         /* check this is a valid item */
                    492:         if (cur == NULL)  {
                    493:                 return(NULL);
                    494:         }
                    495: 
                    496:         if (cur->direct->head->bFile) {
                    497:                 return(cur->direct->head->rootname);
                    498:         }
                    499: 
                    500:         /* remember to include the NULL when sizing */
                    501:         size = lstrlen(cur->name) + 1;
                    502: 
                    503:         size += lstrlen(cur->direct->relname);
                    504: 
                    505:         /* add on root name */
                    506:         head = cur->direct->head->rootname;
                    507:         size += lstrlen(head);
                    508: 
                    509:         /* root names may not end in a slash. we need to
                    510:          * insert one in this case. Also, relnames always begin .\, so
                    511:          * we skip the . always, and the .\ if we don't need to
                    512:          * append a slash
                    513:          *
                    514:          */
                    515:         size--;         /* omit the '.' */
                    516:         if (head[lstrlen(head) -1] == '\\') {
                    517:                 size--;                         /* omit the .\ */
                    518:         }
                    519: 
                    520:         name = gmem_get(hHeap, size);
                    521: 
                    522:         lstrcpy(name, cur->direct->head->rootname);
                    523: 
                    524:         /* add relname and then name, omiting the .\ */
                    525: 
                    526:                 /* skip . or .\ before relname */
                    527:                 if (head[lstrlen(head) -1] == '\\') {
                    528:                         lstrcat(name, &cur->direct->relname[2]);
                    529:                 } else {
                    530:                         lstrcat(name, &cur->direct->relname[1]);
                    531:                 }
                    532:                 lstrcat(name, cur->name);
                    533:         return(name);
                    534: } /* dir_getfullname */
                    535: 
                    536: 
                    537: /***************************************************************************
                    538:  * Function: dir_getroot_list
                    539:  *
                    540:  * Purpose:
                    541:  *
                    542:  * Return the name of the tree root given a handle to the DIRLIST.
                    543:  */
                    544: LPSTR
                    545: dir_getroot_list(DIRLIST dl)
                    546: {
                    547:         if (dl == NULL) 
                    548:                 return(NULL);
                    549:         return(dl->rootname);
                    550: } /* dir_getroot_list */
                    551: 
                    552: /***************************************************************************
                    553:  * Function: dir_getroot_item
                    554:  *
                    555:  * Purpose:
                    556:  *
                    557:  * Return the root name of this tree given a handle to a DIRITEM in the
                    558:  * list.
                    559:  */
                    560: LPSTR dir_getroot_item(DIRITEM item)
                    561: {
                    562:         if (item == NULL) 
                    563:                 return(NULL);
                    564: 
                    565:         return(dir_getroot_list(item->direct->head));
                    566: }
                    567: 
                    568: 
                    569: /***************************************************************************
                    570:  * Function: dir_freerelname
                    571:  *
                    572:  * Purpose:
                    573:  *
                    574:  * Free up a relname that we allocated. This interface allows us
                    575:  * some flexibility in how we store relative and complete names
                    576:  *
                    577:  */
                    578: void
                    579: dir_freerelname(DIRITEM cur, LPSTR name)
                    580: {
                    581:         if((cur != NULL) && (name != NULL))
                    582:                         gmem_free(hHeap, name, lstrlen(name) +1);
                    583: } /* dir_freerelname */
                    584: 
                    585: /***************************************************************************
                    586:  * Function: dir_freefullname
                    587:  *
                    588:  * Purpose:
                    589:  *
                    590:  */
                    591: void
                    592: dir_freefullname(DIRITEM cur, LPSTR name)
                    593: {
                    594:         if (cur->direct->head->bFile)
                    595:                 return;
                    596: 
                    597:         if (name != NULL) 
                    598:                 gmem_free(hHeap, name, lstrlen(name) + 1);
                    599: } /* dir_freefullname            */
                    600: 
                    601: /***************************************************************************
                    602:  * Function: dir_freeroot_list
                    603:  *
                    604:  * Purpose:
                    605:  *
                    606:  * Free up rootname allocated by dir_getroot_list.
                    607:  * We just gave a pointer to the rootname, so do nothing.
                    608:  */
                    609: void
                    610: dir_freeroot_list(DIRLIST dl, LPSTR name)
                    611: {
                    612:         if ((dl == NULL) || (name == NULL)) {
                    613:                 return;
                    614:         }
                    615:         return;
                    616: } /* dir_freeroot_list */
                    617: 
                    618: /***************************************************************************
                    619:  * Function: dir_freeroot_item
                    620:  *
                    621:  * Purpose:
                    622:  *
                    623:  * Free up memory alloc-ed by a call to dir_getroot_item. 
                    624:  */
                    625: void
                    626: dir_freeroot_item(DIRITEM item, LPSTR name)
                    627: {
                    628:         if ((item == NULL) || (name == NULL)) 
                    629:                 return;
                    630:         dir_freeroot_list(item->direct->head, name);
                    631: }
                    632: 
                    633: /***************************************************************************
                    634:  * Function: dir_getopenname
                    635:  *
                    636:  * Purpose:
                    637:  *
                    638:  * Get an open-able name for the file. This will be the same as the fullname.
                    639:  */
                    640: LPSTR
                    641: dir_getopenname(DIRITEM item)
                    642: {
                    643:         LPSTR fname;
                    644: 
                    645:         if (item == NULL) 
                    646:                 return(NULL);
                    647: 
                    648:         fname = dir_getfullname(item);
                    649: 
                    650:                 return(fname);
                    651: } /* dir_getopenname */
                    652: 
                    653: 
                    654: /***************************************************************************
                    655:  * Function: dir_freeopenname
                    656:  *
                    657:  * Purpose:
                    658:  *
                    659:  * Free up memory created by a call to dir_getopenname(). This *may*
                    660:  * cause the file to be deleted if it was a temporary copy.
                    661:  */
                    662: void
                    663: dir_freeopenname(DIRITEM item, LPSTR openname)
                    664: {
                    665:         if ((item == NULL) || (openname == NULL)) 
                    666:                 return;
                    667: 
                    668:         dir_freefullname(item, openname);
                    669: } /* dir_freeopenname */
                    670: 
                    671: /***************************************************************************
                    672:  * Function: dir_openfile
                    673:  *
                    674:  * Purpose:
                    675:  *
                    676:  * Return an open file handle to the file. 
                    677:  */
                    678: int
                    679: dir_openfile(DIRITEM item)
                    680: {
                    681:         LPSTR fname;
                    682:         int fh;
                    683:         OFSTRUCT os;
                    684: 
                    685:         fname = dir_getfullname(item);
                    686:         fh = OpenFile(fname, &os, OF_READ|OF_SHARE_DENY_NONE);
                    687:         dir_freefullname(item, fname);
                    688:         return(fh);
                    689: } /* dir_openfile */
                    690: 
                    691: /***************************************************************************
                    692:  * Function: dir_closefile
                    693:  *
                    694:  * Purpose:
                    695:  *
                    696:  * Close a file opened with dir_openfile.
                    697:  */
                    698: void
                    699: dir_closefile(DIRITEM item, int fh)
                    700: {
                    701:         _lclose(fh);
                    702: 
                    703: } /* dir_closefile */
                    704: 
                    705: 
                    706: /***************************************************************************
                    707:  * Function: dir_getfilesize
                    708:  *
                    709:  * Purpose:
                    710:  *
                    711:  * Return the file size (set during scanning) 
                    712:  */
                    713: long
                    714: dir_getfilesize(DIRITEM cur)
                    715: {
                    716:         /* check this is a valid item */
                    717:         if (cur == NULL)
                    718:                 return(0);
                    719: 
                    720:         return(cur->size);
                    721: } /* dir_getfilesize */
                    722: 
                    723: 
                    724: 
                    725: /* ss_endcopy returns a number indicating the number of files copied,
                    726:    but we may have some local copies too.  We need to count these
                    727:    ourselves and add them in
                    728: */
                    729: 
                    730: int nLocalCopies;        /* cleared in startcopy, ++d in copy
                    731:                                 ** inspected in endcopy
                    732:                                 */
                    733: 
                    734: /***************************************************************************
                    735:  * Function: dir_startcopy
                    736:  *
                    737:  * Purpose:
                    738:  *
                    739:  * Start a bulk copy 
                    740:  */
                    741: BOOL dir_startcopy(DIRLIST dl)
                    742: {
                    743:         nLocalCopies = 0;
                    744:         return(TRUE);
                    745: 
                    746: } /* dir_startcopy */
                    747: /***************************************************************************
                    748:  * Function: dir_endcopy
                    749:  *
                    750:  */
                    751:  
                    752: int dir_endcopy(DIRLIST dl)
                    753: {
                    754:         return(nLocalCopies);
                    755: 
                    756: } /* dir_endcopy */
                    757: 
                    758: /***************************************************************************
                    759:  * Function: dir_copy
                    760:  *
                    761:  * Purpose:
                    762:  *
                    763:  * Create a copy of the file, in the new root directory. Creates sub-dirs as
                    764:  * necessary. 
                    765:  *
                    766:  * Returns TRUE for success and FALSE for failure.
                    767:  */
                    768: BOOL dir_copy(DIRITEM item, LPSTR newroot)
                    769: {
                    770:         static char newpath[256];
                    771:         LPSTR relname, fullname;
                    772:         LPSTR pstart, pdest, pel;
                    773:         BOOL bOK;
                    774: 
                    775:         BY_HANDLE_FILE_INFORMATION bhfi;
                    776:         HANDLE hfile;
                    777: 
                    778:         /*
                    779:          * check that the newroot directory itself exists
                    780:          */
                    781:         if ((item == NULL) || !dir_isvaliddir(newroot)) {
                    782:                 return(FALSE);
                    783:         }
                    784: 
                    785:         /*
                    786:          * name of file relative to the tree root
                    787:          */
                    788:         relname = dir_getrelname(item);
                    789: 
                    790:         /*
                    791:          * build the new pathname by concatenating the new root and
                    792:          * the old relative name. add one path element at a time and
                    793:          * ensure that the directory exists, creating it if necessary.
                    794:          */
                    795:         lstrcpy(newpath, newroot);
                    796: 
                    797:         /* add separating slash if not already there */
                    798:         if (newpath[lstrlen(newpath) -1] != '\\') {
                    799:                 lstrcat(newpath, "\\");
                    800:         }
                    801: 
                    802:         pstart = relname;
                    803:         while ( (pel = strchr(pstart, '\\')) != NULL) {
                    804: 
                    805:                 /* found another element ending in slash. incr past the \\ */
                    806:                 pel++;
                    807: 
                    808:                 /*
                    809:                  * ignore .
                    810:                  */
                    811:                 if (strncmp(pstart, ".\\", 2) != 0) {
                    812: 
                    813:                         pdest = &newpath[lstrlen(newpath)];
                    814:                         strncpy(pdest, pstart, pel - pstart);
                    815:                         pdest[pel - pstart] = '\0';
                    816: 
                    817:                         /* create subdir if necessary */
                    818:                         if (!dir_isvaliddir(newpath)) {
                    819:                                 if (_mkdir(newpath) != 0) {
                    820:                                         return(FALSE);
                    821:                                 }
                    822:                         }
                    823:                 }
                    824: 
                    825:                 pstart = pel;
                    826:         }
                    827: 
                    828:         /*
                    829:          * there are no more slashes, so pstart points at the final
                    830:          * element
                    831:          */
                    832:         lstrcat(newpath, pstart);
                    833: 
                    834:         fullname = dir_getfullname(item);
                    835: 
                    836:                 bOK = CopyFile(fullname, newpath, FALSE);
                    837: 
                    838:                 /* having copied the file, now copy the times, attributes */
                    839:                 hfile = CreateFile(fullname, GENERIC_READ, 0, NULL,
                    840:                                 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
                    841:                 bhfi.dwFileAttributes = GetFileAttributes(fullname);
                    842:                 GetFileTime(hfile, &bhfi.ftCreationTime,
                    843:                                 &bhfi.ftLastAccessTime, &bhfi.ftLastWriteTime);
                    844:                 CloseHandle(hfile);
                    845: 
                    846:                 hfile = CreateFile(newpath, GENERIC_WRITE, 0, NULL,
                    847:                                 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
                    848:                 SetFileTime(hfile, &bhfi.ftCreationTime,
                    849:                                    &bhfi.ftLastAccessTime,
                    850:                                    &bhfi.ftLastWriteTime);
                    851:                 CloseHandle(hfile);
                    852:                 SetFileAttributes(newpath, bhfi.dwFileAttributes);
                    853: 
                    854: 
                    855:                 if (bOK) ++nLocalCopies;
                    856: 
                    857:         dir_freerelname(item, relname);
                    858:         dir_freefullname(item, fullname);
                    859: 
                    860:         return(bOK);
                    861: } /* dir_copy */
                    862: 
                    863: 
                    864: /***************************************************************************
                    865:  * Function: dir_dirinit
                    866:  *
                    867:  * Purpose:
                    868:  *
                    869:  * Fill out a new DIRECT for a subdirectory (pre-allocated).
                    870:  * Init files and dirs lists to empty (List_Create). Set the relname
                    871:  * of the directory by pre-pending the parent relname if there
                    872:  * is a parent, and appending a trailing slash (if there isn't one).
                    873:  */
                    874: void
                    875: dir_dirinit(DIRECT dir, DIRLIST head, DIRECT parent, LPSTR name)
                    876: {
                    877:         int size;
                    878: 
                    879:         dir->head = head;
                    880:         dir->parent = parent;
                    881: 
                    882:         /* add on one for the null and one for the trailing slash */
                    883:         size = lstrlen(name) + 2;
                    884:         if (parent != NULL) {
                    885:                 size += lstrlen(parent->relname);
                    886:         }
                    887: 
                    888:         /* build the relname from the parent and the current name
                    889:          * with a terminating slash
                    890:          */
                    891:         dir->relname = gmem_get(hHeap, size);
                    892:         if (parent != NULL) {
                    893:                 lstrcpy(dir->relname, parent->relname);
                    894:         } else{
                    895:                 dir->relname[0] = '\0';
                    896:         }
                    897: 
                    898:         lstrcat(dir->relname, name);
                    899: 
                    900:         if (dir->relname[lstrlen(dir->relname) -1] != '\\') {
                    901:                 lstrcat(dir->relname, "\\");
                    902:         }
                    903: 
                    904:         /* force name to lowercase */
                    905:         AnsiLowerBuff(dir->relname, lstrlen(dir->relname));
                    906: 
                    907:         dir->diritems = List_Create();
                    908:         dir->directs = List_Create();
                    909:         dir->bScanned = FALSE;
                    910:         dir->pos = DL_FILES;
                    911: 
                    912: } /* dir_dirinit */
                    913: 
                    914: 
                    915: /***************************************************************************
                    916:  * Function: dir_fileinit
                    917:  *
                    918:  * Purpose:
                    919:  *
                    920:  * Initialise the contents of an (allocated) DIRITEM struct. 
                    921:  */
                    922: void
                    923: dir_fileinit(DIRITEM pfile, DIRECT dir, LPSTR path, long size)
                    924: {
                    925: 
                    926:         pfile->name = gmem_get(hHeap, lstrlen(path) + 1);
                    927:         lstrcpy(pfile->name, path);
                    928: 
                    929:         /* force name to lower case */
                    930:         AnsiLowerBuff(pfile->name, lstrlen(path));
                    931: 
                    932:         pfile->direct = dir;
                    933:         pfile->size = size;
                    934: 
                    935:         pfile->localname = NULL;
                    936: 
                    937: } /* dir_fileinit */
                    938: 
                    939: /***************************************************************************
                    940:  * Function: dir_isfilevalid
                    941:  *
                    942:  * Purpose:
                    943:  *
                    944:  * Is this a valid file or not 
                    945:  */
                    946: BOOL
                    947: dir_isvalidfile(LPSTR path)
                    948: {
                    949:         DWORD dwAttrib;
                    950: 
                    951:         dwAttrib = GetFileAttributes(path);
                    952:         if (dwAttrib == -1) {
                    953:                 return(FALSE);
                    954:         }
                    955:         if (dwAttrib & FILE_ATTRIBUTE_DIRECTORY) {
                    956:                 return(FALSE);
                    957:         }
                    958:         return(TRUE);
                    959: } /* dir_isvalidfile */
                    960: 
                    961: /***************************************************************************
                    962:  * Function: dir_isvaliddir
                    963:  *
                    964:  * Purpose:
                    965:  *
                    966:  * Is this a valid directory ? 
                    967:  */
                    968: BOOL
                    969: dir_isvaliddir(LPSTR path)
                    970: {
                    971:         DWORD dwAttrib;
                    972: 
                    973:         dwAttrib = GetFileAttributes(path);
                    974:         if (dwAttrib == -1) {
                    975:                 return(FALSE);
                    976:         }
                    977:         if (dwAttrib & FILE_ATTRIBUTE_DIRECTORY) {
                    978:                 return(TRUE);
                    979:         }
                    980:         return(FALSE);
                    981: } /* dir_isvaliddir */
                    982: 
                    983: /***************************************************************************
                    984:  * Function: dir_scan
                    985:  *
                    986:  * Purpose:
                    987:  *
                    988:  * Scan the directory given. Add all files to the list
                    989:  * in alphabetic order, and add all directories in alphabetic
                    990:  * order to the list of child DIRITEMs. If bRecurse is true, go on to
                    991:  * recursive call dir_scan for each of the child DIRITEMs
                    992:  */
                    993: void
                    994: dir_scan(DIRECT dir, BOOL bRecurse)
                    995: {
                    996:         PSTR path;
                    997:         int size;
                    998:         DIRECT child;
                    999:         BOOL bMore;
                   1000:         long filesize;
                   1001:         BOOL bIsDir;
                   1002:         LPSTR name;
                   1003: 
                   1004:         HANDLE hFind;
                   1005:         WIN32_FIND_DATA finddata;
                   1006: 
                   1007:         char debugmsg[200];
                   1008:         wsprintf(debugmsg, "scandir: %s %s\n",
                   1009:                  dir->relname, bRecurse?"recursive":"non-recursive"
                   1010:                 );
                   1011: 
                   1012:         /* make the complete search string including *.* */
                   1013:         size = lstrlen(dir->head->rootname);
                   1014:         size += lstrlen(dir->relname);
                   1015: 
                   1016:         /* add on one null and *.* */
                   1017:         size += 4;
                   1018: 
                   1019:         path = LocalLock(LocalAlloc(LHND, size));
                   1020: 
                   1021:         lstrcpy(path, dir->head->rootname);
                   1022: 
                   1023:         /* omit the . at the beginning of the relname, and the
                   1024:          * .\ if there is a trailing \ on the rootname
                   1025:          */
                   1026:         if (path[strlen(path)-1] == '\\') {
                   1027:                 lstrcat(path, &dir->relname[2]);
                   1028:         } else {
                   1029:                 lstrcat(path, &dir->relname[1]);
                   1030:         }
                   1031:         lstrcat(path, "*.*");
                   1032: 
                   1033:         /* read all entries in the directory */
                   1034:         hFind = FindFirstFile(path, &finddata);
                   1035:         bMore = (hFind != (HANDLE) -1);
                   1036:         LocalUnlock(LocalHandle ( (PSTR) path));
                   1037:         LocalFree(LocalHandle ( (PSTR) path));
                   1038: 
                   1039:         while (bMore) {
                   1040: 
                   1041:                 bIsDir = (finddata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
                   1042:                 name = (LPSTR) &finddata.cFileName;
                   1043:                 filesize = finddata.nFileSizeLow;
                   1044:                 if (!bIsDir) {
                   1045: 
                   1046:                         dir_addfile(dir, name, filesize);
                   1047: 
                   1048:                 } else if ( (lstrcmp(name, ".") != 0) &&
                   1049:                            ( lstrcmp(name, "..") != 0) ) {
                   1050: 
                   1051:                         dir_adddirect(dir, name);
                   1052:                 }
                   1053: 
                   1054:                 bMore = FindNextFile(hFind, &finddata);
                   1055:         }
                   1056: 
                   1057:         FindClose(hFind);
                   1058: 
                   1059:         dir->bScanned = TRUE;
                   1060:         dir->pos = DL_FILES;
                   1061: 
                   1062:         if (bRecurse) {
                   1063:                 List_TRAVERSE(dir->directs, child) {
                   1064:                         dir_scan(child, TRUE);
                   1065:                 }
                   1066:         }
                   1067: 
                   1068: } /* dir_scan */
                   1069: 
                   1070: 
                   1071: /***************************************************************************
                   1072:  * Function: dir_addfile
                   1073:  *
                   1074:  * Purpose:
                   1075:  *
                   1076:  * Add the file 'path' to the list of files in dir, in order.
                   1077:  */
                   1078: void
                   1079: dir_addfile(DIRECT dir, LPSTR path, DWORD size)
                   1080: {
                   1081:         DIRITEM pfile;
                   1082: 
                   1083:         AnsiLowerBuff(path, lstrlen(path));  // needless?
                   1084: 
                   1085:         List_TRAVERSE(dir->diritems, pfile) {
                   1086:                 /////if (lstrcmpi(pfile->name, path) > 0) {
                   1087:                 if (utils_CompPath(pfile->name, path) > 0) {
                   1088: 
                   1089:                         /* goes before this one */
                   1090:                         pfile = List_NewBefore(dir->diritems, pfile, sizeof(struct diritem));
                   1091:                         dir_fileinit(pfile, dir, path, size);
                   1092:                         return;
                   1093:                 }
                   1094:         }
                   1095:         /* goes at end */
                   1096:         pfile = List_NewLast(dir->diritems, sizeof(struct diritem));
                   1097:         dir_fileinit(pfile, dir, path, size);
                   1098: } /* dir_addfile */
                   1099: 
                   1100: 
                   1101: /***************************************************************************
                   1102:  * Function: dir_addirect
                   1103:  *
                   1104:  * Purpose:
                   1105:  *
                   1106:  * Add a new directory in alphabetic order on
                   1107:  * the list dir->directs
                   1108:  *
                   1109:  */
                   1110: void
                   1111: dir_adddirect(DIRECT dir, LPSTR path)
                   1112: {
                   1113:         DIRECT child;
                   1114:         LPSTR finalel;
                   1115:         char achTempName[256];
                   1116: 
                   1117:         AnsiLowerBuff(path, lstrlen(path));
                   1118:         List_TRAVERSE(dir->directs, child) {
                   1119: 
                   1120:                 int cmpval;
                   1121: 
                   1122:                 /* we need to compare the child name with the new name.
                   1123:                  * the child name is a relname with a trailing
                   1124:                  * slash - so compare only the name up to but
                   1125:                  * not including the final slash.
                   1126:                  */
                   1127:                 finalel = dir_finalelem(child->relname);
                   1128: 
                   1129:                 /*
                   1130:                  * we cannot use strnicmp since this uses a different
                   1131:                  * collating sequence to lstrcmpi. So copy the portion
                   1132:                  * we are interested in to a null-term. buffer.
                   1133:                  */
                   1134:                 strncpy(achTempName, finalel, lstrlen(finalel)-1);
                   1135:                 achTempName[lstrlen(finalel)-1] = '\0';
                   1136: 
                   1137:                 cmpval = utils_CompPath(achTempName, path);
                   1138: 
                   1139:                 if (cmpval > 0) {
                   1140: 
                   1141:                         /* goes before this one */
                   1142:                         child = List_NewBefore(dir->directs, child, sizeof(struct direct));
                   1143:                         dir_dirinit(child, dir->head, dir, path);
                   1144:                         return;
                   1145:                 }
                   1146:         }
                   1147:         /* goes at end */
                   1148:         child = List_NewLast(dir->directs, sizeof(struct direct));
                   1149:         dir_dirinit(child, dir->head, dir, path);
                   1150: } /* dir_adddirect */
                   1151: 
                   1152: 
                   1153: /***************************************************************************
                   1154:  * Function: dir_cleardirect
                   1155:  *
                   1156:  * Purpose:
                   1157:  *
                   1158:  * Free all memory associated with a DIRECT (including freeing
                   1159:  * child lists). Don't de-alloc the direct itself (allocated on a list)
                   1160:  */
                   1161: void
                   1162: dir_cleardirect(DIRECT dir)
                   1163: {
                   1164:         DIRITEM pfile;
                   1165:         DIRECT child;
                   1166: 
                   1167:         /* clear contents of files list */
                   1168:         List_TRAVERSE(dir->diritems, pfile) {
                   1169:                 gmem_free(hHeap, pfile->name, lstrlen(pfile->name));
                   1170:                 if ((pfile->localname) && (pfile->bLocalIsTemp)) {
                   1171: 
                   1172:                         /*
                   1173:                          * the copy will have copied the attributes,
                   1174:                          * including read-only. We should unset this bit
                   1175:                          * so we can delete the temp file.
                   1176:                          */
                   1177:                         SetFileAttributes(pfile->localname,
                   1178:                                 GetFileAttributes(pfile->localname)
                   1179:                                         & ~FILE_ATTRIBUTE_READONLY);
                   1180:                         DeleteFile(pfile->localname);
                   1181:                         gmem_free(hHeap, pfile->localname, 256);
                   1182:                         pfile->localname = NULL;
                   1183:                 }
                   1184: 
                   1185:         }
                   1186:         List_Destroy(&dir->diritems);
                   1187: 
                   1188:         /* clear contents of dirs list (recursively) */
                   1189:         List_TRAVERSE(dir->directs, child) {
                   1190:                 dir_cleardirect(child);
                   1191:         }
                   1192:         List_Destroy(&dir->directs);
                   1193: 
                   1194:         gmem_free(hHeap, dir->relname, lstrlen(dir->relname) + 1);
                   1195: 
                   1196: } /* dir_cleardirect */
                   1197: 
                   1198: /***************************************************************************
                   1199:  * Function: dir_finalelem
                   1200:  *
                   1201:  * Purpose:
                   1202:  *
                   1203:  * Return a pointer to the final element in a path. Note that
                   1204:  * we may be passed relnames with a trailing final slash - ignore this
                   1205:  * and return the element before that final slash.
                   1206:  */
                   1207: LPSTR
                   1208: dir_finalelem(LPSTR path)
                   1209: {
                   1210:         LPSTR chp;
                   1211:         int size;
                   1212: 
                   1213:         /* is the final character a slash ? */
                   1214:         size = lstrlen(path) - 1;
                   1215:         if (path[size] == '\\') {
                   1216:                 /* find the slash before this */
                   1217:                 for (size-- ; size > 0; size--) {
                   1218:                         if (path[size] == '\\') {
                   1219:                                 /* skip the slash itself */
                   1220:                                 size++;
                   1221:                                 break;
                   1222:                         }
                   1223:                 }
                   1224:                 return(&path[size]);
                   1225:         }
                   1226:         /* look for final slash */
                   1227:         chp = strrchr(path, '\\');
                   1228:         if (chp != NULL) {
                   1229:                 return(chp+1);
                   1230:         }
                   1231: 
                   1232:         /* no slash - is there a drive letter ? */
                   1233:         chp = strrchr(path, ':');
                   1234:         if (chp != NULL) {
                   1235:                 return(chp+1);
                   1236:         }
                   1237: 
                   1238:         /* this is a final-element anyway */
                   1239:         return(path);
                   1240: 
                   1241: } /* dir_finalelem */
                   1242: 
                   1243: /***************************************************************************
                   1244:  * Function: dir_getpathsize
                   1245:  *
                   1246:  * Purpose:
                   1247:  *
                   1248:  * Find the size of a file given a pathname to it 
                   1249:  */
                   1250: long
                   1251: dir_getpathsize(LPSTR path)
                   1252: {
                   1253:         int fh;
                   1254:         OFSTRUCT os;
                   1255:         long size;
                   1256:         fh = OpenFile(path, &os, OF_READ|OF_SHARE_DENY_NONE);
                   1257:         if (fh == -1) {
                   1258:                 return(0);
                   1259:         }
                   1260: 
                   1261:         size = GetFileSize( (HANDLE) fh, NULL);
                   1262:         _lclose(fh);
                   1263:         return(size);
                   1264: } /* dir_getpathsize */
                   1265: 
                   1266: 

unix.superglobalmegacorp.com

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