~ubuntu-branches/ubuntu/warty/dnprogs/warty

« back to all changes in this revision

Viewing changes to fal/task.cc

  • Committer: Bazaar Package Importer
  • Author(s): Patrick Caulfield
  • Date: 2004-05-30 10:13:57 UTC
  • Revision ID: james.westby@ubuntu.com-20040530101357-1geqhhh0teccu0cm
Tags: 2.27
* Fix signal handling in sethost so it doesn't die with an embarrassing
  "Alarm clock" message.
* Add dependancy on modutils. Closes: #251508

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/******************************************************************************
2
 
    (c) 1998-2000 P.J. Caulfield               patrick@tykepenguin.cix.co.uk
3
 
    
 
2
    (c) 1998-2002 P.J. Caulfield               patrick@tykepenguin.cix.co.uk
 
3
 
4
4
    This program is free software; you can redistribute it and/or modify
5
5
    it under the terms of the GNU General Public License as published by
6
6
    the Free Software Foundation; either version 2 of the License, or
14
14
 */
15
15
// task.cc
16
16
// Base class for a task within a FAL server process.
17
 
// All real tasks subclass this but we provide here some basic services such 
 
17
// All real tasks subclass this but we provide here some basic services such
18
18
// as filename conversion and parsing that they all need.
19
19
#include <sys/types.h>
20
20
#include <sys/socket.h>
54
54
// Send and error packet based on the passed error code
55
55
void fal_task::return_error(int code)
56
56
{
57
 
    if (verbose > 1) 
 
57
    if (verbose > 1)
58
58
        DAPLOG((LOG_ERR, "fal_task error: %s\n", strerror(code)));
59
59
 
60
60
    // If the other end went away there's no point in sending the message
88
88
        return vms_format=false;
89
89
}
90
90
 
 
91
/* Add the virtual "root" directory to the filename */
 
92
void fal_task::add_vroot(char *name)
 
93
{
 
94
    // Add in the vroot
 
95
    if (params.vroot_len)
 
96
    {
 
97
        int oldlen = strlen(name);
 
98
 
 
99
        /* Security measure...if the name has ".." in it then blank the whole lot out and
 
100
           confuse the user.
 
101
           well, it stops them escaping the root
 
102
        */
 
103
        if (strstr(name, ".."))
 
104
            name[0] = '\0';
 
105
 
 
106
        if (verbose > 3) DAPLOG((LOG_DEBUG, "add_vroot: name is %s, vroot='%s' (len=%d)\n", name, params.vroot, params.vroot_len));
 
107
        memmove(name + params.vroot_len, name, oldlen);
 
108
        memmove(name, params.vroot, params.vroot_len);
 
109
 
 
110
        /* Make sure it's NUL-terminated */
 
111
        name[oldlen+params.vroot_len] = '\0';
 
112
 
 
113
        if (verbose > 3) DAPLOG((LOG_DEBUG, "add_vroot: name is now %s\n", name));
 
114
    }
 
115
}
 
116
 
 
117
/* Remove the virtual "root" directory to the filename */
 
118
void fal_task::remove_vroot(char *name)
 
119
{
 
120
    if (params.vroot_len)
 
121
    {
 
122
        if (verbose > 3) DAPLOG((LOG_INFO, "remove_vroot: name is %s\n", name));
 
123
 
 
124
        memmove(name, name + params.vroot_len-1, strlen(name)+1);
 
125
 
 
126
        if (verbose > 3) DAPLOG((LOG_INFO, "remove_vroot: name is now %s\n", name));
 
127
    }
 
128
 
 
129
}
 
130
 
91
131
// Splits a filename up into volume, directory and file parts.
92
132
// The volume and directory are just for display purposes (they get sent back
93
 
// to the client). file is the (possibly) wildcard filespec to use for 
94
 
// searching for files. 
 
133
// to the client). file is the (possibly) wildcard filespec to use for
 
134
// searching for files.
95
135
//
96
136
// Unix filenames are just returned as-is.
97
137
//
100
140
//
101
141
void fal_task::split_filespec(char *volume, char *directory, char *file)
102
142
{
 
143
    // If the remote client is RSX then lower-case the filename
 
144
    if (params.remote_os == 4)
 
145
    {
 
146
        dap_connection::makelower(file);
 
147
    }
 
148
 
103
149
    if (is_vms_name(file))
104
150
    {
105
151
        // This converts the VMS name to a Unix name and back again. This
150
196
    int         i;
151
197
    char       *lastslash;
152
198
    struct stat st;
153
 
    
 
199
 
154
200
    // Resolve all relative bits and symbolic links
155
201
    realpath(unixname, fullname);
156
202
 
 
203
    // Remove the vroot, but leave a leading slash
 
204
    remove_vroot(fullname);
 
205
 
157
206
    // Find the last slash in the name
158
207
    lastslash = fullname + strlen(fullname);
159
208
    while (*(--lastslash) != '/') ;
162
211
    // expect one as does dapfs.
163
212
    if (!strchr(lastslash, '.'))
164
213
        strcat(fullname, ".");
165
 
    
 
214
 
166
215
    // If it's a directory then add .DIR;1
167
216
    if (lstat(unixname, &st)==0 && S_ISDIR(st.st_mode))
168
217
    {
169
218
        // Take care of dots embedded in directory names (/etc/rc.d)
170
219
        if (fullname[strlen(fullname)-1] != '.')
171
220
            strcat(fullname, ".");
172
 
        
 
221
 
173
222
        strcat(fullname, "DIR;1"); // last dot has already been added
174
223
    }
175
224
    else // else just add a version number unless the file already has one
199
248
    // and so on...
200
249
 
201
250
    int slashes = 0;
202
 
    
 
251
 
203
252
    // Oh, also make it all upper case for VMS's benefit.
204
253
    for (i=0; i<(int)strlen(fullname); i++)
205
254
    {
209
258
            slashes++;
210
259
        }
211
260
    }
212
 
    
 
261
 
213
262
    // File is in the root directory
214
263
    if (slashes == 1)
215
264
    {
276
325
        ptr = colon+1;
277
326
        *ptr = saved;
278
327
    }
279
 
    
 
328
 
280
329
    char *enddir = strchr(ptr, ']');
281
330
    if (*ptr == '[' && enddir) // we have a directory
282
331
    {
287
336
        ptr = enddir+1;
288
337
        *ptr = saved;
289
338
    }
290
 
    
 
339
 
291
340
    // Copy the rest of the filename using memmove 'cos it might overlap
292
341
    if (ptr != file)
293
342
        memmove(file, ptr, strlen(ptr)+1);
294
 
    
 
343
 
295
344
}
296
345
 
297
346
// Convert a VMS filespec into a Unix filespec
314
363
    // If the filename has a trailing dot them remove that too
315
364
    if (file[strlen(file)-1] == '.')
316
365
        file[strlen(file)-1] = '\0';
317
 
    
 
366
 
318
367
    unixname[0] = '\0';
319
368
 
320
369
    // Split it into its component parts
323
372
    // Remove the trailing colon from the volume name
324
373
    if (volume[strlen(volume)-1] == ':')
325
374
        volume[strlen(volume)-1] = '\0';
326
 
    
 
375
 
327
376
    // If the filename has the dummy SYSDISK volume then start from the
328
377
    // filesystem root
329
378
    if (strcasecmp(volume, sysdisk_name) == 0)
339
388
        }
340
389
    }
341
390
    ptr = strlen(unixname);
342
 
    
 
391
 
343
392
    // Copy the directory
344
393
    for (i=0; i< (int)strlen(dir); i++)
345
394
    {
364
413
        else
365
414
        {
366
415
            // Skip root directory specs
367
 
            if (dir[i] == '0' && strncmp(&dir[i], "000000", 6))
 
416
            if (dir[i] == '0' && (strncmp(&dir[i], "000000", 6) == 0))
368
417
            {
369
418
                i += 5;
370
419
                continue;
371
420
            }
372
 
            if (dir[i] == '0' && strncmp(&dir[i], "0,0", 3))
 
421
            if (dir[i] == '0' && (strncmp(&dir[i], "0,0", 3) == 0))
373
422
            {
374
423
                i += 2;
375
424
                continue;
408
457
            if (ext) *ext = '\0';
409
458
        }
410
459
    }
 
460
    add_vroot(unixname);
411
461
}
412
462
 
413
463
// Convert VMS wildcards to Unix wildcards
427
477
 
428
478
//
429
479
// Most of the subclasses use these routines to send the file attributes in
430
 
// response to an ACCESS message. 
 
480
// response to an ACCESS message.
431
481
// The option to send the DEV field is really for CREATE because when VMS
432
482
// sees the block device it tries to send the file in block mode and we then
433
483
// end up with an RMS file on Linux and that's not very useful.
440
490
}
441
491
 
442
492
 
443
 
bool fal_task::send_file_attributes(unsigned int &block_size, 
 
493
bool fal_task::send_file_attributes(unsigned int &block_size,
444
494
                                    bool &use_records,
445
 
                                    char *filename, 
446
 
                                    int display, 
 
495
                                    char *filename,
 
496
                                    int display,
447
497
                                    dev_option show_dev)
448
498
{
449
499
    struct stat st;
478
528
        }
479
529
 
480
530
        // There's hardly anything in this message but it keeps VMS quiet
481
 
        if (display & dap_access_message::DISPLAY_ALLOC_MASK)   
 
531
        if (display & dap_access_message::DISPLAY_ALLOC_MASK)
482
532
        {
483
533
            dap_alloc_message alloc_msg;
484
 
            
 
534
 
485
535
            if (!alloc_msg.write(conn)) return false;
486
536
        }
487
537
 
489
539
        if (display & dap_access_message::DISPLAY_DATE_MASK)
490
540
        {
491
541
            dap_date_message date_msg;
492
 
            
 
542
 
493
543
            date_msg.set_cdt(st.st_ctime);
494
544
            date_msg.set_rdt(st.st_mtime);
495
545
            date_msg.set_rvn(1);
496
546
            if (!date_msg.write(conn)) return false;
497
547
        }
498
 
        
 
548
 
499
549
        // Send the protection
500
550
        if (display & dap_access_message::DISPLAY_PROT_MASK)
501
551
        {
502
552
            dap_protect_message prot_msg;
503
 
            
 
553
 
504
554
            prot_msg.set_protection(st.st_mode);
505
555
            prot_msg.set_owner(st.st_gid, st.st_uid);
506
556
            if (!prot_msg.write(conn)) return false;
510
560
        if (display & dap_access_message::DISPLAY_NAME_MASK)
511
561
        {
512
562
            dap_name_message name_msg;
513
 
            
514
 
            if (vms_format)
 
563
 
 
564
            if (vms_format || params.remote_os == 4)
515
565
            {
516
566
                char vmsname[PATH_MAX];
517
 
                
 
567
 
518
568
                make_vms_filespec(filename, vmsname, true);
519
569
                name_msg.set_namespec(vmsname);
520
570
                name_msg.set_nametype(dap_name_message::FILESPEC);
573
623
        return true;
574
624
 
575
625
    // Guess file type
576
 
    if (params.auto_type == fal_params::GUESS_TYPE) 
 
626
    if (params.auto_type == fal_params::GUESS_TYPE)
577
627
        return guess_file_type(blocksize, send_records, name, attrib_msg);
578
 
    if (params.auto_type == fal_params::CHECK_EXT) 
 
628
    if (params.auto_type == fal_params::CHECK_EXT)
579
629
        return check_file_type(blocksize, send_records, name, attrib_msg);
580
630
 
581
631
    return false;
583
633
 
584
634
// Guess the file type based on the first few bytes and set the attrib
585
635
// message
586
 
bool fal_task::guess_file_type(unsigned int &block_size, bool &send_records, 
 
636
bool fal_task::guess_file_type(unsigned int &block_size, bool &send_records,
587
637
                               const char *name, dap_attrib_message *attrib_msg)
588
638
{
589
639
    char   buf[132]; // Arbitrary amounts R us
757
807
                {
758
808
                    strncpy(num, fileptr, numlen);
759
809
                    num[numlen] = '\0';
760
 
                    
 
810
 
761
811
                    block_size = atoi(num);
762
812
                }
763
813
            }
764
814
            auto_types *new_type = new auto_types(extension, use_records, block_size);
765
815
            if (verbose > 2)
766
 
                DAPLOG((LOG_DEBUG, "Type: %s, %c, %d\n", 
 
816
                DAPLOG((LOG_DEBUG, "Type: %s, %c, %d\n",
767
817
                        extension, use_records?'r':'b', block_size));
768
818
 
769
819
 
854
904
    struct stat st;
855
905
    if (stat(metafile, &st) == -1 && errno == ENOENT)
856
906
    {
857
 
        mkdir(metafile, 0700);
 
907
        // Make Unix do as it's fucking told.
 
908
        mode_t old_umask = umask(0);
 
909
        mkdir(metafile, 0777);
 
910
        umask(old_umask);
858
911
    }
859
912
    strcat(metafile, "/");
860
913
    strcat(metafile, endpath);
861
914
}
862
915
 
863
916
// Read file metadata - return true if it exists, false otherwise
864
 
bool fal_task::read_metafile(unsigned int &block_size, bool &send_records, 
 
917
bool fal_task::read_metafile(unsigned int &block_size, bool &send_records,
865
918
                             const char *name, dap_attrib_message *attrib_msg)
866
919
{
867
920
    char metafile[PATH_MAX];
916
969
            {
917
970
                // For variable-length records we always send as records if we
918
971
                // need to consult the metadata.
919
 
                if (metadata.rfm & dap_attrib_message::FB$VAR && 
 
972
                if (metadata.rfm & dap_attrib_message::FB$VAR &&
920
973
                    record_lengths != NULL)
921
974
                {
922
975
                    if (verbose>1) DAPLOG((LOG_DEBUG, "Sending VAR file as records\n"));
956
1009
        metadata.mrs = attrib_msg->get_mrs();
957
1010
        metadata.version = metafile_data::METAFILE_VERSION;
958
1011
        metadata.num_records = current_record;
959
 
        
 
1012
 
960
1013
        // Calculate Longest Record Length.
961
1014
        unsigned int lrl = 0;
962
1015
        for (unsigned int i=0; i<current_record; i++)
963
1016
            if (record_lengths[i] > lrl) lrl = record_lengths[i];
964
 
        
965
 
        // Our record lengths include the terminating LF so 
 
1017
 
 
1018
        // Our record lengths include the terminating LF so
966
1019
        // subtract that from the length.
967
1020
        // If there are no records then put MRS in there.
968
1021
        metadata.lrl = (lrl?(lrl - 1):metadata.mrs);
979
1032
            if (verbose > 1) DAPLOG((LOG_INFO, "Writing metafile with %d records\n", current_record));
980
1033
            ::fwrite(record_lengths, sizeof(short), current_record, mf);
981
1034
        }
 
1035
 
 
1036
        // Set the file ownership & protecttion of the metafile so it
 
1037
        // matches the real file.
 
1038
        struct stat st;
 
1039
        if (stat(name, &st) == 0)
 
1040
        {
 
1041
            fchown(fileno(mf), st.st_uid, st.st_gid);
 
1042
            fchmod(fileno(mf), st.st_mode & 0777);
 
1043
        }
982
1044
        fclose(mf);
983
1045
    }
984
1046
}
985
1047
 
986
1048
// Read VMS NFS "ADF" file - return true if it exists, false otherwise
987
 
bool fal_task::read_adf(unsigned int &block_size, bool &send_records, 
 
1049
bool fal_task::read_adf(unsigned int &block_size, bool &send_records,
988
1050
                        const char *name, dap_attrib_message *attrib_msg)
989
1051
{
990
1052
    char adfname[PATH_MAX];
1003
1065
            return false;
1004
1066
        }
1005
1067
        fclose(adf);
1006
 
        
 
1068
 
1007
1069
        adfs.rfm = adfs.rfm & 0xF;
1008
1070
        attrib_msg->set_rfm(adfs.rfm);
1009
1071
        attrib_msg->set_mrs(adfs.mrs);