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
 #define ERRFILE_icmp			( ERRFILE_NET | 0x00390000 )
223
 #define ERRFILE_icmp			( ERRFILE_NET | 0x00390000 )
224
 #define ERRFILE_ping			( ERRFILE_NET | 0x003a0000 )
224
 #define ERRFILE_ping			( ERRFILE_NET | 0x003a0000 )
225
 #define ERRFILE_dhcpv6			( ERRFILE_NET | 0x003b0000 )
225
 #define ERRFILE_dhcpv6			( ERRFILE_NET | 0x003b0000 )
226
+#define ERRFILE_nfs_uri			( ERRFILE_NET | 0x003c0000 )
226
 
227
 
227
 #define ERRFILE_image		      ( ERRFILE_IMAGE | 0x00000000 )
228
 #define ERRFILE_image		      ( ERRFILE_IMAGE | 0x00000000 )
228
 #define ERRFILE_elf		      ( ERRFILE_IMAGE | 0x00010000 )
229
 #define ERRFILE_elf		      ( ERRFILE_IMAGE | 0x00010000 )

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

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
 #include <ipxe/oncrpc_iob.h>
40
 #include <ipxe/oncrpc_iob.h>
41
 #include <ipxe/portmap.h>
41
 #include <ipxe/portmap.h>
42
 #include <ipxe/mount.h>
42
 #include <ipxe/mount.h>
43
+#include <ipxe/nfs_uri.h>
43
 
44
 
44
 /** @file
45
 /** @file
45
  *
46
  *
101
 	struct oncrpc_cred_sys  auth_sys;
102
 	struct oncrpc_cred_sys  auth_sys;
102
 
103
 
103
 	char *                  hostname;
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
 	struct nfs_fh           readlink_fh;
107
 	struct nfs_fh           readlink_fh;
110
 	struct nfs_fh           current_fh;
108
 	struct nfs_fh           current_fh;
127
 	nfs = container_of ( refcnt, struct nfs_request, refcnt );
125
 	nfs = container_of ( refcnt, struct nfs_request, refcnt );
128
 	DBGC ( nfs, "NFS_OPEN %p freed\n", nfs );
126
 	DBGC ( nfs, "NFS_OPEN %p freed\n", nfs );
129
 
127
 
128
+	nfs_uri_free ( &nfs->uri );
129
+
130
 	free ( nfs->hostname );
130
 	free ( nfs->hostname );
131
-	free ( nfs->path );
132
 	free ( nfs->auth_sys.hostname );
131
 	free ( nfs->auth_sys.hostname );
133
 	free ( nfs );
132
 	free ( nfs );
134
 }
133
 }
145
 
144
 
146
 	DBGC ( nfs, "NFS_OPEN %p completed (%s)\n", nfs, strerror ( rc ) );
145
 	DBGC ( nfs, "NFS_OPEN %p completed (%s)\n", nfs, strerror ( rc ) );
147
 
146
 
148
-	free ( nfs->filename - nfs->filename_offset );
149
-
150
 	intf_shutdown ( &nfs->xfer, rc );
147
 	intf_shutdown ( &nfs->xfer, rc );
151
 	intf_shutdown ( &nfs->pm_intf, rc );
148
 	intf_shutdown ( &nfs->pm_intf, rc );
152
 	intf_shutdown ( &nfs->mount_intf, rc );
149
 	intf_shutdown ( &nfs->mount_intf, rc );
276
 
273
 
277
 	if ( nfs->mount_state == NFS_MOUNT_NONE ) {
274
 	if ( nfs->mount_state == NFS_MOUNT_NONE ) {
278
 		DBGC ( nfs, "NFS_OPEN %p MNT call (%s)\n", nfs,
275
 		DBGC ( nfs, "NFS_OPEN %p MNT call (%s)\n", nfs,
279
-		       nfs->mountpoint );
276
+		       nfs_uri_mountpoint ( &nfs->uri ) );
280
 
277
 
281
 		rc = mount_mnt ( &nfs->mount_intf, &nfs->mount_session,
278
 		rc = mount_mnt ( &nfs->mount_intf, &nfs->mount_session,
282
-		                 nfs->mountpoint );
279
+		                 nfs_uri_mountpoint ( &nfs->uri ) );
283
 		if ( rc != 0 )
280
 		if ( rc != 0 )
284
 			goto err;
281
 			goto err;
285
 
282
 
291
 		DBGC ( nfs, "NFS_OPEN %p UMNT call\n", nfs );
288
 		DBGC ( nfs, "NFS_OPEN %p UMNT call\n", nfs );
292
 
289
 
293
 		rc = mount_umnt ( &nfs->mount_intf, &nfs->mount_session,
290
 		rc = mount_umnt ( &nfs->mount_intf, &nfs->mount_session,
294
-		                  nfs->mountpoint );
291
+		                 nfs_uri_mountpoint ( &nfs->uri ) );
295
 		if ( rc != 0 )
292
 		if ( rc != 0 )
296
 			goto err;
293
 			goto err;
297
 	}
294
 	}
305
                                struct io_buffer *io_buf,
302
                                struct io_buffer *io_buf,
306
                                struct xfer_metadata *meta __unused ) {
303
                                struct xfer_metadata *meta __unused ) {
307
 	int                     rc;
304
 	int                     rc;
308
-	char                    *sep;
309
 	struct oncrpc_reply     reply;
305
 	struct oncrpc_reply     reply;
310
 	struct mount_mnt_reply  mnt_reply;
306
 	struct mount_mnt_reply  mnt_reply;
311
 
307
 
320
 		DBGC ( nfs, "NFS_OPEN %p got MNT reply\n", nfs );
316
 		DBGC ( nfs, "NFS_OPEN %p got MNT reply\n", nfs );
321
 		rc = mount_get_mnt_reply ( &mnt_reply, &reply );
317
 		rc = mount_get_mnt_reply ( &mnt_reply, &reply );
322
 		if ( rc != 0 ) {
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
 				goto err;
331
 				goto err;
325
 
332
 
326
-			if ( strcmp ( nfs->mountpoint, "/" ) == 0 )
333
+			if ( ( rc = nfs_uri_next_mountpoint ( &nfs->uri ) ) )
327
 				goto err;
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
 		nfs->current_fh = mnt_reply.fh;
345
 		nfs->current_fh = mnt_reply.fh;
370
 
366
 
371
 static void nfs_step ( struct nfs_request *nfs ) {
367
 static void nfs_step ( struct nfs_request *nfs ) {
372
 	int     rc;
368
 	int     rc;
373
-	char    *path_component = NULL;
369
+	char    *path_component;
374
 
370
 
375
 	if ( ! xfer_window ( &nfs->nfs_intf ) )
371
 	if ( ! xfer_window ( &nfs->nfs_intf ) )
376
 		return;
372
 		return;
377
 
373
 
378
 	if ( nfs->nfs_state == NFS_LOOKUP ) {
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
 		DBGC ( nfs, "NFS_OPEN %p LOOKUP call (%s)\n", nfs,
377
 		DBGC ( nfs, "NFS_OPEN %p LOOKUP call (%s)\n", nfs,
391
                        path_component );
378
                        path_component );
455
 
442
 
456
 		if ( lookup_reply.ent_type == NFS_ATTR_SYMLINK ) {
443
 		if ( lookup_reply.ent_type == NFS_ATTR_SYMLINK ) {
457
 			nfs->readlink_fh = lookup_reply.fh;
444
 			nfs->readlink_fh = lookup_reply.fh;
458
-			nfs->nfs_state = NFS_READLINK;
445
+			nfs->nfs_state   = NFS_READLINK;
459
 		} else {
446
 		} else {
460
 			nfs->current_fh = lookup_reply.fh;
447
 			nfs->current_fh = lookup_reply.fh;
461
 
448
 
462
-			if ( nfs->filename[0] == '\0' )
449
+			if ( nfs->uri.lookup_pos[0] == '\0' )
463
 				nfs->nfs_state = NFS_READ;
450
 				nfs->nfs_state = NFS_READ;
464
 			else
451
 			else
465
 				nfs->nfs_state--;
452
 				nfs->nfs_state--;
470
 	}
457
 	}
471
 
458
 
472
 	if ( nfs->nfs_state == NFS_READLINK_SENT ) {
459
 	if ( nfs->nfs_state == NFS_READLINK_SENT ) {
473
-		char                      *new_filename;
460
+		char                      *path;
474
 		struct nfs_readlink_reply readlink_reply;
461
 		struct nfs_readlink_reply readlink_reply;
475
 
462
 
476
 		DBGC ( nfs, "NFS_OPEN %p got READLINK reply\n", nfs );
463
 		DBGC ( nfs, "NFS_OPEN %p got READLINK reply\n", nfs );
480
 			goto err;
467
 			goto err;
481
 
468
 
482
 		if ( readlink_reply.path_len == 0 )
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
 			rc = -ENOMEM;
478
 			rc = -ENOMEM;
508
 			goto err;
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
 		nfs->nfs_state = NFS_LOOKUP;
488
 		nfs->nfs_state = NFS_LOOKUP;
525
 		nfs_step ( nfs );
489
 		nfs_step ( nfs );
638
 	if ( ! uri || ! uri->host || ! uri->path )
602
 	if ( ! uri || ! uri->host || ! uri->path )
639
 		return -EINVAL;
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
 	if ( ! ( nfs->hostname = strdup ( uri->host ) ) ) {
608
 	if ( ! ( nfs->hostname = strdup ( uri->host ) ) ) {
645
 		rc = -ENOMEM;
609
 		rc = -ENOMEM;
646
 		goto err_hostname;
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
 	return 0;
616
 	return 0;
659
 
617
 
660
-err_filename:
661
-	rc = -EINVAL;
662
-	free ( nfs->hostname );
663
 err_hostname:
618
 err_hostname:
664
-	free ( nfs->path );
619
+	nfs_uri_free ( &nfs->uri );
665
 	return rc;
620
 	return rc;
666
 }
621
 }
667
 
622
 
698
 	mount_init_session ( &nfs->mount_session, &nfs->auth_sys.credential );
653
 	mount_init_session ( &nfs->mount_session, &nfs->auth_sys.credential );
699
 	nfs_init_session ( &nfs->nfs_session, &nfs->auth_sys.credential );
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
 	rc = nfs_connect ( &nfs->pm_intf, PORTMAP_PORT, nfs->hostname );
659
 	rc = nfs_connect ( &nfs->pm_intf, PORTMAP_PORT, nfs->hostname );
702
 	if ( rc != 0 )
660
 	if ( rc != 0 )
703
 		goto err_connect;
661
 		goto err_connect;
711
 err_connect:
669
 err_connect:
712
 	free ( nfs->auth_sys.hostname );
670
 	free ( nfs->auth_sys.hostname );
713
 err_cred:
671
 err_cred:
672
+	nfs_uri_free ( &nfs->uri );
673
+	free ( nfs->hostname );
714
 err_uri:
674
 err_uri:
715
 	free ( nfs );
675
 	free ( nfs );
716
 	return rc;
676
 	return rc;

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

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