get_vdir.c
上传用户:sddyfurun
上传日期:2007-01-04
资源大小:525k
文件大小:14k
源码类别:

代理服务器

开发平台:

Unix_Linux

  1. /*
  2.  * Copyright (c) 1989, 1990, 1991 by the University of Washington
  3.  *
  4.  * For copying and distribution information, please see the file
  5.  * <copyright.h>.
  6.  */
  7. #include "pmachine.h"
  8. #include "pfs.h"
  9. #include "pprot.h"
  10. #include "perrno.h"
  11. #include "pcompat.h"
  12. #include "pauthent.h"
  13. #ifdef DEBUG
  14. extern int pfs_debug;
  15. #endif
  16. extern int pwarn;
  17. extern char p_warn_string[];
  18. extern int perrno;
  19. extern char p_err_string[];
  20. /*
  21.  * get_vdir - Get contents of a directory given its location
  22.  *
  23.  *       GET_VDIR takes a directory location, a list of desired
  24.  *       components, a pointer to a directory structure to be 
  25.  *       filled in, and flags.  It then queries the appropriate 
  26.  *       directory server and retrieves the desired information.
  27.  *
  28.  *      ARGS:   dhost       - Host on which directory resides
  29.  *              dfile       - Directory on that host
  30.  *              components  - The names from the directory we want
  31.  * dir     - Structure to be filled in
  32.  *         flags       - Options.  See FLAGS
  33.  * filters     - filters to be applied to result 
  34.  *              acomp       - Pointer to remaining components
  35.  *
  36.  *     FLAGS: GVD_UNION   - Do not expand union links
  37.  * GVD_EXPAND  - Expand union links locally
  38.  * GVD_REMEXP  - Request remote expansion (& local if refused)
  39.  * GVD_LREMEXP - Request remote expansion of local union links
  40.  * GVD_VERIFY  - Only verify that args are for a directory
  41.  *              GVD_ATTRIB  - Request attributes from directory server
  42.  *              GVD_NOSORT  - Do not sort links when adding to directory
  43.  *
  44.  *   RETURNS:   PSUCCESS (0) or error code
  45.  * On some codes addition information in p_err_string
  46.  *
  47.  *     NOTES:   If acomp is non-null the string it points to might be modified
  48.  *
  49.  *              If the directory passed as an argument already has
  50.  * links or union links, then those lists will be freed
  51.  *              before the new contents are filled in.
  52.  *
  53.  *              If a filter is passed to the procedure, and application of
  54.  *              the filter results in additional union link, then those links
  55.  *              will (or will not) be expanded as specified in the FLAGS field.
  56.  *
  57.  *              If the list of components in NULL, or the null string, then
  58.  *              get_vdir will return all links in the requested directory.
  59.  *
  60.  *      BUGS:   Doesn't process union links yet
  61.  *              Doesn't process errors returned from server
  62.  * Doesn't expand union links if requested to
  63.  */
  64. int
  65. get_vdir(dhost,dfile,components,dir,flags,filters,acomp)
  66.     char *dhost; /* Host on which directory resides           */
  67.     char *dfile; /* Name of file on that host              */
  68.     char *components; /* Component name (wildcards allowed)        */
  69.     PVDIR dir; /* Structure to be filled in      */
  70.     long flags; /* Flags              */
  71.     VLINK filters; /* Filters to be applied to result           */
  72.     char *acomp; /* Components left to be resolved            */
  73.     {
  74.         PTEXT request; /* Text of request to dir server             */
  75. PTEXT resp;      /* Response from dir server              */
  76. char ulcomp[MAX_VPATH];/* Work space for new current component    */
  77. char *comp = components;
  78. VLINK cur_link = NULL;/* Current link being filled in              */
  79. VLINK  exp = NULL;  /* The current ulink being expanded      */
  80. VLINK pul = NULL;     /* Prev union link (insert new one after it) */
  81. VLINK l; /* Temp link pointer       */
  82. int mcomp; /* Flag - check multiple components          */
  83. int unresp; /* Flag - received unresolved response       */
  84. int getattrib = 0;  /* Get attributes from server                */
  85. int vl_insert_flag; /* Flags to vl_insert                        */
  86. int fwdcnt = MAX_FWD_DEPTH;
  87. int no_links = 0;   /* Count of number of links found      */
  88. char options[40];    /* LIST option                               */
  89. char *opt;           /* After leading +                           */
  90. PAUTH authinfo;
  91. /* Treat null string like NULL (return entire directory) */
  92. if(!components || !*components) comp = NULL;
  93. if(acomp && !filters) mcomp = 1;
  94. else mcomp = 0;
  95. if(flags&GVD_ATTRIB) {
  96.     getattrib++;
  97.     flags &= (~GVD_ATTRIB);
  98. }
  99. if(flags&GVD_NOSORT) vl_insert_flag = VLI_NOSORT;
  100. else vl_insert_flag = VLI_ALLOW_CONF;
  101. flags &= (~GVD_NOSORT);
  102. if(filters) comp = NULL;
  103. perrno = 0;
  104. authinfo = get_pauth(PFSA_UNAUTHENTICATED);
  105. *options = '';
  106. if(getattrib) {
  107.     strcat(options,"+ATTRIBUTES");
  108.     flags &= (~GVD_ATTRIB);
  109. }
  110. if(!filters) { /* Can't do remote expansion if filters to be applied */
  111.     if(flags == GVD_REMEXP) strcat(options,"+EXPAND");
  112.     if(flags == GVD_LREMEXP) strcat(options,"+LEXPAND");
  113. }
  114. /* If all we are doing is verifying that dfile is a directory */
  115. /* then we do not want a big response from the directory      */
  116. /* server.  A NOT-FOUND is sufficient.       */
  117. if(flags == GVD_VERIFY)
  118. #ifdef NEWVERIFYOPT
  119.     strcat(options,"+VERIFY");
  120. #else
  121. comp = "%#$PRobably_nOn_existaNT$#%";
  122. #endif
  123. if(*options) opt = options+1;
  124. else opt = "''";
  125.     startover:
  126. request = ptalloc();
  127. sprintf(request->start,
  128. "VERSION %d %snAUTHENTICATOR %s %snDIRECTORY ASCII %snLIST %s COMPONENTS %s%s%sn",
  129. VFPROT_VNO, PFS_SW_ID, authinfo->auth_type,
  130. authinfo->authenticator, dfile, opt,
  131. (comp ? comp : ""), (mcomp ? "/" : ""),
  132. (mcomp ? acomp : ""));
  133. request->length = strlen(request->start);
  134. #ifdef DEBUG
  135. if(pfs_debug > 2)
  136.     fprintf(stderr,"Sending message to dirsrv:n%s",request->start);
  137. #endif
  138. resp = dirsend(request,dhost,0);
  139. #ifdef DEBUG
  140. if(pfs_debug && (resp == NULL)) {
  141.     fprintf(stderr,"Dirsend failed: %dn",perrno);
  142. }
  143. #endif
  144. /* If we don't get a response, then if the requested       */
  145. /* directory, return error, if a ulink, mark it unexpanded */
  146. if(resp == NULL) {
  147.     if(exp) exp->expanded = FAILED;
  148.     else return(perrno);
  149. }
  150. unresp = 0;
  151. /* Here we must parse reponse and put in directory */
  152. /* While looking at each packet     */
  153. while(resp) {
  154.     PTEXT vtmp;
  155.     char *line;
  156.     vtmp = resp;
  157. #ifdef DEBUG
  158.     if(pfs_debug > 3) fprintf(stderr,"%sn",resp->start);
  159. #endif
  160.     /* Look at each line in packet */
  161.     for(line = resp->start;line != NULL;line = nxtline(line)) {
  162. switch (*line) {
  163.     
  164.     /* Temporary variables to hold link info */
  165.     char l_linktype;
  166.     char  l_name[MAX_DIR_LINESIZE];
  167.     char l_type[MAX_DIR_LINESIZE];
  168.     char  l_htype[MAX_DIR_LINESIZE];
  169.     char  l_host[MAX_DIR_LINESIZE];
  170.     char  l_ntype[MAX_DIR_LINESIZE];
  171.     char  l_fname[MAX_DIR_LINESIZE];
  172.     int l_version;
  173.     char  t_unresolved[MAX_DIR_LINESIZE];
  174.     int l_magic;
  175.     int tmp;
  176. case 'L': /* LINK or LINK-INFO */
  177.     if(strncmp(line,"LINK-INFO",9) == 0) {
  178. PATTRIB at;
  179. PATTRIB last_at;
  180. at = parse_attribute(line);
  181. if(!at) break;
  182. /* Cant have link info without a link */
  183. if(!cur_link) {
  184.     perrno = DIRSRV_BAD_FORMAT;
  185.     atfree(at);
  186.     break;
  187. }
  188. if(cur_link->lattrib) {
  189.     last_at = cur_link->lattrib;
  190.     while(last_at->next) last_at = last_at->next;
  191.     at->previous = last_at;
  192.     last_at->next = at;
  193. }
  194. else {
  195.     cur_link->lattrib = at;
  196.     at->previous = NULL;
  197. }
  198. break;
  199.     }
  200.     /* Not LINK-INFO, must be LINK - if not check for error */
  201.     if(strncmp(line,"LINK",4) != 0) goto scanerr;
  202.     /* If only verifying, don't want to change dir */
  203.     if(flags == GVD_VERIFY) {
  204. break;
  205.     }
  206.     /* If first link and some links in dir, free them */
  207.     if(!no_links++) {
  208. if(dir->links) vllfree(dir->links); dir->links=NULL;
  209. if(dir->ulinks) vllfree(dir->ulinks); dir->ulinks=NULL;
  210. }
  211.     cur_link = vlalloc();
  212.     /* parse and insert file info */
  213.     tmp = sscanf(line,"LINK %c %s %s %s %s %s %s %ld %ld", &l_linktype,
  214.  l_type,l_name,l_htype,l_host,l_ntype,l_fname,
  215.  &(cur_link->version),
  216.  &(cur_link->f_magic_no));
  217.     if(tmp != 9) {
  218. perrno = DIRSRV_BAD_FORMAT;
  219. vlfree(cur_link);
  220. break;
  221.     }
  222.     cur_link->linktype = l_linktype;
  223.     cur_link->type = stcopyr(l_type,cur_link->type);
  224.     cur_link->name = stcopyr(unquote(l_name),cur_link->name);
  225.     cur_link->hosttype = stcopyr(l_htype,cur_link->hosttype);
  226.     cur_link->host = stcopyr(l_host,cur_link->host);
  227.     cur_link->nametype = stcopyr(l_ntype,cur_link->nametype);
  228.     cur_link->filename = stcopyr(l_fname,cur_link->filename);
  229.     /* Double check to make sure we don't get */
  230.     /* back unwanted components       */
  231.     /* OK to keep if special (URP) links      */
  232.     /* or if mcomp specified                  */
  233.     if(!mcomp && (cur_link->linktype == 'L') && 
  234.        (!wcmatch(cur_link->name,comp))) {
  235. vlfree(cur_link);
  236. break;
  237.     }
  238.     /* If other optional info was sent back, it must */
  239.     /* also be parsed before inserting link     ***  */
  240.     
  241.     
  242.     if(cur_link->linktype == 'L') 
  243. vl_insert(cur_link,dir,vl_insert_flag);
  244.     else {
  245. tmp = ul_insert(cur_link,dir,pul);
  246. /* If inserted after pul, next one after cur_link */
  247. if(pul && (!tmp || (tmp == UL_INSERT_SUPERSEDING)))
  248.     pul = cur_link;
  249.     }
  250.     
  251.     break;
  252. case 'F': /* FILTER, FAILURE or FORWARDED */
  253.     /* FORWARDED */
  254.     if(strncmp(line,"FORWARDED",9) == 0) {
  255. if(fwdcnt-- <= 0) {
  256.     ptlfree(resp);
  257.     perrno = PFS_MAX_FWD_DEPTH;
  258.     return(perrno);
  259. }
  260. /* parse and start over */
  261. tmp = sscanf(line,"FORWARDED %s %s %s %s %d %d", 
  262.      l_htype,l_host,l_ntype,l_fname,
  263.      &l_version, &l_magic);
  264. dhost = stcopy(l_host);
  265. dfile = stcopy(l_fname);
  266. if(tmp < 4) {
  267.     perrno = DIRSRV_BAD_FORMAT;
  268.     break;
  269. }
  270. ptlfree(resp);
  271. goto startover;
  272.     }
  273.     if(strncmp(line,"FILTER",6) != 0) goto scanerr;
  274.     break;
  275. case 'M': /* MULTI-PACKET (processed by dirsend) */
  276. case 'P': /* PACKET (processed by dirsend) */
  277.     break;
  278. case 'N': /* NOT-A-DIRECTORY or NONE-FOUND */
  279.     /* NONE-FOUND, we just have no links to insert */
  280.     /* It is not an error, but we must clear any   */
  281.     /* old links in the directory arg              */
  282.     if(strncmp(line,"NONE-FOUND",10) == 0) {
  283. /* If only verifying, don't want to change dir */
  284. if(flags == GVD_VERIFY) {
  285.     break;
  286. }
  287. /* If first link and some links in dir, free them */
  288. if(!no_links++) {
  289.     if(dir->links) vllfree(dir->links);
  290.     if(dir->ulinks) vllfree(dir->ulinks);
  291.     dir->links = NULL;
  292.     dir->ulinks = NULL;
  293. }
  294. break;
  295.     }
  296.     /* If NOT-A-DIRECTORY or anything else, scan error */
  297.     goto scanerr;
  298. case 'U': /* UNRESOLVED */
  299.     if(strncmp(line,"UNRESOLVED",10) != 0) {
  300. goto scanerr;
  301.     }
  302.     tmp = sscanf(line,"UNRESOLVED %s", t_unresolved);
  303.     if(tmp < 1) {
  304. perrno = DIRSRV_BAD_FORMAT;
  305. break;
  306.     }
  307.     /* If multiple components were resolved */
  308.     if(strlen(t_unresolved) < strlen(acomp)) {
  309. strcpy(ulcomp,acomp);
  310. /* ulcomp is the components that were resolved */
  311. *(ulcomp+strlen(acomp)-strlen(t_unresolved)-1) = '';
  312. /* Comp gets the last component resolved */
  313. comp = (char *) rindex(ulcomp,'/');
  314. if(comp) comp++;
  315. else comp = ulcomp;
  316. /* Let rd_vdir know what remains */
  317. strcpy(acomp,t_unresolved);
  318.     }
  319.     unresp = 1;
  320.     break;
  321. case 'V': /* VERSION-NOT-SUPPORTED */
  322.     if(strncmp(line,"VERSION-NOT-SUPPORTED",21) == 0) {
  323. perrno = DIRSRV_BAD_VERS;
  324. return(perrno);
  325.     }
  326.     goto scanerr;
  327. scanerr:
  328. default:
  329.     if(*line && (tmp = scan_error(line))) {
  330. ptlfree(resp);
  331. return(tmp);
  332.     }
  333.     break;
  334. }
  335.     }
  336.     resp = resp->next;
  337.     ptfree(vtmp);
  338. }
  339. /* We sent multiple components and weren't told any */
  340. /* were unresolved                                  */
  341. if(mcomp && !unresp) {
  342.     /* ulcomp is the components that were resolved */
  343.     strcpy(ulcomp,acomp);
  344.     /* Comp gets the last component resolved */
  345.     comp = (char *) rindex(ulcomp,'/');
  346.     if(comp) comp++;
  347.     else comp = ulcomp;
  348.     /* If we have union links to resolve, only one component remains */
  349.     mcomp = 0;
  350.     /* Let rd_vdir know what remains */
  351.     *acomp = '';
  352. }
  353. /* If only verifying, we already know it is a directory */
  354. if(flags == GVD_VERIFY) return(PSUCCESS);
  355. /* Don't return if matching was delayed by the need to filter    */
  356. /* if FIND specified, and dir->links is non null, then we have   */
  357. /* found a match, and should return.                             */
  358. if((flags & GVD_FIND) && dir->links && (!filters))
  359.     return(PSUCCESS);
  360. /* If expand specified, and ulinks must be expanded, making sure */
  361.         /* that the order of the links is maintained properly            */
  362. if((flags != GVD_UNION) && (flags != GVD_VERIFY)) {
  363.     l = dir->ulinks;
  364.     /* Find first unexpanded ulink */
  365.     while(l && l->expanded && (l->linktype == 'U')) l = l->next;
  366.     
  367.     /* Only expand if a FILE or DIRECTORY -  Mark as  */
  368.             /* failed otherwise                               */
  369.     /* We must still add support for symbolic ulinks */
  370.     if(l) {
  371. if ((strcmp(l->type,"DIRECTORY") == 0) || 
  372.     (strcmp(l->type,"FILE") == 0)) {
  373.     l->expanded = TRUE;
  374.     exp = l;
  375.     pul = l;
  376.     dhost = l->host;
  377.     dfile = l->filename;
  378.     goto startover; /* was get_contents; */
  379. }
  380. else l->expanded = FAILED;
  381.     }
  382. }
  383. /* Double check to make sure we don't get */
  384. /* back unwanted components   */
  385. /* OK to keep if special (URP) links      */
  386. if(components && *components) {
  387.     l = dir->links;
  388.     while(l) {
  389. VLINK ol;
  390. if((l->linktype == 'L') && (!wcmatch(l->name,components))) {
  391.     if(l == dir->links)
  392. dir->links = l->next;
  393.     else l->previous->next = l->next;
  394.     if(l->next) l->next->previous = l->previous;
  395.     ol = l;
  396.     l = l->next;
  397.     vlfree(ol);
  398. }
  399. else l = l->next;
  400.     }
  401. }
  402. return(PSUCCESS);
  403.     }