Subversion Repositories Kolibri OS

Rev

Rev 437 | Rev 465 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
425 victor 1
$Revision: 442 $
431 serge 2
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3
;;                                                              ;;
4
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
5
;; Distributed under terms of the GNU General Public License    ;;
6
;;                                                              ;;
7
;; RAMDISK functions                                            ;;
8
;; (C) 2004 Ville Turjanmaa, License: GPL                       ;;
9
;; Addings by M.Lisovin                                         ;;
10
;; LFN support by diamond                                       ;;
11
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1 ha 12
 
5 halyavin 13
; calculate fat chain
1 ha 14
 
5 halyavin 15
calculatefatchain:
16
 
17
   pushad
18
 
381 serge 19
   mov  esi,RAMDISK+512
20
   mov  edi,RAMDISK_FAT
5 halyavin 21
 
22
 fcnew:
23
   mov  eax,dword [esi]
24
   mov  ebx,dword [esi+4]
25
   mov  ecx,dword [esi+8]
26
   mov  edx,ecx
27
   shr  edx,4   ;8 ok
28
   shr  dx,4    ;7 ok
29
   xor  ch,ch
30
   shld ecx,ebx,20 ;6 ok
31
   shr  cx,4     ;5 ok
32
   shld ebx,eax,12
33
   and  ebx,0x0fffffff  ;4 ok
34
   shr  bx,4    ;3 ok
35
   shl  eax,4
36
   and  eax,0x0fffffff  ;2 ok
37
   shr  ax,4  ;1 ok
78 diamond 38
   mov  dword [edi],eax
39
   mov  dword [edi+4],ebx
40
   mov  dword [edi+8],ecx
41
   mov  dword [edi+12],edx
42
   add  edi,16
5 halyavin 43
   add  esi,12
44
 
381 serge 45
   cmp  edi,RAMDISK_FAT+2856*2   ;2849 clusters
5 halyavin 46
   jnz  fcnew
47
 
48
   popad
49
   ret
50
 
51
 
52
restorefatchain:   ; restore fat chain
53
 
54
   pushad
55
 
381 serge 56
   mov  esi,RAMDISK_FAT
57
   mov  edi,RAMDISK+512
5 halyavin 58
 
59
  fcnew2:
60
   mov  eax,dword [esi]
61
   mov  ebx,dword [esi+4]
62
   shl  ax,4
63
   shl  eax,4
64
   shl  bx,4
65
   shr  ebx,4
66
   shrd eax,ebx,8
67
   shr  ebx,8
78 diamond 68
   mov  dword [edi],eax
69
   mov  word [edi+4],bx
70
   add  edi,6
5 halyavin 71
   add  esi,8
72
 
381 serge 73
   cmp  edi,RAMDISK+512+4278     ;4274 bytes - all used FAT
5 halyavin 74
   jb   fcnew2
75
 
381 serge 76
   mov  esi,RAMDISK+512           ; duplicate fat chain
77
   mov  edi,RAMDISK+512+0x1200
5 halyavin 78
   mov  ecx,1069        ;4274/4
79
   cld
80
   rep  movsd
81
 
82
   popad
83
   ret
84
 
85
 
1 ha 86
ramdisk_free_space:
87
;---------------------------------------------
88
;
89
; returns free space in edi
90
; rewr.by Mihasik
91
;---------------------------------------------
92
 
93
        push   eax ebx ecx
94
 
381 serge 95
        mov  edi,RAMDISK_FAT ;start of FAT
1 ha 96
        xor  ax,ax    ;Free cluster=0x0000 in FAT
97
        xor  ebx,ebx  ;counter
5 halyavin 98
        mov  ecx,2849 ;2849 clusters
1 ha 99
        cld
100
    rdfs1:
101
        repne scasw
102
        jnz  rdfs2    ;if last cluster not 0
103
        inc  ebx
78 diamond 104
        test    ecx, ecx
105
        jnz     rdfs1
1 ha 106
    rdfs2:
107
        shl  ebx,9    ;free clusters*512
108
        mov  edi,ebx
247 serge 109
 
1 ha 110
        pop    ecx ebx eax
111
        ret
112
 
113
 
114
expand_filename:
115
;---------------------------------------------
116
;
117
; exapand filename with '.' to 11 character
118
; eax - pointer to filename
119
;---------------------------------------------
120
 
121
        push esi edi ebx
122
 
123
        mov  edi,esp                  ; check for '.' in the name
124
        add  edi,12+8
125
 
126
        mov  esi,eax
127
 
128
        mov  eax,edi
129
        mov  [eax+0],dword '    '
130
        mov  [eax+4],dword '    '
131
        mov  [eax+8],dword '    '
132
 
133
      flr1:
134
 
135
        cmp  [esi],byte '.'
136
        jne  flr2
137
        mov  edi,eax
138
        add  edi,7
139
        jmp  flr3
140
 
141
      flr2:
142
 
143
        mov  bl,[esi]
144
        mov  [edi],bl
145
 
146
      flr3:
147
 
148
        inc  esi
149
        inc  edi
150
 
151
        mov  ebx,eax
152
        add  ebx,11
153
 
154
        cmp  edi,ebx
155
        jbe  flr1
156
 
157
        pop  ebx edi esi
158
        ret
159
 
160
fileread:
161
;----------------------------------------------------------------
162
;
163
;  fileread - sys floppy
164
;
165
;  eax  points to filename 11 chars
166
;  ebx  first wanted block       ; 1+ ; if 0 then set to 1
167
;  ecx  number of blocks to read ; 1+ ; if 0 then set to 1
168
;  edx  mem location to return data
169
;  esi  length of filename 12*X 0=root
170
;
171
;  ret ebx = size or 0xffffffff file not found
172
;      eax = 0 ok read or other = errormsg
173
;
174
;--------------------------------------------------------------
175
        test   ebx,ebx ;if ebx=0 - set to 1
176
        jnz    frfl5
177
        inc    ebx
178
      frfl5:
179
        test   ecx,ecx ;if ecx=0 - set to 1
180
        jnz    frfl6
181
        inc    ecx
182
      frfl6:
183
        test   esi,esi          ; return ramdisk root
184
        jnz    fr_noroot        ;if not root
185
        cmp    ebx,14           ;14 clusters=root dir
186
        ja     oorr
187
        cmp    ecx,14
188
        ja     oorr
189
        jmp    fr_do
190
      oorr:
191
        mov    eax,5            ;out of root range (fnf)
192
        xor    ebx,ebx
193
        dec    ebx              ;0xffffffff
194
        ret
195
 
196
      fr_do:                    ;reading rootdir
197
        mov    edi,edx
198
        dec    ebx
199
        push   edx
247 serge 200
        mov    edx,ecx
1 ha 201
        add    edx,ebx
5 halyavin 202
        cmp    edx,15     ;ebx+ecx=14+1
1 ha 203
        pushf
204
        jbe    fr_do1
205
        sub    edx,14
206
        sub    ecx,edx
207
      fr_do1:
208
        shl    ebx,9
381 serge 209
        mov    esi,RAMDISK+512*19
1 ha 210
        add    esi,ebx
211
        shl    ecx,7
212
        cld
213
        rep    movsd
214
        popf
215
        pop    edx
5 halyavin 216
        jae    fr_do2
1 ha 217
        xor    eax,eax ; ok read
218
        xor    ebx,ebx
219
        ret
220
      fr_do2:        ;if last cluster
221
        mov    eax,6  ;end of file
222
        xor    ebx,ebx
223
        ret
224
 
225
     fr_noroot:
226
 
227
        sub    esp,32
228
        call   expand_filename
229
 
230
        dec    ebx
231
 
232
        push   eax
233
 
234
        push   eax ebx ecx edx esi edi
235
        call   rd_findfile
236
        je     fifound
237
        add    esp,32+28   ;if file not found
238
        ret
239
 
240
     fifound:
241
 
242
        mov    ebx,[edi-11+28]          ;file size
243
        mov    [esp+20],ebx
244
        mov    [esp+24],ebx
245
        add    edi,0xf
246
        movzx  eax,word [edi]
247
        mov    edi,eax                  ;edi=cluster
248
 
249
      frnew:
250
 
251
        add    eax,31                   ;bootsector+2*fat+filenames
252
        shl    eax,9                    ;*512
381 serge 253
        add    eax,RAMDISK             ;image base
1 ha 254
        mov    ebx,[esp+8]
255
        mov    ecx,512                  ;[esp+4]
256
 
257
        cmp    [esp+16],dword 0         ; wanted cluster ?
258
        jne    frfl7
259
        call   memmove
260
        add    [esp+8],dword 512
261
        dec    dword [esp+12]           ; last wanted cluster ?
262
        je     frnoread
263
        jmp    frfl8
264
      frfl7:
265
        dec    dword [esp+16]
266
      frfl8:
381 serge 267
        movzx  eax,word [edi*2+RAMDISK_FAT]        ; find next cluster from FAT
1 ha 268
        mov    edi,eax
269
        cmp    edi,4095                 ;eof  - cluster
270
        jz     frnoread2
271
 
272
        cmp    [esp+24],dword 512       ;eof  - size
273
        jb     frnoread
274
        sub    [esp+24],dword 512
275
 
276
        jmp    frnew
277
 
278
      frnoread2:
279
 
280
        cmp    [esp+16],dword 0         ; eof without read ?
281
        je     frnoread
282
 
283
        pop    edi esi edx ecx
284
        add    esp,4
285
        pop    ebx     ; ebx <- eax : size of file
286
        add    esp,36
287
        mov    eax,6   ; end of file
288
        ret
289
 
290
      frnoread:
291
 
292
        pop    edi esi edx ecx
293
        add    esp,4
294
        pop    ebx     ; ebx <- eax : size of file
295
        add    esp,36
296
        xor    eax,eax  ;read ok
297
        ret
298
 
299
filedelete:
300
;--------------------------------------------
301
;
302
; filedelete - sys floppy
303
; in:
304
; eax -  pointer to filename 11 chars
305
;
306
; out:
307
; eax - 0 = successful, 5 = file not found
308
;
309
;--------------------------------------------
310
 
311
        sub    esp,32
312
        call   expand_filename
313
 
314
        push   eax ebx ecx edx esi edi
247 serge 315
 
1 ha 316
        call   rd_findfile
317
        je     fifoundd
318
        pop    edi esi edx ecx ebx eax ;file not found
319
        add    esp,32
320
        mov    eax,5
321
        ret
322
 
323
     fifoundd:
324
 
325
        mov    [edi-11],byte 0xE5       ;mark filename deleted
326
        add    edi,0xf
327
        movzx  eax,word [edi]
328
        mov    edi,eax                  ;edi = cluster
329
 
330
      frnewd:
331
 
332
        shl    edi,1                    ;find next cluster from FAT
381 serge 333
        add    edi,RAMDISK_FAT
1 ha 334
        movzx  eax,word [edi]
335
        mov    [edi],word 0x0           ;clear fat chain cluster
336
        mov    edi,eax
337
        cmp    edi,dword 0xff8          ;last cluster ?
338
        jb     frnewd
339
 
340
        pop    edi esi edx ecx ebx eax
341
        add    esp,32
342
        xor    eax,eax       ; file found
343
        ret
344
 
345
 
247 serge 346
 
1 ha 347
filesave:
348
;----------------------------------------------------------
349
;
350
; filesave - sys floppy
351
;
352
; eax points to filename 11 chars
353
;
354
;        eax      ; pointer to file name
355
;        ebx      ; buffer
356
;        ecx      ; count to write in bytes
357
;        edx      ; 0 create new , 1 append
358
;
359
;-----------------------------------------------------------
360
 
361
        sub  esp,32
362
        call expand_filename
363
        test edx,edx
364
        jnz  fsdel
365
        pusha
366
        call filedelete
367
        popa
368
 
369
      fsdel:
370
 
371
        call   ramdisk_free_space
372
        cmp    ecx,edi
373
        jbe    rd_do_save
374
        add    esp,32
375
        mov    eax,8    ;disk full
376
        ret
377
 
378
      rd_do_save:
379
 
380
        push   eax ebx ecx edx esi edi
381
 
381 serge 382
        mov    edi,RAMDISK+512*18+512  ;Point at directory
1 ha 383
        mov    edx,224 +1
384
        ; find an empty spot for filename in the root dir
385
     l20ds:
386
        dec    edx
387
        jz     frnoreadds
388
     l21ds:
389
        cmp    [edi],byte 0xE5
390
        jz     fifoundds
391
        cmp    [edi],byte 0x0
392
        jz     fifoundds
393
        add    edi,32                   ; Advance to next entry
394
        jmp    l20ds
395
     fifoundds:
396
 
397
        push   edi                      ; move the filename to root dir
398
        mov    esi,[esp+4+20]
399
        mov    ecx,11
400
        cld
401
        rep    movsb
402
        pop    edi
403
        mov    edx,edi
404
        add    edx,11+0xf               ; edx <- cluster save position
405
        mov    ebx,[esp+12]             ; save file size
406
        mov    [edi+28],ebx
407
        mov    [edi+11],byte 0x20       ; attribute
408
; Ivan Poddubny 11/12/2003:
409
call get_date_for_file   ; from FAT32.INC
410
mov [edi+24],ax          ; date
411
call get_time_for_file   ; from FAT32.INC
412
mov [edi+22],ax          ; time
413
; End
381 serge 414
        mov    edi,RAMDISK_FAT            ;pointer to first cluster
1 ha 415
        mov    ecx,2849
416
        cld
417
      frnewds:
418
        xor    ax,ax
419
        repne  scasw
420
        mov    ebx,2848
421
        sub    ebx,ecx
422
        mov    [edx],bx                 ; save next cluster pos. to prev cl.
423
        mov    edx,edi                  ; next save pos abs mem add
424
        dec    edx
425
        dec    edx
426
        call   fdc_filesave
427
        pusha                           ; move save to floppy cluster
428
        add    ebx,31
429
        shl    ebx,9
381 serge 430
        add    ebx,RAMDISK
1 ha 431
        mov    eax,[esp+32+16]
432
        mov    ecx,512
433
        call   memmove
434
        popa
435
 
436
        mov    eax,[esp+12]
437
        cmp    eax,512
48 halyavin 438
        jbe    flnsa
1 ha 439
        sub    eax,512
440
        mov    [esp+12],eax
78 diamond 441
        add     dword [esp+16], 512
1 ha 442
        jmp    frnewds
443
 
444
     flnsa:
78 diamond 445
        mov    [edi-2],word 4095          ; mark end of file - last cluster
1 ha 446
 
447
      frnoreadds:
448
 
449
        pop    edi esi edx ecx ebx eax
450
        add    esp,32
451
 
19 mario79 452
;        pusha
453
;        cli
454
;        call   fdc_commitfile
455
;        sti
456
;        popa
1 ha 457
 
458
        xor    eax,eax ;ok write
459
        ret
460
 
461
   rd_findfile:
462
   ;by Mihasik
463
   ;IN: eax - pointer to filename OUT: filestring+11 in edi or notZero in flags and fnf in eax,ebx
464
 
381 serge 465
        mov    edi,RAMDISK+512*18+512  ;Point at directory
1 ha 466
        cld
467
    rd_newsearch:
468
        mov    esi,eax
469
        mov    ecx,11
470
        rep    cmpsb
471
        je     rd_ff
472
        add    cl,21
473
        add    edi,ecx
381 serge 474
        cmp    edi,RAMDISK+512*33
1 ha 475
        jb     rd_newsearch
476
        mov    eax,5      ;if file not found - eax=5
477
        xor    ebx,ebx
247 serge 478
        dec    ebx    ;ebx=0xffffffff and zf=0
1 ha 479
     rd_ff:
247 serge 480
        ret
1 ha 481
 
71 diamond 482
; \begin{diamond}
483
 
484
uni2ansi_str:
485
; convert UNICODE zero-terminated string to ASCII-string (codepage 866)
486
; in: esi->source, edi->buffer (may be esi=edi)
487
; destroys: eax,esi,edi
83 diamond 488
        lodsw
489
        test    ax, ax
490
        jz      .done
491
        cmp     ax, 0x80
492
        jb      .ascii
493
        cmp     ax, 0x401
494
        jz      .yo1
495
        cmp     ax, 0x451
496
        jz      .yo2
497
        cmp     ax, 0x410
498
        jb      .unk
499
        cmp     ax, 0x440
500
        jb      .rus1
501
        cmp     ax, 0x450
502
        jb      .rus2
71 diamond 503
.unk:
83 diamond 504
        mov     al, '_'
505
        jmp     .doit
71 diamond 506
.yo1:
83 diamond 507
        mov     al, 'ð'
508
        jmp     .doit
71 diamond 509
.yo2:
83 diamond 510
        mov     al, 'ñ'
511
        jmp     .doit
71 diamond 512
.rus1:
513
; 0x410-0x43F -> 0x80-0xAF
83 diamond 514
        add     al, 0x70
515
        jmp     .doit
71 diamond 516
.rus2:
75 diamond 517
; 0x440-0x44F -> 0xE0-0xEF
83 diamond 518
        add     al, 0xA0
71 diamond 519
.ascii:
520
.doit:
83 diamond 521
        stosb
522
        jmp     uni2ansi_str
71 diamond 523
.done:
83 diamond 524
        mov     byte [edi], 0
525
        ret
71 diamond 526
 
75 diamond 527
ansi2uni_char:
528
; convert ANSI character in al to UNICODE character in ax, using cp866 encoding
529
        mov     ah, 0
530
; 0x00-0x7F - trivial map
531
        cmp     al, 0x80
532
        jb      .ret
533
; 0x80-0xAF -> 0x410-0x43F
534
        cmp     al, 0xB0
535
        jae     @f
536
        add     ax, 0x410-0x80
537
.ret:
538
        ret
539
@@:
540
; 0xE0-0xEF -> 0x440-0x44F
541
        cmp     al, 0xE0
542
        jb      .unk
543
        cmp     al, 0xF0
544
        jae     @f
545
        add     ax, 0x440-0xE0
546
        ret
547
; 0xF0 -> 0x401
548
; 0xF1 -> 0x451
549
@@:
550
        cmp     al, 'ð'
551
        jz      .yo1
552
        cmp     al, 'ñ'
553
        jz      .yo2
554
.unk:
555
        mov     al, '_'         ; ah=0
556
        ret
557
.yo1:
558
        mov     ax, 0x401
559
        ret
560
.yo2:
561
        mov     ax, 0x451
562
        ret
563
 
71 diamond 564
char_toupper:
565
; convert character to uppercase, using cp866 encoding
566
; in: al=symbol
567
; out: al=converted symbol
83 diamond 568
        cmp     al, 'a'
569
        jb      .ret
570
        cmp     al, 'z'
571
        jbe     .az
572
        cmp     al, ' '
573
        jb      .ret
574
        cmp     al, 'à'
575
        jb      .rus1
576
        cmp     al, 'ï'
577
        ja      .ret
71 diamond 578
; 0xE0-0xEF -> 0x90-0x9F
83 diamond 579
        sub     al, 'à'-''
71 diamond 580
.ret:
83 diamond 581
        ret
71 diamond 582
.rus1:
583
; 0xA0-0xAF -> 0x80-0x8F
584
.az:
83 diamond 585
        and     al, not 0x20
586
        ret
71 diamond 587
 
588
fat_get_name:
589
; in: edi->FAT entry
590
; out: CF=1 - no valid entry
591
; else CF=0 and ebp->ASCIIZ-name
592
; (maximum length of filename is 255 (wide) symbols without trailing 0,
593
;  but implementation requires buffer 261 words)
594
; destroys eax
83 diamond 595
        cmp     byte [edi], 0
596
        jz      .no
597
        cmp     byte [edi], 0xE5
598
        jnz     @f
71 diamond 599
.no:
83 diamond 600
        stc
601
        ret
71 diamond 602
@@:
83 diamond 603
        cmp     byte [edi+11], 0xF
604
        jz      .longname
399 diamond 605
        test    byte [edi+11], 8
606
        jnz     .no
83 diamond 607
        push    ecx
247 serge 608
        push    edi ebp
78 diamond 609
        test    byte [ebp-4], 1
75 diamond 610
        jnz     .unicode_short
247 serge 611
 
612
        mov     eax, [edi]
613
        mov     ecx, [edi+4]
614
        mov     [ebp], eax
615
        mov     [ebp+4], ecx
616
 
617
        mov     ecx, 8
71 diamond 618
@@:
247 serge 619
        cmp     byte [ebp+ecx-1], ' '
620
        loope    @b
621
 
622
        mov     eax, [edi+8]
623
        cmp     al, ' '
624
        je      .done
625
        shl     eax, 8
626
        mov     al, '.'
627
 
628
        lea ebp, [ebp+ecx+1]
629
        mov     [ebp], eax
83 diamond 630
        mov     ecx, 3
71 diamond 631
@@:
247 serge 632
        rol eax, 8
633
        cmp al, ' '
634
        jne .done
635
        loop   @b
636
        dec ebp
637
.done:
638
        and     byte [ebp+ecx+1], 0   ; CF=0
83 diamond 639
        pop     ebp edi ecx
640
        ret
75 diamond 641
.unicode_short:
247 serge 642
        mov     ecx, 8
643
        push    ecx
75 diamond 644
@@:
645
        mov     al, [edi]
646
        inc     edi
647
        call    ansi2uni_char
648
        mov     [ebp], ax
649
        inc     ebp
650
        inc     ebp
651
        loop    @b
652
        pop     ecx
653
@@:
83 diamond 654
        cmp     word [ebp-2], ' '
655
        jnz     @f
656
        dec     ebp
657
        dec     ebp
658
        loop    @b
75 diamond 659
@@:
83 diamond 660
        mov     word [ebp], '.'
661
        inc     ebp
662
        inc     ebp
663
        mov     ecx, 3
664
        push    ecx
75 diamond 665
@@:
83 diamond 666
        mov     al, [edi]
667
        inc     edi
668
        call    ansi2uni_char
669
        mov     [ebp], ax
75 diamond 670
        inc     ebp
671
        inc     ebp
672
        loop    @b
673
        pop     ecx
674
@@:
83 diamond 675
        cmp     word [ebp-2], ' '
676
        jnz     @f
677
        dec     ebp
678
        dec     ebp
679
        loop    @b
680
        dec     ebp
681
        dec     ebp
75 diamond 682
@@:
83 diamond 683
        and     word [ebp], 0	; CF=0
684
        pop     ebp edi ecx
685
        ret
71 diamond 686
.longname:
687
; LFN
83 diamond 688
        mov     al, byte [edi]
689
        and     eax, 0x3F
690
        dec     eax
691
        cmp     al, 20
692
        jae     .no     ; ignore invalid entries
693
        mov     word [ebp+260*2], 0     ; force null-terminating for orphans
694
        imul    eax, 13*2
695
        add     ebp, eax
696
        test    byte [edi], 0x40
697
        jz      @f
698
        mov     word [ebp+13*2], 0
71 diamond 699
@@:
83 diamond 700
        push    eax
71 diamond 701
; now copy name from edi to ebp ...
83 diamond 702
        mov     eax, [edi+1]
703
        mov     [ebp], eax      ; symbols 1,2
704
        mov     eax, [edi+5]
705
        mov     [ebp+4], eax	; 3,4
706
        mov     eax, [edi+9]
707
        mov     [ebp+8], ax	; 5
708
        mov     eax, [edi+14]
709
        mov     [ebp+10], eax	; 6,7
710
        mov     eax, [edi+18]
711
        mov     [ebp+14], eax	; 8,9
712
        mov     eax, [edi+22]
713
        mov     [ebp+18], eax	; 10,11
714
        mov     eax, [edi+28]
715
        mov     [ebp+22], eax	; 12,13
71 diamond 716
; ... done
83 diamond 717
        pop     eax
718
        sub     ebp, eax
719
        test    eax, eax
720
        jz      @f
71 diamond 721
; if this is not first entry, more processing required
83 diamond 722
        stc
723
        ret
71 diamond 724
@@:
725
; if this is first entry:
78 diamond 726
        test    byte [ebp-4], 1
75 diamond 727
        jnz     .ret
71 diamond 728
; buffer at ebp contains UNICODE name, convert it to ANSI
83 diamond 729
        push    esi edi
730
        mov     esi, ebp
731
        mov     edi, ebp
732
        call    uni2ansi_str
733
        pop     edi esi
75 diamond 734
.ret:
83 diamond 735
        clc
736
        ret
71 diamond 737
 
738
fat_compare_name:
739
; compares ASCIIZ-names, case-insensitive (cp866 encoding)
740
; in: esi->name, ebp->name
741
; out: if names match: ZF=1 and esi->next component of name
742
;      else: ZF=0, esi is not changed
743
; destroys eax
83 diamond 744
        push    ebp esi
71 diamond 745
.loop:
83 diamond 746
        mov     al, [ebp]
747
        inc     ebp
748
        call    char_toupper
749
        push    eax
750
        lodsb
751
        call    char_toupper
752
        cmp     al, [esp]
753
        jnz     .done
754
        pop     eax
755
        test    al, al
756
        jnz     .loop
757
        dec     esi
758
        pop     eax
759
        pop     ebp
760
        xor     eax, eax	; set ZF flag
761
        ret
71 diamond 762
.done:
83 diamond 763
        cmp     al, '/'
764
        jnz     @f
765
        cmp     byte [esp], 0
766
        jnz     @f
767
        mov     [esp+4], esi
71 diamond 768
@@:
83 diamond 769
        pop     eax
770
        pop     esi ebp
771
        ret
71 diamond 772
 
75 diamond 773
fat_time_to_bdfe:
774
; in: eax=FAT time
775
; out: eax=BDFE time
83 diamond 776
        push    ecx edx
777
        mov     ecx, eax
778
        mov     edx, eax
779
        shr     eax, 11
780
        shl     eax, 16	; hours
781
        and     edx, 0x1F
782
        add     edx, edx
783
        mov     al, dl	; seconds
784
        shr     ecx, 5
785
        and     ecx, 0x3F
786
        mov     ah, cl	; minutes
787
        pop     edx ecx
788
        ret
75 diamond 789
 
790
fat_date_to_bdfe:
83 diamond 791
        push    ecx edx
792
        mov     ecx, eax
793
        mov     edx, eax
794
        shr     eax, 9
795
        add     ax, 1980
796
        shl     eax, 16	; year
797
        and     edx, 0x1F
798
        mov     al, dl	; day
799
        shr     ecx, 5
800
        and     ecx, 0xF
801
        mov     ah, cl	; month
802
        pop     edx ecx
803
        ret
75 diamond 804
 
86 diamond 805
bdfe_to_fat_time:
806
        push    edx
807
        mov     edx, eax
808
        shr     eax, 16
809
        and     dh, 0x3F
810
        shl     eax, 6
811
        or      al, dh
812
        shr     dl, 1
813
        and     dl, 0x1F
814
        shl     eax, 5
815
        or      al, dl
816
        pop     edx
817
        ret
818
 
819
bdfe_to_fat_date:
820
        push    edx
821
        mov     edx, eax
822
        shr     eax, 16
823
        sub     ax, 1980
824
        and     dh, 0xF
825
        shl     eax, 4
826
        or      al, dh
827
        and     dl, 0x1F
828
        shl     eax, 5
829
        or      al, dl
830
        pop     edx
831
        ret
832
 
75 diamond 833
fat_entry_to_bdfe:
834
; convert FAT entry at edi to BDFE (block of data of folder entry) at esi, advance esi
835
; destroys eax
86 diamond 836
        mov     eax, [ebp-4]
837
        mov     [esi+4], eax	; ASCII/UNICODE name
838
fat_entry_to_bdfe2:
75 diamond 839
        movzx   eax, byte [edi+11]
840
        mov     [esi], eax	; attributes
841
        movzx   eax, word [edi+14]
842
        call    fat_time_to_bdfe
843
        mov     [esi+8], eax	; creation time
844
        movzx   eax, word [edi+16]
845
        call    fat_date_to_bdfe
846
        mov     [esi+12], eax	; creation date
847
        and     dword [esi+16], 0	; last access time is not supported on FAT
848
        movzx   eax, word [edi+18]
849
        call    fat_date_to_bdfe
850
        mov     [esi+20], eax	; last access date
851
        movzx   eax, word [edi+22]
852
        call    fat_time_to_bdfe
853
        mov     [esi+24], eax	; last write time
854
        movzx   eax, word [edi+24]
855
        call    fat_date_to_bdfe
856
        mov     [esi+28], eax	; last write date
857
        mov     eax, [edi+28]
858
        mov     [esi+32], eax	; file size (low dword)
859
        xor     eax, eax
860
        mov     [esi+36], eax	; file size (high dword)
86 diamond 861
        test    ebp, ebp
862
        jz      .ret
75 diamond 863
        push    ecx edi
864
        lea     edi, [esi+40]
865
        mov     esi, ebp
78 diamond 866
        test    byte [esi-4], 1
867
        jz      .ansi
868
        mov     ecx, 260/2
75 diamond 869
        rep     movsd
78 diamond 870
        mov     [edi-2], ax
871
@@:
75 diamond 872
        mov     esi, edi
873
        pop     edi ecx
86 diamond 874
.ret:
75 diamond 875
        ret
78 diamond 876
.ansi:
877
        mov     ecx, 264/4
878
        rep     movsd
879
        mov     [edi-1], al
880
        jmp     @b
75 diamond 881
 
86 diamond 882
bdfe_to_fat_entry:
883
; convert BDFE at edx to FAT entry at edi
884
; destroys eax
885
; attributes byte
886
        test    byte [edi+11], 8        ; volume label?
887
        jnz     @f
888
        mov     al, [edx]
889
        and     al, 0x27
890
        and     byte [edi+11], 0x10
891
        or      byte [edi+11], al
892
@@:
893
        mov     eax, [edx+8]
894
        call    bdfe_to_fat_time
895
        mov     [edi+14], ax            ; creation time
896
        mov     eax, [edx+12]
897
        call    bdfe_to_fat_date
898
        mov     [edi+16], ax            ; creation date
899
        mov     eax, [edx+20]
900
        call    bdfe_to_fat_date
901
        mov     [edi+18], ax            ; last access date
902
        mov     eax, [edx+24]
903
        call    bdfe_to_fat_time
904
        mov     [edi+22], ax            ; last write time
905
        mov     eax, [edx+28]
906
        call    bdfe_to_fat_date
907
        mov     [edi+24], ax            ; last write date
908
        ret
909
 
910
ramdisk_root_first:
381 serge 911
        mov     edi, RAMDISK+512*19
86 diamond 912
        clc
913
        ret
914
ramdisk_root_next:
915
        add     edi, 0x20
381 serge 916
        cmp     edi, RAMDISK+512*33
86 diamond 917
        cmc
918
        ret
919
 
91 diamond 920
ramdisk_root_extend_dir:
921
        stc
922
        ret
923
 
171 diamond 924
uglobal
925
; this is for delete support
926
rd_prev_sector          dd      ?
927
rd_prev_prev_sector     dd      ?
928
endg
929
 
91 diamond 930
ramdisk_notroot_next:
931
        add     edi, 0x20
932
        test    edi, 0x1FF
933
        jz      ramdisk_notroot_next_sector
934
        ret     ; CF=0
935
ramdisk_notroot_next_sector:
936
        push    ecx
937
        mov     ecx, [eax]
171 diamond 938
        push    [rd_prev_sector]
939
        pop     [rd_prev_prev_sector]
940
        mov     [rd_prev_sector], ecx
381 serge 941
        mov     ecx, [ecx*2+RAMDISK_FAT]
91 diamond 942
        and     ecx, 0xFFF
943
        cmp     ecx, 2849
944
        jae     ramdisk_notroot_first.err2
945
        mov     [eax], ecx
946
        pop     ecx
947
ramdisk_notroot_first:
948
        mov     eax, [eax]
949
        cmp     eax, 2
950
        jb      .err
951
        cmp     eax, 2849
952
        jae     .err
953
        shl     eax, 9
381 serge 954
        lea     edi, [eax+(31 shl 9)+RAMDISK]
91 diamond 955
        clc
956
        ret
957
.err2:
958
        pop     ecx
959
.err:
960
        stc
961
        ret
962
ramdisk_notroot_next_write:
963
        test    edi, 0x1FF
964
        jz      ramdisk_notroot_next_sector
965
ramdisk_root_next_write:
966
        ret
967
 
968
ramdisk_notroot_extend_dir:
969
        pusha
970
        xor     eax, eax
381 serge 971
        mov     edi, RAMDISK_FAT
91 diamond 972
        mov     ecx, 2849
973
        repnz   scasw
974
        jnz     .notfound
975
        mov     word [edi-2], 0xFFF
381 serge 976
        sub     edi, RAMDISK_FAT
91 diamond 977
        shr     edi, 1
978
        dec     edi
979
        mov     eax, [esp+28]
980
        mov     ecx, [eax]
381 serge 981
        mov     [RAMDISK_FAT+ecx*2], di
91 diamond 982
        mov     [eax], edi
983
        shl     edi, 9
381 serge 984
        add     edi, (31 shl 9)+RAMDISK
91 diamond 985
        mov     [esp], edi
986
        xor     eax, eax
987
        mov     ecx, 128
988
        rep     stosd
989
        popa
990
        clc
991
        ret
992
.notfound:
993
        popa
994
        stc
995
        ret
996
 
71 diamond 997
rd_find_lfn:
998
; in: esi->name
999
; out: CF=1 - file not found
1000
;      else CF=0 and edi->direntry
86 diamond 1001
        push    esi edi
91 diamond 1002
        push    0
86 diamond 1003
        push    ramdisk_root_first
1004
        push    ramdisk_root_next
91 diamond 1005
.loop:
86 diamond 1006
        call    fat_find_lfn
1007
        jc      .notfound
1008
        cmp     byte [esi], 0
91 diamond 1009
        jz      .found
1010
        test    byte [edi+11], 10h
1011
        jz      .notfound
1012
        movzx   eax, word [edi+26]
1013
        mov     [esp+8], eax
1014
        mov     dword [esp+4], ramdisk_notroot_first
1015
        mov     dword [esp], ramdisk_notroot_next
1016
        jmp     .loop
1017
.notfound:
86 diamond 1018
        add     esp, 12
1019
        pop     edi esi
78 diamond 1020
        stc
1021
        ret
91 diamond 1022
.found:
1023
        mov     eax, [esp+8]
1024
        add     esp, 16         ; CF=0
1025
        pop     esi
1026
        ret
71 diamond 1027
 
1028
;----------------------------------------------------------------
1029
;
1030
;  fs_RamdiskRead - LFN variant for reading sys floppy
1031
;
1032
;  esi  points to filename
1033
;  ebx  pointer to 64-bit number = first wanted byte, 0+
1034
;       may be ebx=0 - start from first byte
1035
;  ecx  number of bytes to read, 0+
1036
;  edx  mem location to return data
1037
;
77 diamond 1038
;  ret ebx = bytes read or 0xffffffff file not found
71 diamond 1039
;      eax = 0 ok read or other = errormsg
1040
;
1041
;--------------------------------------------------------------
1042
fs_RamdiskRead:
75 diamond 1043
        cmp     byte [esi], 0
1044
        jnz     @f
1045
        or      ebx, -1
1046
        mov     eax, 10         ; access denied
1047
        ret
71 diamond 1048
@@:
75 diamond 1049
        push    edi
1050
        call    rd_find_lfn
1051
        jnc     .found
1052
        pop     edi
1053
        or      ebx, -1
1054
        mov     eax, 5          ; file not found
1055
        ret
71 diamond 1056
.found:
75 diamond 1057
        test    ebx, ebx
1058
        jz      .l1
1059
        cmp     dword [ebx+4], 0
1060
        jz      @f
77 diamond 1061
        xor     ebx, ebx
71 diamond 1062
.reteof:
75 diamond 1063
        mov     eax, 6          ; EOF
1064
        pop     edi
1065
        ret
71 diamond 1066
@@:
75 diamond 1067
        mov     ebx, [ebx]
71 diamond 1068
.l1:
77 diamond 1069
        push    ecx edx
1070
        push    0
1071
        mov     eax, [edi+28]
1072
        sub     eax, ebx
1073
        jb      .eof
1074
        cmp     eax, ecx
1075
        jae     @f
1076
        mov     ecx, eax
1077
        mov     byte [esp], 6           ; EOF
1078
@@:
75 diamond 1079
        movzx   edi, word [edi+26]	; cluster
71 diamond 1080
.new:
75 diamond 1081
        jecxz   .done
1082
        test    edi, edi
1083
        jz      .eof
1084
        cmp     edi, 0xFF8
1085
        jae     .eof
1086
        lea     eax, [edi+31]           ; bootsector+2*fat+filenames
1087
        shl     eax, 9                  ; *512
381 serge 1088
        add     eax, RAMDISK           ; image base
71 diamond 1089
; now eax points to data of cluster
75 diamond 1090
        sub     ebx, 512
1091
        jae     .skip
1092
        lea     eax, [eax+ebx+512]
1093
        neg     ebx
1094
        push    ecx
1095
        cmp     ecx, ebx
1096
        jbe     @f
1097
        mov     ecx, ebx
71 diamond 1098
@@:
75 diamond 1099
        mov     ebx, edx
1100
        call    memmove
1101
        add     edx, ecx
1102
        sub     [esp], ecx
1103
        pop     ecx
1104
        xor     ebx, ebx
71 diamond 1105
.skip:
381 serge 1106
        movzx   edi, word [edi*2+RAMDISK_FAT]      ; find next cluster from FAT
75 diamond 1107
        jmp     .new
71 diamond 1108
.eof:
77 diamond 1109
        mov     ebx, edx
1110
        pop     eax edx ecx
1111
        sub     ebx, edx
75 diamond 1112
        jmp     .reteof
71 diamond 1113
.done:
77 diamond 1114
        mov     ebx, edx
1115
        pop     eax edx ecx edi
1116
        sub     ebx, edx
75 diamond 1117
        ret
71 diamond 1118
 
75 diamond 1119
;----------------------------------------------------------------
1120
;
1121
;  fs_RamdiskReadFolder - LFN variant for reading sys floppy folder
1122
;
1123
;  esi  points to filename; only root is folder on ramdisk
78 diamond 1124
;  ebx  pointer to structure 32-bit number = first wanted block
1125
;                          & flags (bitfields)
1126
; flags: bit 0: 0=ANSI names, 1=UNICODE names
75 diamond 1127
;  ecx  number of blocks to read, 0+
1128
;  edx  mem location to return data
1129
;
1130
;  ret ebx = size or 0xffffffff file not found
1131
;      eax = 0 ok read or other = errormsg
1132
;
1133
;--------------------------------------------------------------
1134
fs_RamdiskReadFolder:
91 diamond 1135
        push    edi
75 diamond 1136
        cmp     byte [esi], 0
91 diamond 1137
        jz      .root
1138
        call    rd_find_lfn
1139
        jnc     .found
1140
        pop     edi
75 diamond 1141
        or      ebx, -1
91 diamond 1142
        mov     eax, ERROR_FILE_NOT_FOUND
75 diamond 1143
        ret
91 diamond 1144
.found:
1145
        test    byte [edi+11], 0x10
1146
        jnz     .found_dir
1147
        pop     edi
1148
        or      ebx, -1
1149
        mov     eax, ERROR_ACCESS_DENIED
1150
        ret
1151
.found_dir:
1152
        movzx   eax, word [edi+26]
1153
        add     eax, 31
1154
        push    0
1155
        jmp     .doit
1156
.root:
1157
        mov     eax, 19
1158
        push    14
1159
.doit:
1160
        push    esi ecx ebp
1161
        sub     esp, 262*2      ; reserve space for LFN
1162
        mov     ebp, esp
1163
        push    dword [ebx+4]   ; for fat_get_name: read ANSI/UNICODE names
1164
        mov     ebx, [ebx]
75 diamond 1165
; init header
91 diamond 1166
        push    eax ecx
75 diamond 1167
        mov     edi, edx
1168
        mov     ecx, 32/4
1169
        xor     eax, eax
1170
        rep     stosd
1171
        mov     byte [edx], 1   ; version
91 diamond 1172
        pop     ecx eax
75 diamond 1173
        mov     esi, edi        ; esi points to block of data of folder entry (BDFE)
91 diamond 1174
.main_loop:
1175
        mov     edi, eax
1176
        shl     edi, 9
381 serge 1177
        add     edi, RAMDISK
91 diamond 1178
        push    eax
75 diamond 1179
.l1:
1180
        call    fat_get_name
1181
        jc      .l2
1182
        cmp     byte [edi+11], 0xF
91 diamond 1183
        jnz     .do_bdfe
75 diamond 1184
        add     edi, 0x20
91 diamond 1185
        test    edi, 0x1FF
1186
        jnz     .do_bdfe
1187
        pop     eax
1188
        inc     eax
1189
        dec     byte [esp+262*2+16]
1190
        jz      .done
1191
        jns     @f
1192
; read next sector from FAT
381 serge 1193
        mov     eax, [(eax-31-1)*2+RAMDISK_FAT]
91 diamond 1194
        and     eax, 0xFFF
1195
        cmp     eax, 0xFF8
1196
        jae     .done
1197
        add     eax, 31
1198
        mov     byte [esp+262*2+16], 0
75 diamond 1199
@@:
91 diamond 1200
        mov     edi, eax
1201
        shl     edi, 9
381 serge 1202
        add     edi, RAMDISK
91 diamond 1203
        push    eax
1204
.do_bdfe:
75 diamond 1205
        inc     dword [edx+8]   ; new file found
1206
        dec     ebx
1207
        jns     .l2
1208
        dec     ecx
1209
        js      .l2
1210
        inc     dword [edx+4]  ; new file block copied
1211
        call    fat_entry_to_bdfe
1212
.l2:
1213
        add     edi, 0x20
91 diamond 1214
        test    edi, 0x1FF
1215
        jnz     .l1
1216
        pop     eax
1217
        inc     eax
1218
        dec     byte [esp+262*2+16]
1219
        jz      .done
1220
        jns     @f
1221
; read next sector from FAT
381 serge 1222
        mov     eax, [(eax-31-1)*2+RAMDISK_FAT]
91 diamond 1223
        and     eax, 0xFFF
1224
        cmp     eax, 0xFF8
1225
        jae     .done
1226
        add     eax, 31
1227
        mov     byte [esp+262*2+16], 0
1228
@@:
1229
        jmp     .main_loop
1230
.done:
75 diamond 1231
        add     esp, 262*2+4
1232
        pop     ebp
77 diamond 1233
        mov     ebx, [edx+4]
75 diamond 1234
        xor     eax, eax
1235
        dec     ecx
1236
        js      @f
1237
        mov     al, ERROR_END_OF_FILE
1238
@@:
91 diamond 1239
        pop     ecx esi edi edi
75 diamond 1240
        ret
1241
 
83 diamond 1242
iglobal
1243
label fat_legal_chars byte
1244
; 0 = not allowed
1245
; 1 = allowed only in long names
1246
; 3 = allowed
1247
        times 32 db 0
1248
;                 ! " # $ % & ' ( ) * + , - . /
1249
        db      1,3,0,3,3,3,3,3,3,3,0,1,1,3,3,0
1250
;               0 1 2 3 4 5 6 7 8 9 : ; < = > ?
1251
        db      3,3,3,3,3,3,3,3,3,3,0,1,0,1,0,0
1252
;               @ A B C D E F G H I J K L M N O
1253
        db      3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3
1254
;               P Q R S T U V W X Y Z [ \ ] ^ _
1255
        db      3,3,3,3,3,3,3,3,3,3,3,1,0,1,3,3
1256
;               ` a b c d e f g h i j k l m n o
1257
        db      3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3
1258
;               p q r s t u v w x y z { | } ~
1259
        db      3,3,3,3,3,3,3,3,3,3,3,3,0,3,3,0
1260
endg
1261
 
1262
fat_name_is_legal:
1263
; in: esi->(long) name
1264
; out: CF set <=> legal
1265
; destroys eax
1266
        push    esi
1267
        xor     eax, eax
1268
@@:
1269
        lodsb
1270
        test    al, al
1271
        jz      .done
1272
        cmp     al, 80h
1273
        jae     .big
1274
        test    [fat_legal_chars+eax], 1
1275
        jnz     @b
1276
.err:
1277
        pop     esi
1278
        clc
1279
        ret
1280
.big:
1281
; 0x80-0xAF, 0xE0-0xEF
1282
        cmp     al, 0xB0
1283
        jb      @b
1284
        cmp     al, 0xE0
1285
        jb      .err
1286
        cmp     al, 0xF0
1287
        jb      @b
1288
        jmp     .err
1289
.done:
1290
        sub     esi, [esp]
1291
        cmp     esi, 257
1292
        pop     esi
1293
        ret
1294
 
1295
fat_next_short_name:
1296
; in: edi->8+3 name
1297
; out: name corrected
1298
;      CF=1 <=> error
1299
        pushad
1300
        mov     ecx, 8
1301
        mov     al, '~'
1302
        std
1303
        push    edi
1304
        add     edi, 7
1305
        repnz   scasb
1306
        pop     edi
1307
        cld
1308
        jz      .tilde
1309
; tilde is not found, insert "~1" at end
1310
        add     edi, 6
1311
        cmp     word [edi], '  '
1312
        jnz     .insert_tilde
1313
@@:     dec     edi
1314
        cmp     byte [edi], ' '
1315
        jz      @b
1316
        inc     edi
1317
.insert_tilde:
1318
        mov     word [edi], '~1'
1319
        popad
442 diamond 1320
        clc
83 diamond 1321
        ret
1322
.tilde:
1323
        push    edi
1324
        add     edi, 7
1325
        xor     ecx, ecx
1326
@@:
1327
; after tilde may be only digits and trailing spaces
1328
        cmp     byte [edi], '~'
1329
        jz      .break
1330
        cmp     byte [edi], ' '
1331
        jz      .space
1332
        cmp     byte [edi], '9'
1333
        jnz     .found
1334
        dec     edi
1335
        jmp     @b
1336
.space:
1337
        dec     edi
1338
        inc     ecx
1339
        jmp     @b
1340
.found:
1341
        inc     byte [edi]
1342
.succ:
1343
        pop     edi
1344
        popad
1345
        clc
1346
        ret
1347
.break:
1348
        jecxz   .noplace
1349
        inc     edi
1350
        mov     al, '1'
1351
@@:
1352
        xchg    al, [edi]
1353
        inc     edi
1354
        cmp     al, ' '
1355
        mov     al, '0'
1356
        jnz     @b
1357
        jmp     .succ
1358
.noplace:
1359
        dec     edi
1360
        cmp     edi, [esp]
1361
        jz      .err
1362
        add     dword [esp], 8
1363
        mov     word [edi], '~1'
1364
        inc     edi
1365
        inc     edi
1366
@@:
1367
        mov     byte [edi], '0'
1368
        inc     edi
1369
        cmp     edi, [esp]
1370
        jb      @b
1371
        pop     edi
1372
        popad
1373
        ;clc    ; automatically
1374
        ret
1375
.err:
1376
        pop     edi
1377
        popad
1378
        stc
1379
        ret
1380
 
1381
fat_gen_short_name:
1382
; in: esi->long name
1383
;     edi->buffer (8+3=11 chars)
1384
; out: buffer filled
1385
        pushad
1386
        mov     eax, '    '
1387
        push    edi
1388
        stosd
1389
        stosd
1390
        stosd
1391
        pop     edi
1392
        xor     eax, eax
1393
        push    8
1394
        pop     ebx
1395
        lea     ecx, [edi+8]
1396
.loop:
1397
        lodsb
1398
        test    al, al
1399
        jz      .done
1400
        call    char_toupper
1401
        cmp     al, ' '
1402
        jz      .space
1403
        cmp     al, 80h
1404
        ja      .big
1405
        test    [fat_legal_chars+eax], 2
1406
        jnz     .symbol
1407
.inv_symbol:
1408
        mov     al, '_'
1409
        or      bh, 1
1410
.symbol:
1411
        cmp     al, '.'
1412
        jz      .dot
1413
.normal_symbol:
1414
        dec     bl
1415
        jns     .store
1416
        mov     bl, 0
1417
.space:
1418
        or      bh, 1
1419
        jmp     .loop
1420
.store:
1421
        stosb
1422
        jmp     .loop
1423
.big:
1424
        cmp     al, 0xB0
1425
        jb      .normal_symbol
1426
        cmp     al, 0xE0
1427
        jb      .inv_symbol
1428
        cmp     al, 0xF0
1429
        jb      .normal_symbol
1430
        jmp     .inv_symbol
1431
.dot:
1432
        test    bh, 2
1433
        jz      .firstdot
1434
        pop     ebx
1435
        add     ebx, edi
1436
        sub     ebx, ecx
1437
        push    ebx
1438
        cmp     edi, ecx
1439
        jbe     .skip
1440
@@:
1441
        dec     edi
1442
        mov     al, ' '
1443
        xchg    al, [edi]
1444
        dec     ebx
1445
        mov     [ebx], al
1446
        cmp     edi, ecx
1447
        ja      @b
1448
.skip:
1449
        mov     bh, 3
1450
        jmp     @f
1451
.firstdot:
1452
        cmp     bl, 8
1453
        jz      .space
1454
        push    edi
1455
        or      bh, 2
1456
@@:
1457
        mov     edi, ecx
1458
        mov     bl, 3
1459
        jmp     .loop
1460
.done:
1461
        test    bh, 2
1462
        jz      @f
1463
        pop     edi
1464
@@:
1465
        lea     edi, [ecx-8]
1466
        test    bh, 1
1467
        jz      @f
1468
        call    fat_next_short_name
1469
@@:
1470
        popad
1471
        ret
1472
 
1473
;----------------------------------------------------------------
1474
;
321 diamond 1475
;  fs_RamdiskRewrite - LFN variant for writing ramdisk
1476
;  fs_RamdiskCreateFolder - create folder on ramdisk
83 diamond 1477
;
321 diamond 1478
;  esi  points to file/folder name
83 diamond 1479
;  ebx  ignored (reserved)
321 diamond 1480
;  ecx  number of bytes to write, 0+ (ignored for folders)
1481
;  edx  mem location to data (ignored for folders)
83 diamond 1482
;
1483
;  ret ebx = number of written bytes
1484
;      eax = 0 ok read or other = errormsg
1485
;
1486
;--------------------------------------------------------------
1487
@@:
1488
        mov     eax, ERROR_ACCESS_DENIED
1489
        xor     ebx, ebx
1490
        ret
1491
 
321 diamond 1492
fs_RamdiskCreateFolder:
1493
        mov     al, 1           ; create folder
1494
        jmp     fs_RamdiskRewrite.common
1495
 
83 diamond 1496
fs_RamdiskRewrite:
321 diamond 1497
        xor     eax, eax        ; create file
1498
.common:
83 diamond 1499
        cmp     byte [esi], 0
1500
        jz      @b
91 diamond 1501
        pushad
1502
        xor     ebp, ebp
83 diamond 1503
        push    esi
1504
@@:
1505
        lodsb
1506
        test    al, al
1507
        jz      @f
1508
        cmp     al, '/'
1509
        jnz     @b
91 diamond 1510
        lea     ebp, [esi-1]
1511
        jmp     @b
1512
@@:
83 diamond 1513
        pop     esi
91 diamond 1514
        test    ebp, ebp
1515
        jnz     .noroot
1516
        push    ramdisk_root_extend_dir
1517
        push    ramdisk_root_next_write
1518
        push    ebp
1519
        push    ramdisk_root_first
1520
        push    ramdisk_root_next
1521
        jmp     .common1
1522
.noroot:
335 diamond 1523
        mov     eax, ERROR_ACCESS_DENIED
1524
        cmp     byte [ebp+1], 0
1525
        jz      .ret1
91 diamond 1526
; check existence
1527
        mov     byte [ebp], 0
1528
        call    rd_find_lfn
1529
        mov     byte [ebp], '/'
1530
        lea     esi, [ebp+1]
1531
        jnc     @f
1532
        mov     eax, ERROR_FILE_NOT_FOUND
1533
.ret1:
1534
        mov     [esp+28], eax
1535
        popad
83 diamond 1536
        xor     ebx, ebx
1537
        ret
1538
@@:
91 diamond 1539
        test    byte [edi+11], 0x10     ; must be directory
1540
        mov     eax, ERROR_ACCESS_DENIED
1541
        jz      .ret1
1542
        movzx   ebp, word [edi+26]      ; ebp=cluster
1543
        mov     eax, ERROR_FAT_TABLE
1544
        cmp     ebp, 2
1545
        jb      .ret1
1546
        cmp     ebp, 2849
1547
        jae     .ret1
1548
        push    ramdisk_notroot_extend_dir
1549
        push    ramdisk_notroot_next_write
1550
        push    ebp
1551
        push    ramdisk_notroot_first
1552
        push    ramdisk_notroot_next
1553
.common1:
1554
        call    fat_find_lfn
83 diamond 1555
        jc      .notfound
321 diamond 1556
; found
91 diamond 1557
        test    byte [edi+11], 10h
321 diamond 1558
        jz      .exists_file
1559
; found directory; if we are creating directory, return OK,
1560
;                  if we are creating file, say "access denied"
1561
        add     esp, 20
1562
        popad
1563
        test    al, al
1564
        mov     eax, ERROR_ACCESS_DENIED
91 diamond 1565
        jz      @f
321 diamond 1566
        mov     al, 0
1567
@@:
1568
        xor     ebx, ebx
1569
        ret
1570
.exists_file:
1571
; found file; if we are creating directory, return "access denied",
1572
;             if we are creating file, delete existing file and continue
1573
        cmp     byte [esp+20+28], 0
1574
        jz      @f
91 diamond 1575
        add     esp, 20
1576
        popad
1577
        mov     eax, ERROR_ACCESS_DENIED
1578
        xor     ebx, ebx
1579
        ret
1580
@@:
1581
; delete FAT chain
83 diamond 1582
        push    edi
1583
        xor     eax, eax
1584
        mov     dword [edi+28], eax     ; zero size
1585
        xchg    ax, word [edi+26]       ; start cluster
1586
        test    eax, eax
1587
        jz      .done1
1588
@@:
1589
        cmp     eax, 0xFF8
1590
        jae     .done1
321 diamond 1591
        lea     edi, [RAMDISK_FAT + eax*2] ; position in FAT
83 diamond 1592
        xor     eax, eax
1593
        xchg    ax, [edi]
1594
        jmp     @b
1595
.done1:
1596
        pop     edi
1597
        call    get_time_for_file
1598
        mov     [edi+22], ax
1599
        call    get_date_for_file
1600
        mov     [edi+24], ax
1601
        mov     [edi+18], ax
1602
        or      byte [edi+11], 20h      ; set 'archive' attribute
1603
        jmp     .doit
1604
.notfound:
1605
; file is not found; generate short name
1606
        call    fat_name_is_legal
1607
        jc      @f
91 diamond 1608
        add     esp, 20
1609
        popad
1610
        mov     eax, ERROR_FILE_NOT_FOUND
1611
        xor     ebx, ebx
1612
        ret
83 diamond 1613
@@:
1614
        sub     esp, 12
1615
        mov     edi, esp
1616
        call    fat_gen_short_name
1617
.test_short_name_loop:
91 diamond 1618
        push    esi edi ecx
1619
        mov     esi, edi
1620
        lea     eax, [esp+12+12+8]
1621
        mov     [eax], ebp
1622
        call    dword [eax-4]
1623
        jc      .found
83 diamond 1624
.test_short_name_entry:
91 diamond 1625
        cmp     byte [edi+11], 0xF
83 diamond 1626
        jz      .test_short_name_cont
1627
        mov     ecx, 11
1628
        push    esi edi
1629
        repz    cmpsb
1630
        pop     edi esi
1631
        jz      .short_name_found
1632
.test_short_name_cont:
91 diamond 1633
        lea     eax, [esp+12+12+8]
1634
        call    dword [eax-8]
1635
        jnc     .test_short_name_entry
83 diamond 1636
        jmp     .found
1637
.short_name_found:
91 diamond 1638
        pop     ecx edi esi
83 diamond 1639
        call    fat_next_short_name
1640
        jnc     .test_short_name_loop
1641
.disk_full:
91 diamond 1642
        add     esp, 12+20
1643
        popad
83 diamond 1644
        mov     eax, ERROR_DISK_FULL
1645
        xor     ebx, ebx
1646
        ret
1647
.found:
91 diamond 1648
        pop     ecx edi esi
83 diamond 1649
; now find space in directory
1650
; we need to save LFN <=> LFN is not equal to short name <=> generated name contains '~'
1651
        mov     al, '~'
1652
        push    ecx edi
1653
        mov     ecx, 8
1654
        repnz   scasb
1655
        push    1
1656
        pop     eax     ; 1 entry
1657
        jnz     .notilde
1658
; we need ceil(strlen(esi)/13) additional entries = floor((strlen(esi)+12+13)/13) total
1659
        xor     eax, eax
1660
@@:
1661
        cmp     byte [esi], 0
1662
        jz      @f
1663
        inc     esi
1664
        inc     eax
1665
        jmp     @b
1666
@@:
1667
        sub     esi, eax
1668
        add     eax, 12+13
1669
        mov     ecx, 13
1670
        push    edx
1671
        cdq
1672
        div     ecx
1673
        pop     edx
1674
.notilde:
91 diamond 1675
        push    -1
1676
        push    -1
83 diamond 1677
; find  successive entries in directory
1678
        xor     ecx, ecx
91 diamond 1679
        push    eax
1680
        lea     eax, [esp+12+8+12+8]
1681
        mov     [eax], ebp
1682
        call    dword [eax-4]
1683
        pop     eax
83 diamond 1684
.scan_dir:
1685
        cmp     byte [edi], 0
1686
        jz      .free
1687
        cmp     byte [edi], 0xE5
1688
        jz      .free
1689
        xor     ecx, ecx
1690
.scan_cont:
91 diamond 1691
        push    eax
1692
        lea     eax, [esp+12+8+12+8]
1693
        call    dword [eax-8]
1694
        pop     eax
1695
        jnc     .scan_dir
1696
        push    eax
1697
        lea     eax, [esp+12+8+12+8]
1698
        call    dword [eax+8]           ; extend directory
1699
        pop     eax
1700
        jnc     .scan_dir
1701
        add     esp, 8+8+12+20
1702
        popad
1703
        mov     eax, ERROR_DISK_FULL
1704
        xor     ebx, ebx
1705
        ret
83 diamond 1706
.free:
91 diamond 1707
        test    ecx, ecx
1708
        jnz     @f
1709
        mov     [esp], edi
1710
        mov     ecx, [esp+8+8+12+8]
1711
        mov     [esp+4], ecx
1712
        xor     ecx, ecx
1713
@@:
83 diamond 1714
        inc     ecx
1715
        cmp     ecx, eax
1716
        jb      .scan_cont
1717
; found!
1718
; calculate name checksum
1719
        push    esi ecx
91 diamond 1720
        mov     esi, [esp+8+8]
83 diamond 1721
        mov     ecx, 11
1722
        xor     eax, eax
1723
@@:
1724
        ror     al, 1
1725
        add     al, [esi]
1726
        inc     esi
1727
        loop    @b
1728
        pop     ecx esi
91 diamond 1729
        pop     edi
1730
        pop     dword [esp+8+12+8]
83 diamond 1731
; edi points to last entry in free chunk
1732
        dec     ecx
1733
        jz      .nolfn
1734
        push    esi
91 diamond 1735
        push    eax
1736
        mov     al, 40h
83 diamond 1737
.writelfn:
91 diamond 1738
        or      al, cl
1739
        mov     esi, [esp+4]
1740
        push    ecx
1741
        dec     ecx
1742
        imul    ecx, 13
1743
        add     esi, ecx
83 diamond 1744
        stosb
1745
        mov     cl, 5
1746
        call    .read_symbols
1747
        mov     ax, 0xF
1748
        stosw
91 diamond 1749
        mov     al, [esp+4]
83 diamond 1750
        stosb
1751
        mov     cl, 6
1752
        call    .read_symbols
1753
        xor     eax, eax
1754
        stosw
1755
        mov     cl, 2
1756
        call    .read_symbols
91 diamond 1757
        pop     ecx
1758
        lea     eax, [esp+8+8+12+8]
1759
        call    dword [eax+4]   ; next write
1760
        xor     eax, eax
83 diamond 1761
        loop    .writelfn
91 diamond 1762
        pop     eax
83 diamond 1763
        pop     esi
1764
.nolfn:
1765
        xchg    esi, [esp]
1766
        mov     ecx, 11
1767
        rep     movsb
1768
        mov     word [edi], 20h         ; attributes
1769
        sub     edi, 11
1770
        pop     esi ecx
1771
        add     esp, 12
1772
        mov     byte [edi+13], 0        ; tenths of a second at file creation time
1773
        call    get_time_for_file
1774
        mov     [edi+14], ax            ; creation time
1775
        mov     [edi+22], ax            ; last write time
1776
        call    get_date_for_file
1777
        mov     [edi+16], ax            ; creation date
1778
        mov     [edi+24], ax            ; last write date
1779
        mov     [edi+18], ax            ; last access date
1780
        and     word [edi+20], 0        ; high word of cluster
1781
        and     word [edi+26], 0        ; low word of cluster - to be filled
1782
        and     dword [edi+28], 0       ; file size - to be filled
321 diamond 1783
        cmp     byte [esp+20+28], 0
1784
        jz      .doit
1785
; create directory
1786
        mov     byte [edi+11], 10h         ; attributes: folder
1787
        mov     ecx, 32*2
1788
        mov     edx, edi
83 diamond 1789
.doit:
91 diamond 1790
        push    edx
83 diamond 1791
        push    ecx
1792
        push    edi
1793
        add     edi, 26         ; edi points to low word of cluster
1794
        push    edi
1795
        jecxz   .done
1796
        mov     ecx, 2849
321 diamond 1797
        mov     edi, RAMDISK_FAT
83 diamond 1798
.write_loop:
1799
; allocate new cluster
1800
        xor     eax, eax
1801
        repnz   scasw
1802
        jnz     .disk_full2
1803
        dec     edi
1804
        dec     edi
321 diamond 1805
        lea     eax, [edi-(RAMDISK_FAT)]
83 diamond 1806
        shr     eax, 1                  ; eax = cluster
1807
        mov     word [edi], 0xFFF       ; mark as last cluster
1808
        xchg    edi, [esp]
1809
        stosw
1810
        pop     edi
1811
        push    edi
1812
        inc     ecx
1813
; write data
321 diamond 1814
        cmp     byte [esp+16+20+28], 0
1815
        jnz     .writedir
83 diamond 1816
        shl     eax, 9
321 diamond 1817
        add     eax, RAMDISK+31*512
1818
.writefile:
83 diamond 1819
        mov     ebx, edx
1820
        xchg    eax, ebx
1821
        push    ecx
1822
        mov     ecx, 512
1823
        cmp     dword [esp+12], ecx
1824
        jae     @f
1825
        mov     ecx, [esp+12]
1826
@@:
1827
        call    memmove
1828
        add     edx, ecx
1829
        sub     [esp+12], ecx
1830
        pop     ecx
1831
        jnz     .write_loop
1832
.done:
1833
        mov     ebx, edx
91 diamond 1834
        pop     edi edi ecx edx
83 diamond 1835
        sub     ebx, edx
1836
        mov     [edi+28], ebx
91 diamond 1837
        add     esp, 20
131 diamond 1838
        mov     [esp+16], ebx
91 diamond 1839
        popad
83 diamond 1840
        xor     eax, eax
1841
        ret
1842
.disk_full2:
1843
        mov     ebx, edx
91 diamond 1844
        pop     edi edi ecx edx
83 diamond 1845
        sub     ebx, edx
1846
        mov     [edi+28], ebx
91 diamond 1847
        add     esp, 20
131 diamond 1848
        mov     [esp+16], ebx
91 diamond 1849
        popad
83 diamond 1850
        push    ERROR_DISK_FULL
1851
        pop     eax
1852
        ret
321 diamond 1853
.writedir:
1854
        mov     edi, eax
1855
        shl     edi, 9
1856
        add     edi, RAMDISK+31*512
1857
        mov     esi, edx
1858
        mov     ecx, 32/4
1859
        push    ecx
1860
        rep     movsd
1861
        mov     dword [edi-32], '.   '
1862
        mov     dword [edi-32+4], '    '
1863
        mov     dword [edi-32+8], '    '
1864
        mov     byte [edi-32+11], 10h
1865
        mov     word [edi-32+26], ax
1866
        mov     esi, edx
1867
        pop     ecx
1868
        rep     movsd
1869
        mov     dword [edi-32], '..  '
1870
        mov     dword [edi-32+4], '    '
1871
        mov     dword [edi-32+8], '    '
1872
        mov     byte [edi-32+11], 10h
1873
        mov     eax, [esp+16+8]
1874
        mov     word [edi-32+26], ax
437 diamond 1875
        xor     eax, eax
1876
        mov     ecx, (512-32*2)/4
1877
        rep     stosd
321 diamond 1878
        pop     edi edi ecx edx
1879
        add     esp, 20
1880
        popad
1881
        xor     eax, eax
1882
        xor     ebx, ebx
1883
        ret
83 diamond 1884
 
1885
.read_symbol:
1886
        or      ax, -1
1887
        test    esi, esi
1888
        jz      .retFFFF
1889
        lodsb
1890
        test    al, al
1891
        jnz     ansi2uni_char
1892
        xor     eax, eax
1893
        xor     esi, esi
1894
.retFFFF:
1895
        ret
1896
 
1897
.read_symbols:
1898
        call    .read_symbol
1899
        stosw
1900
        loop    .read_symbols
1901
        ret
1902
 
131 diamond 1903
;----------------------------------------------------------------
1904
;
1905
;  fs_RamdiskWrite - LFN variant for writing to sys floppy
1906
;
1907
;  esi  points to filename
1908
;  ebx  pointer to 64-bit number = first wanted byte, 0+
1909
;       may be ebx=0 - start from first byte
1910
;  ecx  number of bytes to write, 0+
1911
;  edx  mem location to data
1912
;
1913
;  ret ebx = bytes written (maybe 0)
1914
;      eax = 0 ok write or other = errormsg
1915
;
1916
;--------------------------------------------------------------
1917
@@:
1918
        push    ERROR_ACCESS_DENIED
1919
fs_RamdiskWrite.ret0:
1920
        pop     eax
1921
        xor     ebx, ebx
1922
        ret
1923
 
1924
fs_RamdiskWrite:
1925
        cmp     byte [esi], 0
1926
        jz      @b
1927
        pushad
1928
        call    rd_find_lfn
1929
        jnc     .found
1930
        popad
1931
        push    ERROR_FILE_NOT_FOUND
1932
        jmp     .ret0
1933
.found:
1934
; must not be directory
1935
        test    byte [edi+11], 10h
1936
        jz      @f
1937
        popad
1938
        push    ERROR_ACCESS_DENIED
1939
        jmp     .ret0
1940
@@:
1941
; FAT does not support files larger than 4GB
1942
        test    ebx, ebx
1943
        jz      .l1
1944
        cmp     dword [ebx+4], 0
1945
        jz      @f
1946
.eof:
1947
        popad
1948
        push    ERROR_END_OF_FILE
1949
        jmp     .ret0
1950
@@:
1951
        mov     ebx, [ebx]
1952
.l1:
1953
; now edi points to direntry, ebx=start byte to write,
1954
; ecx=number of bytes to write, edx=data pointer
133 diamond 1955
        call    fat_update_datetime
131 diamond 1956
 
1957
; extend file if needed
1958
        add     ecx, ebx
1959
        jc      .eof    ; FAT does not support files larger than 4GB
1960
        push    0       ; return value=0
1961
        cmp     ecx, [edi+28]
1962
        jbe     .length_ok
1963
        cmp     ecx, ebx
1964
        jz      .length_ok
1965
        call    ramdisk_extend_file
1966
        jnc     .length_ok
1967
; ramdisk_extend_file can return two error codes: FAT table error or disk full.
1968
; First case is fatal error, in second case we may write some data
1969
        mov     [esp], eax
1970
        cmp     al, ERROR_DISK_FULL
1971
        jz      .disk_full
1972
        pop     eax
1973
        mov     [esp+28], eax
1974
        popad
1975
        xor     ebx, ebx
1976
        ret
1977
.disk_full:
1978
; correct number of bytes to write
1979
        mov     ecx, [edi+28]
1980
        cmp     ecx, ebx
1981
        ja      .length_ok
1982
.ret:
1983
        pop     eax
1984
        mov     [esp+28], eax   ; eax=return value
1985
        sub     edx, [esp+20]
1986
        mov     [esp+16], edx   ; ebx=number of written bytes
1987
        popad
1988
        ret
1989
.length_ok:
1990
; now ebx=start pos, ecx=end pos, both lie inside file
1991
        sub     ecx, ebx
1992
        jz      .ret
1993
        movzx   edi, word [edi+26]      ; starting cluster
1994
.write_loop:
1995
        sub     ebx, 0x200
1996
        jae     .next_cluster
1997
        push    ecx
1998
        neg     ebx
1999
        cmp     ecx, ebx
2000
        jbe     @f
2001
        mov     ecx, ebx
2002
@@:
2003
        mov     eax, edi
2004
        shl     eax, 9
381 serge 2005
        add     eax, RAMDISK+31*512+0x200
131 diamond 2006
        sub     eax, ebx
2007
        mov     ebx, eax
2008
        mov     eax, edx
2009
        call    memmove
2010
        xor     ebx, ebx
2011
        add     edx, ecx
2012
        sub     [esp], ecx
2013
        pop     ecx
2014
        jz      .ret
2015
.next_cluster:
381 serge 2016
        movzx   edi, word [edi*2+RAMDISK_FAT]
131 diamond 2017
        jmp     .write_loop
2018
 
2019
ramdisk_extend_file.zero_size:
2020
        xor     eax, eax
2021
        jmp     ramdisk_extend_file.start_extend
2022
 
2023
; extends file on ramdisk to given size, new data area is filled by 0
2024
; in: edi->direntry, ecx=new size
133 diamond 2025
; out: CF=0 => OK, eax=0
131 diamond 2026
;      CF=1 => error, eax=code (ERROR_FAT_TABLE or ERROR_DISK_FULL)
2027
ramdisk_extend_file:
2028
        push    ecx
2029
; find the last cluster of file
2030
        movzx   eax, word [edi+26]      ; first cluster
2031
        mov     ecx, [edi+28]
2032
        jecxz   .zero_size
2033
@@:
2034
        sub     ecx, 0x200
2035
        jbe     @f
381 serge 2036
        mov     eax, [eax*2+RAMDISK_FAT]
131 diamond 2037
        and     eax, 0xFFF
2038
        jz      .fat_err
2039
        cmp     eax, 0xFF8
2040
        jb      @b
2041
.fat_err:
2042
        pop     ecx
2043
        push    ERROR_FAT_TABLE
2044
        pop     eax
2045
        stc
2046
        ret
2047
@@:
2048
        push    eax
381 serge 2049
        mov     eax, [eax*2+RAMDISK_FAT]
131 diamond 2050
        and     eax, 0xFFF
2051
        cmp     eax, 0xFF8
2052
        pop     eax
2053
        jb      .fat_err
2054
; set length to full number of sectors and make sure that last sector is zero-padded
2055
        sub     [edi+28], ecx
2056
        push    eax edi
2057
        mov     edi, eax
2058
        shl     edi, 9
381 serge 2059
        lea     edi, [edi+RAMDISK+31*512+0x200+ecx]
131 diamond 2060
        neg     ecx
2061
        xor     eax, eax
2062
        rep     stosb
2063
        pop     edi eax
2064
.start_extend:
2065
        pop     ecx
2066
; now do extend
2067
        push    edx esi
381 serge 2068
        mov     esi, RAMDISK_FAT+2*2       ; start scan from cluster 2
131 diamond 2069
        mov     edx, 2847               ; number of clusters to scan
2070
.extend_loop:
2071
        cmp     [edi+28], ecx
2072
        jae     .extend_done
2073
; add new sector
2074
        push    ecx
2075
        mov     ecx, edx
2076
        push    edi
2077
        mov     edi, esi
2078
        jecxz   .disk_full
2079
        push    eax
2080
        xor     eax, eax
2081
        repnz   scasw
2082
        pop     eax
2083
        jnz     .disk_full
2084
        mov     word [edi-2], 0xFFF
2085
        mov     esi, edi
2086
        mov     edx, ecx
381 serge 2087
        sub     edi, RAMDISK_FAT
131 diamond 2088
        shr     edi, 1
2089
        dec     edi     ; now edi=new cluster
2090
        test    eax, eax
2091
        jz      .first_cluster
381 serge 2092
        mov     [RAMDISK_FAT+eax*2], di
131 diamond 2093
        jmp     @f
2094
.first_cluster:
2095
        pop     eax     ; eax->direntry
2096
        push    eax
2097
        mov     [eax+26], di
2098
@@:
2099
        push    edi
2100
        shl     edi, 9
381 serge 2101
        add     edi, RAMDISK+31*512
131 diamond 2102
        xor     eax, eax
2103
        mov     ecx, 512/4
2104
        rep     stosd
2105
        pop     eax     ; eax=new cluster
2106
        pop     edi     ; edi->direntry
2107
        pop     ecx     ; ecx=required size
2108
        add     dword [edi+28], 0x200
2109
        jmp     .extend_loop
2110
.extend_done:
2111
        mov     [edi+28], ecx
2112
        pop     esi edx
133 diamond 2113
        xor     eax, eax        ; CF=0
131 diamond 2114
        ret
2115
.disk_full:
2116
        pop     edi ecx
2117
        pop     esi edx
2118
        stc
2119
        push    ERROR_DISK_FULL
2120
        pop     eax
2121
        ret
2122
 
133 diamond 2123
fat_update_datetime:
2124
        call    get_time_for_file
2125
        mov     [edi+22], ax            ; last write time
2126
        call    get_date_for_file
2127
        mov     [edi+24], ax            ; last write date
2128
        mov     [edi+18], ax            ; last access date
2129
        ret
2130
 
2131
;----------------------------------------------------------------
2132
;
2133
;  fs_RamdiskSetFileEnd - set end of file on ramdisk
2134
;
2135
;  esi  points to filename
2136
;  ebx  points to 64-bit number = new file size
2137
;  ecx  ignored (reserved)
2138
;  edx  ignored (reserved)
2139
;
2140
;  ret eax = 0 ok or other = errormsg
2141
;
2142
;--------------------------------------------------------------
2143
fs_RamdiskSetFileEnd:
2144
        cmp     byte [esi], 0
2145
        jnz     @f
2146
.access_denied:
2147
        push    ERROR_ACCESS_DENIED
2148
        jmp     .ret
2149
@@:
2150
        push    edi
2151
        call    rd_find_lfn
2152
        jnc     @f
2153
        pop     edi
2154
        push    ERROR_FILE_NOT_FOUND
2155
.ret:
2156
        pop     eax
2157
        ret
2158
@@:
2159
; must not be directory
2160
        test    byte [edi+11], 10h
2161
        jz      @f
2162
        pop     edi
2163
        jmp     .access_denied
2164
@@:
2165
; file size must not exceed 4Gb
2166
        cmp     dword [ebx+4], 0
2167
        jz      @f
2168
        pop     edi
2169
        push    ERROR_END_OF_FILE
2170
        jmp     .ret
2171
@@:
2172
; set file modification date/time to current
2173
        call    fat_update_datetime
2174
        mov     eax, [ebx]
2175
        cmp     eax, [edi+28]
2176
        jb      .truncate
2177
        ja      .expand
2178
        pop     edi
2179
        xor     eax, eax
2180
        ret
2181
.expand:
2182
        push    ecx
2183
        mov     ecx, eax
2184
        call    ramdisk_extend_file
2185
        pop     ecx
2186
        pop     edi
2187
        ret
2188
.truncate:
2189
        mov     [edi+28], eax
2190
        push    ecx
2191
        movzx   ecx, word [edi+26]
2192
        test    eax, eax
2193
        jz      .zero_size
2194
; find new last sector
2195
@@:
2196
        sub     eax, 0x200
2197
        jbe     @f
381 serge 2198
        movzx   ecx, word [RAMDISK_FAT+ecx*2]
133 diamond 2199
        jmp     @b
2200
@@:
2201
; zero data at the end of last sector
2202
        push    ecx
2203
        mov     edi, ecx
2204
        shl     edi, 9
381 serge 2205
        lea     edi, [edi+RAMDISK+31*512+eax+0x200]
133 diamond 2206
        mov     ecx, eax
2207
        neg     ecx
2208
        xor     eax, eax
2209
        rep     stosb
2210
        pop     ecx
2211
; terminate FAT chain
381 serge 2212
        lea     ecx, [RAMDISK_FAT+ecx+ecx]
133 diamond 2213
        push    dword [ecx]
2214
        mov     word [ecx], 0xFFF
2215
        pop     ecx
2216
        and     ecx, 0xFFF
2217
        jmp     .delete
2218
.zero_size:
2219
        and     word [edi+26], 0
2220
.delete:
2221
; delete FAT chain starting with ecx
2222
; mark all clusters as free
2223
        cmp     ecx, 0xFF8
2224
        jae     .deleted
381 serge 2225
        lea     ecx, [RAMDISK_FAT+ecx+ecx]
133 diamond 2226
        push    dword [ecx]
2227
        and     word [ecx], 0
2228
        pop     ecx
2229
        and     ecx, 0xFFF
2230
        jmp     .delete
2231
.deleted:
2232
        pop     ecx
2233
        pop     edi
2234
        xor     eax, eax
2235
        ret
2236
 
86 diamond 2237
fs_RamdiskGetFileInfo:
2238
        cmp     byte [esi], 0
2239
        jnz     @f
2240
        mov     eax, 2  ; unsupported
2241
        ret
2242
@@:
2243
        push    edi
2244
        call    rd_find_lfn
2245
fs_GetFileInfo_finish:
2246
        jnc     @f
2247
        pop     edi
2248
        mov     eax, ERROR_FILE_NOT_FOUND
2249
        ret
2250
@@:
2251
        push    esi ebp
2252
        xor     ebp, ebp
2253
        mov     esi, edx
2254
        and     dword [esi+4], 0
2255
        call    fat_entry_to_bdfe2
2256
        pop     ebp esi
2257
        pop     edi
2258
        xor     eax, eax
2259
        ret
2260
 
2261
fs_RamdiskSetFileInfo:
2262
        cmp     byte [esi], 0
2263
        jnz     @f
2264
        mov     eax, 2  ; unsupported
2265
        ret
2266
@@:
2267
        push    edi
2268
        call    rd_find_lfn
2269
        jnc     @f
2270
        pop     edi
2271
        mov     eax, ERROR_FILE_NOT_FOUND
2272
        ret
2273
@@:
2274
        call    bdfe_to_fat_entry
2275
        pop     edi
2276
        xor     eax, eax
2277
        ret
2278
 
91 diamond 2279
;----------------------------------------------------------------
2280
;
2281
;  fs_RamdiskExecute - LFN variant for executing on sys floppy
2282
;
2283
;  esi  points to ramdisk filename (e.g. 'launcher')
2284
;  ebp  points to full filename (e.g. '/rd/1/launcher')
2285
;  dword [ebx] = flags
2286
;  dword [ebx+4] = cmdline
2287
;
2288
;  ret ebx,edx destroyed
2289
;      eax > 0 - PID, < 0 - error
2290
;
2291
;--------------------------------------------------------------
2292
fs_RamdiskExecute:
2293
        mov     edx, [ebx]
2294
        mov     ebx, [ebx+4]
2295
        test    ebx, ebx
2296
        jz      @f
2297
        add     ebx, std_application_base_address
2298
@@:
2299
 
2300
;----------------------------------------------------------------
2301
;
2302
; fs_RamdiskExecute.flags - second entry
2303
;
2304
;  esi  points to ramdisk filename (kernel address)
2305
;  ebp  points to full filename
2306
;  edx  flags
2307
;  ebx  cmdline (kernel address)
2308
;
2309
;  ret  eax > 0 - PID, < 0 - error
2310
;
2311
;--------------------------------------------------------------
2312
 
2313
.flags:
2314
        cmp     byte [esi], 0
2315
        jnz     @f
2316
; cannot execute root!
2317
        mov     eax, -ERROR_ACCESS_DENIED
2318
        ret
2319
@@:
2320
        push    edi
2321
        call    rd_find_lfn
2322
        jnc     .found
2323
        pop     edi
2324
        mov     eax, -ERROR_FILE_NOT_FOUND
2325
        ret
2326
.found:
2327
        movzx   eax, word [edi+26]      ; cluster
2328
        push    eax
2329
        push    dword [edi+28]          ; size
2330
        push    .DoRead
2331
        call    fs_execute
2332
        add     esp, 12
2333
        pop     edi
2334
        ret
2335
 
2336
.DoRead:
2337
; read next block
2338
; in: eax->parameters, edi->buffer
2339
; out: eax = error code
2340
        pushad
2341
        cmp     dword [eax], 0  ; file size
2342
        jz      .eof
2343
        mov     edx, [eax+4]    ; cluster
2344
        lea     esi, [edx+31]
2345
        shl     esi, 9
381 serge 2346
        add     esi, RAMDISK
91 diamond 2347
        mov     ecx, 512/4
2348
        rep     movsd
2349
        mov     ecx, [eax]
2350
        sub     ecx, 512
2351
        jae     @f
2352
        add     edi, ecx
2353
        neg     ecx
2354
        push    eax
2355
        xor     eax, eax
2356
        rep     stosb
2357
        pop     eax
2358
@@:
2359
        mov     [eax], ecx
381 serge 2360
        mov     dx, [edx*2+RAMDISK_FAT]
91 diamond 2361
        mov     [eax+4], dx     ; high word is already zero
2362
        popad
2363
        xor     eax, eax
2364
        ret
2365
.eof:
2366
        popad
2367
        mov     eax, 6
2368
        ret
2369
 
171 diamond 2370
;----------------------------------------------------------------
2371
;
2372
;  fs_RamdiskDelete - delete file or empty folder from ramdisk
2373
;
2374
;  esi  points to filename
2375
;
2376
;  ret  eax = 0 ok or other = errormsg
2377
;
2378
;--------------------------------------------------------------
2379
fs_RamdiskDelete:
2380
        cmp     byte [esi], 0
2381
        jnz     @f
2382
; cannot delete root!
2383
.access_denied:
2384
        push    ERROR_ACCESS_DENIED
2385
.pop_ret:
2386
        pop     eax
2387
        ret
2388
@@:
2389
        and     [rd_prev_sector], 0
2390
        and     [rd_prev_prev_sector], 0
2391
        push    edi
2392
        call    rd_find_lfn
2393
        jnc     .found
2394
        pop     edi
2395
        push    ERROR_FILE_NOT_FOUND
2396
        jmp     .pop_ret
2397
.found:
2398
        cmp     dword [edi], '.   '
2399
        jz      .access_denied2
2400
        cmp     dword [edi], '..  '
2401
        jz      .access_denied2
2402
        test    byte [edi+11], 10h
2403
        jz      .dodel
2404
; we can delete only empty folders!
2405
        movzx   eax, word [edi+26]
2406
        push    ebx
2407
        mov     ebx, eax
2408
        shl     ebx, 9
2409
        add     ebx, RAMDISK + 31*0x200 + 2*0x20
2410
.checkempty:
2411
        cmp     byte [ebx], 0
2412
        jz      .empty
2413
        cmp     byte [ebx], 0xE5
2414
        jnz     .notempty
2415
        add     ebx, 0x20
2416
        test    ebx, 0x1FF
2417
        jnz     .checkempty
2418
        movzx   eax, word [RAMDISK_FAT + eax*2]
2419
        test    eax, eax
2420
        jz      .empty
2421
        mov     ebx, eax
2422
        shl     ebx, 9
2423
        add     ebx, RAMDISK + 31*0x200
2424
        jmp     .checkempty
2425
.notempty:
2426
        pop     ebx
2427
.access_denied2:
2428
        pop     edi
2429
        jmp     .access_denied
2430
.empty:
2431
        pop     ebx
2432
.dodel:
2433
        movzx   eax, word [edi+26]
2434
; delete folder entry
2435
        mov     byte [edi], 0xE5
2436
; delete LFN (if present)
2437
.lfndel:
2438
        test    edi, 0x1FF
2439
        jnz     @f
2440
        cmp     [rd_prev_sector], 0
2441
        jz      @f
2442
        cmp     [rd_prev_sector], -1
2443
        jz      .lfndone
2444
        mov     edi, [rd_prev_sector]
2445
        push    [rd_prev_prev_sector]
2446
        pop     [rd_prev_sector]
2447
        or      [rd_prev_prev_sector], -1
2448
        shl     edi, 9
2449
        add     edi, RAMDISK + 31*0x200 + 0x200
2450
@@:
2451
        sub     edi, 0x20
2452
        cmp     byte [edi], 0xE5
2453
        jz      .lfndone
2454
        cmp     byte [edi+11], 0xF
2455
        jnz     .lfndone
2456
        mov     byte [edi], 0xE5
2457
        jmp     .lfndel
2458
.lfndone:
2459
; delete FAT chain
2460
        test    eax, eax
2461
        jz      .done
2462
        lea     eax, [RAMDISK_FAT + eax*2]
2463
        push    dword [eax]
2464
        and     word [eax], 0
2465
        pop     eax
2466
        and     eax, 0xFFF
2467
        jmp     .lfndone
2468
.done:
2469
        pop     edi
2470
        xor     eax, eax
2471
        ret
2472
 
78 diamond 2473
; \end{diamond}