|
@@ -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;
|