forked from FDOS/kernel
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdosfns.c
More file actions
1423 lines (1200 loc) · 39.5 KB
/
Copy pathdosfns.c
File metadata and controls
1423 lines (1200 loc) · 39.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/****************************************************************/
/* */
/* dosfns.c */
/* */
/* DOS functions */
/* */
/* Copyright (c) 1995 */
/* Pasquale J. Villani */
/* All Rights Reserved */
/* */
/* This file is part of DOS-C. */
/* */
/* DOS-C is free software; you can redistribute it and/or */
/* modify it under the terms of the GNU General Public License */
/* as published by the Free Software Foundation; either version */
/* 2, or (at your option) any later version. */
/* */
/* DOS-C is distributed in the hope that it will be useful, but */
/* WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See */
/* the GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public */
/* License along with DOS-C; see the file COPYING. If not, */
/* write to the Free Software Foundation, 675 Mass Ave, */
/* Cambridge, MA 02139, USA. */
/****************************************************************/
#include "portab.h"
#include "globals.h"
#include "debug.h"
/* /// Added for SHARE. - Ron Cemer */
BYTE share_installed = 0;
/* DOS calls this to see if it's okay to open the file.
Returns a file_table entry number to use (>= 0) if okay
to open. Otherwise returns < 0 and may generate a critical
error. If < 0 is returned, it is the negated error return
code, so DOS simply negates this value and returns it in
AX. */
extern int ASMPASCAL
share_open_check(char * filename, /* pointer to fully qualified filename */
unsigned short pspseg, /* psp segment address of owner process */
int openmode, /* 0=read-only, 1=write-only, 2=read-write */
int sharemode); /* SHARE_COMPAT, etc... */
/* DOS calls this to record the fact that it has successfully
closed a file, or the fact that the open for this file failed. */
extern void ASMPASCAL
share_close_file(int fileno); /* file_table entry number */
/* DOS calls this to determine whether it can access (read or
write) a specific section of a file. We call it internally
from lock_unlock (only when locking) to see if any portion
of the requested region is already locked. If pspseg is zero,
then it matches any pspseg in the lock table. Otherwise, only
locks which DO NOT belong to pspseg will be considered.
Returns zero if okay to access or lock (no portion of the
region is already locked). Otherwise returns non-zero and
generates a critical error (if allowcriter is non-zero).
If non-zero is returned, it is the negated return value for
the DOS call. */
extern int ASMPASCAL
share_access_check(unsigned short pspseg, /* psp segment address of owner process */
int fileno, /* file_table entry number */
unsigned long ofs, /* offset into file */
unsigned long len, /* length (in bytes) of region to access */
int allowcriter); /* allow a critical error to be generated */
/* DOS calls this to lock or unlock a specific section of a file.
Returns zero if successfully locked or unlocked. Otherwise
returns non-zero.
If the return value is non-zero, it is the negated error
return code for the DOS 0x5c call. */
extern int ASMPASCAL
share_lock_unlock(unsigned short pspseg, /* psp segment address of owner process */
int fileno, /* file_table entry number */
unsigned long ofs, /* offset into file */
unsigned long len, /* length (in bytes) of region to lock or unlock */
int unlock); /* one to unlock; zero to lock */
/* /// End of additions for SHARE. - Ron Cemer */
STATIC int do_remote_lock_unlock(sft FAR *sftp, /* SFT for file */
unsigned long ofs, /* offset into file */
unsigned long len, /* length (in bytes) of region to lock or unlock */
int unlock); /* one to unlock; zero to lock */
/* get current directory structure for drive
return NULL if the CDS is not valid or the
drive is not within range */
struct cds FAR *get_cds(unsigned drive)
{
struct cds FAR *cdsp;
unsigned flags;
DFnsDbgPrintf(("get_cds(drive=%u ?>= lastdrive=%u)\n", drive, lastdrive));
if (drive >= lastdrive)
return NULL;
cdsp = &CDSp[drive];
flags = cdsp->cdsFlags;
/* Entry is disabled or JOINed drives are accessable by the path only */
if (!(flags & CDSVALID) || (flags & CDSJOINED) != 0)
{
DFnsDbgPrintf(("CDS is not valid or for JOINED drive\n"));
return NULL;
}
if (!(flags & CDSNETWDRV) && cdsp->cdsDpb == NULL)
{
DFnsDbgPrintf(("CDS is network or DBP is NULL\n"));
return NULL;
}
DFnsDbgPrintf(("returning CDS\n"));
return cdsp;
}
/* same, but on input drv is 0 for default or 1=A, 2=B, etc. */
struct cds FAR *get_cds1(unsigned drv)
{
if (drv-- == 0) /* get default drive or convert to 0 = A:, 1 = B:, ... */
drv = default_drive;
return get_cds(drv);
}
#ifdef WITHFAT32
struct dpb FAR * GetDriveDPB(UBYTE drive, COUNT * rc)
{
struct dpb FAR *dpb;
struct cds FAR *cdsp;
cdsp = get_cds1(drive);
if (cdsp == NULL)
{
*rc = DE_INVLDDRV;
return 0;
}
dpb = cdsp->cdsDpb;
if (dpb == 0 || cdsp->cdsFlags & CDSNETWDRV)
{
*rc = DE_INVLDDRV;
return 0;
}
*rc = SUCCESS;
return dpb;
}
#endif
int idx_to_sft_(int SftIndex)
{
/*called from below and int2f/ax=1216*/
sfttbl FAR *sp;
lpCurSft = (sft FAR *) - 1;
if (SftIndex < 0)
return -1;
/* Get the SFT block that contains the SFT */
for (sp = sfthead; sp != (sfttbl FAR *) - 1; sp = sp->sftt_next)
{
if (SftIndex < sp->sftt_count)
{
/* finally, point to the right entry */
lpCurSft = (sft FAR *) & (sp->sftt_table[SftIndex]);
return SftIndex;
}
SftIndex -= sp->sftt_count;
}
/* If not found, return an error */
return -1;
}
sft FAR * idx_to_sft(int SftIndex)
{
/* called internally only */
SftIndex = idx_to_sft_(SftIndex);
/* if not opened, the SFT is useless */
if (SftIndex == -1 || lpCurSft->sft_count == 0)
return (sft FAR *) - 1;
return lpCurSft;
}
int get_sft_idx(unsigned hndl)
{
psp FAR *p = MK_FP(cu_psp, 0);
int idx;
if (hndl >= p->ps_maxfiles)
return DE_INVLDHNDL;
idx = p->ps_filetab[hndl];
return idx == 0xff ? DE_INVLDHNDL : idx;
}
sft FAR *get_sft(UCOUNT hndl)
{
/* Get the SFT block that contains the SFT */
return idx_to_sft(get_sft_idx(hndl));
}
long DosRWSft(int sft_idx, size_t n, void FAR * bp, int mode)
{
/* Get the SFT block that contains the SFT */
sft FAR *s = idx_to_sft(sft_idx);
if (FP_OFF(s) == (size_t) - 1)
{
return DE_INVLDHNDL;
}
/* If for read and write-only or for write and read-only then exit */
if((mode == XFR_READ && (s->sft_mode & O_WRONLY)) ||
(mode == XFR_WRITE && (s->sft_mode & O_ACCMODE) == O_RDONLY))
{
return DE_ACCESS;
}
if (mode == XFR_FORCE_WRITE)
mode = XFR_WRITE;
/*
* Do remote first or return error.
* must have been opened from remote.
*/
if (s->sft_flags & SFT_FSHARED)
{
long XferCount;
VOID FAR *save_dta;
save_dta = dta;
lpCurSft = s;
current_filepos = s->sft_posit; /* needed for MSCDEX */
dta = bp;
XferCount = remote_rw(mode == XFR_READ ? REM_READ : REM_WRITE, s, n);
dta = save_dta;
return XferCount;
}
/* Do a device transfer if device */
if (s->sft_flags & SFT_FDEVICE)
{
struct dhdr FAR *dev = s->sft_dev;
/* Now handle raw and cooked modes */
if (s->sft_flags & SFT_FBINARY)
{
long rc = BinaryCharIO(&dev, n, bp,
mode == XFR_READ ? C_INPUT : C_OUTPUT);
if (mode == XFR_WRITE && rc > 0 && (s->sft_flags & SFT_FCONOUT))
{
size_t cnt = (size_t)rc;
const char FAR *p = bp;
while (cnt--)
update_scr_pos(*p++, 1);
}
return rc;
}
/* cooked mode */
if (mode==XFR_READ)
{
long rc;
/* Test for eof and exit */
/* immediately if it is */
if (!(s->sft_flags & SFT_FEOF))
return 0;
if (s->sft_flags & SFT_FCONIN)
rc = read_line_handle(sft_idx, n, bp);
else
rc = cooked_read(&dev, n, bp);
if (*(char *)bp == CTL_Z)
s->sft_flags &= ~SFT_FEOF;
return rc;
}
else
{
/* reset EOF state (set to no EOF) */
s->sft_flags |= SFT_FEOF;
/* if null just report full transfer */
if (s->sft_flags & SFT_FNUL)
return n;
else
return cooked_write(&dev, n, bp);
}
}
/* a block transfer */
/* /// Added for SHARE - Ron Cemer */
if (IsShareInstalled(FALSE) && (s->sft_shroff >= 0))
{
int rc = share_access_check(cu_psp, s->sft_shroff, s->sft_posit,
(unsigned long)n, 1);
if (rc != SUCCESS)
return rc;
}
/* /// End of additions for SHARE - Ron Cemer */
return rwblock(sft_idx, bp, n, mode);
}
COUNT SftSeek(int sft_idx, LONG new_pos, unsigned mode)
{
sft FAR *s = idx_to_sft(sft_idx);
if (FP_OFF(s) == (size_t) -1)
return DE_INVLDHNDL;
/* Test for invalid mode */
if (mode > SEEK_END)
return DE_INVLDFUNC;
lpCurSft = s;
/* Do special return for character devices */
if (s->sft_flags & SFT_FDEVICE)
{
new_pos = 0;
}
else if (mode == SEEK_CUR)
{
new_pos += s->sft_posit;
}
else if (mode == SEEK_END) /* seek from end of file */
{
/*
* RB list has it as Note:
* this function is called by the DOS 3.1+ kernel, but only when seeking
* from the end of a file opened with sharing modes set in such a manner
* that another process is able to change the size of the file while it
* is already open
* Tested this with Shsucdx ver 0.06 and 1.0. Both now work.
* Lredir via mfs.c from DosEMU works when writing appended files.
* Mfs.c looks for these mode bits set, so here is my best guess.;^)
*/
if ((s->sft_flags & SFT_FSHARED) &&
(s->sft_mode & (O_DENYREAD | O_DENYNONE)))
new_pos = remote_lseek(s, new_pos);
else
new_pos += s->sft_size;
}
s->sft_posit = new_pos;
return SUCCESS;
}
ULONG DosSeek(unsigned hndl, LONG new_pos, COUNT mode, int *rc)
{
int sft_idx = get_sft_idx(hndl);
/* Get the SFT block that contains the SFT */
*rc = SftSeek(sft_idx, new_pos, mode);
if (*rc == SUCCESS)
return idx_to_sft(sft_idx)->sft_posit;
return *rc;
}
STATIC long get_free_hndl(void)
{
psp FAR *p = MK_FP(cu_psp, 0);
UBYTE FAR *q = p->ps_filetab;
UBYTE FAR *r = fmemchr(q, 0xff, p->ps_maxfiles);
if (FP_SEG(r) == 0) return DE_TOOMANY;
return (unsigned)(r - q);
}
STATIC sft FAR *get_free_sft(COUNT * sft_idx)
{
COUNT sys_idx = 0;
sfttbl FAR *sp;
/* Get the SFT block that contains the SFT */
for (sp = sfthead; sp != (sfttbl FAR *) - 1; sp = sp->sftt_next)
{
REG COUNT i = sp->sftt_count;
sft FAR *sfti = sp->sftt_table;
for (; --i >= 0; sys_idx++, sfti++)
{
if (sfti->sft_count == 0)
{
*sft_idx = sys_idx;
/* MS NET uses this on open/creat TE */
{
extern WORD ASM current_sft_idx;
current_sft_idx = sys_idx;
}
return sfti;
}
}
}
/* If not found, return an error */
return (sft FAR *) - 1;
}
const char FAR *get_root(const char FAR * fname)
{
/* find the end */
register unsigned length = fstrlen(fname);
char c;
/* now back up to first path seperator or start */
fname += length;
while (length)
{
length--;
c = *--fname;
if (c == '/' || c == '\\' || c == ':') {
fname++;
break;
}
}
return fname;
}
STATIC void ConvertPathNameToFCBName(char *FCBName, const char *PathName)
{
ConvertNameSZToName83(FCBName, (char *)FP_OFF(get_root(PathName)));
FCBName[FNAME_SIZE + FEXT_SIZE] = '\0';
}
STATIC void set_fcbname(void)
{
ConvertPathNameToFCBName(DirEntBuffer.dir_name, PriPathName);
}
/* initialize SFT fields (for open/creat) for character devices */
STATIC int DeviceOpenSft(struct dhdr FAR *dhp, sft FAR *sftp)
{
int i;
sftp->sft_shroff = -1; /* /// Added for SHARE - Ron Cemer */
sftp->sft_count += 1;
sftp->sft_flags =
(dhp->dh_attr & ~(SFT_MASK | SFT_FSHARED)) | SFT_FDEVICE | SFT_FEOF;
fmemcpy(sftp->sft_name, dhp->dh_name, FNAME_SIZE);
/* pad with spaces */
for (i = FNAME_SIZE + FEXT_SIZE - 1; sftp->sft_name[i] == '\0'; i--)
sftp->sft_name[i] = ' ';
/* and uppercase */
DosUpFMem(sftp->sft_name, FNAME_SIZE + FEXT_SIZE);
sftp->sft_dev = dhp;
sftp->sft_date = dos_getdate();
sftp->sft_time = dos_gettime();
sftp->sft_attrib = D_DEVICE;
if (sftp->sft_dev->dh_attr & SFT_FOCRM)
{
/* if Open/Close/RM bit in driver's attribute is set
* then issue an Open request to the driver
*/
struct dhdr FAR *dev = sftp->sft_dev;
if (BinaryCharIO(&dev, 0, MK_FP(0x0000, 0x0000), C_OPEN) != SUCCESS)
return DE_ACCESS;
}
return SUCCESS;
}
/*
extended open codes
0000 0000 always fail
0000 0001 open O_OPEN
0000 0010 replace O_TRUNC
0001 0000 create new file O_CREAT
0001 0001 create if not exists, open if exists O_CREAT | O_OPEN
0001 0010 create O_CREAT | O_TRUNC
bits for flags (bits 11-8 are internal FreeDOS bits only)
15 O_FCB called from FCB open
14 O_SYNC commit for each write (not implemented yet)
13 O_NOCRIT do not invoke int23 (not implemented yet)
12 O_LARGEFILE allow files >= 2gb but < 4gb (not implemented yet)
11 O_LEGACY not called from int21/ah=6c: find right fn for redirector
10 O_CREAT if file does not exist, create it
9 O_TRUNC if file exists, truncate and open it \ not both
8 O_OPEN if file exists, open it /
7 O_NOINHERIT do not inherit handle on exec
6 \
5 - sharing modes
4 /
3 reserved
2 bits 2,1,0 = 100: RDONLY and do not modify file's last access time
(not implemented yet)
1 \ 0=O_RDONLY, 1=O_WRONLY,
0 / 2=O_RDWR, 3=O_EXECCASE (preserve case for redirector EXEC,
(not implemented yet))
*/
long DosOpenSft(char FAR * fname, unsigned flags, unsigned attrib)
{
COUNT sft_idx;
sft FAR *sftp;
struct dhdr FAR *dhp;
long result;
DFnsDbgPrintf(("DosOpenSft()\n"));
result = truename(fname, PriPathName, CDS_MODE_CHECK_DEV_PATH);
if (result < SUCCESS)
return result;
set_fcbname();
/* now get a free system file table entry */
if ((sftp = get_free_sft(&sft_idx)) == (sft FAR *) - 1)
{
DFnsDbgPrintf(("No free SFT entry\n"));
return DE_TOOMANY;
}
fmemset(sftp, 0, sizeof(sft));
sftp->sft_psp = cu_psp;
sftp->sft_mode = flags & 0xf0ff;
OpenMode = (BYTE) flags;
sftp->sft_shroff = -1; /* /// Added for SHARE - Ron Cemer */
sftp->sft_attrib = attrib = attrib | D_ARCHIVE;
/* check for a device */
if ((result & IS_DEVICE) && (dhp = IsDevice(fname)) != NULL)
{
int rc = DeviceOpenSft(dhp, sftp);
/* check the status code returned by the
* driver when we tried to open it
*/
if (rc < SUCCESS)
return rc;
return sft_idx;
}
if (result & IS_NETWORK)
{
int status;
unsigned cmd;
if ((flags & (O_TRUNC | O_CREAT)) == O_CREAT)
attrib |= 0x100;
lpCurSft = sftp;
cmd = REM_CREATE;
if (!(flags & O_LEGACY))
{
extern UWORD ASM ext_open_mode, ASM ext_open_attrib, ASM ext_open_action;
ext_open_mode = flags & 0x70ff;
ext_open_attrib = attrib & 0xff;
ext_open_action = ((flags & 0x0300) >> 8) | ((flags & O_CREAT) >> 6);
cmd = REM_EXTOC;
}
else if (!(flags & O_CREAT))
{
cmd = REM_OPEN;
attrib = (BYTE)flags;
}
status = (int)network_redirector_mx(cmd, sftp, (void *)attrib);
if (status >= SUCCESS)
{
if (sftp->sft_count == 0)
sftp->sft_count++;
return sft_idx | ((long)status << 16);
}
return status;
}
/* First test the flags to see if the user has passed a valid */
/* file mode... */
if ((flags & O_ACCMODE) > 2)
{
DFnsDbgPrintf(("Invalid open flags - %u\n", (flags & O_ACCMODE)));
return DE_INVLDACC;
}
/* NEVER EVER allow directories to be created */
/* ... though FCBs are weird :) */
if (!(flags & O_FCB) &&
(attrib & ~(D_RDONLY | D_HIDDEN | D_SYSTEM | D_ARCHIVE | D_VOLID)))
return DE_ACCESS;
/* /// Added for SHARE. - Ron Cemer */
if (IsShareInstalled(TRUE))
{
if ((sftp->sft_shroff =
share_open_check(PriPathName, cu_psp,
flags & 0x03, (flags >> 4) & 0x07)) < 0)
return sftp->sft_shroff;
}
/* /// End of additions for SHARE. - Ron Cemer */
sftp->sft_count++;
sftp->sft_flags = PriPathName[0] - 'A';
result = dos_open(PriPathName, flags, attrib, sft_idx);
DFnsDbgPrintf(("dos_open() returned %i\n", result));
if (result < 0)
{
/* /// Added for SHARE *** CURLY BRACES ADDED ALSO!!! ***. - Ron Cemer */
if (IsShareInstalled(TRUE))
{
share_close_file(sftp->sft_shroff);
sftp->sft_shroff = -1;
}
/* /// End of additions for SHARE. - Ron Cemer */
sftp->sft_count--;
return result;
}
return sft_idx | ((long)result << 16);
}
long DosOpen(char FAR * fname, unsigned mode, unsigned attrib)
{
long result;
unsigned hndl;
/* test if mode is in range */
if ((mode & ~O_VALIDMASK) != 0)
return DE_INVLDACC;
/* get a free handle */
if ((result = get_free_hndl()) < 0)
return result;
hndl = (unsigned)result;
result = DosOpenSft(fname, mode, attrib);
if (result < SUCCESS)
return result;
((psp FAR *)MK_FP(cu_psp, 0))->ps_filetab[hndl] = (UBYTE)result;
return hndl | (result & 0xffff0000l);
}
COUNT CloneHandle(unsigned hndl)
{
/* now get the system file table entry */
sft FAR *sftp = get_sft(hndl);
if (sftp == (sft FAR *) -1 || (sftp->sft_mode & O_NOINHERIT))
return DE_INVLDHNDL;
/* now that we have the system file table entry, get the fnode */
/* index, and increment the count, so that we've effectively */
/* cloned the file. */
sftp->sft_count += 1;
return SUCCESS;
}
long DosDup(unsigned Handle)
{
long NewHandle;
if ((NewHandle = get_free_hndl()) < 0)
return NewHandle;
if (DosForceDup(Handle, (unsigned)NewHandle) < 0)
return DE_INVLDHNDL;
else
return NewHandle;
}
COUNT DosForceDup(unsigned OldHandle, unsigned NewHandle)
{
psp FAR *p = MK_FP(cu_psp, 0);
sft FAR *Sftp;
/* Get the SFT block that contains the SFT */
if ((Sftp = get_sft(OldHandle)) == (sft FAR *) - 1)
return DE_INVLDHNDL;
/* now close the new handle if it's open */
if ((UBYTE) p->ps_filetab[NewHandle] != 0xff)
{
COUNT ret;
if ((ret = DosClose(NewHandle)) != SUCCESS)
return ret;
}
/* If everything looks ok, bump it up. */
p->ps_filetab[NewHandle] = p->ps_filetab[OldHandle];
/* possible hazard: integer overflow ska*/
Sftp->sft_count += 1;
return SUCCESS;
}
COUNT DosCloseSft(int sft_idx, BOOL commitonly)
{
sft FAR *sftp = idx_to_sft(sft_idx);
int result;
if (FP_OFF(sftp) == (size_t) - 1)
return DE_INVLDHNDL;
lpCurSft = sftp;
/*
remote sub sft_count.
*/
if (sftp->sft_flags & SFT_FSHARED)
{
/* printf("closing SFT %d = %p\n",sft_idx,sftp); */
return network_redirector_fp(commitonly ? REM_FLUSH: REM_CLOSE, sftp);
}
if (sftp->sft_flags & SFT_FDEVICE)
{
if (sftp->sft_dev->dh_attr & SFT_FOCRM)
{
/* if Open/Close/RM bit in driver's attribute is set
* then issue a Close request to the driver
*/
struct dhdr FAR *dev = sftp->sft_dev;
if (BinaryCharIO(&dev, 0, MK_FP(0x0000, 0x0000), C_CLOSE) != SUCCESS)
return DE_INVLDHNDL;
}
/* now just drop the count if a device */
if (!commitonly)
sftp->sft_count -= 1;
return SUCCESS;
}
/* else call file system handler */
result = dos_close(sft_idx);
if (commitonly || result != SUCCESS)
return result;
/* /// Added for SHARE *** CURLY BRACES ADDED ALSO!!! ***. - Ron Cemer */
if (sftp->sft_count == 1 && IsShareInstalled(TRUE))
{
if (sftp->sft_shroff >= 0)
share_close_file(sftp->sft_shroff);
sftp->sft_shroff = -1;
}
/* /// End of additions for SHARE. - Ron Cemer */
sftp->sft_count -= 1;
return SUCCESS;
}
COUNT DosClose(COUNT hndl)
{
psp FAR *p = MK_FP(cu_psp, 0);
int sft_idx = get_sft_idx(hndl);
if (FP_OFF(idx_to_sft(sft_idx)) == (size_t) - 1)
return DE_INVLDHNDL;
/* We must close the (valid) file handle before any critical error */
/* may occur, else e.g. ABORT will try to close the file twice, */
/* the second time after stdout is already closed */
p->ps_filetab[hndl] = 0xff;
/* Get the SFT block that contains the SFT */
return DosCloseSft(sft_idx, FALSE);
}
UWORD DosGetFree(UBYTE drive, UWORD * navc, UWORD * bps, UWORD * nc)
{
/* navc==NULL means: called from FatGetDrvData, fcbfns.c */
struct dpb FAR *dpbp;
struct cds FAR *cdsp;
COUNT rg[4];
UWORD spc;
/* first check for valid drive */
spc = -1;
cdsp = get_cds1(drive);
if (cdsp == NULL)
return spc;
current_ldt = cdsp;
if (cdsp->cdsFlags & CDSNETWDRV)
{
if (remote_getfree(cdsp, rg) != SUCCESS)
return spc;
/* for int21/ah=1c:
Undoc DOS says, its not supported for
network drives. so it's probably OK */
/* some programs such as RHIDE want it though and
the redirector can provide all info
- Bart, 2002 Apr 1 */
spc = rg[0];
if (navc != NULL)
{
*navc = (COUNT) rg[3];
spc &= 0xff; /* zero out media ID byte */
}
*nc = (COUNT) rg[1];
*bps = (COUNT) rg[2];
return spc;
}
dpbp = cdsp->cdsDpb;
if (dpbp == NULL)
return spc;
if (navc == NULL)
{
/* hazard: no error checking! */
flush_buffers(dpbp->dpb_unit);
dpbp->dpb_flags = M_CHANGED;
}
if (media_check(dpbp) < 0)
return spc;
/* get the data available from dpb */
spc = (dpbp->dpb_clsmask + 1);
*bps = dpbp->dpb_secsize;
/* now tell fs to give us free cluster */
/* count */
#ifdef WITHFAT32
if (ISFAT32(dpbp))
{
ULONG cluster_size, ntotal, nfree;
/* we shift ntotal until it is equal to or below 0xfff6 */
cluster_size = (ULONG) dpbp->dpb_secsize << dpbp->dpb_shftcnt;
ntotal = dpbp->dpb_xsize - 1;
if (navc != NULL)
nfree = dos_free(dpbp);
while (ntotal > FAT_MAGIC16 && cluster_size < 0x8000)
{
cluster_size <<= 1;
spc <<= 1;
ntotal >>= 1;
nfree >>= 1;
}
/* get the data available from dpb */
*nc = ntotal > FAT_MAGIC16 ? FAT_MAGIC16 : (UCOUNT) ntotal;
/* now tell fs to give us free cluster */
/* count */
if (navc != NULL)
*navc = nfree > FAT_MAGIC16 ? FAT_MAGIC16 : (UCOUNT) nfree;
return spc;
}
#endif
/* a passed navc of NULL means: skip free; see FatGetDrvData
fcbfns.c */
if (navc != NULL)
*navc = (COUNT) dos_free(dpbp);
*nc = dpbp->dpb_size - 1;
if (spc > 64)
{
/* fake for 64k clusters do confuse some DOS programs, but let
others work without overflowing */
spc >>= 1;
if (navc != NULL)
*navc = ((unsigned)*navc < FAT_MAGIC16 / 2) ?
((unsigned)*navc << 1) : FAT_MAGIC16;
*nc = ((unsigned)*nc < FAT_MAGIC16 / 2) ? ((unsigned)*nc << 1) : FAT_MAGIC16;
}
return spc;
}
#ifdef WITHFAT32
#define IS_SLASH(ch) (ch == '\\' || ch == '/')
COUNT DosGetExtFree(BYTE FAR * DriveString, struct xfreespace FAR * xfsp)
{
struct dpb FAR *dpbp;
struct cds FAR *cdsp;
UCOUNT rg[4];
/* ensure all fields known value - clear reserved bytes & set xfs_version.actual to 0 */
fmemset(xfsp, 0, sizeof(struct xfreespace));
xfsp->xfs_datasize = sizeof(struct xfreespace);
/*
DriveString should be in form of "C:", "C:\", "\", "", ., or .\
where missing drive is treated as a request for the current drive,
or network name in form "\\SERVER\share"
however, network names like \\SERVER\C aren't supported yet
*/
cdsp = NULL;
if ( !*DriveString || (*DriveString == '.') || (IS_SLASH(DriveString[0]) && !IS_SLASH(DriveString[1])) )
cdsp = get_cds(default_drive); /* if "" or .[\] or \[path] then use current drive */
else if (DriveString[1] == ':')
cdsp = get_cds(DosUpFChar(*DriveString) - 'A'); /* assume drive specified */
if (cdsp == NULL) /* either error, really bad string, or network name */
return DE_INVLDDRV;
if (cdsp->cdsFlags & CDSNETWDRV)
{
if (remote_getfree(cdsp, rg) != SUCCESS)
return DE_INVLDDRV;
xfsp->xfs_clussize = rg[0];
xfsp->xfs_totalclusters = rg[1];
xfsp->xfs_secsize = rg[2];
xfsp->xfs_freeclusters = rg[3];
}
else
{
dpbp = cdsp->cdsDpb;
if (dpbp == NULL || media_check(dpbp) < 0)
return DE_INVLDDRV;
xfsp->xfs_secsize = dpbp->dpb_secsize;
xfsp->xfs_totalclusters =
(ISFAT32(dpbp) ? dpbp->dpb_xsize : dpbp->dpb_size);
xfsp->xfs_freeclusters = dos_free(dpbp);
xfsp->xfs_clussize = dpbp->dpb_clsmask + 1;
}
xfsp->xfs_totalunits = xfsp->xfs_totalclusters;
xfsp->xfs_freeunits = xfsp->xfs_freeclusters;
xfsp->xfs_totalsectors = xfsp->xfs_totalclusters * xfsp->xfs_clussize;
xfsp->xfs_freesectors = xfsp->xfs_freeclusters * xfsp->xfs_clussize;
xfsp->xfs_datasize = sizeof(struct xfreespace);
return SUCCESS;
}
#endif
COUNT DosGetCuDir(UBYTE drive, BYTE FAR * s)
{
char path[3];
if (drive-- == 0) /* get default drive or convert to 0 = A:, 1 = B:, ... */
drive = default_drive;
path[0] = 'A' + (drive & 0x1f);
path[1] = ':';
path[2] = '\0';
if (truename(path, PriPathName, CDS_MODE_SKIP_PHYSICAL) < SUCCESS)
return DE_INVLDDRV;
/* skip d:\ */
fstrcpy(s, PriPathName + 3);
return SUCCESS;
}
#undef CHDIR_DEBUG
COUNT DosChangeDir(BYTE FAR * s)
{
COUNT result;
result = truename(s, PriPathName, CDS_MODE_CHECK_DEV_PATH);
if (result < SUCCESS)
return DE_PATHNOTFND;
set_fcbname();
if ((FP_OFF(current_ldt) != 0xFFFF) &&
(strlen(PriPathName) >= sizeof(current_ldt->cdsCurrentPath)))
return DE_PATHNOTFND;
#if defined(CHDIR_DEBUG)
printf("Remote Chdir: n='%Fs' p='%Fs\n", s, PriPathName);
#endif
/* now get fs to change to new */
/* directory */
result = (result & IS_NETWORK ? network_redirector(REM_CHDIR) :
dos_cd(PriPathName));
#if defined(CHDIR_DEBUG)
printf("status = %04x, new_path='%Fs'\n", result, cdsd->cdsCurrentPath);
#endif
if (result != SUCCESS)
return result;
/*
Copy the path to the current directory
structure.
Some redirectors do not write back to the CDS.
SHSUCdX needs this. jt
*/
if (FP_OFF(current_ldt) != 0xFFFF)
{
fstrcpy(current_ldt->cdsCurrentPath, PriPathName);
if (PriPathName[7] == 0)
current_ldt->cdsCurrentPath[8] = 0; /* Need two Zeros at the end */
}
return SUCCESS;
}
STATIC int pop_dmp(int rc, dmatch FAR * dmp)
{
dta = dmp;
if (rc == SUCCESS)
{
fmemcpy(dta, &sda_tmp_dm, 21);
dmp->dm_attr_fnd = (BYTE) SearchDir.dir_attrib;
dmp->dm_time = SearchDir.dir_time;
dmp->dm_date = SearchDir.dir_date;
dmp->dm_size = (LONG) SearchDir.dir_size;
ConvertName83ToNameSZ(dmp->dm_name, (BYTE FAR *) SearchDir.dir_name);
}
return rc;
}
COUNT DosFindFirst(UCOUNT attr, BYTE FAR * name)