File: Cns_readdirxc.c

package info (click to toggle)
lfc-postgres 1.7.4.7-1
  • links: PTS, VCS
  • area: main
  • in suites: squeeze
  • size: 13,676 kB
  • ctags: 10,779
  • sloc: ansic: 146,136; sh: 13,176; perl: 11,142; python: 5,529; cpp: 5,113; sql: 1,790; makefile: 861; fortran: 113
file content (134 lines) | stat: -rw-r--r-- 3,383 bytes parent folder | download | duplicates (8)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/*
 * Copyright (C) 2001-2006 by CERN/IT/PDP/DM
 * All rights reserved
 */

#ifndef lint
static char sccsid[] = "@(#)$RCSfile: Cns_readdirxc.c,v $ $Revision: 1.2 $ $Date: 2006/08/01 12:41:12 $ CERN IT-PDP/DM Jean-Philippe Baud";
#endif /* not lint */

/*	Cns_readdirxc - read a directory entry including file attributes  and comments */

#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#if defined(_WIN32)
#include <winsock2.h>
#else
#include <unistd.h>
#include <netinet/in.h>
#endif
#include "marshall.h"
#include "Cns_api.h"
#include "Cns.h"
#include "serrno.h"

struct Cns_direnstatc DLL_DECL *
Cns_readdirxc(Cns_DIR *dirp)
{
	int c;
	int direntsz;
	struct Cns_direnstatc *dp;
	char func[16];
	int getattr = 4;
	gid_t gid;
	int msglen;
	int n;
	int nbentries;
	char *q;
	char *rbp;
	char repbuf[DIRBUFSZ+4];
	char *sbp;
	char sendbuf[REQBUFSZ];
	uid_t uid;
 
	strcpy (func, "Cns_readdirx");
	uid = geteuid();
	gid = getegid();
#if defined(_WIN32)
	if (uid < 0 || gid < 0) {
		Cns_errmsg (func, NS053);
		serrno = SENOMAPFND;
		return (NULL);
	}
#endif

	if (! dirp) {
		serrno = EFAULT;
		return (NULL);
	}
	/* compute size of client machine Cns_direnstatc structure excluding d_name */

	dp = (struct Cns_direnstatc *) dirp->dd_buf;
	direntsz = &dp->d_name[0] - (char *) dp;

	if (dirp->dd_size == 0) {	/* no data in the cache */
		if (dirp->eod)
			return (NULL);

		/* Build request header */

		sbp = sendbuf;
		marshall_LONG (sbp, CNS_MAGIC);
		marshall_LONG (sbp, CNS_READDIR);
		q = sbp;        /* save pointer. The next field will be updated */
		msglen = 3 * LONGSIZE;
		marshall_LONG (sbp, msglen);
	 
		/* Build request body */

		marshall_LONG (sbp, uid);
		marshall_LONG (sbp, gid);
		marshall_WORD (sbp, getattr);
		marshall_WORD (sbp, direntsz);
		marshall_HYPER (sbp, dirp->fileid);
		marshall_WORD (sbp, dirp->bod);

		msglen = sbp - sendbuf;
		marshall_LONG (q, msglen);	/* update length field */

		c = send2nsd (&dirp->dd_fd, NULL, sendbuf, msglen,
		    repbuf, sizeof(repbuf));

		if (c < 0)
			return (NULL);
		rbp = repbuf;
		unmarshall_WORD (rbp, nbentries);
		if (nbentries == 0)
			return (NULL);		/* end of directory */

		/* unmarshall reply into the Cns_direnstatc structures */

		dp = (struct Cns_direnstatc *) dirp->dd_buf;
		while (nbentries--) {
			unmarshall_HYPER (rbp, dp->fileid);
			unmarshall_WORD (rbp, dp->filemode);
			unmarshall_LONG (rbp, dp->nlink);
			unmarshall_LONG (rbp, dp->uid);
			unmarshall_LONG (rbp, dp->gid);
			unmarshall_HYPER (rbp, dp->filesize);
			unmarshall_TIME_T (rbp, dp->atime);
			unmarshall_TIME_T (rbp, dp->mtime);
			unmarshall_TIME_T (rbp, dp->ctime);
			unmarshall_WORD (rbp, dp->fileclass);
			unmarshall_BYTE (rbp, dp->status);
			unmarshall_STRING (rbp, dp->d_name);
			dp->d_reclen = direntsz + strlen (dp->d_name) + 1;
			dp->comment = (char *) dp + dp->d_reclen;
			unmarshall_STRING (rbp, dp->comment);
			dp->d_reclen = ((dp->d_reclen + strlen (dp->comment) + 8) / 8) * 8;
			dp = (struct Cns_direnstatc *) ((char *) dp + dp->d_reclen);
		}
		dirp->bod = 0;
		unmarshall_WORD (rbp, dirp->eod);
		dirp->dd_size = (char *) dp - dirp->dd_buf;
	}
	dp = (struct Cns_direnstatc *) (dirp->dd_buf + dirp->dd_loc);
	dirp->dd_loc += dp->d_reclen;
	if (dirp->dd_loc >= dirp->dd_size) {	/* must refill next time */
		dirp->dd_loc = 0;
		dirp->dd_size = 0;
	}
	return (dp);
}