1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <memory.h>
5 #include "ssdef.h"
6 #include "access.h"
7
8 unsigned deaccesshead(struct VIOC *vioc,struct HEAD *head,unsigned idxblk);
9 unsigned accesshead(struct VCB *vcb,struct fiddef *fid,unsigned seg_num,
10 struct VIOC **vioc,struct HEAD **headbuff,
11 unsigned *retidxblk,unsigned wrtflg);
12 unsigned getwindow(struct FCB * fcb,unsigned vbn,struct VCBDEV **devptr,
13 unsigned *phyblk,unsigned *phylen,struct fiddef *hdrfid,
14 unsigned *hdrseq);
15 struct VCBDEV *rvn_to_dev(struct VCB *vcb,unsigned rvn);
16
17
18
19 /* Bitmaps get accesses in 'WORK_UNITs' which can be an integer
20 on a little endian machine but must be a byte on a big endian system */
21
22 #ifdef BIG_ENDIAN
23 #define WORK_UNIT unsigned char
24 #define WORK_MASK 0xff
25 #else
26 #define WORK_UNIT unsigned int
27 #define WORK_MASK 0xffffffff
28 #endif
29 #define WORK_BITS (sizeof(WORK_UNIT) * 8)
30
31 /* update_freecount() to read the device cluster bitmap and compute
32 the number of un-used clusters */
33
update_freecount(struct VCBDEV * vcbdev,unsigned * retcount)34 unsigned update_freecount(struct VCBDEV *vcbdev,unsigned *retcount)
35 {
36 register unsigned sts;
37 register unsigned free_clusters = 0;
38 register unsigned map_block, map_end = (vcbdev->max_cluster + 4095) / 4096 + 2;
39 for (map_block = 2; map_block < map_end; ) {
40 struct VIOC *vioc;
41 unsigned blkcount;
42 WORK_UNIT *bitmap,*work_ptr;
43 register unsigned work_count;
44 sts = accesschunk(vcbdev->mapfcb,map_block, &vioc,(char **) &bitmap,&blkcount,0);
45 if (!(sts & 1)) return sts;
46 if (blkcount > map_end - map_block) blkcount = map_end - map_block + 1;
47 work_ptr = bitmap;
48 work_count = blkcount * 512 / sizeof(WORK_UNIT);
49 do {
50 register WORK_UNIT work_val = *work_ptr++;
51 if (work_val == WORK_MASK) {
52 free_clusters += WORK_BITS;
53 } else {
54 while (work_val != 0) {
55 if (work_val & 1) free_clusters++;
56 work_val = work_val >> 1;
57 }
58 }
59 } while (--work_count > 0);
60 sts = deaccesschunk(vioc,0,0,1);
61 if (!(sts & 1)) return sts;
62 map_block += blkcount;
63 }
64 *retcount = free_clusters;
65 return sts;
66 }
67
68 /* bitmap_modify() will either set or release a block of bits in the
69 device cluster bitmap */
70
bitmap_modify(struct VCBDEV * vcbdev,unsigned cluster,unsigned count,unsigned release_flag)71 unsigned bitmap_modify(struct VCBDEV *vcbdev,unsigned cluster,unsigned count,
72 unsigned release_flag)
73 {
74 register unsigned sts;
75 register unsigned clust_count = count;
76 register unsigned map_block = cluster / 4096 + 2;
77 register unsigned block_offset = cluster % 4096;
78 if (clust_count < 1) return SS$_BADPARAM;
79 if (cluster + clust_count > vcbdev->max_cluster + 1) return SS$_BADPARAM;
80 do {
81 struct VIOC *vioc;
82 unsigned blkcount;
83 WORK_UNIT *bitmap;
84 register WORK_UNIT *work_ptr;
85 register unsigned work_count;
86 sts = accesschunk(vcbdev->mapfcb,map_block,&vioc,(char **) &bitmap,&blkcount,1);
87 if (!(sts & 1)) return sts;
88 work_ptr = bitmap + block_offset / WORK_BITS;
89 if (block_offset % WORK_BITS) {
90 register unsigned bit_no = block_offset % WORK_BITS;
91 register WORK_UNIT bit_mask = WORK_MASK;
92 if (bit_no + clust_count < WORK_BITS) {
93 bit_mask = bit_mask >> (WORK_BITS - clust_count);
94 clust_count = 0;
95 } else {
96 clust_count -= WORK_BITS - bit_no;
97 }
98 bit_mask = bit_mask << bit_no;
99 if (release_flag) {
100 *work_ptr++ |= bit_mask;
101 } else {
102 *work_ptr++ &= ~bit_mask;
103 }
104 block_offset += WORK_BITS - bit_no;
105 }
106 work_count = (blkcount * 4096 - block_offset) / WORK_BITS;
107 if (work_count > clust_count / WORK_BITS) {
108 work_count = clust_count / WORK_BITS;
109 block_offset = 1;
110 } else {
111 block_offset = 0;
112 }
113 clust_count -= work_count * WORK_BITS;
114 if (release_flag) {
115 while (clust_count-- > 0) {
116 *work_ptr++ = WORK_MASK;
117 }
118 } else {
119 while (work_count-- > 0) {
120 *work_ptr++ = 0;
121 }
122 }
123 if (clust_count != 0 && block_offset) {
124 register WORK_UNIT bit_mask = WORK_MASK >> (WORK_BITS - clust_count);
125 if (release_flag) {
126 *work_ptr++ |= bit_mask;
127 } else {
128 *work_ptr++ &= ~bit_mask;
129 }
130 clust_count = 0;
131 }
132 sts = deaccesschunk(vioc,map_block,blkcount,1);
133 if (!(sts & 1)) return sts;
134 map_block += blkcount;
135 block_offset = 0;
136 } while (clust_count != 0);
137 return sts;
138 }
139
140 /* bitmap_search() is a routine to find a pool of free clusters in the
141 device cluster bitmap */
142
bitmap_search(struct VCBDEV * vcbdev,unsigned * position,unsigned * count)143 unsigned bitmap_search(struct VCBDEV *vcbdev,unsigned *position,unsigned *count)
144 {
145 register unsigned sts;
146 register unsigned map_block,block_offset;
147 register unsigned search_words,needed;
148 register unsigned run = 0,cluster;
149 register unsigned best_run = 0,best_cluster = 0;
150 needed = *count;
151 if (needed < 1 || needed > vcbdev->max_cluster + 1) return SS$_BADPARAM;
152 cluster = *position;
153 if (cluster + *count > vcbdev->max_cluster + 1) cluster = 0;
154 map_block = cluster / 4096 + 2;
155 block_offset = cluster % 4096;
156 cluster = cluster - (cluster % WORK_BITS);
157 search_words = vcbdev->max_cluster / WORK_BITS;
158 do {
159 struct VIOC *vioc;
160 unsigned blkcount;
161 WORK_UNIT *bitmap;
162 register WORK_UNIT *work_ptr, work_val;
163 register unsigned work_count;
164 sts = accesschunk(vcbdev->mapfcb,map_block,&vioc,(char **) &bitmap,&blkcount,1);
165 if ((sts & 1) == 0) return sts;
166 work_ptr = bitmap + block_offset / WORK_BITS;
167 work_val = *work_ptr++;
168 if (block_offset % WORK_BITS) {
169 work_val = work_val && (WORK_MASK << block_offset % WORK_BITS);
170 }
171 work_count = (blkcount * 4096 - block_offset) / WORK_BITS;
172 if (work_count > search_words) work_count = search_words;
173 search_words -= work_count;
174 do {
175 if (work_val == WORK_MASK) {
176 run += WORK_BITS;
177 } else {
178 register unsigned bit_no = 0;
179 while (work_val != 0) {
180 if (work_val & 1) {
181 run++;
182 } else {
183 if (run > best_run) {
184 best_run = run;
185 best_cluster = cluster + bit_no;
186 }
187 run = 0;
188 }
189 work_val = work_val >> 1;
190 bit_no++;
191 }
192 if (bit_no < WORK_BITS) {
193 if (run > best_run) {
194 best_run = run;
195 best_cluster = cluster + bit_no;
196 }
197 run = 0;
198 }
199 }
200 cluster += WORK_BITS;
201 if (work_count-- > 0) {
202 work_val = *work_ptr++;
203 } else {
204 break;
205 }
206 } while (best_run < needed);
207 deaccesschunk(vioc,map_block,0,1);
208 if ((sts & 1) == 0) break;
209 map_block += blkcount;
210 block_offset = 0;
211 } while (best_run < needed && search_words != 0);
212 if (best_run > needed) best_run = needed;
213 *count = best_run;
214 *position = best_cluster;
215 return sts;
216 }
217
218 /* headmap_clear() will release a header from the indexf.sys file header
219 bitmap */
220
headmap_clear(struct VCBDEV * vcbdev,unsigned head_no)221 unsigned headmap_clear(struct VCBDEV *vcbdev,unsigned head_no)
222 {
223 WORK_UNIT *bitmap;
224 struct VIOC *vioc;
225 register unsigned sts;
226 register unsigned map_block = head_no / 4096 + vcbdev->home.hm2$w_cluster * 4 + 1;
227 if (head_no < 10) return 0;
228 sts = accesschunk(vcbdev->idxfcb,map_block,&vioc,(char **) &bitmap,NULL,1);
229 if (sts & 1) {
230 bitmap[(head_no % 4096) / WORK_BITS] &= ~(1 << (head_no % WORK_BITS));
231 sts = deaccesschunk(vioc,map_block,1,1);
232 }
233 return sts;
234 }
235
236 /* update_findhead() will locate a free header from indexf.sys */
237
update_findhead(struct VCBDEV * vcbdev,unsigned * rethead_no,struct VIOC ** retvioc,struct HEAD ** headbuff,unsigned * retidxblk)238 unsigned update_findhead(struct VCBDEV *vcbdev,unsigned *rethead_no,
239 struct VIOC **retvioc,struct HEAD **headbuff,
240 unsigned *retidxblk)
241 {
242 unsigned head_no = 0;
243 register unsigned sts;
244 do {
245 struct VIOC *vioc;
246 int modify_flag = 0;
247 unsigned blkcount;
248 WORK_UNIT *bitmap,*work_ptr;
249 register unsigned map_block,work_count;
250 map_block = head_no / 4096 + vcbdev->home.hm2$w_cluster * 4 + 1;
251 sts = accesschunk(vcbdev->idxfcb,map_block,
252 &vioc,(char **) &bitmap,&blkcount,1);
253 if ((sts & 1) == 0) return sts;
254 work_count = (head_no % 4096) / WORK_BITS;
255 work_ptr = bitmap + work_count;
256 work_count = blkcount * 512 / WORK_BITS - work_count;
257 do {
258 register WORK_UNIT work_val = *work_ptr;
259 if (work_val == WORK_MASK) {
260 head_no += WORK_BITS;
261 } else {
262 register unsigned bit_no = 0;
263 for (bit_no = 0; bit_no < WORK_BITS; bit_no++) {
264 if ((work_val & (1 << bit_no)) == 0) {
265 register unsigned idxblk = head_no +
266 VMSWORD(vcbdev->home.hm2$w_ibmapvbn) +
267 VMSWORD(vcbdev->home.hm2$w_ibmapsize);
268 sts = accesschunk(vcbdev->idxfcb,idxblk,retvioc,(char **) headbuff,NULL,1);
269 if (sts & 1) {
270 *work_ptr |= 1 << bit_no;
271 modify_flag = 1;
272 if ((*headbuff)->fh2$w_checksum != 0 || (*headbuff)->fh2$w_fid.fid$w_num != 0 ||
273 VMSLONG((*headbuff)->fh2$l_filechar) & FH2$M_MARKDEL == 0) {
274 sts = deaccesschunk(*retvioc,0,0,0);
275 } else {
276 *rethead_no = head_no + 1;
277 *retidxblk = idxblk;
278 deaccesschunk(vioc,map_block,blkcount,modify_flag);
279 return SS$_NORMAL;
280 }
281 }
282 }
283 head_no++;
284 }
285 }
286 work_ptr++;
287 } while (--work_count != 0);
288 deaccesschunk(vioc,map_block,blkcount,modify_flag);
289 if ((sts & 1) == 0) break;
290 } while (head_no < VMSLONG(vcbdev->home.hm2$l_maxfiles));
291 return sts;
292 }
293
update_addhead(struct VCB * vcb,char * filename,struct fiddef * back,unsigned seg_num,struct fiddef * fid,struct VIOC ** vioc,struct HEAD ** rethead,unsigned * idxblk)294 unsigned update_addhead(struct VCB *vcb,char *filename,struct fiddef *back,
295 unsigned seg_num,struct fiddef *fid,
296 struct VIOC **vioc,struct HEAD **rethead,
297 unsigned *idxblk)
298 {
299 register unsigned free_space = 0;
300 register unsigned device,rvn,sts;
301 unsigned head_no;
302 struct IDENT *id;
303 struct HEAD *head;
304 struct VCBDEV *vcbdev = NULL;
305 for (device = 0; device < vcb->devices; device++) {
306 if (vcb->vcbdev[device].dev != NULL) {
307 if (vcb->vcbdev[device].free_clusters > free_space) {
308 free_space = vcb->vcbdev[device].free_clusters;
309 vcbdev = &vcb->vcbdev[device];
310 rvn = device;
311 }
312 }
313 }
314 if (vcbdev == NULL) return SS$_DEVICEFULL;
315
316 sts = update_findhead(vcbdev,&head_no,vioc,&head,idxblk);
317 if (!(sts & 1)) return sts;
318 printf("Header %d index %d rvn %d\n",head_no,idxblk,rvn);
319 fid->fid$w_num = head_no;
320 fid->fid$w_seq = ++head->fh2$w_fid.fid$w_seq;
321 if (fid->fid$w_seq == 0) fid->fid$w_seq = 1;
322 if (rvn > 0) {
323 fid->fid$b_rvn = rvn + 1;
324 } else {
325 fid->fid$b_rvn = 0;
326 }
327 fid->fid$b_nmx = head_no >> 16;
328 memset(head,0,512);
329 head->fh2$b_idoffset = 40;
330 head->fh2$b_mpoffset = 100;
331 head->fh2$b_acoffset = 255;
332 head->fh2$b_rsoffset = 255;
333 head->fh2$w_seg_num = seg_num;
334 head->fh2$w_struclev = 513;
335 head->fh2$l_fileowner.uic$w_mem = 4;
336 head->fh2$l_fileowner.uic$w_grp = 1;
337 fid_copy(&head->fh2$w_fid,fid,0);
338 if (back != NULL) fid_copy(&head->fh2$w_backlink,back,0);
339 id = (struct IDENT *) ((unsigned short *) head + 40);
340 memset(id->fi2$t_filenamext,' ',66);
341 if (strlen(filename) < 20) {
342 memset(id->fi2$t_filename,' ',20);
343 memcpy(id->fi2$t_filename,filename,strlen(filename));
344 } else {
345 memcpy(id->fi2$t_filename,filename,20);
346 memcpy(id->fi2$t_filenamext,filename+20,strlen(filename+20));
347 }
348 id->fi2$w_revision = 1;
349 sys_gettim(id->fi2$q_credate);
350 memcpy(id->fi2$q_revdate,id->fi2$q_credate,sizeof(id->fi2$q_credate));
351 memcpy(id->fi2$q_expdate,id->fi2$q_credate,sizeof(id->fi2$q_credate));
352 head->fh2$w_recattr.fat$l_efblk = VMSSWAP(1);
353 {
354 unsigned short check = checksum((vmsword *) head);
355 head->fh2$w_checksum = VMSWORD(check);
356 }
357 return 1;
358 }
359
360 /* update_create() will create a new file... */
361
update_create(struct VCB * vcb,struct fiddef * did,char * filename,struct fiddef * fid,struct FCB ** fcb)362 unsigned update_create(struct VCB *vcb,struct fiddef *did,char *filename,
363 struct fiddef *fid,struct FCB **fcb)
364 {
365 struct VIOC *vioc;
366 struct HEAD *head;
367 unsigned idxblk;
368 register unsigned sts;
369 sts = update_addhead(vcb,filename,did,0,fid,&vioc,&head,&idxblk);
370 if (!(sts & 1)) return sts;
371 sts = deaccesshead(vioc,head,idxblk);
372 if (sts & 1 && fcb != NULL) {
373 sts = accessfile(vcb,fid,fcb,1);
374 }
375 printf("(%d,%d,%d) %d\n",fid->fid$w_num,fid->fid$w_seq,fid->fid$b_rvn,sts);
376 return sts;
377 }
378
update_extend(struct FCB * fcb,unsigned blocks,unsigned contig)379 unsigned update_extend(struct FCB *fcb,unsigned blocks,unsigned contig)
380 {
381 register unsigned sts;
382 struct VCBDEV *vcbdev;
383 struct VIOC *vioc;
384 struct HEAD *head;
385 unsigned headvbn;
386 struct fiddef hdrfid;
387 unsigned hdrseq;
388 unsigned start_pos = 0;
389 unsigned block_count = blocks;
390 if (block_count < 1) return 0;
391 if ((fcb->status & FCB_WRITE) == 0) return SS$_WRITLCK;
392 if (fcb->hiblock > 0) {
393 unsigned mapblk,maplen;
394 sts = getwindow(fcb,fcb->hiblock,&vcbdev,&mapblk,&maplen,&hdrfid,&hdrseq);
395 if ((sts & 1) == 0) return sts;
396 start_pos = mapblk + 1;
397 if (hdrseq != 0) {
398 sts = accesshead(fcb->vcb,&hdrfid,hdrseq,&vioc,&head,&headvbn,1);
399 if ((sts & 1) == 0) return sts;
400 } else {
401 head = fcb->head;
402 vioc = NULL;
403 }
404 } else {
405 head = fcb->head;
406 vioc = NULL;
407 start_pos = 0; /* filenum * 3 /indexfsize * volumesize; */
408 }
409 if (vioc == NULL) vcbdev = rvn_to_dev(fcb->vcb,fcb->rvn);
410 if (vcbdev->free_clusters == 0 || head->fh2$b_map_inuse + 4 >=
411 head->fh2$b_acoffset - head->fh2$b_mpoffset) {
412 struct VIOC *nvioc;
413 struct HEAD *nhead;
414 unsigned nidxblk;
415 sts = update_addhead(fcb->vcb,"",&head->fh2$w_fid,head->fh2$w_seg_num+1,
416 &head->fh2$w_ext_fid,&nvioc,&nhead,&nidxblk);
417 if (!(sts & 1)) return sts;
418 if (vioc != NULL) deaccesshead(vioc,head,headvbn);
419 vioc = nvioc;
420 head = nhead;
421 headvbn = nidxblk;
422 vcbdev = rvn_to_dev(fcb->vcb,head->fh2$w_fid.fid$b_rvn);
423 }
424 sts = bitmap_search(vcbdev,&start_pos,&block_count);
425 printf("Update_extend %d %d\n",start_pos,block_count);
426 if (sts & 1) {
427 if (block_count < 1 || contig && block_count * vcbdev->clustersize < blocks) {
428 sts = SS$_DEVICEFULL;
429 } else {
430 register unsigned short *mp;
431 mp = (unsigned short *) head + head->fh2$b_mpoffset + head->fh2$b_map_inuse;
432 *mp++ = (3 << 14) | ((block_count *vcbdev->clustersize - 1) >> 16);
433 *mp++ = (block_count * vcbdev->clustersize - 1) & 0xffff;
434 *mp++ = (start_pos * vcbdev->clustersize) & 0xffff;
435 *mp++ = (start_pos * vcbdev->clustersize) >> 16;
436 head->fh2$b_map_inuse += 4;
437 fcb->hiblock += block_count * vcbdev->clustersize;
438 fcb->head->fh2$w_recattr.fat$l_hiblk = VMSSWAP(fcb->hiblock * vcbdev->clustersize);
439 sts = bitmap_modify(vcbdev,start_pos,block_count,0);
440 }
441 }
442 if (vioc != NULL) deaccesshead(vioc,head,headvbn);
443 return sts;
444 }
445
446
447
448
449 /* This routine has bugs and does NOT work properly yet!!!!
450 It may be something simple but I haven't had time to look...
451 So DON'T use mount/write!!! */
452
deallocfile(struct FCB * fcb)453 unsigned deallocfile(struct FCB *fcb)
454 {
455 register unsigned sts = 1;
456 /*
457 First mark all file clusters as free in BITMAP.SYS
458 */
459 register unsigned vbn = 1;
460 while (vbn <= fcb->hiblock) {
461 register unsigned sts;
462 unsigned phyblk,phylen;
463 struct VCBDEV *vcbdev;
464 sts = getwindow(fcb,vbn,&vcbdev,&phyblk,&phylen,NULL,NULL);
465 if ((sts & 1) == 0) break;
466
467 sts = bitmap_modify(vcbdev,phyblk,phylen,1);
468 if ((sts & 1) == 0) break;
469 }
470 /*
471 Now reset file header bit map in INDEXF.SYS and
472 update each of the file headers...
473 */
474 {
475 unsigned rvn = fcb->rvn;
476 unsigned headvbn = fcb->headvbn;
477 struct HEAD *head = fcb->head;
478 struct VIOC *headvioc = fcb->headvioc;
479 do {
480 unsigned ext_seg_num = 0;
481 struct fiddef extfid;
482 register struct VCBDEV *vcbdev;
483 unsigned *bitmap;
484 struct VIOC *vioc;
485 register unsigned filenum = (head->fh2$w_fid.fid$b_nmx << 16) +
486 head->fh2$w_fid.fid$w_num - 1;
487 register unsigned idxblk;
488 vcbdev = rvn_to_dev(fcb->vcb,rvn);
489 if (vcbdev == NULL) break;
490 idxblk = filenum / 4096 +
491 vcbdev->home.hm2$w_cluster * 4 + 1;
492 sts = accesschunk(vcbdev->idxfcb,idxblk,&vioc,
493 (char **) &bitmap,NULL,1);
494 if (sts & 1) {
495 bitmap[(filenum % 4096) / WORK_BITS] &=
496 ~(1 << (filenum % WORK_BITS));
497 sts = deaccesschunk(vioc,idxblk,1,1);
498 } else {
499 break;
500 }
501 head->fh2$w_fid.fid$w_num = 0;
502 head->fh2$w_fid.fid$b_rvn = 0;
503 head->fh2$w_fid.fid$b_nmx = 0;
504 head->fh2$w_checksum = 0;
505 ext_seg_num++;
506 memcpy(&extfid,&fcb->head->fh2$w_ext_fid,sizeof(struct fiddef));
507 sts = deaccesshead(headvioc,NULL,headvbn);
508 if ((sts & 1) == 0) break;
509 if (extfid.fid$b_rvn == 0) {
510 extfid.fid$b_rvn = rvn;
511 } else {
512 rvn = extfid.fid$b_rvn;
513 }
514 if (extfid.fid$w_num != 0 || extfid.fid$b_nmx != 0) {
515 sts = accesshead(fcb->vcb,&extfid,ext_seg_num,&headvioc,&head,&headvbn,1);
516 if ((sts & 1) == 0) break;
517 } else {
518 break;
519 }
520 } while (1);
521 if (sts & 1) {
522 fcb->headvioc = NULL;
523 cache_untouch(&fcb->cache,0);
524 cache_delete(&fcb->cache);
525 }
526 }
527 return sts;
528 }
529
530
531
532 /* accesserase: delete a file... */
533
accesserase(struct VCB * vcb,struct fiddef * fid)534 unsigned accesserase(struct VCB * vcb,struct fiddef * fid)
535 {
536 struct FCB *fcb;
537 register int sts;
538 sts = accessfile(vcb,fid,&fcb,1);
539 if (sts & 1) {
540 fcb->head->fh2$l_filechar |= FH2$M_MARKDEL;
541 printf("Accesserase ... \n");
542 sts = deaccessfile(fcb);
543 }
544 return sts;
545 }
546
547
548
549
550 #ifdef EXTEND
extend(struct FCB * fcb,unsigned blocks)551 unsigned extend(struct FCB *fcb,unsigned blocks)
552 {
553 register unsigned sts;
554 struct VCBDEV *vcbdev;
555 unsigned clusterno;
556 unsigned extended = 0;
557 if ((fcb->status & FCB_WRITE) == 0) return SS$_WRITLCK;
558 if (fcb->hiblock > 0) {
559 unsigned phyblk,phylen;
560 sts = getwindow(fcb,fcb->hiblock,&vcbdev,&phyblk,&phylen,NULL,NULL);
561 clusterno = (phyblk + 1) / vcbdev->home.hm2$w_cluster;
562 if ((sts & 1) == 0) return sts;
563 } else {
564 vcbdev = fcb->vcb->vcbdev;
565 clusterno = 0; /* filenum * 3 /indexfsize * volumesize; */
566 }
567 while (extended < blocks) {
568 unsigned *bitmap,blkcount;
569 struct VIOC *vioc;
570 register unsigned clustalq = 0;
571 register unsigned clustersz = vcbdev->home.hm2$w_cluster;
572 sts = accesschunk(vcbdev->mapfcb,clusterno / 4096 + 2,
573 &vioc,(char **) &bitmap,&blkcount,1);
574 if ((sts & 1) == 0) return sts;
575 do {
576 register unsigned wordno = (clusterno % 4096) / WORK_BITS;
577 register unsigned wordval = bitmap[wordno];
578 if (wordval == 0xffff) {
579 if (clustalq) break;
580 clusterno = (clusterno % WORK_BITS) *
581 WORK_BITS + 1;
582 } else {
583 register unsigned bitno = clusterno % WORK_BITS;
584 do {
585 if (wordval & (1 << bitno)) {
586 if (clustalq) break;
587 } else {
588 clustalq++;
589 wordval |= 1 << bitno;
590 }
591 clusterno++;
592 if (clustalq >= (extended - blocks)) break;
593 } while (++bitno < WORK_BITS);
594 if (clustalq) {
595 bitmap[wordno] = wordval;
596 if (bitno < WORK_BITS) break;
597 }
598 }
599 } while (++wordno < blkcount * 512 / sizeof(unsigned));
600 mp = (unsigned word *) fcb->head + fcb->head->fh2$b_mpoffset;
601 *mp++ = (3 << 14) | (clustalq >> 16);
602 *mp++ = clustalq & 0xff;
603 *mp++ = clustno & 0xff;
604 *clusertize
605 * mp++ = clustno << 16;
606 fcb->head->fh2$b_map_inuse + 4;
607 fcb->hiblock += clustalq;
608 fcb->head.fh2$w_recattr.fat$l_hiblk[0] = fcb->hiblock >> 16;
609 fcb->head.fh2$w_recattr.fat$l_hiblk[1] = fcb->hiblock & 0xff;
610 sts = deaccesschunk(vioc,clusterno / 4096 + 2,blkcount,1);
611 /* code to append clusterno:clustalq to map */
612 }
613 }
614 #endif
615
616
617
618 #ifdef EXTEND
619
access_create(struct VCB * vcb,struct FCB ** fcbadd,unsigned blocks)620 unsigned access_create(struct VCB * vcb,struct FCB ** fcbadd,unsigned blocks) {
621 register struct FCB *fcb;
622 struct fiddef fid;
623 unsigned create = sizeof(struct FCB);
624 if (wrtflg && ((vcb->status & VCB_WRITE) == 0)) return SS$_WRITLCK;
625
626 sts = headmap_search(struct VCBDEV * vcbdev,struct fiddef * fid,
627 struct VIOC ** vioc,struct HEAD ** headbuff,unsigned *retidxblk,) {
628 fcb = cachesearch((void *) &vcb->fcb,filenum,0,NULL,NULL,&create);
629 if (fcb == NULL) return SS$_INSFMEM;
630 /* If not found make one... */
631 if (create == 0) {
632 fcb->cache.objtype = CACHETYPE_DEV;
633 fcb->rvn = fid->fid_b_rvn;
634 if (fcb->rvn == 0 && vcb->devices > 1) fcb->rvn = 1;
635 fcb->vcb = vcb;
636 fcb->wcb = NULL;
637 fcb->headvbn = 0;
638 fcb->vioc = NULL;
639 fcb->headvioc = NULL;
640 fcb->cache.objmanager = fcbmanager;
641 }
642 if (wrtflg) {
643 if (fcb->headvioc != NULL && (fcb->cache.status & CACHE_WRITE) == 0) {
644 deaccesshead(fcb->headvioc,NULL,0);
645 fcb->headvioc = NULL;
646 }
647 fcb->cache.status |= CACHE_WRITE;
648 }
649 if (fcb->headvioc == NULL) {
650 register unsigned sts;
651 if (vcb->idxboot != NULL) {
652 *fcbadd = fcb;
653 fcb->hiblock = 32767; /* guess at indexf.sys file size */
654 fcb->highwater = 0;
655 fcb->head = vcb->idxboot; /* Load bootup header */
656 }
657 sts = accesshead(vcb,fid,0,&fcb->headvioc,&fcb->head,&fcb->headvbn,wrtflg);
658 if (sts & 1) {
659 fcb->hiblock = VMSSWAP(fcb->head->fh2$w_recattr.fat$l_hiblk);
660 if (fcb->head->fh2$b_idoffset > 39) {
661 fcb->highwater = fcb->head->fh2$l_highwater;
662 } else {
663 fcb->highwater = 0;
664 }
665 } else {
666 printf("Accessfile status %d\n",sts);
667 fcb->cache.objmanager = NULL;
668 cacheuntouch(&fcb->cache,0,0);
669 cachefree(&fcb->cache);
670 return sts;
671 }
672 }
673 *fcbadd = fcb;
674 return SS$_NORMAL;
675 }
676 #endif
677
678