Browse Source

[nfs] Rewrite NFS URI handling

Get the NFS URI manipulation code out of nfs_open.c.  The resulting
code is now much more readable.

Signed-off-by: Marin Hannache <git@mareo.fr>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Marin Hannache 10 years ago
parent
commit
f4e069bf2e
4 changed files with 228 additions and 90 deletions
  1. 1
    0
      src/include/ipxe/errfile.h
  2. 29
    0
      src/include/ipxe/nfs_uri.h
  3. 50
    90
      src/net/oncrpc/nfs_open.c
  4. 148
    0
      src/net/oncrpc/nfs_uri.c

+ 1
- 0
src/include/ipxe/errfile.h View File

@@ -223,6 +223,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
223 223
 #define ERRFILE_icmp			( ERRFILE_NET | 0x00390000 )
224 224
 #define ERRFILE_ping			( ERRFILE_NET | 0x003a0000 )
225 225
 #define ERRFILE_dhcpv6			( ERRFILE_NET | 0x003b0000 )
226
+#define ERRFILE_nfs_uri			( ERRFILE_NET | 0x003c0000 )
226 227
 
227 228
 #define ERRFILE_image		      ( ERRFILE_IMAGE | 0x00000000 )
228 229
 #define ERRFILE_elf		      ( ERRFILE_IMAGE | 0x00010000 )

+ 29
- 0
src/include/ipxe/nfs_uri.h View File

@@ -0,0 +1,29 @@
1
+#ifndef _IPXE_NFS_URI_H
2
+#define _IPXE_NFS_URI_H
3
+
4
+/** @file
5
+ *
6
+ * Network File System protocol URI handling functions
7
+ *
8
+ */
9
+
10
+FILE_LICENCE ( GPL2_OR_LATER );
11
+
12
+#include <ipxe/uri.h>
13
+
14
+struct nfs_uri {
15
+	char *mountpoint;
16
+	char *filename;
17
+	char *path;
18
+	char *lookup_pos;
19
+};
20
+
21
+int nfs_uri_init ( struct nfs_uri *nfs_uri, const struct uri *uri );
22
+int nfs_uri_next_mountpoint ( struct nfs_uri *uri );
23
+int nfs_uri_symlink ( struct nfs_uri *uri, const char *symlink_value );
24
+char *nfs_uri_mountpoint ( const struct nfs_uri *uri );
25
+char *nfs_uri_next_path_component ( struct nfs_uri *uri );
26
+void nfs_uri_free ( struct nfs_uri *uri );
27
+
28
+
29
+#endif /* _IPXE_NFS_URI_H */

+ 50
- 90
src/net/oncrpc/nfs_open.c View File

@@ -40,6 +40,7 @@
40 40
 #include <ipxe/oncrpc_iob.h>
41 41
 #include <ipxe/portmap.h>
42 42
 #include <ipxe/mount.h>
43
+#include <ipxe/nfs_uri.h>
43 44
 
44 45
 /** @file
45 46
  *
@@ -101,10 +102,7 @@ struct nfs_request {
101 102
 	struct oncrpc_cred_sys  auth_sys;
102 103
 
103 104
 	char *                  hostname;
104
-	char *                  path;
105
-	char *                  mountpoint;
106
-	char *                  filename;
107
-	size_t                  filename_offset;
105
+	struct nfs_uri          uri;
108 106
 
109 107
 	struct nfs_fh           readlink_fh;
110 108
 	struct nfs_fh           current_fh;
@@ -127,8 +125,9 @@ static void nfs_free ( struct refcnt *refcnt ) {
127 125
 	nfs = container_of ( refcnt, struct nfs_request, refcnt );
128 126
 	DBGC ( nfs, "NFS_OPEN %p freed\n", nfs );
129 127
 
128
+	nfs_uri_free ( &nfs->uri );
129
+
130 130
 	free ( nfs->hostname );
131
-	free ( nfs->path );
132 131
 	free ( nfs->auth_sys.hostname );
133 132
 	free ( nfs );
134 133
 }
@@ -145,8 +144,6 @@ static void nfs_done ( struct nfs_request *nfs, int rc ) {
145 144
 
146 145
 	DBGC ( nfs, "NFS_OPEN %p completed (%s)\n", nfs, strerror ( rc ) );
147 146
 
148
-	free ( nfs->filename - nfs->filename_offset );
149
-
150 147
 	intf_shutdown ( &nfs->xfer, rc );
151 148
 	intf_shutdown ( &nfs->pm_intf, rc );
152 149
 	intf_shutdown ( &nfs->mount_intf, rc );
@@ -276,10 +273,10 @@ static void nfs_mount_step ( struct nfs_request *nfs ) {
276 273
 
277 274
 	if ( nfs->mount_state == NFS_MOUNT_NONE ) {
278 275
 		DBGC ( nfs, "NFS_OPEN %p MNT call (%s)\n", nfs,
279
-		       nfs->mountpoint );
276
+		       nfs_uri_mountpoint ( &nfs->uri ) );
280 277
 
281 278
 		rc = mount_mnt ( &nfs->mount_intf, &nfs->mount_session,
282
-		                 nfs->mountpoint );
279
+		                 nfs_uri_mountpoint ( &nfs->uri ) );
283 280
 		if ( rc != 0 )
284 281
 			goto err;
285 282
 
@@ -291,7 +288,7 @@ static void nfs_mount_step ( struct nfs_request *nfs ) {
291 288
 		DBGC ( nfs, "NFS_OPEN %p UMNT call\n", nfs );
292 289
 
293 290
 		rc = mount_umnt ( &nfs->mount_intf, &nfs->mount_session,
294
-		                  nfs->mountpoint );
291
+		                 nfs_uri_mountpoint ( &nfs->uri ) );
295 292
 		if ( rc != 0 )
296 293
 			goto err;
297 294
 	}
@@ -305,7 +302,6 @@ static int nfs_mount_deliver ( struct nfs_request *nfs,
305 302
                                struct io_buffer *io_buf,
306 303
                                struct xfer_metadata *meta __unused ) {
307 304
 	int                     rc;
308
-	char                    *sep;
309 305
 	struct oncrpc_reply     reply;
310 306
 	struct mount_mnt_reply  mnt_reply;
311 307
 
@@ -320,30 +316,30 @@ static int nfs_mount_deliver ( struct nfs_request *nfs,
320 316
 		DBGC ( nfs, "NFS_OPEN %p got MNT reply\n", nfs );
321 317
 		rc = mount_get_mnt_reply ( &mnt_reply, &reply );
322 318
 		if ( rc != 0 ) {
323
-			if ( mnt_reply.status != MNT3ERR_NOTDIR )
319
+			switch ( mnt_reply.status ) {
320
+				case MNT3ERR_NOTDIR:
321
+				case MNT3ERR_NOENT:
322
+				case MNT3ERR_ACCES:
323
+					break;
324
+
325
+				default:
326
+					goto err;
327
+			}
328
+
329
+			if ( ! strcmp ( nfs_uri_mountpoint ( &nfs->uri ),
330
+				        "/" ) )
324 331
 				goto err;
325 332
 
326
-			if ( strcmp ( nfs->mountpoint, "/" ) == 0 )
333
+			if ( ( rc = nfs_uri_next_mountpoint ( &nfs->uri ) ) )
327 334
 				goto err;
328 335
 
329
-			sep = strrchr ( nfs->mountpoint, '/' );
330
-			nfs->filename[-1]    = '/';
331
-			nfs->filename_offset = sep + 1 - nfs->filename;
332
-			nfs->filename        = sep + 1;
333
-			*sep = '\0';
336
+			DBGC ( nfs, "NFS_OPEN %p MNT failed retrying with " \
337
+			       "%s\n", nfs, nfs_uri_mountpoint ( &nfs->uri ) );
334 338
 
335
-			DBGC ( nfs, "NFS_OPEN %p ENOTDIR received retrying" \
336
-			       "with %s\n", nfs, nfs->mountpoint );
337
-			goto done;
338
-		}
339
+			nfs->mount_state--;
340
+			nfs_mount_step ( nfs );
339 341
 
340
-		/* We need to strdup() nfs->filename since the code handling
341
-		 * symlink resolution make the assumption that it can be
342
-		 * free()ed. */
343
-		if ( ( nfs->filename = strdup ( nfs->filename ) ) == NULL )
344
-		{
345
-			rc = -ENOMEM;
346
-			goto err;
342
+			goto done;
347 343
 		}
348 344
 
349 345
 		nfs->current_fh = mnt_reply.fh;
@@ -370,22 +366,13 @@ done:
370 366
 
371 367
 static void nfs_step ( struct nfs_request *nfs ) {
372 368
 	int     rc;
373
-	char    *path_component = NULL;
369
+	char    *path_component;
374 370
 
375 371
 	if ( ! xfer_window ( &nfs->nfs_intf ) )
376 372
 		return;
377 373
 
378 374
 	if ( nfs->nfs_state == NFS_LOOKUP ) {
379
-		while ( path_component == NULL || path_component[0] == '\0') {
380
-			path_component = nfs->filename;
381
-			while ( *nfs->filename != '\0' ) {
382
-				nfs->filename_offset++;
383
-				if ( *nfs->filename++ == '/' ) {
384
-					*(nfs->filename - 1) = '\0';
385
-					break;
386
-				}
387
-			}
388
-		}
375
+		path_component = nfs_uri_next_path_component ( &nfs->uri );
389 376
 
390 377
 		DBGC ( nfs, "NFS_OPEN %p LOOKUP call (%s)\n", nfs,
391 378
                        path_component );
@@ -455,11 +442,11 @@ static int nfs_deliver ( struct nfs_request *nfs,
455 442
 
456 443
 		if ( lookup_reply.ent_type == NFS_ATTR_SYMLINK ) {
457 444
 			nfs->readlink_fh = lookup_reply.fh;
458
-			nfs->nfs_state = NFS_READLINK;
445
+			nfs->nfs_state   = NFS_READLINK;
459 446
 		} else {
460 447
 			nfs->current_fh = lookup_reply.fh;
461 448
 
462
-			if ( nfs->filename[0] == '\0' )
449
+			if ( nfs->uri.lookup_pos[0] == '\0' )
463 450
 				nfs->nfs_state = NFS_READ;
464 451
 			else
465 452
 				nfs->nfs_state--;
@@ -470,7 +457,7 @@ static int nfs_deliver ( struct nfs_request *nfs,
470 457
 	}
471 458
 
472 459
 	if ( nfs->nfs_state == NFS_READLINK_SENT ) {
473
-		char                      *new_filename;
460
+		char                      *path;
474 461
 		struct nfs_readlink_reply readlink_reply;
475 462
 
476 463
 		DBGC ( nfs, "NFS_OPEN %p got READLINK reply\n", nfs );
@@ -480,46 +467,23 @@ static int nfs_deliver ( struct nfs_request *nfs,
480 467
 			goto err;
481 468
 
482 469
 		if ( readlink_reply.path_len == 0 )
483
-			return -EINVAL;
484
-
485
-		if ( readlink_reply.path[0] == '/' ) {
486
-			if ( strncmp ( readlink_reply.path, nfs->mountpoint,
487
-			               strlen ( nfs->mountpoint ) ) != 0 )
488
-				return -EINVAL;
489
-
490
-			/* The mountpoint part of the path is ended by a '/' */
491
-			if ( strlen ( nfs->mountpoint ) !=
492
-			     readlink_reply.path_len ) {
493
-				readlink_reply.path     += 1;
494
-				readlink_reply.path_len -= 1;
495
-			}
496
-
497
-			/* We are considering the last part of the absolute
498
-			 * path as a relative path from the mountpoint.
499
-			 */
500
-			readlink_reply.path     += strlen ( nfs->mountpoint );
501
-			readlink_reply.path_len -= strlen ( nfs->mountpoint );
470
+		{
471
+			rc = -EINVAL;
472
+			goto err;
502 473
 		}
503 474
 
504
-		new_filename = malloc ( readlink_reply.path_len +
505
-		                        strlen ( nfs->filename ) + 2 );
506
-		if ( ! new_filename ) {
475
+		if ( ! ( path = strndup ( readlink_reply.path,
476
+		                          readlink_reply.path_len ) ) )
477
+		{
507 478
 			rc = -ENOMEM;
508 479
 			goto err;
509 480
 		}
510 481
 
511
-		memcpy ( new_filename, readlink_reply.path,
512
-		         readlink_reply.path_len );
513
-		strcpy ( new_filename + readlink_reply.path_len + 1,
514
-		         nfs->filename );
515
-		new_filename[readlink_reply.path_len] = '/';
516
-
517
-		free ( nfs->filename - nfs->filename_offset );
518
-		nfs->filename = new_filename;
519
-		nfs->filename_offset = 0;
482
+		nfs_uri_symlink ( &nfs->uri, path );
483
+		free ( path );
520 484
 
521
-		DBGC ( nfs, "NFS_OPEN %p new filename: %s\n", nfs,
522
-		       nfs->filename );
485
+		DBGC ( nfs, "NFS_OPEN %p new path: %s\n", nfs,
486
+		       nfs->uri.path );
523 487
 
524 488
 		nfs->nfs_state = NFS_LOOKUP;
525 489
 		nfs_step ( nfs );
@@ -638,30 +602,21 @@ static int nfs_parse_uri ( struct nfs_request *nfs, const struct uri *uri ) {
638 602
 	if ( ! uri || ! uri->host || ! uri->path )
639 603
 		return -EINVAL;
640 604
 
641
-	if ( ! ( nfs->path = strdup ( uri->path ) ) )
642
-		return -ENOMEM;
605
+	if ( ( rc = nfs_uri_init ( &nfs->uri, uri ) ) != 0 )
606
+		return rc;
643 607
 
644 608
 	if ( ! ( nfs->hostname = strdup ( uri->host ) ) ) {
645 609
 		rc = -ENOMEM;
646 610
 		goto err_hostname;
647 611
 	}
648 612
 
649
-	nfs->filename   = basename ( nfs->path );
650
-	nfs->mountpoint = dirname ( nfs->path );
651
-
652
-	if ( nfs->filename[0] == '\0' )
653
-		goto err_filename;
654
-
655
-	DBGC ( nfs, "NFS_OPEN %p URI parsed: (mountpoint=%s, filename=%s)\n",
656
-	       nfs, nfs->mountpoint, nfs->filename );
613
+	DBGC ( nfs, "NFS_OPEN %p URI parsed: (mountpoint=%s, path=%s)\n",
614
+	       nfs, nfs_uri_mountpoint ( &nfs->uri), nfs->uri.path );
657 615
 
658 616
 	return 0;
659 617
 
660
-err_filename:
661
-	rc = -EINVAL;
662
-	free ( nfs->hostname );
663 618
 err_hostname:
664
-	free ( nfs->path );
619
+	nfs_uri_free ( &nfs->uri );
665 620
 	return rc;
666 621
 }
667 622
 
@@ -698,6 +653,9 @@ static int nfs_open ( struct interface *xfer, struct uri *uri ) {
698 653
 	mount_init_session ( &nfs->mount_session, &nfs->auth_sys.credential );
699 654
 	nfs_init_session ( &nfs->nfs_session, &nfs->auth_sys.credential );
700 655
 
656
+	DBGC ( nfs, "NFS_OPEN %p connecting to port mapper (%s:%d)...\n", nfs,
657
+	       nfs->hostname, PORTMAP_PORT );
658
+
701 659
 	rc = nfs_connect ( &nfs->pm_intf, PORTMAP_PORT, nfs->hostname );
702 660
 	if ( rc != 0 )
703 661
 		goto err_connect;
@@ -711,6 +669,8 @@ static int nfs_open ( struct interface *xfer, struct uri *uri ) {
711 669
 err_connect:
712 670
 	free ( nfs->auth_sys.hostname );
713 671
 err_cred:
672
+	nfs_uri_free ( &nfs->uri );
673
+	free ( nfs->hostname );
714 674
 err_uri:
715 675
 	free ( nfs );
716 676
 	return rc;

+ 148
- 0
src/net/oncrpc/nfs_uri.c View File

@@ -0,0 +1,148 @@
1
+/*
2
+ * Copyright (C) 2014 Marin Hannache <ipxe@mareo.fr>.
3
+ *
4
+ * This program is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU General Public License as
6
+ * published by the Free Software Foundation; either version 2 of the
7
+ * License, or any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful, but
10
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17
+ * 02110-1301, USA.
18
+ */
19
+
20
+#include <stdlib.h>
21
+#include <string.h>
22
+#include <errno.h>
23
+#include <libgen.h>
24
+#include <ipxe/nfs_uri.h>
25
+
26
+/** @file
27
+ *
28
+ * Network File System protocol URI handling functions
29
+ *
30
+ */
31
+
32
+int nfs_uri_init ( struct nfs_uri *nfs_uri, const struct uri *uri ) {
33
+	if ( ! ( nfs_uri->mountpoint = strdup ( uri->path ) ) )
34
+		return -ENOMEM;
35
+
36
+	nfs_uri->filename = basename ( nfs_uri->mountpoint );
37
+	if ( strchr ( uri->path, '/' ) != NULL )
38
+		nfs_uri->mountpoint = dirname ( nfs_uri->mountpoint );
39
+
40
+	if ( nfs_uri->filename[0] == '\0' ) {
41
+		free ( nfs_uri->mountpoint );
42
+		return -EINVAL;
43
+	}
44
+
45
+	if ( ! ( nfs_uri->path = strdup ( nfs_uri->filename ) ) ) {
46
+		free ( nfs_uri->mountpoint );
47
+		return -ENOMEM;
48
+	}
49
+	nfs_uri->lookup_pos = nfs_uri->path;
50
+
51
+	return 0;
52
+}
53
+
54
+char *nfs_uri_mountpoint ( const struct nfs_uri *uri ) {
55
+	if ( uri->mountpoint + 1 == uri->filename ||
56
+	     uri->mountpoint     == uri->filename )
57
+		return "/";
58
+
59
+	return uri->mountpoint;
60
+}
61
+
62
+int nfs_uri_next_mountpoint ( struct nfs_uri *uri ) {
63
+	char *sep;
64
+
65
+	if ( uri->mountpoint + 1 == uri->filename ||
66
+	     uri->mountpoint     == uri->filename )
67
+		return -ENOENT;
68
+
69
+	sep = strrchr ( uri->mountpoint, '/' );
70
+	uri->filename[-1] = '/';
71
+	uri->filename     = sep + 1;
72
+	*sep = '\0';
73
+
74
+	free ( uri->path );
75
+	if ( ! ( uri->path = strdup ( uri->filename ) ) ) {
76
+		uri->path = NULL;
77
+		return -ENOMEM;
78
+	}
79
+	uri->lookup_pos = uri->path;
80
+
81
+	return 0;
82
+}
83
+
84
+int nfs_uri_symlink ( struct nfs_uri *uri, const char *symlink ) {
85
+	size_t len;
86
+	char *new_path;
87
+
88
+	if ( ! uri->path )
89
+		return -EINVAL;
90
+
91
+	if ( *symlink == '/' )
92
+	{
93
+		if ( strncmp ( symlink, uri->mountpoint,
94
+			       strlen ( uri->mountpoint ) ) != 0 )
95
+			return -EINVAL;
96
+
97
+		len = strlen ( uri->lookup_pos ) + strlen ( symlink ) - \
98
+		      strlen ( uri->mountpoint );
99
+		if ( ! ( new_path = malloc ( len * sizeof ( char ) ) ) )
100
+			return -ENOMEM;
101
+
102
+		strcpy ( new_path, symlink + strlen ( uri->mountpoint ) );
103
+		strcpy ( new_path + strlen ( new_path ), uri->lookup_pos );
104
+
105
+	} else {
106
+		len = strlen ( uri->lookup_pos ) + strlen ( symlink );
107
+		if ( ! ( new_path = malloc ( len * sizeof ( char ) ) ) )
108
+			return -ENOMEM;
109
+
110
+
111
+		strcpy ( new_path, symlink );
112
+		strcpy ( new_path + strlen ( new_path ), uri->lookup_pos );
113
+	}
114
+
115
+	free ( uri->path );
116
+	uri->lookup_pos = uri->path = new_path;
117
+
118
+	return 0;
119
+}
120
+
121
+char *nfs_uri_next_path_component ( struct nfs_uri *uri ) {
122
+	char *sep;
123
+	char *start;
124
+
125
+	if ( ! uri->path )
126
+		return NULL;
127
+
128
+	for ( sep = uri->lookup_pos ; *sep != '\0' && *sep != '/'; sep++ )
129
+		;
130
+
131
+	start = uri->lookup_pos;
132
+	uri->lookup_pos = sep;
133
+	if ( *sep != '\0' ) {
134
+		uri->lookup_pos++;
135
+		*sep = '\0';
136
+		if ( *start == '\0' )
137
+			return nfs_uri_next_path_component ( uri );
138
+	}
139
+
140
+	return start;
141
+}
142
+
143
+void nfs_uri_free ( struct nfs_uri *uri ) {
144
+	free ( uri->mountpoint );
145
+	free ( uri->path );
146
+	uri->mountpoint = NULL;
147
+	uri->path       = NULL;
148
+}

Loading…
Cancel
Save