3
** VMS Utility Routines
6
** MD Mark Donszelmann duns@vxdeop.cern.ch
9
** 14 Nov 93 MD Written
24
#include <HTVMSUtils.h>
31
#include <lib$routines.h>
35
#include <LYGlobalDefs.h>
38
#include <LYStrings.h>
40
PUBLIC BOOL HTVMSFileVersions = FALSE; /* Include version numbers in listing? */
43
unsigned long BufferLength : 16;
44
unsigned long ItemCode : 16;
45
unsigned long BufferAddress : 32;
46
unsigned long ReturnLengthAddress : 32;
49
/* PUBLIC HTVMS_authSysPrv()
50
** CHECKS IF THIS PROCESS IS AUTHORIZED TO ENABLE SYSPRV
55
** returns YES if SYSPRV is authorized
57
PUBLIC BOOL HTVMS_authSysPrv NOARGS
60
ItemStruct ItemList[2];
62
unsigned long Buffer[2];
65
ItemList[0].BufferLength = sizeof(Buffer);
66
ItemList[0].BufferAddress = (unsigned long)Buffer;
67
ItemList[0].ReturnLengthAddress = (unsigned long)&Length;
68
ItemList[0].ItemCode = JPI$_AUTHPRIV;
71
ItemList[1].ItemCode = 0;
72
ItemList[1].BufferLength = 0;
75
Result = sys$getjpiw(0, 0, 0, ItemList, 0, 0, 0);
77
if (Result != SS$_NORMAL)
80
if (Buffer[0] & PRV$M_SYSPRV)
88
/* PUBLIC HTVMS_enableSysPrv()
96
PUBLIC void HTVMS_enableSysPrv NOARGS
99
unsigned long Prv[2], PreviousPrv[2];
101
Prv[0] = PRV$M_SYSPRV;
103
Result = sys$setprv(1,&Prv,0,&PreviousPrv);
105
if (Result == SS$_NORMAL) {
106
if (!(PreviousPrv[0] & PRV$M_SYSPRV)) {
107
CTRACE((tfp, "HTVMS_enableSysPrv: Enabled SYSPRV\n"));
114
/* PUBLIC HTVMS_disableSysPrv()
122
PUBLIC void HTVMS_disableSysPrv NOARGS
124
unsigned long Result;
125
unsigned long Prv[2], PreviousPrv[2];
127
Prv[0] = PRV$M_SYSPRV;
129
Result = sys$setprv(0,&Prv,0,&PreviousPrv);
131
if (Result == SS$_NORMAL) {
132
if (PreviousPrv[0] & PRV$M_SYSPRV) {
133
CTRACE((tfp, "HTVMS_disableSysPrv: Disabled SYSPRV\n"));
140
/* PUBLIC HTVMS_checkAccess()
141
** CHECKS ACCESS TO FILE FOR CERTAIN USER
143
** FileName The file to be accessed
144
** UserName Name of the user to check access for.
145
** User nobody, represented by "" is given NO for an answer
146
** Method Name of the method to be chceked
149
** returns YES if access is allowed
152
PUBLIC BOOL HTVMS_checkAccess ARGS3(
153
CONST char *, FileName,
154
CONST char *, UserName,
155
CONST char *, Method)
157
unsigned long Result;
158
ItemStruct ItemList[2];
159
unsigned long Length;
160
unsigned long Buffer;
161
unsigned long ObjType;
165
struct dsc$descriptor_s FileNameDesc;
166
struct dsc$descriptor_s UserNameDesc;
170
/* user nobody should access as from account under which server is running */
171
if (0 == strcmp(UserName,""))
174
/* check Filename and convert */
175
colon = strchr(FileName,':');
177
VmsName = HTVMS_name("",colon+1);
179
VmsName = HTVMS_name("",FileName);
182
if (0 == strcmp(Method,"GET"))
185
ItemList[0].BufferLength = sizeof(Buffer);
186
ItemList[0].BufferAddress = (unsigned long)&Buffer;
187
ItemList[0].ReturnLengthAddress = (unsigned long)&Length;
188
ItemList[0].ItemCode = CHP$_FLAGS;
191
ItemList[1].ItemCode = 0;
192
ItemList[1].BufferLength = 0;
195
ObjType = ACL$C_FILE;
197
UserNameDesc.dsc$w_length = strlen(UserName);
198
UserNameDesc.dsc$b_dtype = DSC$K_DTYPE_T;
199
UserNameDesc.dsc$b_class = DSC$K_CLASS_S;
200
UserNameDesc.dsc$a_pointer = (char *)UserName;
201
FileNameDesc.dsc$w_length = strlen(VmsName);
202
FileNameDesc.dsc$b_dtype = DSC$K_DTYPE_T;
203
FileNameDesc.dsc$b_class = DSC$K_CLASS_S;
204
FileNameDesc.dsc$a_pointer = VmsName;
207
Result = sys$check_access(&ObjType,&FileNameDesc,&UserNameDesc,ItemList);
209
if (Result == SS$_NORMAL)
220
/* PUBLIC HTVMS_wwwName()
221
** CONVERTS VMS Name into WWW Name
223
** vmsname VMS file specification (NO NODE)
226
** returns www file specification
230
** DISK$USER disk$user
231
** DISK$USER: /disk$user/
232
** DISK$USER:[DUNS] /disk$user/duns
233
** DISK$USER:[DUNS.ECHO] /disk$user/duns/echo
235
** [DUNS.ECHO] duns/echo
236
** [DUNS.ECHO.-.TRANS] duns/echo/../trans
237
** [DUNS.ECHO.--.TRANS] duns/echo/../../trans
239
** [.DUNS.ECHO] duns/echo
240
** [.DUNS.ECHO]TEST.COM duns/echo/test.com
245
PUBLIC char * HTVMS_wwwName ARGS1(
246
CONST char *, vmsname)
248
static char wwwname[LY_MAXPATH];
255
if (strchr(src,':')) *(dst++) = '/';
256
for ( ; *src != '\0' ; src++)
260
case ':': *(dst++) = '/'; break;
263
if ((*(src-1)=='[' || *(src-1)=='.' || *(src-1)=='-') &&
264
(*(src+1)=='.' || *(src+1)=='-'))
275
if (*(src-1) == ']') *(dst++) = '/';
281
if (*(src-1) != '[') *(dst++) = '/';
285
if (*(src-1) == ']') *(dst++) = '/';
289
case '[': dir = 1; break;
290
case ']': dir = 0; break;
291
default: if (*(src-1) == ']') *(dst++) = '/';
302
** The code below is for directory browsing by VMS Curses clients.
303
** It is based on the newer WWWLib's HTDirBrw.c. - Foteos Macrides
305
PUBLIC int HTStat ARGS2(
306
CONST char *, filename,
310
the following stuff does not work in VMS with a normal stat...
311
--> /disk$user/duns/www if www is a directory
312
is statted like: /disk$user/duns/www.dir
313
after a normal stat has failed
314
--> /disk$user/duns if duns is a toplevel directory
315
is statted like: /disk$user/000000/duns.dir
316
--> /disk$user since disk$user is a device
317
is statted like: /disk$user/000000/000000.dir
319
searches all devices, no solution yet...
320
--> /vxcern!/disk$cr/wwwteam/login.com
321
is not statted but granted with fake information...
328
/* try normal stat... */
329
Result = stat((char *)filename,info);
333
/* make local copy */
334
StrAllocCopy(Name,filename);
336
/* failed,so do device search in case root is requested */
337
if (!strcmp(Name,"/"))
338
{ /* root requested */
342
/* failed so this might be a directory, add '.dir' */
344
if (Name[Len-1] == '/')
347
/* fail in case of device */
348
Ptr = strchr(Name+1,'/');
349
if ((Ptr == NULL) && (Name[0] == '/'))
350
{ /* device only... */
351
StrAllocCat(Name, "/000000/000000");
355
{ /* correct filename in case of toplevel dir */
356
Ptr2 = strchr(Ptr+1,'/');
357
if ((Ptr2 == NULL) && (Name[0] == '/'))
360
LYstrncpy(End, Ptr, sizeof(End) - 1);
362
StrAllocCat(Name, "000000");
363
StrAllocCat(Name, End);
367
/* try in case a file on toplevel directory or .DIR was already specified */
368
Result = stat(Name,info);
372
/* add .DIR and try again */
373
StrAllocCat(Name, ".dir");
374
Result = stat(Name,info);
378
#ifndef _POSIX_SOURCE
379
#define d_ino d_fileno /* compatability */
383
#endif /* !_POSIX_SOURCE */
385
typedef struct __dirdesc {
386
long context; /* context descriptor for LIB$FIND_FILE calls */
387
char dirname[255+1]; /* keeps the directory name, including *.* */
388
struct dsc$descriptor_s dirname_desc; /* descriptor of dirname */
391
PRIVATE DIR *HTVMSopendir(char *dirname);
392
PRIVATE struct dirent *HTVMSreaddir(DIR *dirp);
393
PRIVATE int HTVMSclosedir(DIR *dirp);
395
/*** #include <sys_dirent.h> ***/
396
/*** "sys_dirent.h" ***/
398
unsigned long d_fileno; /* file number of entry */
399
unsigned short d_namlen; /* length of string in d_name */
400
char d_name[255+1]; /* name (up to MAXNAMLEN + 1) */
403
#ifndef _POSIX_SOURCE
405
* It's unlikely to change, but make sure that sizeof d_name above is
406
* at least MAXNAMLEN + 1 (more may be added for padding).
408
#define MAXNAMLEN 255
410
* The macro DIRSIZ(dp) gives the minimum amount of space required to represent
411
* a directory entry. For any directory entry dp->d_reclen >= DIRSIZ(dp).
412
* Specific filesystem types may use this macro to construct the value
417
(((sizeof(struct dirent) - (MAXNAMLEN+1) + ((dp)->d_namlen+1)) +3) & ~3)
419
#endif /* !_POSIX_SOURCE */
422
PRIVATE DIR *HTVMSopendir(char *dirname)
427
struct dsc$descriptor_s entryname_desc;
428
struct dsc$descriptor_s dirname_desc;
429
static char *DirEntry;
436
/* check if directory exists */
437
/* dirname can look like /disk$user/duns/www/test/multi */
438
/* or like /disk$user/duns/www/test/multi/ */
439
/* DirEntry should look like disk$user:[duns.www.test]multi in both cases */
440
/* dir.dirname should look like disk$user:[duns.www.test.multi] */
441
sprintf(UnixEntry, "%.*s", sizeof(UnixEntry) - 2, dirname);
442
if (UnixEntry[strlen(UnixEntry)-1] != '/')
443
strcat(UnixEntry,"/");
445
StrAllocCopy(DirEntry, HTVMS_name("",UnixEntry));
446
if (strlen(DirEntry) > sizeof(dir.dirname) - 1)
448
strcpy(dir.dirname, DirEntry);
449
index = strlen(DirEntry) - 1;
451
if (DirEntry[index] == ']')
452
DirEntry[index] = '\0';
454
if ((dot = strrchr(DirEntry,'.')) == NULL)
455
{ /* convert disk$user:[duns] into disk$user:[000000]duns.dir */
456
char *openbr = strrchr(DirEntry,'[');
458
{ /* convert disk$user: into disk$user:[000000]000000.dir */
459
if (strlen(dir.dirname) > sizeof(dir.dirname) - 10)
461
sprintf(dir.dirname, "%.*s[000000]", sizeof(dir.dirname) - 9, DirEntry);
462
StrAllocCat(DirEntry,"[000000]000000.dir");
467
strcpy(End,openbr+1);
469
StrAllocCat(DirEntry,"000000]");
470
StrAllocCat(DirEntry,End);
471
StrAllocCat(DirEntry,".dir");
477
StrAllocCat(DirEntry,".dir");
479
/* lib$find_file needs a fixed-size buffer */
480
LYstrncpy(Actual, DirEntry, sizeof(Actual)-1);
483
dirname_desc.dsc$w_length = strlen(Actual);
484
dirname_desc.dsc$b_dtype = DSC$K_DTYPE_T;
485
dirname_desc.dsc$b_class = DSC$K_CLASS_S;
486
dirname_desc.dsc$a_pointer = (char *)&(Actual);
488
/* look for the directory */
489
entryname_desc.dsc$w_length = 255;
490
entryname_desc.dsc$b_dtype = DSC$K_DTYPE_T;
491
entryname_desc.dsc$b_class = DSC$K_CLASS_S;
492
entryname_desc.dsc$a_pointer = VMSentry;
494
status = lib$find_file(&(dirname_desc),
498
if (!(status & 0x01))
499
{ /* directory not found */
503
if (strlen(dir.dirname) > sizeof(dir.dirname) - 10)
505
if (HTVMSFileVersions)
506
strcat(dir.dirname,"*.*;*");
508
strcat(dir.dirname,"*.*");
510
dir.dirname_desc.dsc$w_length = strlen(dir.dirname);
511
dir.dirname_desc.dsc$b_dtype = DSC$K_DTYPE_T;
512
dir.dirname_desc.dsc$b_class = DSC$K_CLASS_S;
513
dir.dirname_desc.dsc$a_pointer = (char *)&(dir.dirname);
517
PRIVATE struct dirent *HTVMSreaddir(DIR *dirp)
519
static struct dirent entry;
521
struct dsc$descriptor_s entryname_desc;
526
entryname_desc.dsc$w_length = 255;
527
entryname_desc.dsc$b_dtype = DSC$K_DTYPE_T;
528
entryname_desc.dsc$b_class = DSC$K_CLASS_S;
529
entryname_desc.dsc$a_pointer = VMSentry;
531
status = lib$find_file(&(dirp->dirname_desc),
535
if (status == RMS$_NMF)
536
{ /* no more files */
541
if (!(status & 0x01)) return(0);
542
if (HTVMSFileVersions)
543
space = strchr(VMSentry,' ');
545
space = strchr(VMSentry,';');
549
/* convert to unix style... */
550
UnixEntry = HTVMS_wwwName(VMSentry);
551
slash = strrchr(UnixEntry,'/') + 1;
552
strcpy(entry.d_name,slash);
553
entry.d_namlen = strlen(entry.d_name);
559
PRIVATE int HTVMSclosedir(DIR *dirp)
563
status = lib$find_file_end(&(dirp->context));
564
if (!(status & 0x01)) exit(status);
569
#include <HTAnchor.h>
572
#include <HTFile.h> /* For HTFileFormat() */
575
** Hypertext object building machinery.
578
#define PUTC(c) (*targetClass.put_character)(target, c)
579
#define PUTS(s) (*targetClass.put_string)(target, s)
580
#define START(e) (*targetClass.start_element)(target, e, 0, 0, -1, 0)
581
#define END(e) (*targetClass.end_element)(target, e, 0)
582
#define FREE_TARGET (*targetClass._free)(target)
583
#define ABORT_TARGET (*targetClass._free)(target)
584
struct _HTStructured {
585
CONST HTStructuredClass * isa;
589
#define STRUCT_DIRENT struct dirent
591
PRIVATE char * months[12] = {
592
"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"
595
typedef struct _VMSEntryInfo {
600
BOOLEAN display; /* show this entry? */
603
PRIVATE void free_VMSEntryInfo_contents ARGS1(VMSEntryInfo *,entry_info)
606
FREE(entry_info->filename);
607
FREE(entry_info->type);
608
FREE(entry_info->date);
610
/* dont free the struct */
613
PUBLIC int compare_VMSEntryInfo_structs ARGS2(VMSEntryInfo *,entry1,
614
VMSEntryInfo *,entry2)
617
char date1[16], date2[16], time1[8], time2[8], month[4];
619
switch(HTfileSortMethod)
622
/* both equal or both 0 */
623
if(entry1->size == entry2->size)
624
return(strcasecomp(entry1->filename,
627
if(entry1->size > entry2->size)
632
if(entry1->type && entry2->type) {
633
status = strcasecomp(entry1->type, entry2->type);
636
/* else fall to filename comparison */
638
return (strcasecomp(entry1->filename,
641
if(entry1->date && entry2->date) {
643
** Make sure we have the correct length. - FM
645
if (strlen(entry1->date) != 12 ||
646
strlen(entry2->date) != 12) {
647
return (strcasecomp(entry1->filename,
651
** Set up for sorting in reverse
652
** chronological order. - FM
654
if (entry1->date[7] != ' ') {
655
strcpy(date1, "9999");
656
strcpy(time1, (char *)&entry1->date[7]);
658
strcpy(date1, (char *)&entry1->date[8]);
659
strcpy(time1, "00:00");
661
strncpy(month, entry1->date, 3);
663
for (i = 0; i < 12; i++) {
664
if (!strcasecomp(month, months[i])) {
669
sprintf(month, "%02d", i);
670
strcat(date1, month);
671
strncat(date1, (char *)&entry1->date[4], 2);
673
if (date1[6] == ' ') {
676
strcat(date1, time1);
677
if (entry2->date[7] != ' ') {
678
strcpy(date2, "9999");
679
strcpy(time2, (char *)&entry2->date[7]);
681
strcpy(date2, (char *)&entry2->date[8]);
682
strcpy(time2, "00:00");
684
strncpy(month, entry2->date, 3);
686
for (i = 0; i < 12; i++) {
687
if (!strcasecomp(month, months[i])) {
692
sprintf(month, "%02d", i);
693
strcat(date2, month);
694
strncat(date2, (char *)&entry2->date[4], 2);
696
if (date2[6] == ' ') {
699
strcat(date2, time2);
701
** Do the comparison. - FM
703
status = strcasecomp(date2, date1);
706
/* else fall to filename comparison */
708
return (strcasecomp(entry1->filename,
712
return (strcmp(entry1->filename,
720
** This function generates a directory listing as an HTML-object
721
** for local file URL's. It assumes the first two elements of
722
** of the path are a device followed by a directory:
724
** file://localhost/device/directory[/[foo]]
726
** Will not accept 000000 as a directory name.
727
** Will offer links to parent through the top directory, unless
728
** a terminal slash was included in the calling URL.
730
** Returns HT_LOADED on success, HTLoadError() messages on error.
732
** Developed for Lynx by Foteos Macrides (macrides@sci.wfeb.edu).
734
PUBLIC int HTVMSBrowseDir ARGS4(
735
CONST char *, address,
736
HTParentAnchor *, anchor,
737
HTFormat, format_out,
741
HTStructured* target;
742
HTStructuredClass targetClass;
743
char *pathname = HTParse(address, "", PARSE_PATH + PARSE_PUNCTUATION);
748
char *relative = NULL;
752
struct stat file_info;
754
static char ThisYear[8];
755
VMSEntryInfo *entry_info = 0;
756
char string_buffer[64];
758
HTUnEscape(pathname);
759
CTRACE((tfp,"HTVMSBrowseDir: Browsing `%s\'\n", pathname));
762
* Require at least two elements (presumably a device and directory)
763
* and disallow the device root (000000 directory). Symbolic paths
764
* (e.g., sys$help) should have been translated and expanded (e.g.,
765
* to /sys$sysroot/syshlp) before calling this routine.
767
if (((*pathname != '/') ||
768
(cp = strchr(pathname+1, '/')) == NULL ||
770
0 == strncmp((cp + 1), "000000", 6)) ||
771
(dp = HTVMSopendir(pathname)) == NULL) {
773
return HTLoadError(sink, 403, COULD_NOT_ACCESS_DIR);
777
* Set up the output stream.
779
_HTProgress (BUILDING_DIR_LIST);
780
if (UCLYhndl_HTFile_for_unspec >= 0) {
781
HTAnchor_setUCInfoStage(anchor,
782
UCLYhndl_HTFile_for_unspec,
786
target = HTML_new(anchor, format_out, sink);
787
targetClass = *(target->isa);
790
* Set up the offset string of the anchor reference,
791
* and strings for the title and header.
793
cp = strrchr(pathname, '/'); /* find lastslash */
794
StrAllocCopy(tail, (cp+1)); /* take slash off the beginning */
796
StrAllocCopy(title, tail);
798
if ((cp1=strrchr(pathname, '/')) != NULL &&
800
strncmp((cp1+1), "000000", 6))
801
StrAllocCopy(parent, (cp1+1));
804
pathname[strlen(pathname)-1] = '\0';
805
cp = strrchr(pathname, '/');
806
StrAllocCopy(title, (cp+1));
807
pathname[strlen(pathname)] = '/';
809
StrAllocCopy(header, pathname);
812
* Initialize path name for HTStat().
814
pathend = strlen(pathname);
815
if (*(pathname+pathend-1) != '/') {
816
StrAllocCat(pathname, "/");
821
* Output the title and header.
843
if (HTDirReadme == HT_DIR_README_TOP) {
845
if (header[strlen(header)-1] != '/')
846
StrAllocCat(header, "/");
847
StrAllocCat(header, HT_DIR_README_FILE);
848
if ((fp = fopen(header, "r")) != NULL) {
861
PUTC((char)(c / 10));
862
PUTC((char) (c % 10));
870
#endif /* NOTDEFINED */
878
HTSprintf0(&relative, "%s/..", tail);
879
HTStartAnchor(target, "", relative);
891
* Set up the date comparison.
893
NowTime = time(NULL);
894
strcpy(ThisYear, (char *)ctime(&NowTime)+20);
898
* Now, generate the Btree and put it out to the output stream.
901
char dottest = 2; /* To avoid two strcmp() each time */
902
STRUCT_DIRENT *dirbuf;
905
/* Set up sort key and initialize BTree */
906
bt = HTBTree_new((HTComparer) compare_VMSEntryInfo_structs);
909
while ((dirbuf = HTVMSreaddir(dp))) {
910
HTAtom *encoding = NULL;
913
/* Skip if not used */
914
if (!dirbuf->d_ino) {
918
/* Current and parent directories are never shown in list */
919
if (dottest && (!strcmp(dirbuf->d_name, ".") ||
920
!strcmp(dirbuf->d_name, ".."))) {
925
/* Don't show the selective enabling file
926
* unless version numbers are included */
927
if (!strcasecomp(dirbuf->d_name, HT_DIR_ENABLE_FILE)) {
931
/* Skip files beginning with a dot? */
932
if ((no_dotfiles || !show_dotfiles) && *dirbuf->d_name == '.') {
936
/* OK, make an lstat() and get a key ready. */
937
*(pathname+pathend) = '\0';
938
StrAllocCat(pathname, dirbuf->d_name);
939
if (HTStat(pathname, &file_info)) {
940
/* for VMS the failure here means the file is not readable...
941
we however continue to browse through the directory... */
944
entry_info = (VMSEntryInfo *)malloc(sizeof(VMSEntryInfo));
945
if (entry_info == NULL)
946
outofmem(__FILE__, "HTVMSBrowseDir");
947
entry_info->type = 0;
948
entry_info->size = 0;
949
entry_info->date = 0;
950
entry_info->filename = 0;
951
entry_info->display = TRUE;
954
format = HTFileFormat(dirbuf->d_name, &encoding,
957
if(!strncmp(HTAtom_name(format), "application",11))
959
cp = HTAtom_name(format) + 12;
960
if(!strncmp(cp,"x-", 2))
964
cp = HTAtom_name(format);
966
StrAllocCopy(entry_info->type, cp);
968
StrAllocCopy(entry_info->filename, dirbuf->d_name);
969
if (S_ISDIR(file_info.st_mode)) {
970
/* strip .DIR part... */
972
dot = strstr(entry_info->filename, ".DIR");
975
LYLowerCase(entry_info->filename);
976
StrAllocCopy(entry_info->type, "Directory");
978
if ((cp = strstr(entry_info->filename, "READ")) == NULL) {
979
cp = entry_info->filename;
982
if (!strncmp(cp, "ME", 2)) {
984
while (cp && *cp && *cp != '.') {
987
} else if (!strncmp(cp, ".ME", 3)) {
988
cp = (entry_info->filename +
989
strlen(entry_info->filename));
991
cp = entry_info->filename;
995
if (((len = strlen(entry_info->filename)) > 2) &&
996
entry_info->filename[len-1] == 'z') {
997
if (entry_info->filename[len-2] == '.' ||
998
entry_info->filename[len-2] == '_')
999
entry_info->filename[len-1] = 'Z';
1005
char *t = (char *)ctime((CONST time_t *)&file_info.st_ctime);
1008
StrAllocCopy(entry_info->date, (t+4));
1009
*((entry_info->date)+7) = '\0';
1010
if ((atoi((t+19))) < atoi(ThisYear))
1011
StrAllocCat(entry_info->date, (t+19));
1013
StrAllocCat(entry_info->date, (t+11));
1014
*((entry_info->date)+12) = '\0';
1019
if (!S_ISDIR(file_info.st_mode))
1020
entry_info->size = (unsigned int)file_info.st_size;
1022
entry_info->size = 0;
1024
/* Now, update the BTree etc. */
1025
if(entry_info->display)
1027
CTRACE((tfp,"Adding file to BTree: %s\n",
1028
entry_info->filename));
1029
HTBTree_add(bt, entry_info);
1032
} /* End while HTVMSreaddir() */
1039
* Run through the BTree printing out in order
1044
for (ele = HTBTree_next(bt, NULL);
1046
ele = HTBTree_next(bt, ele))
1048
entry_info = (VMSEntryInfo *)HTBTree_object(ele);
1050
/* Output the date */
1051
if(entry_info->date)
1053
PUTS(entry_info->date);
1059
/* Output the type */
1060
if(entry_info->type)
1062
for(i = 0; entry_info->type[i] != '\0' && i < 15; i++)
1063
PUTC(entry_info->type[i]);
1069
/* Output the link for the name */
1070
HTDirEntry(target, tail, entry_info->filename);
1071
PUTS(entry_info->filename);
1074
/* Output the size */
1075
if(entry_info->size)
1077
if(entry_info->size < 1024)
1078
sprintf(string_buffer," %d bytes",
1081
sprintf(string_buffer," %dKb",
1082
entry_info->size/1024);
1083
PUTS(string_buffer);
1086
PUTC('\n'); /* end of this entry */
1088
free_VMSEntryInfo_contents(entry_info);
1092
HTBTreeAndObject_free(bt);
1094
} /* End of both BTree loops */
1097
* Complete the output stream.
1110
} /* End of directory reading section */
1113
* Remove all versions of the given file. We assume there are no permissions
1114
* problems, since we do this mainly for removing temporary files.
1116
int HTVMS_remove(char *filename)
1118
int code = remove(filename); /* return the first status code */
1119
while (remove(filename) == 0)
1125
* Remove all older versions of the given file. We may fail to remove some
1126
* version due to permissions -- the loop stops either at that point, or when
1127
* we run out of older versions to remove.
1129
void HTVMS_purge(char *filename)
1131
char *older_file = 0;
1132
char *oldest_file = 0;
1135
StrAllocCopy(older_file, filename);
1136
StrAllocCat(older_file, ";-1");
1138
while (remove(older_file) == 0)
1141
* If we do not have any more older versions, it is safe to rename the
1142
* current file to version #1.
1144
if (stat(older_file, &sb) != 0) {
1145
StrAllocCopy(oldest_file, filename);
1146
StrAllocCat(oldest_file, ";1");
1147
rename(older_file, oldest_file);